--- a/make/CompileJavaModules.gmk Tue Feb 13 14:41:54 2018 -0500
+++ b/make/CompileJavaModules.gmk Sat Feb 10 09:25:35 2018 +0100
@@ -443,6 +443,7 @@
#
jdk.internal.vm.compiler_EXCLUDES += \
+ org.graalvm.collections.test \
org.graalvm.compiler.core.match.processor \
org.graalvm.compiler.nodeinfo.processor \
org.graalvm.compiler.options.processor \
@@ -461,6 +462,7 @@
org.graalvm.compiler.graph.test \
org.graalvm.compiler.hotspot.amd64.test \
org.graalvm.compiler.hotspot.lir.test \
+ org.graalvm.compiler.hotspot.sparc.test \
org.graalvm.compiler.hotspot.test \
org.graalvm.compiler.jtt \
org.graalvm.compiler.lir.jtt \
--- a/make/CompileToolsHotspot.gmk Tue Feb 13 14:41:54 2018 -0500
+++ b/make/CompileToolsHotspot.gmk Sat Feb 10 09:25:35 2018 +0100
@@ -48,6 +48,7 @@
SETUP := GENERATE_OLDBYTECODE, \
SRC := \
$(SRC_DIR)/org.graalvm.word/src \
+ $(SRC_DIR)/org.graalvm.collections/src \
$(SRC_DIR)/org.graalvm.compiler.core/src \
$(SRC_DIR)/org.graalvm.compiler.core.common/src \
$(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \
@@ -101,6 +102,7 @@
$(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_OPTIONS_PROCESSOR, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := \
+ $(SRC_DIR)/org.graalvm.collections/src \
$(SRC_DIR)/org.graalvm.compiler.options/src \
$(SRC_DIR)/org.graalvm.compiler.options.processor/src \
$(SRC_DIR)/org.graalvm.util/src \
@@ -117,6 +119,7 @@
SETUP := GENERATE_OLDBYTECODE, \
SRC := \
$(SRC_DIR)/org.graalvm.word/src \
+ $(SRC_DIR)/org.graalvm.collections/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \
$(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
$(SRC_DIR)/org.graalvm.compiler.code/src \
--- a/make/test/JtregNativeHotspot.gmk Tue Feb 13 14:41:54 2018 -0500
+++ b/make/test/JtregNativeHotspot.gmk Sat Feb 10 09:25:35 2018 +0100
@@ -67,6 +67,7 @@
$(TOPDIR)/test/hotspot/jtreg/compiler/calls \
$(TOPDIR)/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup \
$(TOPDIR)/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption \
+ $(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/CanGenerateAllClassHook \
$(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorInfo \
$(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorStackDepthInfo \
$(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/GetNamedModule \
@@ -101,6 +102,7 @@
ifeq ($(TOOLCHAIN_TYPE), solstudio)
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc
+ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libCanGenerateAllClassHook := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetOwnedMonitorInfoTest := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetOwnedMonitorStackDepthInfoTest := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -2532,7 +2532,7 @@
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CounterData(), "need CounterData for calls");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
Register mdo = op->mdo()->as_register();
__ mov_metadata(mdo, md->constant_encoding());
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, 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
@@ -3150,7 +3150,7 @@
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CounterData(), "need CounterData for calls");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
Register mdo = op->mdo()->as_register();
assert(op->tmp1()->is_register(), "tmp1 must be allocated");
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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.
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -2746,7 +2746,7 @@
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CounterData(), "need CounterData for calls");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
Register mdo = op->mdo()->as_register();
#ifdef _LP64
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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.
* Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -2715,7 +2715,7 @@
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CounterData(), "need CounterData for calls");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
Register mdo = op->mdo()->as_register();
assert(op->tmp1()->is_double_cpu(), "tmp1 must be allocated");
--- a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -2761,7 +2761,7 @@
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CounterData(), "need CounterData for calls");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
Register mdo = op->mdo()->as_register();
assert(op->tmp1()->is_double_cpu(), "tmp1 must be allocated");
--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -3504,7 +3504,7 @@
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
- assert(data->is_CounterData(), "need CounterData for calls");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
Register mdo = op->mdo()->as_register();
__ mov_metadata(mdo, md->constant_encoding());
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -676,6 +676,7 @@
assert_different_registers(start, count);
BarrierSet* bs = Universe::heap()->barrier_set();
switch (bs->kind()) {
+#if INCLUDE_ALL_GCS
case BarrierSet::G1SATBCTLogging:
// With G1, don't generate the call if we statically know that the target in uninitialized
if (!uninitialized_target) {
@@ -703,6 +704,7 @@
__ bind(filtered);
}
break;
+#endif // INCLUDE_ALL_GCS
case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
case BarrierSet::ModRef:
@@ -726,6 +728,7 @@
BarrierSet* bs = Universe::heap()->barrier_set();
assert_different_registers(start, count);
switch (bs->kind()) {
+#if INCLUDE_ALL_GCS
case BarrierSet::G1SATBCTLogging:
{
__ pusha(); // push registers
@@ -734,6 +737,7 @@
__ popa();
}
break;
+#endif // INCLUDE_ALL_GCS
case BarrierSet::CardTableForRS:
case BarrierSet::CardTableExtension:
--- a/src/hotspot/os/aix/os_aix.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/os/aix/os_aix.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -188,6 +188,7 @@
////////////////////////////////////////////////////////////////////////////////
// local variables
+static volatile jlong max_real_time = 0;
static jlong initial_time_count = 0;
static int clock_tics_per_sec = 100;
static sigset_t check_signal_done; // For diagnostics to print a message once (see run_periodic_checks)
@@ -1076,32 +1077,50 @@
nanos = jlong(time.tv_usec) * 1000;
}
+// We use mread_real_time here.
+// On AIX: If the CPU has a time register, the result will be RTC_POWER and
+// it has to be converted to real time. AIX documentations suggests to do
+// this unconditionally, so we do it.
+//
+// See: https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/read_real_time.htm
+//
+// On PASE: mread_real_time will always return RTC_POWER_PC data, so no
+// conversion is necessary. However, mread_real_time will not return
+// monotonic results but merely matches read_real_time. So we need a tweak
+// to ensure monotonic results.
+//
+// For PASE no public documentation exists, just word by IBM
jlong os::javaTimeNanos() {
+ timebasestruct_t time;
+ int rc = mread_real_time(&time, TIMEBASE_SZ);
if (os::Aix::on_pase()) {
-
- timeval time;
- int status = gettimeofday(&time, NULL);
- assert(status != -1, "PASE error at gettimeofday()");
- jlong usecs = jlong((unsigned long long) time.tv_sec * (1000 * 1000) + time.tv_usec);
- return 1000 * usecs;
-
+ assert(rc == RTC_POWER, "expected time format RTC_POWER from mread_real_time in PASE");
+ jlong now = jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
+ jlong prev = max_real_time;
+ if (now <= prev) {
+ return prev; // same or retrograde time;
+ }
+ jlong obsv = Atomic::cmpxchg(now, &max_real_time, prev);
+ assert(obsv >= prev, "invariant"); // Monotonicity
+ // If the CAS succeeded then we're done and return "now".
+ // If the CAS failed and the observed value "obsv" is >= now then
+ // we should return "obsv". If the CAS failed and now > obsv > prv then
+ // some other thread raced this thread and installed a new value, in which case
+ // we could either (a) retry the entire operation, (b) retry trying to install now
+ // or (c) just return obsv. We use (c). No loop is required although in some cases
+ // we might discard a higher "now" value in deference to a slightly lower but freshly
+ // installed obsv value. That's entirely benign -- it admits no new orderings compared
+ // to (a) or (b) -- and greatly reduces coherence traffic.
+ // We might also condition (c) on the magnitude of the delta between obsv and now.
+ // Avoiding excessive CAS operations to hot RW locations is critical.
+ // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
+ return (prev == obsv) ? now : obsv;
} else {
- // On AIX use the precision of processors real time clock
- // or time base registers.
- timebasestruct_t time;
- int rc;
-
- // If the CPU has a time register, it will be used and
- // we have to convert to real time first. After convertion we have following data:
- // time.tb_high [seconds since 00:00:00 UTC on 1.1.1970]
- // time.tb_low [nanoseconds after the last full second above]
- // We better use mread_real_time here instead of read_real_time
- // to ensure that we will get a monotonic increasing time.
- if (mread_real_time(&time, TIMEBASE_SZ) != RTC_POWER) {
+ if (rc != RTC_POWER) {
rc = time_base_to_time(&time, TIMEBASE_SZ);
- assert(rc != -1, "aix error at time_base_to_time()");
+ assert(rc != -1, "error calling time_base_to_time()");
}
- return jlong(time.tb_high) * (1000 * 1000 * 1000) + jlong(time.tb_low);
+ return jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
}
}
--- a/src/hotspot/os/bsd/jvm_bsd.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/os/bsd/jvm_bsd.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, 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
@@ -51,6 +51,12 @@
case SIGILL:
case SIGSEGV:
+#if defined(__APPLE__)
+ /* On Darwin, memory access errors commonly results in SIGBUS instead
+ * of SIGSEGV. */
+ case SIGBUS:
+#endif
+
/* The following signal is used by the VM to dump thread stacks unless
ReduceSignalUsage is set, in which case the user is allowed to set
his own _native_ handler for this signal; thus, in either case,
--- a/src/hotspot/os/bsd/os_bsd.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/os/bsd/os_bsd.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -2206,7 +2206,7 @@
bool os::release_memory_special(char* base, size_t bytes) {
if (MemTracker::tracking_level() > NMT_minimal) {
- Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+ Tracker tkr(Tracker::release);
// detaching the SHM segment will also delete it, see reserve_memory_special()
int rslt = shmdt(base);
if (rslt == 0) {
--- a/src/hotspot/os/linux/osContainer_linux.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/os/linux/osContainer_linux.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -122,35 +122,40 @@
char file[MAXPATHLEN+1];
char buf[MAXPATHLEN+1];
- if (c != NULL && c->subsystem_path() != NULL) {
- strncpy(file, c->subsystem_path(), MAXPATHLEN);
- file[MAXPATHLEN-1] = '\0';
- int filelen = strlen(file);
- if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) {
- log_debug(os, container)("File path too long %s, %s", file, filename);
- return OSCONTAINER_ERROR;
- }
- strncat(file, filename, MAXPATHLEN-filelen);
- log_trace(os, container)("Path to %s is %s", filename, file);
- fp = fopen(file, "r");
- if (fp != NULL) {
- p = fgets(buf, MAXPATHLEN, fp);
- if (p != NULL) {
- int matched = sscanf(p, scan_fmt, returnval);
- if (matched == 1) {
- fclose(fp);
- return 0;
- } else {
- log_debug(os, container)("Type %s not found in file %s",
- scan_fmt , file);
- }
+ if (c == NULL) {
+ log_debug(os, container)("subsystem_file_contents: CgroupSubsytem* is NULL");
+ return OSCONTAINER_ERROR;
+ }
+ if (c->subsystem_path() == NULL) {
+ log_debug(os, container)("subsystem_file_contents: subsystem path is NULL");
+ return OSCONTAINER_ERROR;
+ }
+
+ strncpy(file, c->subsystem_path(), MAXPATHLEN);
+ file[MAXPATHLEN-1] = '\0';
+ int filelen = strlen(file);
+ if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) {
+ log_debug(os, container)("File path too long %s, %s", file, filename);
+ return OSCONTAINER_ERROR;
+ }
+ strncat(file, filename, MAXPATHLEN-filelen);
+ log_trace(os, container)("Path to %s is %s", filename, file);
+ fp = fopen(file, "r");
+ if (fp != NULL) {
+ p = fgets(buf, MAXPATHLEN, fp);
+ if (p != NULL) {
+ int matched = sscanf(p, scan_fmt, returnval);
+ if (matched == 1) {
+ fclose(fp);
+ return 0;
} else {
- log_debug(os, container)("Empty file %s", file);
+ log_debug(os, container)("Type %s not found in file %s", scan_fmt, file);
}
} else {
- log_debug(os, container)("Open of file %s failed, %s", file,
- os::strerror(errno));
+ log_debug(os, container)("Empty file %s", file);
}
+ } else {
+ log_debug(os, container)("Open of file %s failed, %s", file, os::strerror(errno));
}
if (fp != NULL)
fclose(fp);
@@ -273,7 +278,7 @@
else {
log_debug(os, container)("Incompatible str containing cgroup and cpuset: %s", p);
}
- } else if (strstr(p, "cpu,cpuacct") != NULL) {
+ } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) {
int matched = sscanf(p, "%d %d %d:%d %s %s",
&mountid,
&parentid,
@@ -322,8 +327,20 @@
fclose(mntinfo);
- if (memory == NULL || cpuset == NULL || cpu == NULL || cpuacct == NULL) {
- log_debug(os, container)("Required cgroup subsystems not found");
+ if (memory == NULL) {
+ log_debug(os, container)("Required cgroup memory subsystem not found");
+ return;
+ }
+ if (cpuset == NULL) {
+ log_debug(os, container)("Required cgroup cpuset subsystem not found");
+ return;
+ }
+ if (cpu == NULL) {
+ log_debug(os, container)("Required cgroup cpu subsystem not found");
+ return;
+ }
+ if (cpuacct == NULL) {
+ log_debug(os, container)("Required cgroup cpuacct subsystem not found");
return;
}
@@ -374,7 +391,7 @@
memory->set_subsystem_path(base);
} else if (strstr(controller, "cpuset") != NULL) {
cpuset->set_subsystem_path(base);
- } else if (strstr(controller, "cpu,cpuacct") != NULL) {
+ } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) {
cpu->set_subsystem_path(base);
cpuacct->set_subsystem_path(base);
} else if (strstr(controller, "cpuacct") != NULL) {
--- a/src/hotspot/os/linux/os_linux.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/os/linux/os_linux.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -3862,7 +3862,7 @@
bool os::release_memory_special(char* base, size_t bytes) {
bool res;
if (MemTracker::tracking_level() > NMT_minimal) {
- Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+ Tracker tkr(Tracker::release);
res = os::Linux::release_memory_special_impl(base, bytes);
if (res) {
tkr.record((address)base, bytes);
--- a/src/hotspot/os/windows/perfMemory_windows.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/os/windows/perfMemory_windows.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -1840,7 +1840,7 @@
if (MemTracker::tracking_level() > NMT_minimal) {
// it does not go through os api, the operation has to record from here
- Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+ Tracker tkr(Tracker::release);
remove_file_mapping(addr);
tkr.record((address)addr, bytes);
} else {
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -1556,8 +1556,6 @@
}
if (profile_return() && x->type()->is_object_kind()) {
ciMethod* caller = state()->scope()->method();
- ciMethodData* md = caller->method_data_or_null();
- ciProfileData* data = md->bci_to_data(invoke_bci);
profile_return_type(x, method(), caller, invoke_bci);
}
}
--- a/src/hotspot/share/classfile/classLoaderData.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -80,6 +80,9 @@
#include "trace/tracing.hpp"
#endif
+volatile size_t ClassLoaderDataGraph::_num_array_classes = 0;
+volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0;
+
ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) :
@@ -329,36 +332,36 @@
ClassLoaderData * const from_cld = this;
ClassLoaderData * const to_cld = k->class_loader_data();
- // Dependency to the null class loader data doesn't need to be recorded
- // because the null class loader data never goes away.
- if (to_cld->is_the_null_class_loader_data()) {
+ // 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.)
+ 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
+ // loader data.)
+ if (to_cld == from_cld) {
+ return;
+ }
// Anonymous class dependencies are through the mirror.
to = k->java_mirror();
} else {
to = to_cld->class_loader();
-
- // If from_cld is anonymous, even if it's class_loader is a parent of 'to'
- // we still have to add it. The class_loader won't keep from_cld alive.
- if (!from_cld->is_anonymous()) {
- // Check that this dependency isn't from the same or parent class_loader
- oop from = from_cld->class_loader();
+ oop from = from_cld->class_loader();
- oop curr = from;
- while (curr != NULL) {
- if (curr == to) {
- return; // this class loader is in the parent list, no need to add it.
- }
- curr = java_lang_ClassLoader::parent(curr);
- }
+ // Just return if this dependency is to a class with the same or a parent
+ // class_loader.
+ if (from == to || java_lang_ClassLoader::isAncestor(from, to)) {
+ return; // this class loader is in the parent list, no need to add it.
}
}
- // It's a dependency we won't find through GC, add it. This is relatively rare
+ // It's a dependency we won't find through GC, add it. This is relatively rare.
// Must handle over GC point.
Handle dependency(THREAD, to);
from_cld->_dependencies.add(dependency, CHECK);
@@ -443,6 +446,11 @@
// Link the new item into the list, making sure the linked class is stable
// since the list can be walked without a lock
OrderAccess::release_store(&_klasses, k);
+ if (k->is_array_klass()) {
+ ClassLoaderDataGraph::inc_array_classes(1);
+ } else {
+ ClassLoaderDataGraph::inc_instance_classes(1);
+ }
}
if (publicize && k->class_loader_data() != NULL) {
@@ -468,9 +476,9 @@
InstanceKlass* try_get_next_class() {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
- int max_classes = InstanceKlass::number_of_instance_classes();
+ size_t max_classes = ClassLoaderDataGraph::num_instance_classes();
assert(max_classes > 0, "should not be called with no instance classes");
- for (int i = 0; i < max_classes; ) {
+ for (size_t i = 0; i < max_classes; ) {
if (_current_class_entry != NULL) {
Klass* k = _current_class_entry;
@@ -545,6 +553,13 @@
Klass* next = k->next_link();
prev->set_next_link(next);
}
+
+ if (k->is_array_klass()) {
+ ClassLoaderDataGraph::dec_array_classes(1);
+ } else {
+ ClassLoaderDataGraph::dec_instance_classes(1);
+ }
+
return;
}
prev = k;
@@ -639,9 +654,34 @@
return alive;
}
+class ReleaseKlassClosure: public KlassClosure {
+private:
+ size_t _instance_class_released;
+ size_t _array_class_released;
+public:
+ ReleaseKlassClosure() : _instance_class_released(0), _array_class_released(0) { }
+
+ size_t instance_class_released() const { return _instance_class_released; }
+ size_t array_class_released() const { return _array_class_released; }
+
+ void do_klass(Klass* k) {
+ if (k->is_array_klass()) {
+ _array_class_released ++;
+ } else {
+ assert(k->is_instance_klass(), "Must be");
+ _instance_class_released ++;
+ InstanceKlass::release_C_heap_structures(InstanceKlass::cast(k));
+ }
+ }
+};
+
ClassLoaderData::~ClassLoaderData() {
// Release C heap structures for all the classes.
- classes_do(InstanceKlass::release_C_heap_structures);
+ ReleaseKlassClosure cl;
+ classes_do(&cl);
+
+ ClassLoaderDataGraph::dec_array_classes(cl.array_class_released());
+ ClassLoaderDataGraph::dec_instance_classes(cl.instance_class_released());
// Release C heap allocated hashtable for all the packages.
if (_packages != NULL) {
@@ -693,25 +733,37 @@
}
}
-// Returns true if this class loader data is for the system class loader.
+// 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.)
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.)
bool ClassLoaderData::is_platform_class_loader_data() const {
return SystemDictionary::is_platform_class_loader(class_loader());
}
-// Returns true if this class loader data is one of the 3 builtin
-// (boot, application/system or platform) class loaders. Note, the
-// builtin loaders are not freed by a GC.
+// 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
+// even if its class loader is one of these loaders.
bool ClassLoaderData::is_builtin_class_loader_data() const {
- return (is_the_null_class_loader_data() ||
+ return (is_boot_class_loader_data() ||
SystemDictionary::is_system_class_loader(class_loader()) ||
SystemDictionary::is_platform_class_loader(class_loader()));
}
+// 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.
+bool ClassLoaderData::is_permanent_class_loader_data() const {
+ return is_builtin_class_loader_data() && !is_anonymous();
+}
+
Metaspace* ClassLoaderData::metaspace_non_null() {
// If the metaspace has not been allocated, create a new one. Might want
// to create smaller arena for Reflection class loaders also.
--- a/src/hotspot/share/classfile/classLoaderData.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -80,6 +80,9 @@
// allocations until class unloading
static bool _metaspace_oom;
+ static volatile size_t _num_instance_classes;
+ static volatile size_t _num_array_classes;
+
static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS);
static void post_class_unload_events();
public:
@@ -154,6 +157,15 @@
static void print_creation(outputStream* out, Handle loader, ClassLoaderData* cld, TRAPS);
static bool unload_list_contains(const void* x);
+
+ // instance and array class counters
+ static inline size_t num_instance_classes();
+ static inline size_t num_array_classes();
+ static inline void inc_instance_classes(size_t count);
+ static inline void dec_instance_classes(size_t count);
+ static inline void inc_array_classes(size_t count);
+ static inline void dec_array_classes(size_t count);
+
#ifndef PRODUCT
static bool contains_loader_data(ClassLoaderData* loader_data);
#endif
@@ -344,7 +356,15 @@
}
bool is_system_class_loader_data() const;
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.)
+ bool is_boot_class_loader_data() const {
+ return class_loader() == NULL;
+ }
+
bool is_builtin_class_loader_data() const;
+ bool is_permanent_class_loader_data() const;
// The Metaspace is created lazily so may be NULL. This
// method will allocate a Metaspace if needed.
--- a/src/hotspot/share/classfile/classLoaderData.inline.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/classfile/classLoaderData.inline.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -50,3 +50,29 @@
}
return ClassLoaderDataGraph::add(loader, false, THREAD);
}
+
+size_t ClassLoaderDataGraph::num_instance_classes() {
+ return _num_instance_classes;
+}
+
+size_t ClassLoaderDataGraph::num_array_classes() {
+ return _num_array_classes;
+}
+
+void ClassLoaderDataGraph::inc_instance_classes(size_t count) {
+ Atomic::add(count, &_num_instance_classes);
+}
+
+void ClassLoaderDataGraph::dec_instance_classes(size_t count) {
+ assert(count <= _num_instance_classes, "Sanity");
+ Atomic::sub(count, &_num_instance_classes);
+}
+
+void ClassLoaderDataGraph::inc_array_classes(size_t count) {
+ Atomic::add(count, &_num_array_classes);
+}
+
+void ClassLoaderDataGraph::dec_array_classes(size_t count) {
+ assert(count <= _num_array_classes, "Sanity");
+ Atomic::sub(count, &_num_array_classes);
+}
--- a/src/hotspot/share/classfile/moduleEntry.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/classfile/moduleEntry.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -103,7 +103,11 @@
void set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd);
ClassLoaderData* loader_data() const { return _loader_data; }
- void set_loader_data(ClassLoaderData* l) { _loader_data = l; }
+
+ void set_loader_data(ClassLoaderData* cld) {
+ assert(!cld->is_anonymous(), "Unexpected anonymous class loader data");
+ _loader_data = cld;
+ }
Symbol* version() const { return _version; }
void set_version(Symbol* version);
--- a/src/hotspot/share/code/compiledIC.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/code/compiledIC.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -417,7 +417,7 @@
bool static_bound = info.is_optimized() || (info.cached_metadata() == NULL);
#ifdef ASSERT
CodeBlob* cb = CodeCache::find_blob_unsafe(info.entry());
- assert (cb->is_compiled(), "must be compiled!");
+ assert (cb != NULL && cb->is_compiled(), "must be compiled!");
#endif /* ASSERT */
// This is MT safe if we come from a clean-cache and go through a
--- a/src/hotspot/share/code/nmethod.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/code/nmethod.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -955,6 +955,7 @@
CompiledIC *ic = CompiledIC_at(&iter);
// Ok, to lookup references to zombies here
CodeBlob *cb = CodeCache::find_blob_unsafe(ic->ic_destination());
+ assert(cb != NULL, "destination not in CodeBlob?");
nmethod* nm = cb->as_nmethod_or_null();
if( nm != NULL ) {
// Verify that inline caches pointing to both zombie and not_entrant methods are clean
@@ -967,6 +968,7 @@
case relocInfo::static_call_type: {
CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc());
CodeBlob *cb = CodeCache::find_blob_unsafe(csc->destination());
+ assert(cb != NULL, "destination not in CodeBlob?");
nmethod* nm = cb->as_nmethod_or_null();
if( nm != NULL ) {
// Verify that inline caches pointing to both zombie and not_entrant methods are clean
@@ -2732,7 +2734,7 @@
virtual void verify_resolve_call(address dest) const {
CodeBlob* db = CodeCache::find_blob_unsafe(dest);
- assert(!db->is_adapter_blob(), "must use stub!");
+ assert(db != NULL && !db->is_adapter_blob(), "must use stub!");
}
virtual bool is_call_to_interpreted(address dest) const {
--- a/src/hotspot/share/gc/shared/oopStorage.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -26,7 +26,9 @@
#include "gc/shared/oopStorage.inline.hpp"
#include "gc/shared/oopStorageParState.inline.hpp"
#include "logging/log.hpp"
+#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutex.hpp"
@@ -107,7 +109,7 @@
}
// Blocks start with an array of BitsPerWord oop entries. That array
-// is divided into conceptual BytesPerWord sections of BitsPerWord
+// is divided into conceptual BytesPerWord sections of BitsPerByte
// entries. Blocks are allocated aligned on section boundaries, for
// the convenience of mapping from an entry to the containing block;
// see block_for_ptr(). Aligning on section boundary rather than on
@@ -130,7 +132,9 @@
_owner(owner),
_memory(memory),
_active_entry(),
- _allocate_entry()
+ _allocate_entry(),
+ _deferred_updates_next(NULL),
+ _release_refcount(0)
{
STATIC_ASSERT(_data_pos == 0);
STATIC_ASSERT(section_size * section_count == ARRAY_SIZE(_data));
@@ -143,6 +147,8 @@
#endif
OopStorage::Block::~Block() {
+ assert(_release_refcount == 0, "deleting block while releasing");
+ assert(_deferred_updates_next == NULL, "deleting block with deferred update");
// Clear fields used by block_for_ptr and entry validation, which
// might help catch bugs. Volatile to prevent dead-store elimination.
const_cast<uintx volatile&>(_allocated_bitmask) = 0;
@@ -182,8 +188,24 @@
return bitmask_for_index(get_index(ptr));
}
-uintx OopStorage::Block::cmpxchg_allocated_bitmask(uintx new_value, uintx compare_value) {
- return Atomic::cmpxchg(new_value, &_allocated_bitmask, compare_value);
+// A block is deletable if
+// (1) It is empty.
+// (2) There is not a release() operation currently operating on it.
+// (3) It is not in the deferred updates list.
+// The order of tests is important for proper interaction between release()
+// and concurrent deletion.
+bool OopStorage::Block::is_deletable() const {
+ return (OrderAccess::load_acquire(&_allocated_bitmask) == 0) &&
+ (OrderAccess::load_acquire(&_release_refcount) == 0) &&
+ (OrderAccess::load_acquire(&_deferred_updates_next) == NULL);
+}
+
+OopStorage::Block* OopStorage::Block::deferred_updates_next() const {
+ return _deferred_updates_next;
+}
+
+void OopStorage::Block::set_deferred_updates_next(Block* block) {
+ _deferred_updates_next = block;
}
bool OopStorage::Block::contains(const oop* ptr) const {
@@ -203,7 +225,7 @@
assert(!is_full_bitmask(allocated), "attempt to allocate from full block");
unsigned index = count_trailing_zeros(~allocated);
uintx new_value = allocated | bitmask_for_index(index);
- uintx fetched = cmpxchg_allocated_bitmask(new_value, allocated);
+ uintx fetched = Atomic::cmpxchg(new_value, &_allocated_bitmask, allocated);
if (fetched == allocated) {
return get_pointer(index); // CAS succeeded; return entry for index.
}
@@ -261,20 +283,6 @@
return NULL;
}
-bool OopStorage::is_valid_block_locked_or_safepoint(const Block* check_block) const {
- assert_locked_or_safepoint(_allocate_mutex);
- // For now, simple linear search. Do something more clever if this
- // is a performance bottleneck, particularly for allocation_status.
- for (const Block* block = _active_list.chead();
- block != NULL;
- block = _active_list.next(*block)) {
- if (check_block == block) {
- return true;
- }
- }
- return false;
-}
-
#ifdef ASSERT
void OopStorage::assert_at_safepoint() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
@@ -291,39 +299,49 @@
// kept at the end of the _allocate_list, to make it easy for empty block
// deletion to find them.
//
-// allocate(), release(), and delete_empty_blocks_concurrent() all lock the
+// allocate(), and delete_empty_blocks_concurrent() lock the
// _allocate_mutex while performing any list modifications.
//
// allocate() and release() update a block's _allocated_bitmask using CAS
-// loops. This prevents loss of updates even though release() may perform
-// some updates without any locking.
+// loops. This prevents loss of updates even though release() performs
+// its updates without any locking.
//
// allocate() obtains the entry from the first block in the _allocate_list,
// and updates that block's _allocated_bitmask to indicate the entry is in
// use. If this makes the block full (all entries in use), the block is
// removed from the _allocate_list so it won't be considered by future
-// allocations until some entries in it are relased.
+// allocations until some entries in it are released.
//
-// release() looks up the block for the entry without locking. Once the block
-// has been determined, its _allocated_bitmask needs to be updated, and its
-// position in the _allocate_list may need to be updated. There are two
-// cases:
+// release() is performed lock-free. release() first looks up the block for
+// the entry, using address alignment to find the enclosing block (thereby
+// avoiding iteration over the _active_list). Once the block has been
+// determined, its _allocated_bitmask needs to be updated, and its position in
+// the _allocate_list may need to be updated. There are two cases:
//
// (a) If the block is neither full nor would become empty with the release of
// the entry, only its _allocated_bitmask needs to be updated. But if the CAS
// update fails, the applicable case may change for the retry.
//
-// (b) Otherwise, the _allocate_list will also need to be modified. This
-// requires locking the _allocate_mutex, and then attempting to CAS the
-// _allocated_bitmask. If the CAS fails, the applicable case may change for
-// the retry. If the CAS succeeds, then update the _allocate_list according
-// to the the state changes. If the block changed from full to not full, then
-// it needs to be added to the _allocate_list, for use in future allocations.
-// If the block changed from not empty to empty, then it is moved to the end
-// of the _allocate_list, for ease of empty block deletion processing.
+// (b) Otherwise, the _allocate_list also needs to be modified. This requires
+// locking the _allocate_mutex. To keep the release() operation lock-free,
+// rather than updating the _allocate_list itself, it instead performs a
+// lock-free push of the block onto the _deferred_updates list. Entries on
+// that list are processed by allocate() and delete_empty_blocks_XXX(), while
+// they already hold the necessary lock. That processing makes the block's
+// list state consistent with its current _allocated_bitmask. The block is
+// added to the _allocate_list if not already present and the bitmask is not
+// full. The block is moved to the end of the _allocated_list if the bitmask
+// is empty, for ease of empty block deletion processing.
oop* OopStorage::allocate() {
MutexLockerEx ml(_allocate_mutex, Mutex::_no_safepoint_check_flag);
+ // Do some deferred update processing every time we allocate.
+ // Continue processing deferred updates if _allocate_list is empty,
+ // in the hope that we'll get a block from that, rather than
+ // allocating a new block.
+ while (reduce_deferred_updates() && (_allocate_list.head() == NULL)) {}
+
+ // Use the first block in _allocate_list for the allocation.
Block* block = _allocate_list.head();
if (block == NULL) {
// No available blocks; make a new one, and add to storage.
@@ -331,7 +349,17 @@
MutexUnlockerEx mul(_allocate_mutex, Mutex::_no_safepoint_check_flag);
block = Block::new_block(this);
}
- if (block != NULL) {
+ if (block == NULL) {
+ while (_allocate_list.head() == NULL) {
+ if (!reduce_deferred_updates()) {
+ // Failed to make new block, no other thread made a block
+ // available while the mutex was released, and didn't get
+ // one from a deferred update either, so return failure.
+ log_info(oopstorage, ref)("%s: failed allocation", name());
+ return NULL;
+ }
+ }
+ } else {
// Add new block to storage.
log_info(oopstorage, blocks)("%s: new block " PTR_FORMAT, name(), p2i(block));
@@ -340,22 +368,14 @@
// to allocate from non-empty blocks, to allow empty blocks to
// be deleted.
_allocate_list.push_back(*block);
- ++_empty_block_count;
// Add to front of _active_list, and then record as the head
// block, for concurrent iteration protocol.
_active_list.push_front(*block);
++_block_count;
// Ensure all setup of block is complete before making it visible.
OrderAccess::release_store(&_active_head, block);
- } else {
- log_info(oopstorage, blocks)("%s: failed new block allocation", name());
}
block = _allocate_list.head();
- if (block == NULL) {
- // Failed to make new block, and no other thread made a block
- // available while the mutex was released, so return failure.
- return NULL;
- }
}
// Allocate from first block.
assert(block != NULL, "invariant");
@@ -363,7 +383,6 @@
if (block->is_empty()) {
// Transitioning from empty to not empty.
log_debug(oopstorage, blocks)("%s: block not empty " PTR_FORMAT, name(), p2i(block));
- --_empty_block_count;
}
oop* result = block->allocate();
assert(result != NULL, "allocation failed");
@@ -384,72 +403,115 @@
return Block::block_for_ptr(this, ptr);
}
-void OopStorage::release_from_block(Block& block, uintx releasing) {
- assert(releasing != 0, "invariant");
- uintx allocated = block.allocated_bitmask();
- while (true) {
- assert(releasing == (allocated & releasing), "invariant");
- uintx new_value = allocated ^ releasing;
- // CAS new_value into block's allocated bitmask, retrying with
- // updated allocated bitmask until the CAS succeeds.
- uintx fetched;
- if (!is_full_bitmask(allocated) && !is_empty_bitmask(new_value)) {
- fetched = block.cmpxchg_allocated_bitmask(new_value, allocated);
- if (fetched == allocated) return;
- } else {
- // Need special handling if transitioning from full to not full,
- // or from not empty to empty. For those cases, must hold the
- // _allocation_mutex when updating the allocated bitmask, to
- // ensure the associated list manipulations will be consistent
- // with the allocation bitmask that is visible to other threads
- // in allocate() or deleting empty blocks.
- MutexLockerEx ml(_allocate_mutex, Mutex::_no_safepoint_check_flag);
- fetched = block.cmpxchg_allocated_bitmask(new_value, allocated);
- if (fetched == allocated) {
- // CAS succeeded; handle special cases, which might no longer apply.
- if (is_full_bitmask(allocated)) {
- // Transitioning from full to not-full; add to _allocate_list.
- log_debug(oopstorage, blocks)("%s: block not full " PTR_FORMAT, name(), p2i(&block));
- _allocate_list.push_front(block);
- assert(!block.is_full(), "invariant"); // Still not full.
- }
- if (is_empty_bitmask(new_value)) {
- // Transitioning from not-empty to empty; move to end of
- // _allocate_list, to make it a deletion candidate.
- log_debug(oopstorage, blocks)("%s: block empty " PTR_FORMAT, name(), p2i(&block));
- _allocate_list.unlink(block);
- _allocate_list.push_back(block);
- ++_empty_block_count;
- assert(block.is_empty(), "invariant"); // Still empty.
- }
- return; // Successful CAS and transitions handled.
- }
- }
- // CAS failed; retry with latest value.
- allocated = fetched;
+static void log_release_transitions(uintx releasing,
+ uintx old_allocated,
+ const OopStorage* owner,
+ const void* block) {
+ ResourceMark rm;
+ Log(oopstorage, blocks) log;
+ LogStream ls(log.debug());
+ if (is_full_bitmask(old_allocated)) {
+ ls.print_cr("%s: block not full " PTR_FORMAT, owner->name(), p2i(block));
+ }
+ if (releasing == old_allocated) {
+ ls.print_cr("%s: block empty " PTR_FORMAT, owner->name(), p2i(block));
}
}
-#ifdef ASSERT
-void OopStorage::check_release(const Block* block, const oop* ptr) const {
- switch (allocation_status_validating_block(block, ptr)) {
- case INVALID_ENTRY:
- fatal("Releasing invalid entry: " PTR_FORMAT, p2i(ptr));
- break;
+void OopStorage::Block::release_entries(uintx releasing, Block* volatile* deferred_list) {
+ assert(releasing != 0, "preconditon");
+ // Prevent empty block deletion when transitioning to empty.
+ Atomic::inc(&_release_refcount);
+
+ // Atomically update allocated bitmask.
+ uintx old_allocated = _allocated_bitmask;
+ while (true) {
+ assert((releasing & ~old_allocated) == 0, "releasing unallocated entries");
+ uintx new_value = old_allocated ^ releasing;
+ uintx fetched = Atomic::cmpxchg(new_value, &_allocated_bitmask, old_allocated);
+ if (fetched == old_allocated) break; // Successful update.
+ old_allocated = fetched; // Retry with updated bitmask.
+ }
- case UNALLOCATED_ENTRY:
- fatal("Releasing unallocated entry: " PTR_FORMAT, p2i(ptr));
- break;
+ // Now that the bitmask has been updated, if we have a state transition
+ // (updated bitmask is empty or old bitmask was full), atomically push
+ // this block onto the deferred updates list. Some future call to
+ // reduce_deferred_updates will make any needed changes related to this
+ // block and _allocate_list. This deferral avoids list updates and the
+ // associated locking here.
+ if ((releasing == old_allocated) || is_full_bitmask(old_allocated)) {
+ // Log transitions. Both transitions are possible in a single update.
+ if (log_is_enabled(Debug, oopstorage, blocks)) {
+ log_release_transitions(releasing, old_allocated, _owner, this);
+ }
+ // Attempt to claim responsibility for adding this block to the deferred
+ // list, by setting the link to non-NULL by self-looping. If this fails,
+ // then someone else has made such a claim and the deferred update has not
+ // yet been processed and will include our change, so we don't need to do
+ // anything further.
+ if (Atomic::replace_if_null(this, &_deferred_updates_next)) {
+ // Successfully claimed. Push, with self-loop for end-of-list.
+ Block* head = *deferred_list;
+ while (true) {
+ _deferred_updates_next = (head == NULL) ? this : head;
+ Block* fetched = Atomic::cmpxchg(this, deferred_list, head);
+ if (fetched == head) break; // Successful update.
+ head = fetched; // Retry with updated head.
+ }
+ log_debug(oopstorage, blocks)("%s: deferred update " PTR_FORMAT,
+ _owner->name(), p2i(this));
+ }
+ }
+ // Release hold on empty block deletion.
+ Atomic::dec(&_release_refcount);
+}
- case ALLOCATED_ENTRY:
- assert(block->contains(ptr), "invariant");
- break;
+// Process one available deferred update. Returns true if one was processed.
+bool OopStorage::reduce_deferred_updates() {
+ assert_locked_or_safepoint(_allocate_mutex);
+ // Atomically pop a block off the list, if any available.
+ // No ABA issue because this is only called by one thread at a time.
+ // The atomicity is wrto pushes by release().
+ Block* block = OrderAccess::load_acquire(&_deferred_updates);
+ while (true) {
+ if (block == NULL) return false;
+ // Try atomic pop of block from list.
+ Block* tail = block->deferred_updates_next();
+ if (block == tail) tail = NULL; // Handle self-loop end marker.
+ Block* fetched = Atomic::cmpxchg(tail, &_deferred_updates, block);
+ if (fetched == block) break; // Update successful.
+ block = fetched; // Retry with updated block.
+ }
+ block->set_deferred_updates_next(NULL); // Clear tail after updating head.
+ // Ensure bitmask read after pop is complete, including clearing tail, for
+ // ordering with release(). Without this, we may be processing a stale
+ // bitmask state here while blocking a release() operation from recording
+ // the deferred update needed for its bitmask change.
+ OrderAccess::storeload();
+ // Process popped block.
+ uintx allocated = block->allocated_bitmask();
- default:
- ShouldNotReachHere();
+ // Make membership in list consistent with bitmask state.
+ if ((_allocate_list.ctail() != NULL) &&
+ ((_allocate_list.ctail() == block) ||
+ (_allocate_list.next(*block) != NULL))) {
+ // Block is in the allocate list.
+ assert(!is_full_bitmask(allocated), "invariant");
+ } else if (!is_full_bitmask(allocated)) {
+ // Block is not in the allocate list, but now should be.
+ _allocate_list.push_front(*block);
+ } // Else block is full and not in list, which is correct.
+
+ // Move empty block to end of list, for possible deletion.
+ if (is_empty_bitmask(allocated)) {
+ _allocate_list.unlink(*block);
+ _allocate_list.push_back(*block);
}
+
+ log_debug(oopstorage, blocks)("%s: processed deferred update " PTR_FORMAT,
+ name(), p2i(block));
+ return true; // Processed one pending update.
}
-#endif // ASSERT
inline void check_release_entry(const oop* entry) {
assert(entry != NULL, "Releasing NULL");
@@ -459,9 +521,9 @@
void OopStorage::release(const oop* ptr) {
check_release_entry(ptr);
Block* block = find_block_or_null(ptr);
- check_release(block, ptr);
+ assert(block != NULL, "%s: invalid release " PTR_FORMAT, name(), p2i(ptr));
log_info(oopstorage, ref)("%s: released " PTR_FORMAT, name(), p2i(ptr));
- release_from_block(*block, block->bitmask_for_entry(ptr));
+ block->release_entries(block->bitmask_for_entry(ptr), &_deferred_updates);
Atomic::dec(&_allocation_count);
}
@@ -470,15 +532,15 @@
while (i < size) {
check_release_entry(ptrs[i]);
Block* block = find_block_or_null(ptrs[i]);
- check_release(block, ptrs[i]);
+ assert(block != NULL, "%s: invalid release " PTR_FORMAT, name(), p2i(ptrs[i]));
log_info(oopstorage, ref)("%s: released " PTR_FORMAT, name(), p2i(ptrs[i]));
size_t count = 0;
uintx releasing = 0;
for ( ; i < size; ++i) {
const oop* entry = ptrs[i];
+ check_release_entry(entry);
// If entry not in block, finish block and resume outer loop with entry.
if (!block->contains(entry)) break;
- check_release_entry(entry);
// Add entry to releasing bitmap.
log_info(oopstorage, ref)("%s: released " PTR_FORMAT, name(), p2i(entry));
uintx entry_bitmask = block->bitmask_for_entry(entry);
@@ -488,7 +550,7 @@
++count;
}
// Release the contiguous entries that are in block.
- release_from_block(*block, releasing);
+ block->release_entries(releasing, &_deferred_updates);
Atomic::sub(count, &_allocation_count);
}
}
@@ -506,11 +568,11 @@
_active_list(&Block::get_active_entry),
_allocate_list(&Block::get_allocate_entry),
_active_head(NULL),
+ _deferred_updates(NULL),
_allocate_mutex(allocate_mutex),
_active_mutex(active_mutex),
_allocation_count(0),
_block_count(0),
- _empty_block_count(0),
_concurrent_iteration_active(false)
{
assert(_active_mutex->rank() < _allocate_mutex->rank(),
@@ -529,6 +591,10 @@
OopStorage::~OopStorage() {
Block* block;
+ while ((block = _deferred_updates) != NULL) {
+ _deferred_updates = block->deferred_updates_next();
+ block->set_deferred_updates_next(NULL);
+ }
while ((block = _allocate_list.head()) != NULL) {
_allocate_list.unlink(*block);
}
@@ -539,43 +605,47 @@
FREE_C_HEAP_ARRAY(char, _name);
}
-void OopStorage::delete_empty_blocks_safepoint(size_t retain) {
+void OopStorage::delete_empty_blocks_safepoint() {
assert_at_safepoint();
+ // Process any pending release updates, which may make more empty
+ // blocks available for deletion.
+ while (reduce_deferred_updates()) {}
// Don't interfere with a concurrent iteration.
if (_concurrent_iteration_active) return;
- // Compute the number of blocks to remove, to minimize volatile accesses.
- size_t empty_blocks = _empty_block_count;
- if (retain < empty_blocks) {
- size_t remove_count = empty_blocks - retain;
- // Update volatile counters once.
- _block_count -= remove_count;
- _empty_block_count -= remove_count;
- do {
- const Block* block = _allocate_list.ctail();
- assert(block != NULL, "invariant");
- assert(block->is_empty(), "invariant");
- // Remove block from lists, and delete it.
- _active_list.unlink(*block);
- _allocate_list.unlink(*block);
- delete_empty_block(*block);
- } while (--remove_count > 0);
- // Update _active_head, in case current value was in deleted set.
- _active_head = _active_list.head();
+ // Delete empty (and otherwise deletable) blocks from end of _allocate_list.
+ for (const Block* block = _allocate_list.ctail();
+ (block != NULL) && block->is_deletable();
+ block = _allocate_list.ctail()) {
+ _active_list.unlink(*block);
+ _allocate_list.unlink(*block);
+ delete_empty_block(*block);
+ --_block_count;
}
+ // Update _active_head, in case current value was in deleted set.
+ _active_head = _active_list.head();
}
-void OopStorage::delete_empty_blocks_concurrent(size_t retain) {
+void OopStorage::delete_empty_blocks_concurrent() {
MutexLockerEx ml(_allocate_mutex, Mutex::_no_safepoint_check_flag);
// Other threads could be adding to the empty block count while we
// release the mutex across the block deletions. Set an upper bound
// on how many blocks we'll try to release, so other threads can't
// cause an unbounded stay in this function.
- if (_empty_block_count <= retain) return;
- size_t limit = _empty_block_count - retain;
- for (size_t i = 0; (i < limit) && (retain < _empty_block_count); ++i) {
+ size_t limit = _block_count;
+
+ for (size_t i = 0; i < limit; ++i) {
+ // Additional updates might become available while we dropped the
+ // lock. But limit number processed to limit lock duration.
+ reduce_deferred_updates();
+
const Block* block = _allocate_list.ctail();
- assert(block != NULL, "invariant");
- assert(block->is_empty(), "invariant");
+ if ((block == NULL) || !block->is_deletable()) {
+ // No block to delete, so done. There could be more pending
+ // deferred updates that could give us more work to do; deal with
+ // that in some later call, to limit lock duration here.
+ return;
+ }
+
{
MutexLockerEx aml(_active_mutex, Mutex::_no_safepoint_check_flag);
// Don't interfere with a concurrent iteration.
@@ -589,28 +659,31 @@
}
// Remove block from _allocate_list and delete it.
_allocate_list.unlink(*block);
- --_empty_block_count;
// Release mutex while deleting block.
MutexUnlockerEx ul(_allocate_mutex, Mutex::_no_safepoint_check_flag);
delete_empty_block(*block);
}
}
-OopStorage::EntryStatus
-OopStorage::allocation_status_validating_block(const Block* block,
- const oop* ptr) const {
- MutexLockerEx ml(_allocate_mutex, Mutex::_no_safepoint_check_flag);
- if ((block == NULL) || !is_valid_block_locked_or_safepoint(block)) {
- return INVALID_ENTRY;
- } else if ((block->allocated_bitmask() & block->bitmask_for_entry(ptr)) != 0) {
- return ALLOCATED_ENTRY;
- } else {
- return UNALLOCATED_ENTRY;
+OopStorage::EntryStatus OopStorage::allocation_status(const oop* ptr) const {
+ const Block* block = find_block_or_null(ptr);
+ if (block != NULL) {
+ // Verify block is a real block. For now, simple linear search.
+ // Do something more clever if this is a performance bottleneck.
+ MutexLockerEx ml(_allocate_mutex, Mutex::_no_safepoint_check_flag);
+ for (const Block* check_block = _active_list.chead();
+ check_block != NULL;
+ check_block = _active_list.next(*check_block)) {
+ if (check_block == block) {
+ if ((block->allocated_bitmask() & block->bitmask_for_entry(ptr)) != 0) {
+ return ALLOCATED_ENTRY;
+ } else {
+ return UNALLOCATED_ENTRY;
+ }
+ }
+ }
}
-}
-
-OopStorage::EntryStatus OopStorage::allocation_status(const oop* ptr) const {
- return allocation_status_validating_block(find_block_or_null(ptr), ptr);
+ return INVALID_ENTRY;
}
size_t OopStorage::allocation_count() const {
@@ -621,10 +694,6 @@
return _block_count;
}
-size_t OopStorage::empty_block_count() const {
- return _empty_block_count;
-}
-
size_t OopStorage::total_memory_usage() const {
size_t total_size = sizeof(OopStorage);
total_size += strlen(name()) + 1;
@@ -690,17 +759,12 @@
void OopStorage::print_on(outputStream* st) const {
size_t allocations = _allocation_count;
size_t blocks = _block_count;
- size_t empties = _empty_block_count;
- // Comparison is being careful about racy accesses.
- size_t used = (blocks < empties) ? 0 : (blocks - empties);
double data_size = section_size * section_count;
- double alloc_percentage = percent_of((double)allocations, used * data_size);
+ double alloc_percentage = percent_of((double)allocations, blocks * data_size);
- st->print("%s: " SIZE_FORMAT " entries in " SIZE_FORMAT " blocks (%.F%%), "
- SIZE_FORMAT " empties, " SIZE_FORMAT " bytes",
- name(), allocations, used, alloc_percentage,
- empties, total_memory_usage());
+ st->print("%s: " SIZE_FORMAT " entries in " SIZE_FORMAT " blocks (%.F%%), " SIZE_FORMAT " bytes",
+ name(), allocations, blocks, alloc_percentage, total_memory_usage());
if (_concurrent_iteration_active) {
st->print(", concurrent iteration active");
}
--- a/src/hotspot/share/gc/shared/oopStorage.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/gc/shared/oopStorage.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -84,10 +84,6 @@
// The number of blocks of entries. Useful for sizing parallel iteration.
size_t block_count() const;
- // The number of blocks with no allocated entries. Useful for sizing
- // parallel iteration and scheduling block deletion.
- size_t empty_block_count() const;
-
// Total number of blocks * memory allocation per block, plus
// bookkeeping overhead, including this storage object.
size_t total_memory_usage() const;
@@ -107,14 +103,13 @@
// postcondition: *result == NULL.
oop* allocate();
- // Deallocates ptr, after setting its value to NULL. Locks _allocate_mutex.
+ // Deallocates ptr. No locking.
// precondition: ptr is a valid allocated entry.
// precondition: *ptr == NULL.
void release(const oop* ptr);
// Releases all the ptrs. Possibly faster than individual calls to
- // release(oop*). Best if ptrs is sorted by address. Locks
- // _allocate_mutex.
+ // release(oop*). Best if ptrs is sorted by address. No locking.
// precondition: All elements of ptrs are valid allocated entries.
// precondition: *ptrs[i] == NULL, for i in [0,size).
void release(const oop* const* ptrs, size_t size);
@@ -160,8 +155,8 @@
// Block cleanup functions are for the exclusive use of the GC.
// Both stop deleting if there is an in-progress concurrent iteration.
// Concurrent deletion locks both the allocate_mutex and the active_mutex.
- void delete_empty_blocks_safepoint(size_t retain = 1);
- void delete_empty_blocks_concurrent(size_t retain = 1);
+ void delete_empty_blocks_safepoint();
+ void delete_empty_blocks_concurrent();
// Debugging and logging support.
const char* name() const;
@@ -231,6 +226,7 @@
BlockList _active_list;
BlockList _allocate_list;
Block* volatile _active_head;
+ Block* volatile _deferred_updates;
Mutex* _allocate_mutex;
Mutex* _active_mutex;
@@ -238,16 +234,12 @@
// Counts are volatile for racy unlocked accesses.
volatile size_t _allocation_count;
volatile size_t _block_count;
- volatile size_t _empty_block_count;
// mutable because this gets set even for const iteration.
mutable bool _concurrent_iteration_active;
Block* find_block_or_null(const oop* ptr) const;
- bool is_valid_block_locked_or_safepoint(const Block* block) const;
- EntryStatus allocation_status_validating_block(const Block* block, const oop* ptr) const;
- void check_release(const Block* block, const oop* ptr) const NOT_DEBUG_RETURN;
- void release_from_block(Block& block, uintx release_bitmask);
void delete_empty_block(const Block& block);
+ bool reduce_deferred_updates();
static void assert_at_safepoint() NOT_DEBUG_RETURN;
--- a/src/hotspot/share/gc/shared/oopStorage.inline.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/gc/shared/oopStorage.inline.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -44,6 +44,8 @@
void* _memory; // Unaligned storage containing block.
BlockEntry _active_entry;
BlockEntry _allocate_entry;
+ Block* volatile _deferred_updates_next;
+ volatile uintx _release_refcount;
Block(const OopStorage* owner, void* memory);
~Block();
@@ -75,7 +77,10 @@
bool is_full() const;
bool is_empty() const;
uintx allocated_bitmask() const;
- uintx cmpxchg_allocated_bitmask(uintx new_value, uintx compare_value);
+ bool is_deletable() const;
+
+ Block* deferred_updates_next() const;
+ void set_deferred_updates_next(Block* new_next);
bool contains(const oop* ptr) const;
@@ -86,6 +91,8 @@
static Block* new_block(const OopStorage* owner);
static void delete_block(const Block& block);
+ void release_entries(uintx releasing, Block* volatile* deferred_list);
+
template<typename F> bool iterate(F f);
template<typename F> bool iterate(F f) const;
}; // class Block
--- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -594,10 +594,6 @@
VERIFY_OOP(rcvr);
}
#endif
-// #define HACK
-#ifdef HACK
- bool interesting = false;
-#endif // HACK
/* QQQ this should be a stack method so we don't know actual direction */
guarantee(istate->msg() == initialize ||
@@ -649,19 +645,6 @@
os::breakpoint();
}
-#ifdef HACK
- {
- ResourceMark rm;
- char *method_name = istate->method()->name_and_sig_as_C_string();
- if (strstr(method_name, "runThese$TestRunner.run()V") != NULL) {
- tty->print_cr("entering: depth %d bci: %d",
- (istate->_stack_base - istate->_stack),
- istate->_bcp - istate->_method->code_base());
- interesting = true;
- }
- }
-#endif // HACK
-
// Lock method if synchronized.
if (METHOD->is_synchronized()) {
// oop rcvr = locals[0].j.r;
@@ -793,18 +776,6 @@
// resume
os::breakpoint();
}
-#ifdef HACK
- {
- ResourceMark rm;
- char *method_name = istate->method()->name_and_sig_as_C_string();
- if (strstr(method_name, "runThese$TestRunner.run()V") != NULL) {
- tty->print_cr("resume: depth %d bci: %d",
- (istate->_stack_base - istate->_stack) ,
- istate->_bcp - istate->_method->code_base());
- interesting = true;
- }
- }
-#endif // HACK
// returned from a java call, continue executing.
if (THREAD->pop_frame_pending() && !THREAD->pop_frame_in_process()) {
goto handle_Pop_Frame;
--- a/src/hotspot/share/logging/logTag.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/logging/logTag.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -66,6 +66,7 @@
LOG_TAG(exceptions) \
LOG_TAG(exit) \
LOG_TAG(fingerprint) \
+ LOG_TAG(free) \
LOG_TAG(freelist) \
LOG_TAG(gc) \
LOG_TAG(handshake) \
@@ -85,6 +86,7 @@
LOG_TAG(load) /* Trace all classes loaded */ \
LOG_TAG(loader) \
LOG_TAG(logging) \
+ LOG_TAG(malloc) \
LOG_TAG(mark) \
LOG_TAG(marking) \
LOG_TAG(membername) \
--- a/src/hotspot/share/memory/allocation.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/memory/allocation.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -210,18 +210,6 @@
}
#endif // ASSERT
-
-void trace_heap_malloc(size_t size, const char* name, void* p) {
- // A lock is not needed here - tty uses a lock internally
- tty->print_cr("Heap malloc " INTPTR_FORMAT " " SIZE_FORMAT " %s", p2i(p), size, name == NULL ? "" : name);
-}
-
-
-void trace_heap_free(void* p) {
- // A lock is not needed here - tty uses a lock internally
- tty->print_cr("Heap free " INTPTR_FORMAT, p2i(p));
-}
-
//--------------------------------------------------------------------------------------
// Non-product code
--- a/src/hotspot/share/memory/allocation.inline.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/memory/allocation.inline.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -33,9 +33,6 @@
// Explicit C-heap memory management
-void trace_heap_malloc(size_t size, const char* name, void *p);
-void trace_heap_free(void *p);
-
#ifndef PRODUCT
// Increments unsigned long value for statistics (not atomic on MP).
inline void inc_stat_counter(volatile julong* dest, julong add_value) {
@@ -56,9 +53,6 @@
const NativeCallStack& stack,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
char* p = (char*) os::malloc(size, flags, stack);
- #ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, "AllocateHeap", p);
- #endif
if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "AllocateHeap");
}
@@ -73,9 +67,6 @@
ALWAYSINLINE char* ReallocateHeap(char *old, size_t size, MEMFLAGS flag,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
char* p = (char*) os::realloc(old, size, flag, CURRENT_PC);
- #ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, "ReallocateHeap", p);
- #endif
if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "ReallocateHeap");
}
@@ -83,20 +74,13 @@
}
inline void FreeHeap(void* p) {
- #ifdef ASSERT
- if (PrintMallocFree) trace_heap_free(p);
- #endif
os::free(p);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size,
const NativeCallStack& stack) throw() {
- void* p = (void*)AllocateHeap(size, F, stack);
-#ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
-#endif
- return p;
+ return (void*)AllocateHeap(size, F, stack);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size) throw() {
@@ -104,14 +88,9 @@
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
- const std::nothrow_t& nothrow_constant, const NativeCallStack& stack) throw() {
- void* p = (void*)AllocateHeap(size, F, stack,
- AllocFailStrategy::RETURN_NULL);
-#ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
-#endif
- return p;
- }
+ const std::nothrow_t& nothrow_constant, const NativeCallStack& stack) throw() {
+ return (void*)AllocateHeap(size, F, stack, AllocFailStrategy::RETURN_NULL);
+}
template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
const std::nothrow_t& nothrow_constant) throw() {
--- a/src/hotspot/share/memory/arena.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/memory/arena.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -299,23 +299,11 @@
// dynamic memory type binding
void* Arena::operator new(size_t size, MEMFLAGS flags) throw() {
-#ifdef ASSERT
- void* p = (void*)AllocateHeap(size, flags, CALLER_PC);
- if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
- return p;
-#else
return (void *) AllocateHeap(size, flags, CALLER_PC);
-#endif
}
void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw() {
-#ifdef ASSERT
- void* p = os::malloc(size, flags, CALLER_PC);
- if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
- return p;
-#else
- return os::malloc(size, flags, CALLER_PC);
-#endif
+ return (void*)AllocateHeap(size, flags, CALLER_PC, AllocFailStrategy::RETURN_NULL);
}
void Arena::operator delete(void* p) {
--- a/src/hotspot/share/oops/instanceKlass.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/oops/instanceKlass.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -124,8 +124,6 @@
#endif // ndef DTRACE_ENABLED
-volatile int InstanceKlass::_total_instanceKlass_count = 0;
-
static inline bool is_class_loader(const Symbol* class_name,
const ClassFileParser& parser) {
assert(class_name != NULL, "invariant");
@@ -193,8 +191,6 @@
// Add all classes to our internal class loader list here,
// including classes in the bootstrap (NULL) class loader.
loader_data->add_class(ik, publicize);
- Atomic::inc(&_total_instanceKlass_count);
-
return ik;
}
@@ -2241,9 +2237,6 @@
// class can't be referenced anymore).
if (_array_name != NULL) _array_name->decrement_refcount();
if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension);
-
- assert(_total_instanceKlass_count >= 1, "Sanity check");
- Atomic::dec(&_total_instanceKlass_count);
}
void InstanceKlass::set_source_debug_extension(const char* array, int length) {
--- a/src/hotspot/share/oops/instanceKlass.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/oops/instanceKlass.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -135,10 +135,7 @@
initialization_error // error happened during initialization
};
- static int number_of_instance_classes() { return _total_instanceKlass_count; }
-
private:
- static volatile int _total_instanceKlass_count;
static InstanceKlass* allocate_instance_klass(const ClassFileParser& parser, TRAPS);
protected:
--- a/src/hotspot/share/opto/escape.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/opto/escape.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -3226,7 +3226,7 @@
n->Opcode() == Op_EncodeISOArray) {
// get the memory projection
n = n->find_out_with(Op_SCMemProj);
- assert(n->Opcode() == Op_SCMemProj, "memory projection required");
+ assert(n != NULL && n->Opcode() == Op_SCMemProj, "memory projection required");
} else {
assert(n->is_Mem(), "memory node required.");
Node *addr = n->in(MemNode::Address);
@@ -3250,7 +3250,7 @@
} else if (n->is_LoadStore()) {
// get the memory projection
n = n->find_out_with(Op_SCMemProj);
- assert(n->Opcode() == Op_SCMemProj, "memory projection required");
+ assert(n != NULL && n->Opcode() == Op_SCMemProj, "memory projection required");
}
}
// push user on appropriate worklist
--- a/src/hotspot/share/opto/parse2.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/opto/parse2.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -2264,7 +2264,7 @@
ciMethodData* methodData = method()->method_data();
if (!methodData->is_mature()) break;
ciProfileData* data = methodData->bci_to_data(bci());
- assert( data->is_JumpData(), "" );
+ assert(data != NULL && data->is_JumpData(), "need JumpData for taken branch");
int taken = ((ciJumpData*)data)->taken();
taken = method()->scale_count(taken);
target_block->set_count(taken);
--- a/src/hotspot/share/opto/parseHelper.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/opto/parseHelper.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -459,7 +459,7 @@
ciMethodData* md = method()->method_data();
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(cur_bci);
- assert(data->is_JumpData(), "need JumpData for taken branch");
+ assert(data != NULL && data->is_JumpData(), "need JumpData for taken branch");
increment_md_counter_at(md, data, JumpData::taken_offset());
}
@@ -470,6 +470,7 @@
ciMethodData* md = method()->method_data();
if (osr_site) {
ciProfileData* data = md->bci_to_data(cur_bci);
+ assert(data != NULL && data->is_JumpData(), "need JumpData for taken branch");
int limit = (CompileThreshold
* (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100;
test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit);
@@ -495,7 +496,7 @@
ciMethodData* md = method()->method_data();
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(bci());
- assert(data->is_BranchData(), "need BranchData for not taken branch");
+ assert(data != NULL && data->is_BranchData(), "need BranchData for not taken branch");
increment_md_counter_at(md, data, BranchData::not_taken_offset());
}
@@ -526,7 +527,7 @@
ciMethodData* md = method()->method_data();
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(bci());
- assert(data->is_CounterData(), "need CounterData for not taken branch");
+ assert(data != NULL && data->is_CounterData(), "need CounterData for not taken branch");
increment_md_counter_at(md, data, CounterData::count_offset());
}
@@ -537,7 +538,7 @@
ciMethodData* md = method()->method_data();
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(bci());
- assert(data->is_ReceiverTypeData(), "need ReceiverTypeData here");
+ assert(data != NULL && data->is_ReceiverTypeData(), "need ReceiverTypeData here");
// Skip if we aren't tracking receivers
if (TypeProfileWidth < 1) {
@@ -568,7 +569,7 @@
ciMethodData* md = method()->method_data();
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(bci());
- assert(data->is_RetData(), "need RetData for ret");
+ assert(data != NULL && data->is_RetData(), "need RetData for ret");
ciRetData* ret_data = (ciRetData*)data->as_RetData();
// Look for the target_bci is already in the table
@@ -601,7 +602,7 @@
ciMethodData* md = method()->method_data();
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(bci());
- assert(data->is_BitData(), "need BitData for checkcast");
+ assert(data != NULL && data->is_BitData(), "need BitData for checkcast");
set_md_flag_at(md, data, BitData::null_seen_byte_constant());
}
@@ -613,7 +614,7 @@
assert(md != NULL, "expected valid ciMethodData");
ciProfileData* data = md->bci_to_data(bci());
- assert(data->is_MultiBranchData(), "need MultiBranchData for switch case");
+ assert(data != NULL && data->is_MultiBranchData(), "need MultiBranchData for switch case");
if (table_index >= 0) {
increment_md_counter_at(md, data, MultiBranchData::case_count_offset(table_index));
} else {
--- a/src/hotspot/share/prims/jvmtiExport.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/prims/jvmtiExport.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -597,12 +597,10 @@
}
void JvmtiExport::enter_early_start_phase() {
- JvmtiManageCapabilities::recompute_always_capabilities();
set_early_vmstart_recorded(true);
}
void JvmtiExport::enter_start_phase() {
- JvmtiManageCapabilities::recompute_always_capabilities();
JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
}
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -29,6 +29,9 @@
#include "prims/jvmtiGetLoadedClasses.hpp"
#include "runtime/thread.hpp"
#include "utilities/stack.inline.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
+#endif
// The closure for GetLoadedClasses
@@ -38,6 +41,20 @@
JvmtiEnv* _env;
Thread* _cur_thread;
+// Tell the GC to keep this klass alive
+static void ensure_klass_alive(oop o) {
+ // A klass that was previously considered dead can be looked up in the
+ // CLD/SD, and its _java_mirror or _class_loader can be stored in a root
+ // or a reachable object making it alive again. The SATB part of G1 needs
+ // to get notified about this potential resurrection, otherwise the marking
+ // might not find the object.
+#if INCLUDE_ALL_GCS
+ if (UseG1GC && o != NULL) {
+ G1SATBCardTableModRefBS::enqueue(o);
+ }
+#endif
+}
+
public:
LoadedClassesClosure(Thread* thread, JvmtiEnv* env) : _cur_thread(thread), _env(env) {
assert(_cur_thread == Thread::current(), "must be current thread");
@@ -46,6 +63,7 @@
void do_klass(Klass* k) {
// Collect all jclasses
_classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
+ ensure_klass_alive(k->java_mirror());
}
int extract(jclass* result_list) {
--- a/src/hotspot/share/prims/jvmtiManageCapabilities.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/prims/jvmtiManageCapabilities.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -57,9 +57,6 @@
void JvmtiManageCapabilities::initialize() {
always_capabilities = init_always_capabilities();
- if (JvmtiEnv::get_phase() != JVMTI_PHASE_ONLOAD) {
- recompute_always_capabilities();
- }
onload_capabilities = init_onload_capabilities();
always_solo_capabilities = init_always_solo_capabilities();
onload_solo_capabilities = init_onload_solo_capabilities();
@@ -68,19 +65,6 @@
memset(&acquired_capabilities, 0, sizeof(acquired_capabilities));
}
-// if the capability sets are initialized in the onload phase then
-// it happens before class data sharing (CDS) is initialized. If it
-// turns out that CDS gets disabled then we must adjust the always
-// capabilities. To ensure a consistent view of the capabililties
-// anything we add here should already be in the onload set.
-void JvmtiManageCapabilities::recompute_always_capabilities() {
- if (!UseSharedSpaces) {
- jvmtiCapabilities jc = always_capabilities;
- jc.can_generate_all_class_hook_events = 1;
- always_capabilities = jc;
- }
-}
-
// corresponding init functions
jvmtiCapabilities JvmtiManageCapabilities::init_always_capabilities() {
@@ -94,6 +78,7 @@
jc.can_get_synthetic_attribute = 1;
jc.can_get_monitor_info = 1;
jc.can_get_constant_pool = 1;
+ jc.can_generate_all_class_hook_events = 1;
jc.can_generate_monitor_events = 1;
jc.can_generate_garbage_collection_events = 1;
jc.can_generate_compiled_method_load_events = 1;
@@ -126,7 +111,6 @@
jc.can_get_source_debug_extension = 1;
jc.can_access_local_variables = 1;
jc.can_maintain_original_method_order = 1;
- jc.can_generate_all_class_hook_events = 1;
jc.can_generate_single_step_events = 1;
jc.can_generate_exception_events = 1;
jc.can_generate_frame_pop_events = 1;
--- a/src/hotspot/share/prims/jvmtiManageCapabilities.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/prims/jvmtiManageCapabilities.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -64,9 +64,6 @@
public:
static void initialize();
- // may have to adjust always capabilities when VM initialization has completed
- static void recompute_always_capabilities();
-
// queries and actions
static void get_potential_capabilities(const jvmtiCapabilities *current,
const jvmtiCapabilities *prohibited,
--- a/src/hotspot/share/runtime/arguments.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/runtime/arguments.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -514,7 +514,9 @@
{ "DeferThrSuspendLoopCount", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) },
{ "DeferPollingPageLoopCount", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) },
{ "IgnoreUnverifiableClassesDuringDump", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
- { "CheckEndorsedAndExtDirs", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
+ { "CheckEndorsedAndExtDirs", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
+ { "CompilerThreadHintNoPreempt", JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) },
+ { "VMThreadHintNoPreempt", JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) },
// --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
{ "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() },
@@ -527,6 +529,8 @@
{ "ConvertYieldToSleep", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "CheckAssertionStatusDirectives",JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
+ { "PrintMallocFree", JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
+ { "PrintMalloc", JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
{ "PermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "MaxPermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "SharedReadWriteSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
--- a/src/hotspot/share/runtime/compilationPolicy.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/runtime/compilationPolicy.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "code/compiledIC.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"
@@ -312,10 +313,10 @@
// and hence GC's will not be going on, all Java mutators are suspended
// at this point and hence SystemDictionary_lock is also not needed.
assert(SafepointSynchronize::is_at_safepoint(), "can only be executed at a safepoint");
- int nclasses = InstanceKlass::number_of_instance_classes();
- int classes_per_tick = nclasses * (CounterDecayMinIntervalLength * 1e-3 /
+ size_t nclasses = ClassLoaderDataGraph::num_instance_classes();
+ size_t classes_per_tick = nclasses * (CounterDecayMinIntervalLength * 1e-3 /
CounterHalfLifeTime);
- for (int i = 0; i < classes_per_tick; i++) {
+ for (size_t i = 0; i < classes_per_tick; i++) {
InstanceKlass* k = ClassLoaderDataGraph::try_get_next_class();
if (k != NULL) {
k->methods_do(do_method);
--- a/src/hotspot/share/runtime/globals.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/runtime/globals.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -893,18 +893,12 @@
develop(bool, TraceJavaAssertions, false, \
"Trace java language assertions") \
\
- notproduct(bool, PrintMallocFree, false, \
- "Trace calls to C heap malloc/free allocation") \
- \
notproduct(bool, VerifyCodeCache, false, \
"Verify code cache on memory allocation/deallocation") \
\
develop(bool, UseMallocOnly, false, \
"Use only malloc/free for allocation (no resource area/arena)") \
\
- develop(bool, PrintMalloc, false, \
- "Print all malloc/free calls") \
- \
develop(bool, PrintMallocStatistics, false, \
"Print malloc/free statistics") \
\
@@ -3545,7 +3539,7 @@
"(-1 means no change)") \
range(-1, 127) \
\
- product(bool, CompilerThreadHintNoPreempt, true, \
+ product(bool, CompilerThreadHintNoPreempt, false, \
"(Solaris only) Give compiler threads an extra quanta") \
\
product(bool, VMThreadHintNoPreempt, false, \
--- a/src/hotspot/share/runtime/memprofiler.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/runtime/memprofiler.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
@@ -116,10 +117,10 @@
}
// Print trace line in log
- fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",",
+ fprintf(_log_fp, "%6.1f,%5d," SIZE_FORMAT_W(5) "," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",",
os::elapsedTime(),
jtiwh.length(),
- InstanceKlass::number_of_instance_classes(),
+ ClassLoaderDataGraph::num_instance_classes(),
Universe::heap()->used() / K,
Universe::heap()->capacity() / K);
}
--- a/src/hotspot/share/runtime/mutexLocker.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -253,10 +253,10 @@
// 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 , special-1, true, Monitor::_safepoint_check_never);
- def(JNIGlobalActive_lock , PaddedMutex , special-2, true, Monitor::_safepoint_check_never);
- def(JNIWeakAlloc_lock , PaddedMutex , special-1, true, Monitor::_safepoint_check_never);
- def(JNIWeakActive_lock , PaddedMutex , special-2, true, Monitor::_safepoint_check_never);
+ 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);
+ def(JNIWeakActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never);
def(JNICritical_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); // used for JNI critical regions
def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_always);
--- a/src/hotspot/share/runtime/os.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/runtime/os.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -33,6 +33,7 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "gc/shared/vmGCOperations.hpp"
+#include "logging/log.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
@@ -610,9 +611,12 @@
static void verify_memory(void* ptr) {
GuardedMemory guarded(ptr);
if (!guarded.verify_guards()) {
- tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
- tty->print_cr("## memory stomp:");
- guarded.print_on(tty);
+ LogTarget(Warning, malloc, free) lt;
+ ResourceMark rm;
+ LogStream ls(lt);
+ ls.print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
+ ls.print_cr("## memory stomp:");
+ guarded.print_on(&ls);
fatal("memory stomping error");
}
}
@@ -684,13 +688,10 @@
ptr = guarded.get_user_ptr();
#endif
if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
- tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, p2i(ptr));
+ log_warning(malloc, free)("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, p2i(ptr));
breakpoint();
}
debug_only(if (paranoid) verify_memory(ptr));
- if (PrintMalloc && tty != NULL) {
- tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, p2i(ptr));
- }
// we do not track guard memory
return MemTracker::record_malloc((address)ptr, size, memflags, stack, level);
@@ -727,7 +728,7 @@
return os::malloc(size, memflags, stack);
}
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
- tty->print_cr("os::realloc caught " PTR_FORMAT, p2i(memblock));
+ log_warning(malloc, free)("os::realloc caught " PTR_FORMAT, p2i(memblock));
breakpoint();
}
// NMT support
@@ -735,18 +736,15 @@
verify_memory(membase);
// always move the block
void* ptr = os::malloc(size, memflags, stack);
- if (PrintMalloc && tty != NULL) {
- tty->print_cr("os::realloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, p2i(memblock), p2i(ptr));
- }
// Copy to new memory if malloc didn't fail
- if ( ptr != NULL ) {
+ if (ptr != NULL ) {
GuardedMemory guarded(MemTracker::malloc_base(memblock));
// Guard's user data contains NMT header
size_t memblock_size = guarded.get_user_size() - MemTracker::malloc_header_size(memblock);
memcpy(ptr, memblock, MIN2(size, memblock_size));
if (paranoid) verify_memory(MemTracker::malloc_base(ptr));
if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
- tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, p2i(ptr));
+ log_warning(malloc, free)("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, p2i(ptr));
breakpoint();
}
os::free(memblock);
@@ -761,7 +759,7 @@
#ifdef ASSERT
if (memblock == NULL) return;
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
- if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, p2i(memblock));
+ log_warning(malloc, free)("os::free caught " PTR_FORMAT, p2i(memblock));
breakpoint();
}
void* membase = MemTracker::record_free(memblock);
@@ -771,9 +769,6 @@
size_t size = guarded.get_user_size();
inc_stat_counter(&free_bytes, size);
membase = guarded.release_for_freeing();
- if (PrintMalloc && tty != NULL) {
- fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)membase);
- }
::free(membase);
#else
void* membase = MemTracker::record_free(memblock);
@@ -1754,7 +1749,7 @@
bool os::uncommit_memory(char* addr, size_t bytes) {
bool res;
if (MemTracker::tracking_level() > NMT_minimal) {
- Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
+ Tracker tkr(Tracker::uncommit);
res = pd_uncommit_memory(addr, bytes);
if (res) {
tkr.record((address)addr, bytes);
@@ -1768,7 +1763,7 @@
bool os::release_memory(char* addr, size_t bytes) {
bool res;
if (MemTracker::tracking_level() > NMT_minimal) {
- Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+ Tracker tkr(Tracker::release);
res = pd_release_memory(addr, bytes);
if (res) {
tkr.record((address)addr, bytes);
@@ -1805,7 +1800,7 @@
bool os::unmap_memory(char *addr, size_t bytes) {
bool result;
if (MemTracker::tracking_level() > NMT_minimal) {
- Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+ Tracker tkr(Tracker::release);
result = pd_unmap_memory(addr, bytes);
if (result) {
tkr.record((address)addr, bytes);
--- a/src/hotspot/share/services/memBaseline.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/services/memBaseline.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
#include "memory/allocation.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
@@ -180,7 +181,8 @@
bool MemBaseline::baseline(bool summaryOnly) {
reset();
- _class_count = InstanceKlass::number_of_instance_classes();
+ _instance_class_count = ClassLoaderDataGraph::num_instance_classes();
+ _array_class_count = ClassLoaderDataGraph::num_array_classes();
if (!baseline_summary()) {
return false;
--- a/src/hotspot/share/services/memBaseline.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/services/memBaseline.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -67,7 +67,8 @@
VirtualMemorySnapshot _virtual_memory_snapshot;
MetaspaceSnapshot _metaspace_snapshot;
- size_t _class_count;
+ size_t _instance_class_count;
+ size_t _array_class_count;
// Allocation sites information
// Malloc allocation sites
@@ -89,7 +90,7 @@
// create a memory baseline
MemBaseline():
_baseline_type(Not_baselined),
- _class_count(0) {
+ _instance_class_count(0), _array_class_count(0) {
}
bool baseline(bool summaryOnly = true);
@@ -160,7 +161,17 @@
size_t class_count() const {
assert(baseline_type() != Not_baselined, "Not yet baselined");
- return _class_count;
+ return _instance_class_count + _array_class_count;
+ }
+
+ size_t instance_class_count() const {
+ assert(baseline_type() != Not_baselined, "Not yet baselined");
+ return _instance_class_count;
+ }
+
+ size_t array_class_count() const {
+ assert(baseline_type() != Not_baselined, "Not yet baselined");
+ return _array_class_count;
}
size_t thread_count() const {
@@ -172,7 +183,8 @@
void reset() {
_baseline_type = Not_baselined;
// _malloc_memory_snapshot and _virtual_memory_snapshot are copied over.
- _class_count = 0;
+ _instance_class_count = 0;
+ _array_class_count = 0;
_malloc_sites.clear();
_virtual_memory_sites.clear();
--- a/src/hotspot/share/services/memReporter.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/services/memReporter.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -145,7 +145,10 @@
if (flag == mtClass) {
// report class count
- out->print_cr("%27s (classes #" SIZE_FORMAT ")", " ", _class_count);
+ out->print_cr("%27s (classes #" SIZE_FORMAT ")",
+ " ", (_instance_class_count + _array_class_count));
+ out->print_cr("%27s ( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")",
+ " ", _instance_class_count, _array_class_count);
} else if (flag == mtThread) {
// report thread count
out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", _malloc_snapshot->thread_count());
@@ -459,6 +462,17 @@
out->print(" %+d", (int)(_current_baseline.class_count() - _early_baseline.class_count()));
}
out->print_cr(")");
+
+ out->print("%27s ( instance classes #" SIZE_FORMAT, " ", _current_baseline.instance_class_count());
+ if (_current_baseline.instance_class_count() != _early_baseline.instance_class_count()) {
+ out->print(" %+d", (int)(_current_baseline.instance_class_count() - _early_baseline.instance_class_count()));
+ }
+ out->print(", array classes #" SIZE_FORMAT, _current_baseline.array_class_count());
+ if (_current_baseline.array_class_count() != _early_baseline.array_class_count()) {
+ out->print(" %+d", (int)(_current_baseline.array_class_count() - _early_baseline.array_class_count()));
+ }
+ out->print_cr(")");
+
} else if (flag == mtThread) {
// report thread count
out->print("%27s (thread #" SIZE_FORMAT "", " ", _current_baseline.thread_count());
--- a/src/hotspot/share/services/memReporter.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/services/memReporter.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -94,7 +94,8 @@
private:
MallocMemorySnapshot* _malloc_snapshot;
VirtualMemorySnapshot* _vm_snapshot;
- size_t _class_count;
+ size_t _instance_class_count;
+ size_t _array_class_count;
public:
// This constructor is for normal reporting from a recent baseline.
@@ -102,7 +103,8 @@
size_t scale = K) : MemReporterBase(output, scale),
_malloc_snapshot(baseline.malloc_memory_snapshot()),
_vm_snapshot(baseline.virtual_memory_snapshot()),
- _class_count(baseline.class_count()) { }
+ _instance_class_count(baseline.instance_class_count()),
+ _array_class_count(baseline.array_class_count()) { }
// Generate summary report
--- a/src/hotspot/share/services/memTracker.hpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/services/memTracker.hpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -36,8 +36,14 @@
class Tracker : public StackObj {
public:
- Tracker() { }
- void record(address addr, size_t size) { }
+ enum TrackerType {
+ uncommit,
+ release
+ };
+ Tracker(enum TrackerType type) : _type(type) { }
+ void record(address addr, size_t size);
+ private:
+ enum TrackerType _type;
};
class MemTracker : AllStatic {
@@ -63,8 +69,6 @@
static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
const NativeCallStack& stack, MEMFLAGS flag = mtNone) { }
static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { }
- static inline Tracker get_virtual_memory_uncommit_tracker() { return Tracker(); }
- static inline Tracker get_virtual_memory_release_tracker() { return Tracker(); }
static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { }
static inline void record_thread_stack(void* addr, size_t size) { }
static inline void release_thread_stack(void* addr, size_t size) { }
@@ -227,16 +231,6 @@
}
}
- static inline Tracker get_virtual_memory_uncommit_tracker() {
- assert(tracking_level() >= NMT_summary, "Check by caller");
- return Tracker(Tracker::uncommit);
- }
-
- static inline Tracker get_virtual_memory_release_tracker() {
- assert(tracking_level() >= NMT_summary, "Check by caller");
- return Tracker(Tracker::release);
- }
-
static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) {
if (tracking_level() < NMT_summary) return;
if (addr != NULL) {
--- a/src/hotspot/share/utilities/ostream.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/src/hotspot/share/utilities/ostream.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -947,18 +947,11 @@
delete classlist_file;
}
#endif
- {
- // we temporaly disable PrintMallocFree here
- // as otherwise it'll lead to using of almost deleted
- // tty or defaultStream::instance in logging facility
- // of HeapFree(), see 6391258
- DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);)
- if (tty != defaultStream::instance) {
- delete tty;
- }
- if (defaultStream::instance != NULL) {
- delete defaultStream::instance;
- }
+ if (tty != defaultStream::instance) {
+ delete tty;
+ }
+ if (defaultStream::instance != NULL) {
+ delete defaultStream::instance;
}
tty = NULL;
xtty = NULL;
--- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java Sat Feb 10 09:25:35 2018 +0100
@@ -37,7 +37,7 @@
* unless the argument is specified to be unused or specified to accept a
* {@code null} value.
*
- * @since 10
+ * @since 11
*/
public final class ConstantBootstraps {
// implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java Sat Feb 10 09:25:35 2018 +0100
@@ -143,7 +143,7 @@
int alignment = data.getAlignment();
byte[] value = new byte[size];
ByteBuffer buffer = ByteBuffer.wrap(value).order(ByteOrder.nativeOrder());
- DataSection.emit(buffer, data, p -> {
+ DataSection.emit(buffer, data, (p, c) -> {
});
String targetSymbol = "data.M" + methodInfo.getCodeId() + "." + dataOffset;
Symbol relocationSymbol = binaryContainer.getSymbol(targetSymbol);
--- a/src/jdk.internal.vm.compiler/.mx.graal/suite.py Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/.mx.graal/suite.py Sat Feb 10 09:25:35 2018 +0100
@@ -82,6 +82,24 @@
"javaCompliance" : "1.8",
"workingSets" : "API,SDK",
},
+ "org.graalvm.collections" : {
+ "subDir" : "share/classes",
+ "sourceDirs" : ["src"],
+ "checkstyle" : "org.graalvm.word",
+ "javaCompliance" : "1.8",
+ "workingSets" : "API,SDK",
+ },
+ "org.graalvm.collections.test" : {
+ "subDir" : "share/classes",
+ "sourceDirs" : ["src"],
+ "dependencies" : [
+ "mx:JUNIT",
+ "org.graalvm.collections",
+ ],
+ "checkstyle" : "org.graalvm.word",
+ "javaCompliance" : "1.8",
+ "workingSets" : "API,SDK,Test",
+ },
# ------------- Graal -------------
@@ -190,6 +208,9 @@
"org.graalvm.util" : {
"subDir" : "share/classes",
"sourceDirs" : ["src"],
+ "dependencies" : [
+ "org.graalvm.collections",
+ ],
"checkstyle" : "org.graalvm.compiler.graph",
"javaCompliance" : "1.8",
"workingSets" : "API,Graal",
@@ -201,6 +222,7 @@
"dependencies" : [
"mx:JUNIT",
"org.graalvm.util",
+ "org.graalvm.compiler.core.test",
],
"checkstyle" : "org.graalvm.compiler.graph",
"javaCompliance" : "1.8",
@@ -970,10 +992,11 @@
"workingSets" : "Graal,SPARC",
},
- "org.graalvm.compiler.core.sparc.test" : {
+ "org.graalvm.compiler.hotspot.sparc.test" : {
"subDir" : "share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
+ "org.graalvm.compiler.hotspot",
"org.graalvm.compiler.lir.jtt",
"JVMCI_HOTSPOT"
],
@@ -1007,6 +1030,7 @@
"subDir" : "share/classes",
"sourceDirs" : ["src"],
"dependencies" : [
+ "org.graalvm.collections",
"org.graalvm.compiler.debug",
"org.graalvm.word",
],
@@ -1037,7 +1061,6 @@
"sourceDirs" : ["src"],
"dependencies" : [
"org.graalvm.compiler.debug",
- "org.graalvm.util",
"mx:JUNIT",
],
"checkstyle" : "org.graalvm.compiler.graph",
@@ -1225,11 +1248,11 @@
"org.graalvm.compiler.asm.amd64.test",
"org.graalvm.compiler.core.aarch64.test",
"org.graalvm.compiler.core.amd64.test",
- "org.graalvm.compiler.core.sparc.test",
"org.graalvm.compiler.debug.test",
"org.graalvm.compiler.hotspot.aarch64.test",
"org.graalvm.compiler.hotspot.amd64.test",
"org.graalvm.compiler.hotspot.lir.test",
+ "org.graalvm.compiler.hotspot.sparc.test",
"org.graalvm.compiler.options.test",
"org.graalvm.compiler.jtt",
"org.graalvm.compiler.lir.jtt",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections.test;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicSet;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicMapImplTest {
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveNull() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create(10);
+ map.removeKey(null);
+ }
+
+ @Test
+ public void testInitFromHashSet() {
+ UnmodifiableEconomicSet<Integer> set = new UnmodifiableEconomicSet<Integer>() {
+
+ @Override
+ public boolean contains(Integer element) {
+ return element == 0;
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public Iterator<Integer> iterator() {
+ return new Iterator<Integer>() {
+
+ private boolean visited = false;
+
+ @Override
+ public boolean hasNext() {
+ return !visited;
+ }
+
+ @Override
+ public Integer next() {
+ if (visited) {
+ return null;
+ } else {
+ visited = true;
+ return 1;
+ }
+ }
+ };
+ }
+ };
+
+ EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.DEFAULT, set);
+ Assert.assertEquals(newSet.size(), 1);
+ }
+
+ @Test
+ public void testCopyHash() {
+ EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
+ set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+ EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.IDENTITY, set);
+ Assert.assertEquals(newSet.size(), 10);
+ newSet.remove(8);
+ newSet.remove(9);
+ Assert.assertEquals(newSet.size(), 8);
+ }
+
+ @Test
+ public void testNewEquivalence() {
+ EconomicSet<Integer> set = EconomicSet.create(new Equivalence() {
+ @Override
+ public boolean equals(Object a, Object b) {
+ return false;
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return 0;
+ }
+ });
+ set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+ Assert.assertTrue(set.add(new Integer(0)));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testMapPutNull() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ map.put(null, null);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections.test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Objects;
+import java.util.Random;
+
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
+import org.graalvm.collections.UnmodifiableMapCursor;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class EconomicMapLargeTest {
+
+ @Parameter(value = 0) public EconomicMap<Object, Object> testMap;
+ @Parameter(value = 1) public EconomicMap<Object, Object> referenceMap;
+ @Parameter(value = 2) public String name;
+
+ @Parameters(name = "{2}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.create(Equivalence.DEFAULT), "EconomicMap"},
+ new Object[]{EconomicMap.create(Equivalence.IDENTITY), EconomicMap.create(Equivalence.IDENTITY), "EconomicMap(IDENTITY)"},
+ new Object[]{EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE),
+ "EconomicMap(IDENTITY_WITH_SYSTEM_HASHCODE)"},
+ new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.wrapMap(new LinkedHashMap<>()), "EconomicMap<->wrapMap"},
+ new Object[]{EconomicMap.wrapMap(new LinkedHashMap<>()), EconomicMap.wrapMap(new LinkedHashMap<>()), "wrapMap"});
+ }
+
+ private static int[] createRandomRange(Random random, int count) {
+ int[] result = new int[count];
+ for (int i = 0; i < count; ++i) {
+ int range = random.nextInt(14);
+ if (range == 0 || range > 10) {
+ range = Integer.MAX_VALUE;
+ } else if (range == 10) {
+ range = 100;
+ }
+ result[i] = range;
+ }
+ return result;
+ }
+
+ private static final class BadHashClass {
+ private int value;
+
+ BadHashClass(int randomInt) {
+ this.value = randomInt;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof BadHashClass) {
+ BadHashClass badHashClass = (BadHashClass) other;
+ return badHashClass.value == value;
+ }
+ return false;
+ }
+ }
+
+ interface MapAction {
+ Object perform(EconomicMap<Object, Object> map, int randomInt);
+ }
+
+ static final Object EXISTING_VALUE = new Object();
+
+ static final MapAction[] INCREASE_ACTIONS = new MapAction[]{
+ (map, randomInt) -> map.put(randomInt, "value"),
+ (map, randomInt) -> map.get(randomInt)
+ };
+
+ static final MapAction[] ACTIONS = new MapAction[]{
+ (map, randomInt) -> map.removeKey(randomInt),
+ (map, randomInt) -> map.put(randomInt, "value"),
+ (map, randomInt) -> map.put(randomInt, null),
+ (map, randomInt) -> map.put(EXISTING_VALUE, randomInt),
+ (map, randomInt) -> {
+ if (randomInt == 0) {
+ map.clear();
+ }
+ return map.isEmpty();
+ },
+ (map, randomInt) -> map.containsKey(randomInt),
+ (map, randomInt) -> map.get(randomInt),
+ (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"),
+ (map, randomInt) -> {
+ if (randomInt == 0) {
+ map.replaceAll((key, value) -> Objects.toString(value) + "!");
+ }
+ return map.isEmpty();
+ }
+
+ };
+
+ @Test
+ public void testVeryLarge() {
+ testMap.clear();
+ referenceMap.clear();
+
+ Random random = new Random(0);
+ for (int i = 0; i < 200000; ++i) {
+ for (int j = 0; j < INCREASE_ACTIONS.length; ++j) {
+ int nextInt = random.nextInt(10000000);
+ MapAction action = INCREASE_ACTIONS[j];
+ Object result = action.perform(testMap, nextInt);
+ Object referenceResult = action.perform(referenceMap, nextInt);
+ Assert.assertEquals(result, referenceResult);
+ }
+ }
+ }
+
+ /**
+ * Tests a sequence of random operations on the map.
+ */
+ @Test
+ public void testAddRemove() {
+ testMap.clear();
+ referenceMap.clear();
+
+ for (int seed = 0; seed < 10; ++seed) {
+ Random random = new Random(seed);
+ int[] ranges = createRandomRange(random, ACTIONS.length);
+ int value = random.nextInt(10000);
+ for (int i = 0; i < value; ++i) {
+ for (int j = 0; j < ACTIONS.length; ++j) {
+ if (random.nextInt(ranges[j]) == 0) {
+ int nextInt = random.nextInt(100);
+ MapAction action = ACTIONS[j];
+ Object result = action.perform(testMap, nextInt);
+ Object referenceResult = action.perform(referenceMap, nextInt);
+ Assert.assertEquals(result, referenceResult);
+ if (j % 100 == 0) {
+ checkEquality(testMap, referenceMap);
+ }
+ }
+ }
+
+ if (random.nextInt(20) == 0) {
+ removeElement(random.nextInt(100), testMap, referenceMap);
+ }
+ }
+ }
+ }
+
+ private static void removeElement(int index, EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
+ Assert.assertEquals(referenceMap.size(), map.size());
+ MapCursor<?, ?> cursor = map.getEntries();
+ MapCursor<?, ?> referenceCursor = referenceMap.getEntries();
+ int z = 0;
+ while (cursor.advance()) {
+ Assert.assertTrue(referenceCursor.advance());
+ Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
+ Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
+ if (index == z) {
+ cursor.remove();
+ referenceCursor.remove();
+ }
+ ++z;
+ }
+
+ Assert.assertFalse(referenceCursor.advance());
+ }
+
+ private static void checkEquality(EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
+ Assert.assertEquals(referenceMap.size(), map.size());
+
+ // Check entries.
+ UnmodifiableMapCursor<?, ?> cursor = map.getEntries();
+ UnmodifiableMapCursor<?, ?> referenceCursor = referenceMap.getEntries();
+ while (cursor.advance()) {
+ Assert.assertTrue(referenceCursor.advance());
+ Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
+ Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
+ }
+
+ // Check keys.
+ Iterator<?> iterator = map.getKeys().iterator();
+ Iterator<?> referenceIterator = referenceMap.getKeys().iterator();
+ while (iterator.hasNext()) {
+ Assert.assertTrue(referenceIterator.hasNext());
+ Assert.assertEquals(iterator.next(), referenceIterator.next());
+ }
+
+ // Check values.
+ iterator = map.getValues().iterator();
+ referenceIterator = referenceMap.getValues().iterator();
+ while (iterator.hasNext()) {
+ Assert.assertTrue(referenceIterator.hasNext());
+ Assert.assertEquals(iterator.next(), referenceIterator.next());
+ }
+ Assert.assertFalse(referenceIterator.hasNext());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections.test;
+
+import java.util.LinkedHashMap;
+
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.UnmodifiableEconomicMap;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicMapTest {
+
+ @Test
+ public void testMapGetDefault() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ map.put(0, 1);
+ Assert.assertEquals(map.get(0, 2), Integer.valueOf(1));
+ Assert.assertEquals(map.get(1, 2), Integer.valueOf(2));
+ }
+
+ @Test
+ public void testMapPutAll() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ EconomicMap<Integer, Integer> newMap = EconomicMap.wrapMap(new LinkedHashMap<>());
+ newMap.put(1, 1);
+ newMap.put(2, 4);
+ map.putAll(newMap);
+ Assert.assertEquals(map.size(), 2);
+
+ UnmodifiableEconomicMap<Integer, Integer> unmodifiableEconomicMap = EconomicMap.create(newMap);
+
+ map.removeKey(1);
+ map.put(2, 2);
+ map.put(3, 9);
+
+ map.putAll(unmodifiableEconomicMap);
+ Assert.assertEquals(map.size(), 3);
+ Assert.assertEquals(map.get(2), Integer.valueOf(4));
+ }
+
+ @Test
+ public void testToString() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ map.put(0, 0);
+ map.put(1, 1);
+ Assert.assertEquals(map.toString(), "map(size=2, {(0,0),(1,1)})");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicSetTest {
+
+ @Test
+ public void testUtilities() {
+ EconomicSet<Integer> set = EconomicSet.create(0);
+ set.add(0);
+ Assert.assertTrue(set.add(1));
+ Assert.assertEquals(set.size(), 2);
+ Assert.assertFalse(set.add(1));
+ Assert.assertEquals(set.size(), 2);
+ set.remove(1);
+ Assert.assertEquals(set.size(), 1);
+ set.remove(2);
+ Assert.assertEquals(set.size(), 1);
+ Assert.assertTrue(set.add(1));
+ set.clear();
+ Assert.assertEquals(set.size(), 0);
+ }
+
+ @Test
+ public void testAddAll() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1, 0));
+ Assert.assertEquals(set.size(), 2);
+
+ EconomicSet<Integer> newSet = EconomicSet.create();
+ newSet.addAll(Arrays.asList(1, 2));
+ Assert.assertEquals(newSet.size(), 2);
+ newSet.addAll(set);
+ Assert.assertEquals(newSet.size(), 3);
+ }
+
+ @Test
+ public void testRemoveAll() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1));
+
+ set.removeAll(Arrays.asList(1, 2));
+ Assert.assertEquals(set.size(), 1);
+
+ set.removeAll(EconomicSet.create(set));
+ Assert.assertEquals(set.size(), 0);
+ }
+
+ @Test
+ public void testRetainAll() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1, 2));
+
+ EconomicSet<Integer> newSet = EconomicSet.create();
+ newSet.addAll(Arrays.asList(2, 3));
+
+ set.retainAll(newSet);
+ Assert.assertEquals(set.size(), 1);
+ }
+
+ @Test
+ public void testToArray() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1));
+ Assert.assertArrayEquals(set.toArray(new Integer[2]), new Integer[]{0, 1});
+ }
+
+ @Test
+ public void testToString() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1));
+ Assert.assertEquals(set.toString(), "set(size=2, {0,1})");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testToUnalignedArray() {
+ Assert.assertArrayEquals(EconomicSet.create().toArray(new Integer[2]), new Integer[0]);
+ }
+
+ @Test
+ public void testSetRemoval() {
+ ArrayList<Integer> initialList = new ArrayList<>();
+ ArrayList<Integer> removalList = new ArrayList<>();
+ ArrayList<Integer> finalList = new ArrayList<>();
+ EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
+ set.add(1);
+ set.add(2);
+ set.add(3);
+ set.add(4);
+ set.add(5);
+ set.add(6);
+ set.add(7);
+ set.add(8);
+ set.add(9);
+ Iterator<Integer> i1 = set.iterator();
+ while (i1.hasNext()) {
+ initialList.add(i1.next());
+ }
+ int size = 0;
+ Iterator<Integer> i2 = set.iterator();
+ while (i2.hasNext()) {
+ Integer elem = i2.next();
+ if (size++ < 8) {
+ i2.remove();
+ }
+ removalList.add(elem);
+ }
+ Iterator<Integer> i3 = set.iterator();
+ while (i3.hasNext()) {
+ finalList.add(i3.next());
+ }
+ Assert.assertEquals(initialList, removalList);
+ Assert.assertEquals(1, finalList.size());
+ Assert.assertEquals(new Integer(9), finalList.get(0));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections.test;
+
+import org.graalvm.collections.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EquivalenceTest {
+
+ private static final String TEST_STRING = "Graal";
+ private static final String TEST_STRING2 = "Graal2";
+
+ @Test
+ public void testDEFAULT() {
+ Assert.assertTrue(Equivalence.DEFAULT.equals(TEST_STRING, new String(TEST_STRING)));
+ Assert.assertEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(new String(TEST_STRING)));
+ Assert.assertFalse(Equivalence.DEFAULT.equals(TEST_STRING, TEST_STRING2));
+ Assert.assertNotEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(TEST_STRING2));
+ }
+
+ @Test
+ public void testIDENTITY() {
+ Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, new String(TEST_STRING)));
+ Assert.assertEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(new String(TEST_STRING)));
+ Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, TEST_STRING2));
+ Assert.assertNotEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(TEST_STRING2));
+ }
+
+ @Test
+ public void testIDENTITYWITHSYSTEMHASHCODE() {
+ Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, new String(TEST_STRING)));
+ Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(new String(TEST_STRING)));
+ Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, TEST_STRING2));
+ Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING2));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections.test;
+
+import org.graalvm.collections.Pair;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PairTest {
+
+ @Test
+ public void testCreate() {
+ Assert.assertEquals(Pair.create(null, null), Pair.empty());
+ Assert.assertNotEquals(Pair.create(null, null), null);
+ Assert.assertEquals(Pair.createLeft(null), Pair.empty());
+ Assert.assertEquals(Pair.createRight(null), Pair.empty());
+ Assert.assertEquals(Pair.create(1, null), Pair.createLeft(1));
+ Assert.assertEquals(Pair.create(null, 1), Pair.createRight(1));
+ }
+
+ @Test
+ public void testUtilities() {
+ Pair<Integer, Integer> pair = Pair.create(1, null);
+ Assert.assertEquals(pair.getLeft(), Integer.valueOf(1));
+ Assert.assertEquals(pair.getRight(), null);
+ Assert.assertEquals(pair.toString(), "(1, null)");
+ Assert.assertEquals(pair.hashCode(), Pair.createLeft(1).hashCode());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+/**
+ * Memory efficient map data structure.
+ *
+ * @since 1.0
+ */
+public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
+
+ /**
+ * Associates {@code value} with {@code key} in this map. If the map previously contained a
+ * mapping for {@code key}, the old value is replaced by {@code value}.
+ *
+ * @return the previous value associated with {@code key}, or {@code null} if there was no
+ * mapping for {@code key}.
+ * @since 1.0
+ */
+ V put(K key, V value);
+
+ /**
+ * Copies all of the mappings from {@code other} to this map.
+ *
+ * @since 1.0
+ */
+ default void putAll(EconomicMap<K, V> other) {
+ MapCursor<K, V> e = other.getEntries();
+ while (e.advance()) {
+ put(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Copies all of the mappings from {@code other} to this map.
+ *
+ * @since 1.0
+ */
+ default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
+ UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
+ while (entry.advance()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Removes all of the mappings from this map. The map will be empty after this call returns.
+ *
+ * @since 1.0
+ */
+ void clear();
+
+ /**
+ * Removes the mapping for {@code key} from this map if it is present. The map will not contain
+ * a mapping for {@code key} once the call returns.
+ *
+ * @return the previous value associated with {@code key}, or {@code null} if there was no
+ * mapping for {@code key}.
+ * @since 1.0
+ */
+ V removeKey(K key);
+
+ /**
+ * Returns a {@link MapCursor} view of the mappings contained in this map.
+ *
+ * @since 1.0
+ */
+ @Override
+ MapCursor<K, V> getEntries();
+
+ /**
+ * Replaces each entry's value with the result of invoking {@code function} on that entry until
+ * all entries have been processed or the function throws an exception. Exceptions thrown by the
+ * function are relayed to the caller.
+ *
+ * @since 1.0
+ */
+ void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the default
+ * {@link Equivalence#DEFAULT} comparison strategy for keys.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create() {
+ return EconomicMap.create(Equivalence.DEFAULT);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the default
+ * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
+ * capacity.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(int initialCapacity) {
+ return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the given comparison
+ * strategy for keys.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
+ return EconomicMapImpl.create(strategy, false);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the default
+ * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
+ * specified existing map.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
+ return EconomicMap.create(Equivalence.DEFAULT, m);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set and copies all elements from
+ * the specified existing map.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
+ return EconomicMapImpl.create(strategy, m, false);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set and initializes with a
+ * specified capacity.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
+ return EconomicMapImpl.create(strategy, initialCapacity, false);
+ }
+
+ /**
+ * Wraps an existing {@link Map} as an {@link EconomicMap}.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
+ return new EconomicMap<K, V>() {
+
+ @Override
+ public V get(K key) {
+ V result = map.get(key);
+ return result;
+ }
+
+ @Override
+ public V put(K key, V value) {
+ V result = map.put(key, value);
+ return result;
+ }
+
+ @Override
+ public int size() {
+ int result = map.size();
+ return result;
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public void clear() {
+ map.clear();
+ }
+
+ @Override
+ public V removeKey(K key) {
+ V result = map.remove(key);
+ return result;
+ }
+
+ @Override
+ public Iterable<V> getValues() {
+ return map.values();
+ }
+
+ @Override
+ public Iterable<K> getKeys() {
+ return map.keySet();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ @Override
+ public MapCursor<K, V> getEntries() {
+ Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
+ return new MapCursor<K, V>() {
+
+ private Map.Entry<K, V> current;
+
+ @Override
+ public boolean advance() {
+ boolean result = iterator.hasNext();
+ if (result) {
+ current = iterator.next();
+ }
+
+ return result;
+ }
+
+ @Override
+ public K getKey() {
+ return current.getKey();
+ }
+
+ @Override
+ public V getValue() {
+ return current.getValue();
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
+ };
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ map.replaceAll(function);
+ }
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,857 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * Implementation of a map with a memory-efficient structure that always preserves insertion order
+ * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal
+ * {@link #INITIAL_CAPACITY} or smaller 256.
+ *
+ * The key/value pairs are kept in an expanding flat object array with keys at even indices and
+ * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there
+ * is no additional hash data structure and comparisons are done via linear checking of the
+ * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an
+ * object identity comparison), this limit below which the map is without an actual hash table is
+ * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}.
+ *
+ * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash
+ * array where an entry of 0 means no hit and otherwise denotes the entry number in the
+ * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit
+ * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of
+ * integer values in other cases.
+ *
+ * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take
+ * the place of the values in the {@link #entries} array.
+ *
+ * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the
+ * map falls below a specific threshold, the map will be compressed via the
+ * {@link #maybeCompress(int)} method.
+ */
+final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
+
+ /**
+ * Initial number of key/value pair entries that is allocated in the first entries array.
+ */
+ private static final int INITIAL_CAPACITY = 4;
+
+ /**
+ * Maximum number of entries that are moved linearly forward if a key is removed.
+ */
+ private static final int COMPRESS_IMMEDIATE_CAPACITY = 8;
+
+ /**
+ * Minimum number of key/value pair entries added when the entries array is increased in size.
+ */
+ private static final int MIN_CAPACITY_INCREASE = 8;
+
+ /**
+ * Number of entries above which a hash table is created.
+ */
+ private static final int HASH_THRESHOLD = 4;
+
+ /**
+ * Number of entries above which a hash table is created when equality can be checked with
+ * object identity.
+ */
+ private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8;
+
+ /**
+ * Maximum number of entries allowed in the map.
+ */
+ private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1;
+
+ /**
+ * Number of entries above which more than 1 byte is necessary for the hash index.
+ */
+ private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1);
+
+ /**
+ * Number of entries above which more than 2 bytes are are necessary for the hash index.
+ */
+ private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE);
+
+ /**
+ * Total number of entries (actual entries plus deleted entries).
+ */
+ private int totalEntries;
+
+ /**
+ * Number of deleted entries.
+ */
+ private int deletedEntries;
+
+ /**
+ * Entries array with even indices storing keys and odd indices storing values.
+ */
+ private Object[] entries;
+
+ /**
+ * Hash array that is interpreted either as byte or short or int array depending on number of
+ * map entries.
+ */
+ private byte[] hashArray;
+
+ /**
+ * The strategy used for comparing keys or {@code null} for denoting special strategy
+ * {@link Equivalence#IDENTITY}.
+ */
+ private final Equivalence strategy;
+
+ /**
+ * Intercept method for debugging purposes.
+ */
+ private static <K, V> EconomicMapImpl<K, V> intercept(EconomicMapImpl<K, V> map) {
+ return map;
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, isSet));
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, int initialCapacity, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, initialCapacity, isSet));
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, other, isSet));
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, other, isSet));
+ }
+
+ private EconomicMapImpl(Equivalence strategy, boolean isSet) {
+ if (strategy == Equivalence.IDENTITY) {
+ this.strategy = null;
+ } else {
+ this.strategy = strategy;
+ }
+ this.isSet = isSet;
+ }
+
+ private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) {
+ this(strategy, isSet);
+ init(initialCapacity);
+ }
+
+ private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
+ this(strategy, isSet);
+ if (!initFrom(other)) {
+ init(other.size());
+ putAll(other);
+ }
+ }
+
+ private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
+ this(strategy, isSet);
+ if (!initFrom(other)) {
+ init(other.size());
+ addAll(other);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean initFrom(Object o) {
+ if (o instanceof EconomicMapImpl) {
+ EconomicMapImpl<K, V> otherMap = (EconomicMapImpl<K, V>) o;
+ // We are only allowed to directly copy if the strategies of the two maps are the same.
+ if (strategy == otherMap.strategy) {
+ totalEntries = otherMap.totalEntries;
+ deletedEntries = otherMap.deletedEntries;
+ if (otherMap.entries != null) {
+ entries = otherMap.entries.clone();
+ }
+ if (otherMap.hashArray != null) {
+ hashArray = otherMap.hashArray.clone();
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void init(int size) {
+ if (size > INITIAL_CAPACITY) {
+ entries = new Object[size << 1];
+ }
+ }
+
+ /**
+ * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from
+ * other map on construction.
+ */
+ private static final class CollisionLink {
+
+ CollisionLink(Object value, int next) {
+ this.value = value;
+ this.next = next;
+ }
+
+ final Object value;
+
+ /**
+ * Index plus one of the next entry in the collision link chain.
+ */
+ final int next;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(K key) {
+ Objects.requireNonNull(key);
+
+ int index = find(key);
+ if (index != -1) {
+ return (V) getValue(index);
+ }
+ return null;
+ }
+
+ private int find(K key) {
+ if (hasHashArray()) {
+ return findHash(key);
+ } else {
+ return findLinear(key);
+ }
+ }
+
+ private int findLinear(K key) {
+ for (int i = 0; i < totalEntries; i++) {
+ Object entryKey = entries[i << 1];
+ if (entryKey != null && compareKeys(key, entryKey)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private boolean compareKeys(Object key, Object entryKey) {
+ if (key == entryKey) {
+ return true;
+ }
+ if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+ if (strategy == Equivalence.DEFAULT) {
+ return key.equals(entryKey);
+ } else {
+ return strategy.equals(key, entryKey);
+ }
+ }
+ return false;
+ }
+
+ private int findHash(K key) {
+ int index = getHashArray(getHashIndex(key)) - 1;
+ if (index != -1) {
+ Object entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ return index;
+ } else {
+ Object entryValue = getRawValue(index);
+ if (entryValue instanceof CollisionLink) {
+ return findWithCollision(key, (CollisionLink) entryValue);
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private int findWithCollision(K key, CollisionLink initialEntryValue) {
+ int index;
+ Object entryKey;
+ CollisionLink entryValue = initialEntryValue;
+ while (true) {
+ CollisionLink collisionLink = entryValue;
+ index = collisionLink.next;
+ entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ return index;
+ } else {
+ Object value = getRawValue(index);
+ if (value instanceof CollisionLink) {
+ entryValue = (CollisionLink) getRawValue(index);
+ } else {
+ return -1;
+ }
+ }
+ }
+ }
+
+ private int getHashArray(int index) {
+ if (entries.length < LARGE_HASH_THRESHOLD) {
+ return (hashArray[index] & 0xFF);
+ } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+ int adjustedIndex = index << 1;
+ return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8);
+ } else {
+ int adjustedIndex = index << 2;
+ return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24);
+ }
+ }
+
+ private void setHashArray(int index, int value) {
+ if (entries.length < LARGE_HASH_THRESHOLD) {
+ hashArray[index] = (byte) value;
+ } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+ int adjustedIndex = index << 1;
+ hashArray[adjustedIndex] = (byte) value;
+ hashArray[adjustedIndex + 1] = (byte) (value >> 8);
+ } else {
+ int adjustedIndex = index << 2;
+ hashArray[adjustedIndex] = (byte) value;
+ hashArray[adjustedIndex + 1] = (byte) (value >> 8);
+ hashArray[adjustedIndex + 2] = (byte) (value >> 16);
+ hashArray[adjustedIndex + 3] = (byte) (value >> 24);
+ }
+ }
+
+ private int findAndRemoveHash(Object key) {
+ int hashIndex = getHashIndex(key);
+ int index = getHashArray(hashIndex) - 1;
+ if (index != -1) {
+ Object entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ Object value = getRawValue(index);
+ int nextIndex = -1;
+ if (value instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) value;
+ nextIndex = collisionLink.next;
+ }
+ setHashArray(hashIndex, nextIndex + 1);
+ return index;
+ } else {
+ Object entryValue = getRawValue(index);
+ if (entryValue instanceof CollisionLink) {
+ return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index);
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) {
+ int index;
+ Object entryKey;
+ CollisionLink entryValue = initialEntryValue;
+ int lastIndex = initialIndexValue;
+ while (true) {
+ CollisionLink collisionLink = entryValue;
+ index = collisionLink.next;
+ entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ Object value = getRawValue(index);
+ if (value instanceof CollisionLink) {
+ CollisionLink thisCollisionLink = (CollisionLink) value;
+ setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next));
+ } else {
+ setRawValue(lastIndex, collisionLink.value);
+ }
+ return index;
+ } else {
+ Object value = getRawValue(index);
+ if (value instanceof CollisionLink) {
+ entryValue = (CollisionLink) getRawValue(index);
+ lastIndex = index;
+ } else {
+ return -1;
+ }
+ }
+ }
+ }
+
+ private int getHashIndex(Object key) {
+ int hash;
+ if (strategy != null && strategy != Equivalence.DEFAULT) {
+ if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+ hash = System.identityHashCode(key);
+ } else {
+ hash = strategy.hashCode(key);
+ }
+ } else {
+ hash = key.hashCode();
+ }
+ hash = hash ^ (hash >>> 16);
+ return hash & (getHashTableSize() - 1);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V put(K key, V value) {
+ if (key == null) {
+ throw new UnsupportedOperationException("null not supported as key!");
+ }
+ int index = find(key);
+ if (index != -1) {
+ Object oldValue = getValue(index);
+ setValue(index, value);
+ return (V) oldValue;
+ }
+
+ int nextEntryIndex = totalEntries;
+ if (entries == null) {
+ entries = new Object[INITIAL_CAPACITY << 1];
+ } else if (entries.length == nextEntryIndex << 1) {
+ grow();
+
+ assert entries.length > totalEntries << 1;
+ // Can change if grow is actually compressing.
+ nextEntryIndex = totalEntries;
+ }
+
+ setKey(nextEntryIndex, key);
+ setValue(nextEntryIndex, value);
+ totalEntries++;
+
+ if (hasHashArray()) {
+ // Rehash on collision if hash table is more than three quarters full.
+ boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1)));
+ putHashEntry(key, nextEntryIndex, rehashOnCollision);
+ } else if (totalEntries > getHashThreshold()) {
+ createHash();
+ }
+
+ return null;
+ }
+
+ /**
+ * Number of entries above which a hash table should be constructed.
+ */
+ private int getHashThreshold() {
+ if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+ return HASH_THRESHOLD_IDENTITY_COMPARE;
+ } else {
+ return HASH_THRESHOLD;
+ }
+ }
+
+ private void grow() {
+ int entriesLength = entries.length;
+ int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2);
+ if (newSize > MAX_ELEMENT_COUNT) {
+ throw new UnsupportedOperationException("map grown too large!");
+ }
+ Object[] newEntries = new Object[newSize << 1];
+ System.arraycopy(entries, 0, newEntries, 0, entriesLength);
+ entries = newEntries;
+ if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) ||
+ (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) {
+ // Rehash in order to change number of bits reserved for hash indices.
+ createHash();
+ }
+ }
+
+ /**
+ * Compresses the graph if there is a large number of deleted entries and returns the translated
+ * new next index.
+ */
+ private int maybeCompress(int nextIndex) {
+ if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) {
+ return compressLarge(nextIndex);
+ }
+ return nextIndex;
+ }
+
+ /**
+ * Compresses the graph and returns the translated new next index.
+ */
+ private int compressLarge(int nextIndex) {
+ int size = INITIAL_CAPACITY;
+ int remaining = totalEntries - deletedEntries;
+
+ while (size <= remaining) {
+ size += Math.max(MIN_CAPACITY_INCREASE, size >> 1);
+ }
+
+ Object[] newEntries = new Object[size << 1];
+ int z = 0;
+ int newNextIndex = remaining;
+ for (int i = 0; i < totalEntries; ++i) {
+ Object key = getKey(i);
+ if (i == nextIndex) {
+ newNextIndex = z;
+ }
+ if (key != null) {
+ newEntries[z << 1] = key;
+ newEntries[(z << 1) + 1] = getValue(i);
+ z++;
+ }
+ }
+
+ this.entries = newEntries;
+ totalEntries = z;
+ deletedEntries = 0;
+ if (z <= getHashThreshold()) {
+ this.hashArray = null;
+ } else {
+ createHash();
+ }
+ return newNextIndex;
+ }
+
+ private int getHashTableSize() {
+ if (entries.length < LARGE_HASH_THRESHOLD) {
+ return hashArray.length;
+ } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+ return hashArray.length >> 1;
+ } else {
+ return hashArray.length >> 2;
+ }
+ }
+
+ private void createHash() {
+ int entryCount = size();
+
+ // Calculate smallest 2^n that is greater number of entries.
+ int size = getHashThreshold();
+ while (size <= entryCount) {
+ size <<= 1;
+ }
+
+ // Give extra size to avoid collisions.
+ size <<= 1;
+
+ if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) {
+ // Every entry has 4 bytes.
+ size <<= 2;
+ } else if (this.entries.length >= LARGE_HASH_THRESHOLD) {
+ // Every entry has 2 bytes.
+ size <<= 1;
+ } else {
+ // Entries are very small => give extra size to further reduce collisions.
+ size <<= 1;
+ }
+
+ hashArray = new byte[size];
+ for (int i = 0; i < totalEntries; i++) {
+ Object entryKey = getKey(i);
+ if (entryKey != null) {
+ putHashEntry(entryKey, i, false);
+ }
+ }
+ }
+
+ private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) {
+ int hashIndex = getHashIndex(key);
+ int oldIndex = getHashArray(hashIndex) - 1;
+ if (oldIndex != -1 && rehashOnCollision) {
+ this.createHash();
+ return;
+ }
+ setHashArray(hashIndex, entryIndex + 1);
+ Object value = getRawValue(entryIndex);
+ if (oldIndex != -1) {
+ assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle";
+ if (value instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) value;
+ setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex));
+ } else {
+ setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex));
+ }
+ } else {
+ if (value instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) value;
+ setRawValue(entryIndex, collisionLink.value);
+ }
+ }
+ }
+
+ @Override
+ public int size() {
+ return totalEntries - deletedEntries;
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return find(key) != -1;
+ }
+
+ @Override
+ public void clear() {
+ entries = null;
+ hashArray = null;
+ totalEntries = deletedEntries = 0;
+ }
+
+ private boolean hasHashArray() {
+ return hashArray != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V removeKey(K key) {
+ if (key == null) {
+ throw new UnsupportedOperationException("null not supported as key!");
+ }
+ int index;
+ if (hasHashArray()) {
+ index = this.findAndRemoveHash(key);
+ } else {
+ index = this.findLinear(key);
+ }
+
+ if (index != -1) {
+ Object value = getValue(index);
+ remove(index);
+ return (V) value;
+ }
+ return null;
+ }
+
+ /**
+ * Removes the element at the specific index and returns the index of the next element. This can
+ * be a different value if graph compression was triggered.
+ */
+ private int remove(int indexToRemove) {
+ int index = indexToRemove;
+ int entriesAfterIndex = totalEntries - index - 1;
+ int result = index + 1;
+
+ // Without hash array, compress immediately.
+ if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) {
+ while (index < totalEntries - 1) {
+ setKey(index, getKey(index + 1));
+ setRawValue(index, getRawValue(index + 1));
+ index++;
+ }
+ result--;
+ }
+
+ setKey(index, null);
+ setRawValue(index, null);
+ if (index == totalEntries - 1) {
+ // Make sure last element is always non-null.
+ totalEntries--;
+ while (index > 0 && getKey(index - 1) == null) {
+ totalEntries--;
+ deletedEntries--;
+ index--;
+ }
+ } else {
+ deletedEntries++;
+ result = maybeCompress(result);
+ }
+
+ return result;
+ }
+
+ private abstract class SparseMapIterator<E> implements Iterator<E> {
+
+ protected int current;
+
+ @Override
+ public boolean hasNext() {
+ return current < totalEntries;
+ }
+
+ @Override
+ public void remove() {
+ if (hasHashArray()) {
+ EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1));
+ }
+ current = EconomicMapImpl.this.remove(current - 1);
+ }
+ }
+
+ @Override
+ public Iterable<V> getValues() {
+ return new Iterable<V>() {
+ @Override
+ public Iterator<V> iterator() {
+ return new SparseMapIterator<V>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public V next() {
+ Object result;
+ while (true) {
+ result = getValue(current);
+ if (result == null && getKey(current) == null) {
+ // values can be null, double-check if key is also null
+ current++;
+ } else {
+ current++;
+ break;
+ }
+ }
+ return (V) result;
+ }
+ };
+ }
+ };
+ }
+
+ @Override
+ public Iterable<K> getKeys() {
+ return this;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.size() == 0;
+ }
+
+ @Override
+ public MapCursor<K, V> getEntries() {
+ return new MapCursor<K, V>() {
+ int current = -1;
+
+ @Override
+ public boolean advance() {
+ current++;
+ if (current >= totalEntries) {
+ return false;
+ } else {
+ while (EconomicMapImpl.this.getKey(current) == null) {
+ // Skip over null entries
+ current++;
+ }
+ return true;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public K getKey() {
+ return (K) EconomicMapImpl.this.getKey(current);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V getValue() {
+ return (V) EconomicMapImpl.this.getValue(current);
+ }
+
+ @Override
+ public void remove() {
+ if (hasHashArray()) {
+ EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current));
+ }
+ current = EconomicMapImpl.this.remove(current) - 1;
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ for (int i = 0; i < totalEntries; i++) {
+ Object entryKey = getKey(i);
+ if (entryKey != null) {
+ Object newValue = function.apply((K) entryKey, (V) getValue(i));
+ setValue(i, newValue);
+ }
+ }
+ }
+
+ private Object getKey(int index) {
+ return entries[index << 1];
+ }
+
+ private void setKey(int index, Object newValue) {
+ entries[index << 1] = newValue;
+ }
+
+ private void setValue(int index, Object newValue) {
+ Object oldValue = getRawValue(index);
+ if (oldValue instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) oldValue;
+ setRawValue(index, new CollisionLink(newValue, collisionLink.next));
+ } else {
+ setRawValue(index, newValue);
+ }
+ }
+
+ private void setRawValue(int index, Object newValue) {
+ entries[(index << 1) + 1] = newValue;
+ }
+
+ private Object getRawValue(int index) {
+ return entries[(index << 1) + 1];
+ }
+
+ private Object getValue(int index) {
+ Object object = getRawValue(index);
+ if (object instanceof CollisionLink) {
+ return ((CollisionLink) object).value;
+ }
+ return object;
+ }
+
+ private final boolean isSet;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {");
+ String sep = "";
+ MapCursor<K, V> cursor = getEntries();
+ while (cursor.advance()) {
+ builder.append(sep);
+ if (isSet) {
+ builder.append(cursor.getKey());
+ } else {
+ builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append(")");
+ }
+ sep = ",";
+ }
+ builder.append("})");
+ return builder.toString();
+ }
+
+ @Override
+ public Iterator<K> iterator() {
+ return new SparseMapIterator<K>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public K next() {
+ Object result;
+ while ((result = getKey(current++)) == null) {
+ // skip null entries
+ }
+ return (K) result;
+ }
+ };
+ }
+
+ @Override
+ public boolean contains(K element) {
+ return containsKey(element);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean add(K element) {
+ return put(element, (V) element) == null;
+ }
+
+ @Override
+ public void remove(K element) {
+ removeKey(element);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+import java.util.Iterator;
+
+/**
+ * Memory efficient set data structure.
+ *
+ * @since 1.0
+ */
+public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
+
+ /**
+ * Adds {@code element} to this set if it is not already present.
+ *
+ * @return {@code true} if this set did not already contain {@code element}.
+ * @since 1.0
+ */
+ boolean add(E element);
+
+ /**
+ * Removes {@code element} from this set if it is present. This set will not contain
+ * {@code element} once the call returns.
+ *
+ * @since 1.0
+ */
+ void remove(E element);
+
+ /**
+ * Removes all of the elements from this set. The set will be empty after this call returns.
+ *
+ * @since 1.0
+ */
+ void clear();
+
+ /**
+ * Adds all of the elements in {@code other} to this set if they're not already present.
+ *
+ * @since 1.0
+ */
+ default void addAll(EconomicSet<E> other) {
+ addAll(other.iterator());
+ }
+
+ /**
+ * Adds all of the elements in {@code values} to this set if they're not already present.
+ *
+ * @since 1.0
+ */
+ default void addAll(Iterable<E> values) {
+ addAll(values.iterator());
+ }
+
+ /**
+ * Adds all of the elements enumerated by {@code iterator} to this set if they're not already
+ * present.
+ *
+ * @since 1.0
+ */
+ default void addAll(Iterator<E> iterator) {
+ while (iterator.hasNext()) {
+ add(iterator.next());
+ }
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in {@code other}.
+ *
+ * @since 1.0
+ */
+ default void removeAll(EconomicSet<E> other) {
+ removeAll(other.iterator());
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in {@code values}.
+ *
+ * @since 1.0
+ */
+ default void removeAll(Iterable<E> values) {
+ removeAll(values.iterator());
+ }
+
+ /**
+ * Removes from this set all of its elements that are enumerated by {@code iterator}.
+ *
+ * @since 1.0
+ */
+ default void removeAll(Iterator<E> iterator) {
+ while (iterator.hasNext()) {
+ remove(iterator.next());
+ }
+ }
+
+ /**
+ * Removes from this set all of its elements that are not contained in {@code other}.
+ *
+ * @since 1.0
+ */
+ default void retainAll(EconomicSet<E> other) {
+ Iterator<E> iterator = iterator();
+ while (iterator.hasNext()) {
+ E key = iterator.next();
+ if (!other.contains(key)) {
+ iterator.remove();
+ }
+ }
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements with the
+ * default {@link Equivalence#DEFAULT} comparison strategy.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create() {
+ return EconomicSet.create(Equivalence.DEFAULT);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(Equivalence strategy) {
+ return EconomicMapImpl.create(strategy, true);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements with the
+ * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
+ * specified collection.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(int initialCapacity) {
+ return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements with the
+ * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
+ * specified collection.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
+ return EconomicSet.create(Equivalence.DEFAULT, c);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements and
+ * initializes with the given capacity.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
+ return EconomicMapImpl.create(strategy, initialCapacity, true);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements and inserts
+ * all elements of the specified collection.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E> c) {
+ return EconomicMapImpl.create(strategy, c, true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+/**
+ * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
+ * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
+ *
+ * @since 1.0
+ */
+public abstract class Equivalence {
+
+ /**
+ * Default equivalence calling {@link #equals(Object)} to check equality and {@link #hashCode()}
+ * for obtaining hash values. Do not change the logic of this class as it may be inlined in
+ * other places.
+ *
+ * @since 1.0
+ */
+ public static final Equivalence DEFAULT = new Equivalence() {
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ return a.equals(b);
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return o.hashCode();
+ }
+ };
+
+ /**
+ * Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining
+ * hash values. Do not change the logic of this class as it may be inlined in other places.
+ *
+ * @since 1.0
+ */
+ public static final Equivalence IDENTITY = new Equivalence() {
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ return a == b;
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return o.hashCode();
+ }
+ };
+
+ /**
+ * Identity equivalence using {@code ==} to check equality and
+ * {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of
+ * this class as it may be inlined in other places.
+ *
+ * @since 1.0
+ */
+ public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ return a == b;
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return System.identityHashCode(o);
+ }
+ };
+
+ /**
+ * Subclass for creating custom equivalence definitions.
+ *
+ * @since 1.0
+ */
+ protected Equivalence() {
+ }
+
+ /**
+ * Returns {@code true} if the non-{@code null} arguments are equal to each other and
+ * {@code false} otherwise.
+ *
+ * @since 1.0
+ */
+ public abstract boolean equals(Object a, Object b);
+
+ /**
+ * Returns the hash code of a non-{@code null} argument {@code o}.
+ *
+ * @since 1.0
+ */
+ public abstract int hashCode(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+/**
+ * Cursor to iterate over a mutable map.
+ *
+ * @since 1.0
+ */
+public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
+ /**
+ * Remove the current entry from the map. May only be called once. After calling
+ * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
+ * the current entry.
+ *
+ * @since 1.0
+ */
+ void remove();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+import java.util.Objects;
+
+/**
+ * Utility class representing a pair of values.
+ *
+ * @since 1.0
+ */
+public final class Pair<L, R> {
+
+ private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);
+
+ private final L left;
+ private final R right;
+
+ /**
+ * Returns an empty pair.
+ *
+ * @since 1.0
+ */
+ @SuppressWarnings("unchecked")
+ public static <L, R> Pair<L, R> empty() {
+ return (Pair<L, R>) EMPTY;
+ }
+
+ /**
+ * Constructs a pair with its left value being {@code left}, or returns an empty pair if
+ * {@code left} is null.
+ *
+ * @return the constructed pair or an empty pair if {@code left} is null.
+ * @since 1.0
+ */
+ public static <L, R> Pair<L, R> createLeft(L left) {
+ if (left == null) {
+ return empty();
+ } else {
+ return new Pair<>(left, null);
+ }
+ }
+
+ /**
+ * Constructs a pair with its right value being {@code right}, or returns an empty pair if
+ * {@code right} is null.
+ *
+ * @return the constructed pair or an empty pair if {@code right} is null.
+ * @since 1.0
+ */
+ public static <L, R> Pair<L, R> createRight(R right) {
+ if (right == null) {
+ return empty();
+ } else {
+ return new Pair<>(null, right);
+ }
+ }
+
+ /**
+ * Constructs a pair with its left value being {@code left}, and its right value being
+ * {@code right}, or returns an empty pair if both inputs are null.
+ *
+ * @return the constructed pair or an empty pair if both inputs are null.
+ * @since 1.0
+ */
+ public static <L, R> Pair<L, R> create(L left, R right) {
+ if (right == null && left == null) {
+ return empty();
+ } else {
+ return new Pair<>(left, right);
+ }
+ }
+
+ private Pair(L left, R right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ /**
+ * Returns the left value of this pair.
+ *
+ * @since 1.0
+ */
+ public L getLeft() {
+ return left;
+ }
+
+ /**
+ * Returns the right value of this pair.
+ *
+ * @since 1.0
+ */
+ public R getRight() {
+ return right;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.0
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(left) + 31 * Objects.hashCode(right);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.0
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof Pair) {
+ Pair<L, R> pair = (Pair<L, R>) obj;
+ return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.0
+ */
+ @Override
+ public String toString() {
+ return String.format("(%s, %s)", left, right);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+/**
+ * Unmodifiable memory efficient map data structure.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableEconomicMap<K, V> {
+
+ /**
+ * Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
+ * mapping for {@code key}.
+ *
+ * @since 1.0
+ */
+ V get(K key);
+
+ /**
+ * Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
+ * contains no mapping for {@code key}.
+ *
+ * @since 1.0
+ */
+ default V get(K key, V defaultValue) {
+ V v = get(key);
+ if (v == null) {
+ return defaultValue;
+ }
+ return v;
+ }
+
+ /**
+ * Returns {@code true} if this map contains a mapping for {@code key}.
+ *
+ * @since 1.0
+ */
+ boolean containsKey(K key);
+
+ /**
+ * Returns the number of key-value mappings in this map.
+ *
+ * @since 1.0
+ */
+ int size();
+
+ /**
+ * Returns {@code true} if this map contains no key-value mappings.
+ *
+ * @since 1.0
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns a {@link Iterable} view of the values contained in this map.
+ *
+ * @since 1.0
+ */
+ Iterable<V> getValues();
+
+ /**
+ * Returns a {@link Iterable} view of the keys contained in this map.
+ *
+ * @since 1.0
+ */
+ Iterable<K> getKeys();
+
+ /**
+ * Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map.
+ *
+ * @since 1.0
+ */
+ UnmodifiableMapCursor<K, V> getEntries();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+/**
+ * Unmodifiable memory efficient set data structure.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
+
+ /**
+ * Returns {@code true} if this set contains a mapping for the {@code element}.
+ *
+ * @since 1.0
+ */
+ boolean contains(E element);
+
+ /**
+ * Returns the number of elements in this set.
+ *
+ * @since 1.0
+ */
+ int size();
+
+ /**
+ * Returns {@code true} if this set contains no elements.
+ *
+ * @since 1.0
+ */
+ boolean isEmpty();
+
+ /**
+ * Stores all of the elements in this set into {@code target}. An
+ * {@link UnsupportedOperationException} will be thrown if the length of {@code target} does not
+ * match the size of this set.
+ *
+ * @return an array containing all the elements in this set.
+ * @throws UnsupportedOperationException if the length of {@code target} does not equal the size
+ * of this set.
+ * @since 1.0
+ */
+ default E[] toArray(E[] target) {
+ if (target.length != size()) {
+ throw new UnsupportedOperationException("Length of target array must equal the size of the set.");
+ }
+
+ int index = 0;
+ for (E element : this) {
+ target[index++] = element;
+ }
+
+ return target;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 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. 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.graalvm.collections;
+
+/**
+ * Cursor to iterate over a map without changing its contents.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableMapCursor<K, V> {
+ /**
+ * Advances to the next entry.
+ *
+ * @return {@code true} if a next entry exists, {@code false} if there is no next entry.
+ * @since 1.0
+ */
+ boolean advance();
+
+ /**
+ * The key of the current entry.
+ *
+ * @since 1.0
+ */
+ K getKey();
+
+ /**
+ * The value of the current entry.
+ *
+ * @since 1.0
+ */
+ V getValue();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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. 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.
+ */
+/**
+ * The Graal-SDK collections package contains memory efficient data structures.
+ *
+ * @see org.graalvm.collections.EconomicMap
+ * @see org.graalvm.collections.EconomicSet
+ *
+ * @since 1.0
+ */
+package org.graalvm.collections;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -50,6 +50,21 @@
test("branchProbabilitySnippet", 5);
}
+ public static int branchProbabilitySnippet2(int arg) {
+ if (!GraalDirectives.injectBranchProbability(0.125, arg <= 0)) {
+ GraalDirectives.controlFlowAnchor(); // prevent removal of the if
+ return 2;
+ } else {
+ GraalDirectives.controlFlowAnchor(); // prevent removal of the if
+ return 1;
+ }
+ }
+
+ @Test
+ public void testBranchProbability2() {
+ test("branchProbabilitySnippet2", 5);
+ }
+
@Override
protected boolean checkLowTierGraph(StructuredGraph graph) {
NodeIterable<IfNode> ifNodes = graph.getNodes(IfNode.TYPE);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java Sat Feb 10 09:25:35 2018 +0100
@@ -50,6 +50,13 @@
}
/**
+ * Directive for the compiler to fall back to the bytecode interpreter at this point, invalidate
+ * the compiled code, record a speculation and reprofile the method.
+ */
+ public static void deoptimizeAndInvalidateWithSpeculation() {
+ }
+
+ /**
* Returns a boolean value indicating whether the method is executed in Graal-compiled code.
*/
public static boolean inCompiledCode() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/MethodSubstitution.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,15 +26,52 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Array;
import jdk.vm.ci.meta.Signature;
/**
* Denotes a method whose body is used by a compiler as the substitute (or intrinsification) of
- * another method. The exact method used to do the substitution is compiler dependent but every
+ * another method. The exact mechanism used to do the substitution is compiler dependent but every
* compiler should require substitute methods to be annotated with {@link MethodSubstitution}. In
* addition, a compiler is recommended to implement {@link MethodSubstitutionRegistry} to advertise
* the mechanism by which it supports registration of method substitutes.
+ *
+ * A compiler may support partial intrinsification where only a part of a method is implemented by
+ * the compiler. The unsupported path is expressed by a call to either the original or substitute
+ * method from within the substitute method. Such as call is a <i>partial intrinsic exit</i>.
+ *
+ * For example, here's a HotSpot specific intrinsic for {@link Array#newInstance(Class, int)} that
+ * only handles the case where the VM representation of the array class to be instantiated already
+ * exists:
+ *
+ * <pre>
+ * @MethodSubstitution
+ * public static Object newInstance(Class<?> componentType, int length) {
+ * if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
+ * // Array class not yet created - exit the intrinsic and call the original method
+ * return newInstance(componentType, length);
+ * }
+ * return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length, JavaKind.Object);
+ * }
+ * </pre>
+ *
+ * Here's the same intrinsification where the exit is expressed as a call to the original method:
+ *
+ * <pre>
+ * @MethodSubstitution
+ * public static Object newInstance(Class<?> componentType, int length) {
+ * if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
+ * // Array class not yet created - exit the intrinsic and call the original method
+ * return java.lang.reflect.newInstance(componentType, length);
+ * }
+ * return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length, JavaKind.Object);
+ * }
+ * </pre>
+ *
+ * A condition for a partial intrinsic exit is that it is uses the unmodified parameters of the
+ * substitute as arguments to the partial intrinsic exit call. There must also be no side effecting
+ * instruction between the start of the substitute method and the partial intrinsic exit.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -90,4 +90,12 @@
* if this provider cannot provide a value of the requested type
*/
<T> T getInjectedNodeIntrinsicParameter(Class<T> type);
+
+ /**
+ * Get the original Java class corresponding to a {@link ResolvedJavaType}.
+ *
+ * @param type the type for which the original Java class is requested
+ * @return the original Java class corresponding to the {@code type} parameter
+ */
+ Class<?> originalClass(ResolvedJavaType type);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.runtime/src/org/graalvm/compiler/api/runtime/GraalRuntime.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,9 +22,19 @@
*/
package org.graalvm.compiler.api.runtime;
+import jdk.vm.ci.common.JVMCIError;
+
public interface GraalRuntime {
String getName();
<T> T getCapability(Class<T> clazz);
+
+ default <T> T getRequiredCapability(Class<T> clazz) {
+ T ret = getCapability(clazz);
+ if (ret == null) {
+ throw new JVMCIError("The VM does not expose the required Graal capability %s.", clazz.getName());
+ }
+ return ret;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Sat Feb 10 09:25:35 2018 +0100
@@ -208,7 +208,6 @@
}
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;
@@ -861,9 +860,26 @@
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;
- 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;
@@ -881,20 +897,6 @@
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:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
- }
int encode;
if (noNds) {
encode = asm.simdPrefixAndEncode(dst, Register.None, src, pre, opc, attributes);
@@ -938,9 +940,26 @@
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;
- 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;
@@ -958,20 +977,6 @@
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:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
- }
if (noNds) {
asm.simdPrefix(dst, Register.None, src, pre, opc, attributes);
} else {
@@ -1055,8 +1060,7 @@
opc = VexOpcode.VEX_OPCODE_0F_3A;
break;
default:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
+ throw GraalError.shouldNotReachHere("invalid VEX instruction prefix");
}
int encode;
encode = asm.simdPrefixAndEncode(dst, nds, src, pre, opc, attributes);
@@ -1096,8 +1100,7 @@
opc = VexOpcode.VEX_OPCODE_0F_3A;
break;
default:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
+ throw GraalError.shouldNotReachHere("invalid VEX instruction prefix");
}
asm.simdPrefix(dst, nds, src, pre, opc, attributes);
asm.emitByte(op);
@@ -1163,9 +1166,26 @@
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;
- 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;
@@ -1183,20 +1203,6 @@
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:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
- }
int encode;
if (noNds) {
encode = asm.simdPrefixAndEncode(src, Register.None, dst, pre, opc, attributes);
@@ -1222,9 +1228,26 @@
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;
- 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;
@@ -1242,20 +1265,6 @@
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:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
- }
asm.simdPrefix(src, Register.None, dst, pre, opc, attributes);
asm.emitByte(op);
asm.emitOperandHelper(src, dst, 0);
@@ -1390,9 +1399,26 @@
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;
- int opc;
AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
int curPrefix = size.sizePrefix | prefix1;
switch (curPrefix) {
@@ -1409,20 +1435,6 @@
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:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
- }
int encode;
if (noNds) {
encode = asm.simdPrefixAndEncode(dst, Register.None, src, pre, opc, attributes);
@@ -1453,9 +1465,26 @@
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;
- int opc;
AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, asm.target);
int curPrefix = size.sizePrefix | prefix1;
switch (curPrefix) {
@@ -1472,21 +1501,6 @@
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:
- opc = VexOpcode.VEX_OPCODE_NONE;
- break;
- }
-
if (noNds) {
asm.simdPrefix(dst, Register.None, src, pre, opc, attributes);
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Sat Feb 10 09:25:35 2018 +0100
@@ -33,9 +33,9 @@
import java.util.List;
import java.util.Objects;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.graph.NodeSourcePosition;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.StackSlot;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java Sat Feb 10 09:25:35 2018 +0100
@@ -40,7 +40,7 @@
public interface Patches {
- void registerPatch(VMConstant c);
+ void registerPatch(int position, VMConstant c);
}
public abstract static class Data {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,7 +27,6 @@
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
-import org.graalvm.compiler.core.common.type.PrimitiveStamp;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -107,7 +106,9 @@
ret.setBase(add.getX());
ret.setIndex(considerNegation(graph, add.getY(), isBaseNegated));
return true;
- } else if (ret.getBase() == null && ret.getIndex() instanceof AddNode) {
+ }
+
+ if (ret.getBase() == null && ret.getIndex() instanceof AddNode) {
AddNode add = (AddNode) ret.getIndex();
ret.setBase(considerNegation(graph, add.getX(), isIndexNegated));
ret.setIndex(add.getY());
@@ -188,7 +189,7 @@
return improveConstDisp(address, node, c, null, shift, negateExtractedDisplacement);
} else {
if (node.stamp(NodeView.DEFAULT) instanceof IntegerStamp) {
- assert PrimitiveStamp.getBits(node.stamp(NodeView.DEFAULT)) == ADDRESS_BITS;
+ assert IntegerStamp.getBits(node.stamp(NodeView.DEFAULT)) == ADDRESS_BITS;
/*
* we can't swallow zero-extends because of multiple reasons:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64CompressAddressLowering.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.graalvm.compiler.core.amd64;
+
+import jdk.vm.ci.code.Register;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.CounterKey;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.CompressionNode;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.FloatingNode;
+import org.graalvm.compiler.nodes.spi.LIRLowerable;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
+
+public abstract class AMD64CompressAddressLowering extends AMD64AddressLowering {
+ private static final CounterKey counterFoldedUncompressDuringAddressLowering = DebugContext.counter("FoldedUncompressDuringAddressLowering");
+
+ @Override
+ protected final boolean improve(StructuredGraph graph, DebugContext debug, AMD64AddressNode addr, boolean isBaseNegated, boolean isIndexNegated) {
+ if (super.improve(graph, debug, addr, isBaseNegated, isIndexNegated)) {
+ return true;
+ }
+
+ if (!isBaseNegated && !isIndexNegated && addr.getScale() == AMD64Address.Scale.Times1) {
+ ValueNode base = addr.getBase();
+ ValueNode index = addr.getIndex();
+
+ if (tryToImproveUncompression(addr, index, base) || tryToImproveUncompression(addr, base, index)) {
+ counterFoldedUncompressDuringAddressLowering.increment(debug);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean tryToImproveUncompression(AMD64AddressNode addr, ValueNode value, ValueNode other) {
+ if (value instanceof CompressionNode) {
+ CompressionNode compression = (CompressionNode) value;
+ if (compression.getOp() == CompressionNode.CompressionOp.Uncompress && improveUncompression(addr, compression, other)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected abstract boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other);
+
+ @NodeInfo(cycles = CYCLES_0, size = SIZE_0)
+ public static class HeapBaseNode extends FloatingNode implements LIRLowerable {
+
+ public static final NodeClass<HeapBaseNode> TYPE = NodeClass.create(HeapBaseNode.class);
+
+ private final Register heapBaseRegister;
+
+ public HeapBaseNode(Register heapBaseRegister) {
+ super(TYPE, StampFactory.pointer());
+ this.heapBaseRegister = heapBaseRegister;
+ }
+
+ @Override
+ public void generate(NodeLIRBuilderTool generator) {
+ LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT));
+ generator.setResult(this, heapBaseRegister.asValue(kind));
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,14 +26,14 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.lir.VirtualStackSlot;
import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64PushPopStackMove;
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Architecture;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Sat Feb 10 09:25:35 2018 +0100
@@ -44,6 +44,7 @@
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.gen.NodeLIRBuilder;
import org.graalvm.compiler.core.gen.NodeMatchRules;
@@ -128,7 +129,7 @@
}
protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) {
- Condition cond = compare.condition();
+ Condition cond = compare.condition().asCondition();
AMD64Kind kind = getMemoryKind(access);
boolean matchedAsConstant = false; // For assertion checking
@@ -303,7 +304,7 @@
@MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))")
@MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))")
public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) {
- assert compare.condition() == Condition.EQ;
+ assert compare.condition() == CanonicalCondition.EQ;
if (value == cas.getExpectedValue() && cas.usages().count() == 1) {
return builder -> {
LIRKind kind = getLirKind(cas);
@@ -326,7 +327,7 @@
@MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))")
public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) {
JavaConstant constant = value.asJavaConstant();
- assert compare.condition() == Condition.EQ;
+ assert compare.condition() == CanonicalCondition.EQ;
if (constant != null && cas.usages().count() == 1) {
long constantValue = constant.asLong();
boolean successIsTrue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Sat Feb 10 09:25:35 2018 +0100
@@ -233,6 +233,9 @@
public static final OptionKey<Boolean> OptScheduleOutOfLoops = new OptionKey<>(true);
@Option(help = "", type = OptionType.Debug)
+ public static final OptionKey<Boolean> GuardPriorities = new OptionKey<>(true);
+
+ @Option(help = "", type = OptionType.Debug)
public static final OptionKey<Boolean> OptEliminateGuards = new OptionKey<>(true);
@Option(help = "", type = OptionType.Debug)
@@ -271,4 +274,7 @@
@Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug)
public static final OptionKey<Boolean> TraceRA = new OptionKey<>(false);
+ @Option(help = "How to trace inlining decisions, one of: None, Linear, Tree", type = OptionType.Debug)
+ public static final OptionKey<TraceInliningMode> TraceInlining = new OptionKey<>(TraceInliningMode.None);
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * 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.core.common;
+
+public enum TraceInliningMode {
+ None(false),
+ Linear(true),
+ Tree(true);
+
+ private final boolean tracing;
+
+ TraceInliningMode(boolean tracing) {
+ this.tracing = tracing;
+ }
+
+ public boolean isTracing() {
+ return tracing;
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,9 +22,9 @@
*/
package org.graalvm.compiler.core.common.alloc;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/CanonicalCondition.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009, 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.core.common.calc;
+
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.PrimitiveConstant;
+
+public enum CanonicalCondition {
+ EQ(Condition.EQ),
+ LT(Condition.LT),
+ BT(Condition.BT);
+
+ private final Condition condition;
+
+ CanonicalCondition(Condition condition) {
+ assert condition.isCanonical();
+ this.condition = condition;
+ }
+
+ public Condition asCondition() {
+ return condition;
+ }
+
+ public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
+ return asCondition().foldCondition(lt, rt, constantReflection, unorderedIsTrue);
+ }
+
+ public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) {
+ return asCondition().foldCondition(lp, rp, unorderedIsTrue);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java Sat Feb 10 09:25:35 2018 +0100
@@ -115,6 +115,55 @@
throw new IllegalArgumentException(this.toString());
}
+ public static final class CanonicalizedCondition {
+ private final CanonicalCondition canonicalCondition;
+ private final boolean mirror;
+ private final boolean negate;
+
+ private CanonicalizedCondition(CanonicalCondition canonicalCondition, boolean mirror, boolean negate) {
+ this.canonicalCondition = canonicalCondition;
+ this.mirror = mirror;
+ this.negate = negate;
+ }
+
+ public CanonicalCondition getCanonicalCondition() {
+ return canonicalCondition;
+ }
+
+ public boolean mustMirror() {
+ return mirror;
+ }
+
+ public boolean mustNegate() {
+ return negate;
+ }
+ }
+
+ public CanonicalizedCondition canonicalize() {
+ CanonicalCondition canonicalCondition;
+ switch (this) {
+ case EQ:
+ case NE:
+ canonicalCondition = CanonicalCondition.EQ;
+ break;
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ canonicalCondition = CanonicalCondition.LT;
+ break;
+ case BT:
+ case BE:
+ case AT:
+ case AE:
+ canonicalCondition = CanonicalCondition.BT;
+ break;
+ default:
+ throw new IllegalArgumentException(this.toString());
+ }
+ return new CanonicalizedCondition(canonicalCondition, canonicalMirror(), canonicalNegate());
+ }
+
/**
* Given a condition and its negation, this method returns true for one of the two and false for
* the other one. This can be used to keep comparisons in a canonical form.
@@ -151,7 +200,7 @@
* Returns true if the condition needs to be mirrored to get to a canonical condition. The
* result of the mirroring operation might still need to be negated to achieve a canonical form.
*/
- public boolean canonicalMirror() {
+ private boolean canonicalMirror() {
switch (this) {
case EQ:
return false;
@@ -181,7 +230,7 @@
* Returns true if the condition needs to be negated to get to a canonical condition. The result
* of the negation might still need to be mirrored to achieve a canonical form.
*/
- public boolean canonicalNegate() {
+ private boolean canonicalNegate() {
switch (this) {
case EQ:
return false;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ArrayOffsetProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,32 @@
+/*
+ * 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.common.spi;
+
+import jdk.vm.ci.meta.JavaKind;
+
+public interface ArrayOffsetProvider {
+
+ int arrayBaseOffset(JavaKind elementKind);
+
+ int arrayScalingFactor(JavaKind elementKind);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/CodeGenProviders.java Sat Feb 10 09:25:35 2018 +0100
@@ -40,4 +40,5 @@
ConstantReflectionProvider getConstantReflection();
+ ArrayOffsetProvider getArrayOffsetProvider();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,9 @@
import java.util.Objects;
import java.util.function.Function;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaKind;
+
import org.graalvm.compiler.core.common.calc.FloatConvert;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And;
@@ -51,9 +54,6 @@
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt;
import org.graalvm.util.CollectionsUtil;
-import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.JavaKind;
-
/**
* Information about arithmetic operations.
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,8 +25,8 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
/**
* Creates an array of T objects order by the occurrence frequency of each object. The most
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Sat Feb 10 09:25:35 2018 +0100
@@ -58,6 +58,9 @@
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.gen.NodeMatchRules;
import org.graalvm.compiler.core.match.ComplexMatchResult;
import org.graalvm.compiler.core.match.MatchRule;
@@ -70,9 +73,6 @@
import org.graalvm.compiler.graph.Position;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
/**
* Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * 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
- * 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.sparc.test;
-
-import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure;
-import static org.graalvm.compiler.core.common.GraalOptions.TraceRA;
-import static org.junit.Assume.assumeTrue;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import org.graalvm.compiler.core.test.backend.AllocatorTest;
-
-import jdk.vm.ci.sparc.SPARC;
-
-public class SPARCAllocatorTest extends AllocatorTest {
-
- @Before
- public void checkSPARC() {
- assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC);
- assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null);
- assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions()));
- }
-
- @Test
- public void test1() {
- testAllocation("test1snippet", 2, 0, 0);
- }
-
- public static long test1snippet(long x) {
- return x + 41;
- }
-
- @Test
- public void test2() {
- testAllocation("test2snippet", 2, 0, 0);
- }
-
- public static long test2snippet(long x) {
- return x * 41;
- }
-
- @Test
- public void test3() {
- testAllocation("test3snippet", 4, 0, 0);
- }
-
- public static long test3snippet(long x) {
- return x / 41 + x % 41;
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,6 +29,7 @@
import static jdk.vm.ci.sparc.SPARCKind.XWORD;
import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.gen.NodeMatchRules;
import org.graalvm.compiler.core.match.ComplexMatchResult;
@@ -147,7 +148,7 @@
@MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))")
public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) {
JavaConstant constant = value.asJavaConstant();
- assert compare.condition() == Condition.EQ;
+ assert compare.condition() == CanonicalCondition.EQ;
if (constant != null && cas.usages().count() == 1) {
long constantValue = constant.asLong();
boolean successIsTrue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java Sat Feb 10 09:25:35 2018 +0100
@@ -123,19 +123,19 @@
public static int test6Snippet(int a) {
if ((a & 8) != 0) {
- GraalDirectives.deoptimizeAndInvalidate();
+ GraalDirectives.deoptimize();
}
if ((a & 15) != 15) {
- GraalDirectives.deoptimizeAndInvalidate();
+ GraalDirectives.deoptimize();
}
return 0;
}
public static int reference6Snippet(int a) {
if ((a & 8) != 0) {
- GraalDirectives.deoptimizeAndInvalidate();
+ GraalDirectives.deoptimize();
}
- GraalDirectives.deoptimizeAndInvalidate();
+ GraalDirectives.deoptimize();
return 0;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Sat Feb 10 09:25:35 2018 +0100
@@ -74,7 +74,6 @@
new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context);
canonicalizer.apply(graph, context);
canonicalizer.apply(graph, context);
- new ConvertDeoptimizeToGuardPhase().apply(graph, context);
} catch (Throwable t) {
debug.handle(t);
}
@@ -86,7 +85,6 @@
}
canonicalizer.apply(referenceGraph, context);
canonicalizer.apply(referenceGraph, context);
- new ConvertDeoptimizeToGuardPhase().apply(graph, context);
} catch (Throwable t) {
debug.handle(t);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,14 +25,12 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
-import org.graalvm.compiler.nodes.NodeView;
-import org.junit.Test;
-
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.loop.InductionVariable;
import org.graalvm.compiler.loop.LoopsData;
import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
@@ -42,6 +40,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.junit.Test;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -117,6 +116,21 @@
test("incrementSnippet", 0, 256, 3);
}
+ @Test
+ public void increment4() {
+ test("incrementSnippet", -10, Integer.MAX_VALUE, 1);
+ }
+
+ @Test
+ public void increment5() {
+ test("incrementSnippet", 256, 256, 1);
+ }
+
+ @Test
+ public void increment6() {
+ test("incrementSnippet", 257, 256, 1);
+ }
+
public static Result incrementEqSnippet(int start, int limit, int step) {
int i;
int inc = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive
@@ -144,6 +158,21 @@
test("incrementEqSnippet", 0, 256, 3);
}
+ @Test
+ public void incrementEq4() {
+ test("incrementEqSnippet", -10, 0, Integer.MAX_VALUE);
+ }
+
+ @Test
+ public void incrementEq5() {
+ test("incrementEqSnippet", 256, 256, 1);
+ }
+
+ @Test
+ public void incrementEq6() {
+ test("incrementEqSnippet", 257, 256, 1);
+ }
+
public static Result decrementSnippet(int start, int limit, int step) {
int i;
int dec = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive
@@ -198,6 +227,11 @@
test("decrementEqSnippet", 256, 0, 3);
}
+ @Test
+ public void decrementEq4() {
+ test("decrementEqSnippet", -10, 0, Integer.MAX_VALUE);
+ }
+
public static Result twoVariablesSnippet() {
Result ret = new Result();
int j = 0;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,10 +27,10 @@
import java.nio.file.Files;
import java.nio.file.Path;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
import org.junit.Test;
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -561,7 +561,7 @@
* @return a scheduled textual dump of {@code graph} .
*/
protected static String getScheduledGraphString(StructuredGraph graph) {
- SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
+ SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
schedule.apply(graph);
ScheduleResult scheduleResult = graph.getLastSchedule();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,14 +22,14 @@
*/
package org.graalvm.compiler.core.test;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.DebugContext.Scope;
import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.debug.DebugContext.Scope;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
import org.junit.Assert;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,20 +24,29 @@
import java.util.List;
-import org.junit.Assert;
-
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeMap;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
+import org.junit.Assert;
+
+import jdk.vm.ci.meta.SpeculationLog;
public class GraphScheduleTest extends GraalCompilerTest {
protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) {
- SchedulePhase ibp = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST);
+ assertOrderedAfterSchedule(graph, SchedulePhase.SchedulingStrategy.LATEST, a, b);
+ }
+
+ protected void assertOrderedAfterSchedule(StructuredGraph graph, SchedulePhase.SchedulingStrategy strategy, Node a, Node b) {
+ SchedulePhase ibp = new SchedulePhase(strategy);
ibp.apply(graph);
+ assertOrderedAfterLastSchedule(graph, a, b);
+ }
+
+ protected void assertOrderedAfterLastSchedule(StructuredGraph graph, Node a, Node b) {
assertOrderedAfterSchedule(graph.getLastSchedule(), a, b);
}
@@ -48,7 +57,7 @@
if (bBlock == aBlock) {
List<Node> instructions = ibp.nodesFor(bBlock);
- Assert.assertTrue(instructions.indexOf(b) > instructions.indexOf(a));
+ Assert.assertTrue(a + " should be before " + b, instructions.indexOf(b) > instructions.indexOf(a));
} else {
Block block = bBlock;
while (block != null) {
@@ -60,4 +69,9 @@
Assert.fail("block of A doesn't dominate the block of B");
}
}
+
+ @Override
+ protected SpeculationLog getSpeculationLog() {
+ return getCodeCache().createSpeculationLog();
+ }
}
--- /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/GuardPrioritiesTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.test;
+
+import static org.graalvm.compiler.graph.test.matchers.NodeIterableCount.hasCount;
+import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isNotEmpty;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeThat;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.Iterator;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.graph.iterators.NodeIterable;
+import org.graalvm.compiler.nodes.GuardNode;
+import org.graalvm.compiler.nodes.ParameterNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.calc.IntegerLowerThanNode;
+import org.graalvm.compiler.nodes.calc.IsNullNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
+import org.graalvm.compiler.phases.common.FloatingReadPhase;
+import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Test;
+
+public class GuardPrioritiesTest extends GraphScheduleTest {
+ private int[] array;
+ private int size;
+
+ public void growing(int e) {
+ if (size >= array.length) {
+ // grow
+ GraalDirectives.deoptimizeAndInvalidateWithSpeculation();
+ }
+ array[size++] = e;
+ }
+
+ @Test
+ public void growingTest() {
+ assumeTrue("GuardPriorities must be turned one", GraalOptions.GuardPriorities.getValue(getInitialOptions()));
+ StructuredGraph graph = prepareGraph("growing");
+
+ NodeIterable<GuardNode> guards = graph.getNodes(GuardNode.TYPE).filter(n -> n.inputs().filter(i -> i instanceof IntegerLowerThanNode).isNotEmpty());
+ assertThat(guards, isNotEmpty());
+ assumeThat(guards, hasCount(2));
+
+ Iterator<GuardNode> iterator = guards.iterator();
+ GuardNode g1 = iterator.next();
+ GuardNode g2 = iterator.next();
+ assertTrue("There should be one guard with speculation, the other one without", g1.getSpeculation().isNull() ^ g2.getSpeculation().isNull());
+ GuardNode withSpeculation = g1.getSpeculation().isNull() ? g2 : g1;
+ GuardNode withoutSpeculation = g1.getSpeculation().isNull() ? g1 : g2;
+
+ assertOrderedAfterSchedule(graph, SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, withSpeculation, withoutSpeculation);
+ }
+
+ private StructuredGraph prepareGraph(String method) {
+ StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES);
+ HighTierContext highTierContext = getDefaultHighTierContext();
+ CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+ new ConvertDeoptimizeToGuardPhase().apply(graph, highTierContext);
+ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
+ new FloatingReadPhase().apply(graph);
+ return graph;
+ }
+
+ public int unknownCondition(Integer c, Object o, int[] a, Integer i) {
+ if (o != null) {
+ GraalDirectives.deoptimizeAndInvalidate();
+ }
+ if (i > 5560) {
+ GraalDirectives.deoptimizeAndInvalidate();
+ }
+ if (c >= 10) {
+ GraalDirectives.deoptimizeAndInvalidateWithSpeculation();
+ }
+ return array[8] + a[i];
+ }
+
+ @Test
+ public void unknownTest() {
+ assumeTrue("GuardPriorities must be turned one", GraalOptions.GuardPriorities.getValue(getInitialOptions()));
+ StructuredGraph graph = prepareGraph("unknownCondition");
+
+ new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER).apply(graph);
+ for (GuardNode g1 : graph.getNodes(GuardNode.TYPE)) {
+ for (GuardNode g2 : graph.getNodes(GuardNode.TYPE)) {
+ if (g1.getSpeculation().isNull() ^ g2.getSpeculation().isNull()) {
+ GuardNode withSpeculation = g1.getSpeculation().isNull() ? g2 : g1;
+ GuardNode withoutSpeculation = g1.getSpeculation().isNull() ? g1 : g2;
+
+ if (withoutSpeculation.isNegated() && withoutSpeculation.getCondition() instanceof IsNullNode) {
+ IsNullNode isNullNode = (IsNullNode) withoutSpeculation.getCondition();
+ if (isNullNode.getValue() instanceof ParameterNode && ((ParameterNode) isNullNode.getValue()).index() == 1) {
+ // this is the null check before the speculative guard, it's the only
+ // one that should be above
+ assertOrderedAfterLastSchedule(graph, withoutSpeculation, withSpeculation);
+ continue;
+ }
+ }
+
+ assertOrderedAfterLastSchedule(graph, withSpeculation, withoutSpeculation);
+ }
+ }
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -44,7 +44,7 @@
public static final int N = 10000;
- private static final SchedulingStrategy[] Strategies = new SchedulingStrategy[]{SchedulingStrategy.EARLIEST};
+ private static final SchedulingStrategy[] Strategies = new SchedulingStrategy[]{SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER};
@Test
public void testLongAddChain() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,13 +31,13 @@
import java.util.Map;
import java.util.Properties;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionDescriptor;
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
/**
* An implementation of {@link OptionDescriptor} that uses reflection to create descriptors from a
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Sat Feb 10 09:25:35 2018 +0100
@@ -70,7 +70,7 @@
returnNode.replaceAtPredecessor(beginNode);
beginNode.setNext(returnNode);
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
- SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST);
+ SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
schedulePhase.apply(graph);
ScheduleResult schedule = graph.getLastSchedule();
BlockMap<List<Node>> blockToNodesMap = schedule.getBlockToNodesMap();
--- /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/TrivialInliningExplosionTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.java.BytecodeParserOptions;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.options.OptionValues;
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Tests that the defaults for {@link GraalOptions#TrivialInliningSize} and
+ * {@link BytecodeParserOptions#InlineDuringParsingMaxDepth} prevent explosive graph growth for code
+ * with small recursive methods.
+ */
+public class TrivialInliningExplosionTest extends GraalCompilerTest {
+
+ public static void trivial() {
+ trivial();
+ trivial();
+ trivial();
+ }
+
+ public static void main() {
+ trivial();
+ trivial();
+ trivial();
+ trivial();
+ trivial();
+ trivial();
+ trivial();
+ trivial();
+ trivial();
+ }
+
+ private int afterParseSize;
+
+ @Override
+ protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) {
+ final StructuredGraph graph = super.parseForCompile(method, compilationId, options);
+ this.afterParseSize = graph.getNodeCount();
+ return graph;
+ }
+
+ @Test
+ public void test() {
+ ResolvedJavaMethod methodm0 = getResolvedJavaMethod("trivial");
+ Assert.assertTrue(methodm0.getCodeSize() <= GraalOptions.TrivialInliningSize.getValue(getInitialOptions()));
+ test("main");
+ int afterCompileSize = lastCompiledGraph.getNodeCount();
+
+ // The values of afterParseSize and afterCompileSize when this
+ // test was written were 849 and 848 respectively.
+ Assert.assertTrue(afterParseSize < 2000);
+ Assert.assertTrue(afterCompileSize < 2000);
+
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.TTY;
@@ -43,7 +44,6 @@
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.graalvm.util.EconomicSet;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,7 @@
import java.util.Collection;
import java.util.List;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
import org.graalvm.compiler.core.common.GraalOptions;
@@ -64,7 +65,6 @@
import org.graalvm.compiler.phases.tiers.Suites;
import org.graalvm.compiler.phases.tiers.TargetProvider;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,8 @@
import java.util.Arrays;
import java.util.Queue;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
@@ -42,8 +44,6 @@
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.virtual.nodes.MaterializedObjectState;
import org.graalvm.compiler.virtual.nodes.VirtualObjectState;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.VirtualObject;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -33,6 +33,8 @@
import java.util.Collection;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
@@ -100,8 +102,6 @@
import org.graalvm.compiler.nodes.spi.NodeValueMap;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.UnmodifiableMapCursor;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.StackSlot;
@@ -538,7 +538,8 @@
public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind();
- gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
+ gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition().asCondition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor,
+ trueSuccessorProbability);
}
public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
@@ -566,7 +567,7 @@
} else if (node instanceof CompareNode) {
CompareNode compare = (CompareNode) node;
PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind();
- return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
+ return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition().asCondition(), compare.unorderedIsTrue(), trueValue, falseValue);
} else if (node instanceof LogicConstantNode) {
return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue);
} else if (node instanceof IntegerTestNode) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,8 @@
import java.util.Arrays;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.gen.NodeLIRBuilder;
import org.graalvm.compiler.core.match.MatchPattern.Result;
import org.graalvm.compiler.debug.DebugContext;
@@ -35,8 +37,6 @@
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
/**
* Container for state captured during a match.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,6 +27,9 @@
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.core.gen.NodeMatchRules;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
@@ -36,9 +39,6 @@
import org.graalvm.compiler.graph.Position;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
public class MatchRuleRegistry {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.core.phases;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph.NodeEvent;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
@@ -32,8 +34,6 @@
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
/**
* A utility phase for detecting when a phase would change the graph and reporting extra information
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import java.util.ArrayList;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
@@ -44,7 +45,6 @@
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.phases.tiers.TargetProvider;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.CodeCacheProvider;
@@ -204,31 +204,48 @@
}
try (DebugContext.Scope s2 = debug.scope("CodeInstall", debugContext);
DebugContext.Activation a = debug.activate()) {
- for (CodeInstallationTask task : tasks) {
- task.preProcess(compilationResult);
+ preCodeInstallationTasks(tasks, compilationResult);
+
+ InstalledCode installedCode;
+ try {
+ CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult);
+ installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
+ } catch (Throwable t) {
+ failCodeInstallationTasks(tasks, t);
+ throw t;
}
- CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult);
- InstalledCode installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
+ postCodeInstallationTasks(tasks, installedCode);
- // Run post-code installation tasks.
- try {
- for (CodeInstallationTask task : tasks) {
- task.postProcess(installedCode);
- }
- for (CodeInstallationTask task : tasks) {
- task.releaseInstallation(installedCode);
- }
- } catch (Throwable t) {
- installedCode.invalidate();
- throw t;
- }
return installedCode;
} catch (Throwable e) {
throw debug.handle(e);
}
}
+ private static void failCodeInstallationTasks(CodeInstallationTask[] tasks, Throwable t) {
+ for (CodeInstallationTask task : tasks) {
+ task.installFailed(t);
+ }
+ }
+
+ private static void preCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult) {
+ for (CodeInstallationTask task : tasks) {
+ task.preProcess(compilationResult);
+ }
+ }
+
+ private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, InstalledCode installedCode) {
+ try {
+ for (CodeInstallationTask task : tasks) {
+ task.postProcess(installedCode);
+ }
+ } catch (Throwable t) {
+ installedCode.invalidate();
+ throw t;
+ }
+ }
+
/**
* Installs code based on a given compilation result.
*
@@ -301,11 +318,10 @@
}
/**
- * Task to run after all the post-code installation tasks are complete, used to release the
- * installed code.
+ * Invoked after {@link #preProcess} when code installation fails.
*/
@SuppressWarnings("unused")
- public void releaseInstallation(InstalledCode installedCode) {
+ public void installFailed(Throwable t) {
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,7 @@
import java.util.Formatter;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.Assertions;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
@@ -46,7 +47,6 @@
import org.graalvm.compiler.debug.DebugVerifyHandler;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
import java.lang.management.ThreadMXBean;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugOptions;
@@ -37,7 +38,6 @@
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.debug;
-import org.graalvm.util.Pair;
+import org.graalvm.collections.Pair;
class CounterKeyImpl extends AbstractKey implements CounterKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Sat Feb 10 09:25:35 2018 +0100
@@ -56,12 +56,12 @@
import java.util.SortedMap;
import java.util.TreeMap;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Pair;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.graphio.GraphOutput;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Pair;
import jdk.vm.ci.meta.JavaMethod;
@@ -1937,10 +1937,17 @@
if (description != null) {
printMetrics(description);
}
- if (metricsEnabled && globalMetrics != null && metricValues != null) {
+ if (metricsEnabled && metricValues != null && globalMetrics != null) {
globalMetrics.add(this);
}
metricValues = null;
+ if (sharedChannel != null) {
+ try {
+ sharedChannel.realClose();
+ } catch (IOException ex) {
+ // ignore.
+ }
+ }
}
public void closeDumpHandlers(boolean ignoreErrors) {
@@ -2022,7 +2029,6 @@
}
}
}
-
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,11 +27,11 @@
import java.nio.file.Path;
import java.nio.file.Paths;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
/**
* Options that configure a {@link DebugContext} and related functionality.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,10 +29,10 @@
import java.util.Collections;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.MapCursor;
+import org.graalvm.collections.Pair;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
-import org.graalvm.util.Pair;
/**
* Metric values that can be {@linkplain #add(DebugContext) updated} by multiple threads.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,7 +25,7 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.util.EconomicMap;
+import org.graalvm.collections.EconomicMap;
/**
* Registry for allocating a globally unique integer id to each {@link AbstractKey}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE;
-import org.graalvm.util.Pair;
+import org.graalvm.collections.Pair;
class MemUseTrackerKeyImpl extends AccumulatedKey implements MemUseTrackerKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import java.util.Comparator;
-import org.graalvm.util.Pair;
+import org.graalvm.collections.Pair;
/**
* A key for a metric.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,7 +26,7 @@
import java.util.concurrent.TimeUnit;
-import org.graalvm.util.Pair;
+import org.graalvm.collections.Pair;
final class TimerKeyImpl extends AccumulatedKey implements TimerKey {
static class FlatTimer extends AbstractKey implements TimerKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import java.util.function.Consumer;
-import org.graalvm.util.UnmodifiableEconomicMap;
+import org.graalvm.collections.UnmodifiableEconomicMap;
/**
* This class is a container of a graph that needs to be readonly and optionally a lazily created
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,9 @@
import java.util.Iterator;
import java.util.function.Consumer;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
@@ -41,9 +44,6 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
/**
* This class is a graph container, it contains the set of nodes that belong to this graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java Sat Feb 10 09:25:35 2018 +0100
@@ -160,6 +160,12 @@
}
}
+ public void invert() {
+ for (int i = 0; i < bits.length; i++) {
+ bits[i] = ~bits[i];
+ }
+ }
+
public void grow() {
nodeCount = Math.max(nodeCount, graph().nodeIdCount());
int newLength = sizeForNodeCount(nodeCount);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Sat Feb 10 09:25:35 2018 +0100
@@ -42,6 +42,8 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.FieldIntrospection;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.FieldsScanner;
@@ -65,8 +67,6 @@
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.NodeSize;
import org.graalvm.compiler.nodeinfo.Verbosity;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
/**
* Metadata for every {@link Node} type. The metadata includes:
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,8 @@
import java.util.Iterator;
import java.util.function.BiFunction;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.MapCursor;
public class NodeMap<T> extends NodeIdAccessor implements EconomicMap<Node, T> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java Sat Feb 10 09:25:35 2018 +0100
@@ -74,6 +74,10 @@
return tos == 0;
}
+ public void clear() {
+ tos = 0;
+ }
+
@Override
public String toString() {
if (tos == 0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.hotspot.aarch64;
-import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
import static java.lang.reflect.Modifier.isStatic;
import static jdk.vm.ci.aarch64.AArch64.lr;
import static jdk.vm.ci.aarch64.AArch64.r10;
@@ -30,7 +29,9 @@
import static jdk.vm.ci.aarch64.AArch64.zr;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp;
+import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.aarch64.AArch64Address;
@@ -42,11 +43,11 @@
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.stubs.Stub;
@@ -64,7 +65,6 @@
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Sat Feb 10 09:25:35 2018 +0100
@@ -49,6 +49,7 @@
import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
@@ -136,7 +137,7 @@
replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider);
}
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
- plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider);
+ plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, lowerer, metaAccess, snippetReflection, replacements, wordTypes, stampProvider);
replacements.setGraphBuilderPlugins(plugins);
}
try (InitTimer rt = timer("create Suites provider")) {
@@ -152,9 +153,10 @@
}
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection,
- HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements,
- HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) {
- Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements);
+ HotSpotHostForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection,
+ HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) {
+ Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider,
+ replacements);
AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider());
return plugins;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/ArrayAccessInLoopToAddressTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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.amd64.test;
+
+import jdk.vm.ci.hotspot.HotSpotSpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.junit.Test;
+
+public class ArrayAccessInLoopToAddressTest extends GraalCompilerTest {
+
+ public static int positiveInductionVariable(short[] array) {
+ int sum = 0;
+ for (int i = 0; i < array.length - 1; i++) {
+ sum += array[i + 1];
+ }
+ return sum;
+ }
+
+ @Test
+ public void testPositiveInductionVariable() {
+ test("positiveInductionVariable", new short[]{1, 3, 7, 9});
+ }
+
+ public static int negativeInductionVariable(short[] array) {
+ int sum = 0;
+ for (int i = -array.length; i < array.length - 4; i++) {
+ sum += array[i + 4];
+ }
+ return sum;
+ }
+
+ @Test
+ public void testNegativeInductionVariable() {
+ test("negativeInductionVariable", new short[]{1, 3, 7, 9});
+ }
+
+ @Override
+ protected SpeculationLog getSpeculationLog() {
+ return new HotSpotSpeculationLog();
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,64 +24,50 @@
package org.graalvm.compiler.hotspot.amd64;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
-import org.graalvm.compiler.core.amd64.AMD64AddressLowering;
import org.graalvm.compiler.core.amd64.AMD64AddressNode;
+import org.graalvm.compiler.core.amd64.AMD64CompressAddressLowering;
import org.graalvm.compiler.core.common.CompressEncoding;
-import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
-import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.debug.CounterKey;
-import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.loop.BasicInductionVariable;
+import org.graalvm.compiler.loop.CountedLoopInfo;
+import org.graalvm.compiler.loop.DerivedInductionVariable;
+import org.graalvm.compiler.loop.InductionVariable;
+import org.graalvm.compiler.loop.LoopEx;
+import org.graalvm.compiler.loop.LoopsData;
import org.graalvm.compiler.nodes.CompressionNode;
-import org.graalvm.compiler.nodes.CompressionNode.CompressionOp;
+import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.calc.FloatingNode;
-import org.graalvm.compiler.nodes.spi.LIRLowerable;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.nodes.calc.AddNode;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.JavaKind;
-public class AMD64HotSpotAddressLowering extends AMD64AddressLowering {
+public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering {
- private static final CounterKey counterFoldedUncompressDuringAddressLowering = DebugContext.counter("FoldedUncompressDuringAddressLowering");
+ private static final int ADDRESS_BITS = 64;
+ private static final int INT_BITS = 32;
private final long heapBase;
private final Register heapBaseRegister;
private final GraalHotSpotVMConfig config;
private final boolean generatePIC;
- @NodeInfo(cycles = CYCLES_0, size = SIZE_0)
- public static class HeapBaseNode extends FloatingNode implements LIRLowerable {
-
- public static final NodeClass<HeapBaseNode> TYPE = NodeClass.create(HeapBaseNode.class);
-
- private final Register heapBaseRegister;
-
- public HeapBaseNode(Register heapBaseRegister) {
- super(TYPE, StampFactory.pointer());
- this.heapBaseRegister = heapBaseRegister;
- }
-
- @Override
- public void generate(NodeLIRBuilderTool generator) {
- LIRKind kind = generator.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT));
- generator.setResult(this, heapBaseRegister.asValue(kind));
- }
- }
-
public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) {
this.heapBase = config.getOopEncoding().getBase();
this.config = config;
@@ -94,35 +80,7 @@
}
@Override
- protected boolean improve(StructuredGraph graph, DebugContext debug, AMD64AddressNode addr, boolean isBaseNegated, boolean isIndexNegated) {
- if (super.improve(graph, debug, addr, isBaseNegated, isIndexNegated)) {
- return true;
- }
-
- if (addr.getScale() == Scale.Times1) {
- if (addr.getIndex() instanceof CompressionNode) {
- if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase(), isBaseNegated, isIndexNegated)) {
- counterFoldedUncompressDuringAddressLowering.increment(debug);
- return true;
- }
- }
-
- if (addr.getBase() instanceof CompressionNode) {
- if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex(), isBaseNegated, isIndexNegated)) {
- counterFoldedUncompressDuringAddressLowering.increment(debug);
- return true;
- }
- }
- }
-
- return false;
- }
-
- private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other, boolean isBaseNegated, boolean isIndexNegated) {
- if (isBaseNegated || isIndexNegated || compression.getOp() != CompressionOp.Uncompress) {
- return false;
- }
-
+ protected final boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) {
CompressEncoding encoding = compression.getEncoding();
Scale scale = Scale.fromShift(encoding.getShift());
if (scale == null) {
@@ -147,7 +105,7 @@
return false;
}
} else {
- if (updateDisplacement(addr, encoding.getBase(), isBaseNegated)) {
+ if (updateDisplacement(addr, encoding.getBase(), false)) {
addr.setBase(other);
} else {
return false;
@@ -161,4 +119,117 @@
addr.setIndex(compression.getValue());
return true;
}
+
+ @Override
+ public void preProcess(StructuredGraph graph) {
+ if (graph.hasLoops()) {
+ LoopsData loopsData = new LoopsData(graph);
+ loopsData.detectedCountedLoops();
+ for (LoopEx loop : loopsData.countedLoops()) {
+ for (OffsetAddressNode offsetAdressNode : loop.whole().nodes().filter(OffsetAddressNode.class)) {
+ tryOptimize(offsetAdressNode, loop);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void postProcess(AddressNode lowered) {
+ // Allow implicit zero extend for always positive input. This
+ // assumes that the upper bits of the operand is zero out by
+ // the backend.
+ AMD64AddressNode address = (AMD64AddressNode) lowered;
+ address.setBase(tryImplicitZeroExtend(address.getBase()));
+ address.setIndex(tryImplicitZeroExtend(address.getIndex()));
+ }
+
+ private static void tryOptimize(OffsetAddressNode offsetAddress, LoopEx loop) {
+ EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
+ InductionVariable currentIV = ivs.get(offsetAddress.getOffset());
+ while (currentIV != null) {
+ if (!(currentIV instanceof DerivedInductionVariable)) {
+ break;
+ }
+ ValueNode currentValue = currentIV.valueNode();
+ if (currentValue.isDeleted()) {
+ break;
+ }
+
+ if (currentValue instanceof ZeroExtendNode) {
+ ZeroExtendNode zeroExtendNode = (ZeroExtendNode) currentValue;
+ if (applicableToImplicitZeroExtend(zeroExtendNode)) {
+ ValueNode input = zeroExtendNode.getValue();
+ if (input instanceof AddNode) {
+ AddNode add = (AddNode) input;
+ if (add.getX().isConstant()) {
+ optimizeAdd(zeroExtendNode, (ConstantNode) add.getX(), add.getY(), loop);
+ } else if (add.getY().isConstant()) {
+ optimizeAdd(zeroExtendNode, (ConstantNode) add.getY(), add.getX(), loop);
+ }
+ }
+ }
+ }
+
+ currentIV = ((DerivedInductionVariable) currentIV).getBase();
+ }
+ }
+
+ /**
+ * Given that Add(a, cst) is always positive, performs the following: ZeroExtend(Add(a, cst)) ->
+ * Add(SignExtend(a), SignExtend(cst)).
+ */
+ private static void optimizeAdd(ZeroExtendNode zeroExtendNode, ConstantNode constant, ValueNode other, LoopEx loop) {
+ StructuredGraph graph = zeroExtendNode.graph();
+ AddNode addNode = graph.unique(new AddNode(signExtend(other, loop), ConstantNode.forLong(constant.asJavaConstant().asInt(), graph)));
+ zeroExtendNode.replaceAtUsages(addNode);
+ }
+
+ /**
+ * Create a sign extend for {@code input}, or zero extend if {@code input} can be proven
+ * positive.
+ */
+ private static ValueNode signExtend(ValueNode input, LoopEx loop) {
+ StructuredGraph graph = input.graph();
+ if (input instanceof PhiNode) {
+ EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
+ InductionVariable inductionVariable = ivs.get(input);
+ if (inductionVariable != null && inductionVariable instanceof BasicInductionVariable) {
+ CountedLoopInfo countedLoopInfo = loop.counted();
+ IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
+ if (initStamp.isPositive()) {
+ if (inductionVariable.isConstantExtremum()) {
+ long init = inductionVariable.constantInit();
+ long stride = inductionVariable.constantStride();
+ long extremum = inductionVariable.constantExtremum();
+
+ if (init >= 0 && extremum >= 0) {
+ long shortestTrip = (extremum - init) / stride + 1;
+ if (shortestTrip == countedLoopInfo.constantMaxTripCount()) {
+ return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
+ }
+ }
+ }
+ if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) {
+ return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
+ }
+ }
+ }
+ }
+ return input.graph().maybeAddOrUnique(SignExtendNode.create(input, ADDRESS_BITS, NodeView.DEFAULT));
+ }
+
+ private static boolean applicableToImplicitZeroExtend(ZeroExtendNode zeroExtendNode) {
+ return zeroExtendNode.isInputAlwaysPositive() && zeroExtendNode.getInputBits() == INT_BITS && zeroExtendNode.getResultBits() == ADDRESS_BITS;
+ }
+
+ private static ValueNode tryImplicitZeroExtend(ValueNode input) {
+ if (input instanceof ZeroExtendNode) {
+ ZeroExtendNode zeroExtendNode = (ZeroExtendNode) input;
+ if (applicableToImplicitZeroExtend(zeroExtendNode)) {
+ return zeroExtendNode.getValue();
+ }
+ }
+ return input;
+ }
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
@@ -66,7 +67,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64Kind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Sat Feb 10 09:25:35 2018 +0100
@@ -49,6 +49,7 @@
import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
@@ -137,7 +138,7 @@
replacements = createReplacements(options, p, snippetReflection, bytecodeProvider);
}
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
- plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes,
+ plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, lowerer, metaAccess, snippetReflection, replacements, wordTypes,
stampProvider);
replacements.setGraphBuilderPlugins(plugins);
}
@@ -154,9 +155,10 @@
}
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target,
- HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
+ HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) {
- Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements);
+ Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider,
+ replacements);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options));
return plugins;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Sat Feb 10 09:25:35 2018 +0100
@@ -572,7 +572,7 @@
if (inputKind.isReference(0)) {
// oop
Variable result = newVariable(lirKindTool.getNarrowOopKind());
- append(new AMD64Move.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, getLIRKindTool()));
+ append(new AMD64Move.CompressPointerOp(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, getLIRKindTool()));
return result;
} else {
// metaspace pointer
@@ -589,7 +589,7 @@
base = emitLoadConstant(lirKindTool.getWordKind(), JavaConstant.forLong(encoding.getBase()));
}
}
- append(new AMD64Move.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull, getLIRKindTool()));
+ append(new AMD64Move.CompressPointerOp(result, asAllocatable(pointer), base, encoding, nonNull, getLIRKindTool()));
return result;
}
}
@@ -602,7 +602,7 @@
if (inputKind.isReference(0)) {
// oop
Variable result = newVariable(lirKindTool.getObjectKind());
- append(new AMD64Move.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, lirKindTool));
+ append(new AMD64Move.UncompressPointerOp(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, lirKindTool));
return result;
} else {
// metaspace pointer
@@ -620,7 +620,7 @@
base = emitLoadConstant(uncompressedKind, JavaConstant.forLong(encoding.getBase()));
}
}
- append(new AMD64Move.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull, lirKindTool));
+ append(new AMD64Move.UncompressPointerOp(result, asAllocatable(pointer), base, encoding, nonNull, lirKindTool));
return result;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -67,7 +67,8 @@
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options)
- ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) : null;
+ ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
+ : null;
super.initialize(options, factories, providers, config);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -60,6 +60,7 @@
crb.recordMark(invokeKind == InvokeKind.Virtual ? config.MARKID_INVOKEVIRTUAL : config.MARKID_INVOKEINTERFACE);
// This must be emitted exactly like this to ensure it's patchable
masm.movq(AMD64.rax, config.nonOopBits);
- super.emitCode(crb, masm);
+ int offset = super.emitCall(crb, masm);
+ crb.recordInvokeVirtualOrInterfaceCallOp(offset, getPosition());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64IndirectCallOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -70,7 +70,8 @@
crb.recordMark(config.MARKID_INLINE_INVOKE);
Register callReg = asRegister(targetAddress);
assert !callReg.equals(METHOD);
- AMD64Call.indirectCall(crb, masm, callReg, callTarget, state);
+ int pcOffset = AMD64Call.indirectCall(crb, masm, callReg, callTarget, state);
+ crb.recordInlineInvokeCallOp(pcOffset, getPosition());
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,75 @@
+/*
+ * 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.core.sparc.test;
+
+import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure;
+import static org.graalvm.compiler.core.common.GraalOptions.TraceRA;
+import static org.junit.Assume.assumeTrue;
+
+import org.graalvm.compiler.core.test.backend.AllocatorTest;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.sparc.SPARC;
+
+public class SPARCAllocatorTest extends AllocatorTest {
+
+ private final GraalHotSpotVMConfig config = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig();
+
+ @Before
+ public void checkSPARC() {
+ assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC);
+ assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null);
+ assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions()));
+ }
+
+ @Test
+ public void test1() {
+ testAllocation("test1snippet", config.threadLocalHandshakes ? 1 : 2, 0, 0);
+ }
+
+ public static long test1snippet(long x) {
+ return x + 41;
+ }
+
+ @Test
+ public void test2() {
+ testAllocation("test2snippet", config.threadLocalHandshakes ? 1 : 2, 0, 0);
+ }
+
+ public static long test2snippet(long x) {
+ return x * 41;
+ }
+
+ @Test
+ public void test3() {
+ testAllocation("test3snippet", config.threadLocalHandshakes ? 3 : 4, 0, 0);
+ }
+
+ public static long test3snippet(long x) {
+ return x / 41 + x % 41;
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Sat Feb 10 09:25:35 2018 +0100
@@ -46,6 +46,9 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.sparc.SPARCAddress;
@@ -92,9 +95,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Sat Feb 10 09:25:35 2018 +0100
@@ -101,7 +101,7 @@
HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes);
BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target);
- Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes);
+ Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, lowerer, stampProvider, snippetReflection, replacements, wordTypes);
replacements.setGraphBuilderPlugins(plugins);
HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements);
HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
@@ -112,9 +112,10 @@
}
protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess,
- HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider,
+ HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, HotSpotStampProvider stampProvider,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
- Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements);
+ Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, lowerer, stampProvider,
+ replacements);
SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider());
return plugins;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayNewInstanceTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.test;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ArrayNewInstanceTest extends GraalCompilerTest {
+
+ @Parameters(name = "{index}: class {0} length {1}")
+ public static Iterable<Object[]> data() {
+ ArrayList<Object[]> parameters = new ArrayList<>();
+ Class<?>[] classesToTest = new Class<?>[]{
+ byte.class,
+ boolean.class,
+ short.class,
+ char.class,
+ int.class,
+ long.class,
+ Void.class,
+ ArrayNewInstanceTest.class
+ };
+ for (Class<?> clazz : classesToTest) {
+ // Negative sizes always deopt
+ parameters.add(new Object[]{clazz, -1, true});
+ parameters.add(new Object[]{clazz, 0, false});
+ parameters.add(new Object[]{clazz, 42, false});
+ }
+ // The void type always throws an exception where graal deopts
+ parameters.add(new Object[]{void.class, -1, true});
+ parameters.add(new Object[]{void.class, 0, true});
+ parameters.add(new Object[]{void.class, 42, true});
+ return parameters;
+ }
+
+ private final Class<?> type;
+ private final int length;
+ private final boolean shouldDeopt;
+ private final DeoptimizationBox box = new DeoptimizationBox();
+
+ public ArrayNewInstanceTest(Class<?> type, int length, boolean shouldDeopt) {
+ super();
+ this.type = type;
+ this.length = length;
+ this.shouldDeopt = shouldDeopt;
+ }
+
+ public static Object newArray(Class<?> klass, int length, DeoptimizationBox box) {
+ Object result = Array.newInstance(klass, length);
+ box.inCompiledCode = GraalDirectives.inCompiledCode();
+ return result;
+ }
+
+ @Test
+ public void testNewArray() {
+ test("newArray", type, length, box);
+ assertTrue(box.inCompiledCode != shouldDeopt);
+ }
+
+ public static Object newArrayInLoop(Class<?> klass, int length, int iterations, DeoptimizationBox box) {
+ Object o = null;
+ for (int i = 0; i < iterations; i++) {
+ o = Array.newInstance(klass, length);
+ }
+ box.inCompiledCode = GraalDirectives.inCompiledCode();
+ return o;
+ }
+
+ @Test
+ public void testNewArrayInLoop() {
+ test("newArrayInLoop", type, length, 2, box);
+ assertTrue(box.inCompiledCode != shouldDeopt);
+ }
+
+ private static class DeoptimizationBox {
+ volatile boolean inCompiledCode = false;
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Sat Feb 10 09:25:35 2018 +0100
@@ -32,6 +32,8 @@
import java.util.TreeSet;
import java.util.stream.Collectors;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -43,8 +45,6 @@
import org.graalvm.compiler.runtime.RuntimeProvider;
import org.graalvm.compiler.serviceprovider.JDK9Method;
import org.graalvm.compiler.test.GraalTest;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
import org.junit.Test;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
@@ -416,6 +416,12 @@
"java/lang/StringUTF16.toBytes([CII)[B");
}
+ if (isJDK10OrHigher()) {
+ add(TO_BE_INVESTIGATED,
+ "java/lang/Math.multiplyHigh(JJ)J",
+ "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
+ }
+
if (!getHostArchitectureName().equals("amd64")) {
// Can we implement these on non-AMD64 platforms? C2 seems to.
add(TO_BE_INVESTIGATED,
@@ -539,6 +545,10 @@
return JDK9Method.JAVA_SPECIFICATION_VERSION >= 9;
}
+ private static boolean isJDK10OrHigher() {
+ return JDK9Method.JAVA_SPECIFICATION_VERSION >= 10;
+ }
+
private static String getHostArchitectureName() {
String arch = System.getProperty("os.arch");
if (arch.equals("x86_64")) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Sat Feb 10 09:25:35 2018 +0100
@@ -68,6 +68,8 @@
import java.util.jar.JarFile;
import java.util.stream.Collectors;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.bytecode.Bytecodes;
import org.graalvm.compiler.core.CompilerThreadFactory;
@@ -85,8 +87,6 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.options.OptionsParser;
import org.graalvm.compiler.serviceprovider.JDK9Method;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.UnmodifiableEconomicMap;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,12 +25,12 @@
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
import org.junit.Test;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -32,6 +32,7 @@
import java.util.HashSet;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.debug.DebugContext;
@@ -40,13 +41,12 @@
import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
-import org.junit.Assume;
-import org.junit.BeforeClass;
/**
* Test on-stack-replacement with locks.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,8 +31,8 @@
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
+import java.util.Arrays;
-import java.util.Arrays;
import javax.management.Attribute;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
@@ -41,11 +41,11 @@
import javax.management.ObjectInstance;
import javax.management.ObjectName;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.test.GraalTest;
-import org.graalvm.util.EconomicMap;
import org.junit.Assume;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,8 +23,10 @@
package org.graalvm.compiler.hotspot.test;
import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID;
+
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
@@ -36,10 +38,9 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.util.EconomicMap;
import org.junit.Test;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Scope;
@@ -58,7 +59,6 @@
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.util.EconomicMap;
import org.graalvm.word.LocationIdentity;
import org.junit.Assert;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,6 +29,7 @@
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.CompilationPrinter;
@@ -45,7 +46,6 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.CodeCacheProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,6 +29,7 @@
import java.util.List;
import java.util.stream.Collectors;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
@@ -36,7 +37,6 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.serviceprovider.GraalServices;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.common.InitTimer;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Sat Feb 10 09:25:35 2018 +0100
@@ -64,10 +64,10 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.word.Word;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.word.Pointer;
import jdk.vm.ci.code.CompilationRequest;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -98,8 +98,8 @@
ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());
Builder<DataPatch> patchBuilder = Stream.builder();
- data.buildDataSection(buffer, vmConstant -> {
- patchBuilder.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
+ data.buildDataSection(buffer, (position, vmConstant) -> {
+ patchBuilder.accept(new DataPatch(position, new ConstantReference(vmConstant)));
});
int dataSectionAlignment = data.getSectionAlignment();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,11 +22,13 @@
*/
package org.graalvm.compiler.hotspot;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
import java.util.Arrays;
+
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.debug.GraalError;
@@ -34,7 +36,6 @@
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LIRInstructionClass;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -56,41 +56,30 @@
@Override
public Data createDataItem(Constant constant) {
- int size;
- if (constant instanceof VMConstant) {
+ if (JavaConstant.isNull(constant)) {
+ boolean compressed = COMPRESSED_NULL.equals(constant);
+ int size = compressed ? 4 : target.wordSize;
+ return ZeroData.create(size, size);
+ } else if (constant instanceof VMConstant) {
VMConstant vmConstant = (VMConstant) constant;
- boolean compressed;
- if (constant instanceof HotSpotConstant) {
- HotSpotConstant c = (HotSpotConstant) vmConstant;
- compressed = c.isCompressed();
- } else {
+ if (!(constant instanceof HotSpotConstant)) {
throw new GraalError(String.valueOf(constant));
}
- size = compressed ? 4 : target.wordSize;
- if (size == 4) {
- return new Data(size, size) {
-
- @Override
- protected void emit(ByteBuffer buffer, Patches patches) {
- patches.registerPatch(vmConstant);
+ HotSpotConstant c = (HotSpotConstant) vmConstant;
+ int size = c.isCompressed() ? 4 : target.wordSize;
+ return new Data(size, size) {
+ @Override
+ protected void emit(ByteBuffer buffer, Patches patches) {
+ int position = buffer.position();
+ if (getSize() == Integer.BYTES) {
buffer.putInt(0xDEADDEAD);
- }
- };
- } else {
- return new Data(size, size) {
-
- @Override
- protected void emit(ByteBuffer buffer, Patches patches) {
- patches.registerPatch(vmConstant);
+ } else {
buffer.putLong(0xDEADDEADDEADDEADL);
}
- };
- }
- } else if (JavaConstant.isNull(constant)) {
- boolean compressed = COMPRESSED_NULL.equals(constant);
- size = compressed ? 4 : target.wordSize;
- return ZeroData.create(size, size);
+ patches.registerPatch(position, vmConstant);
+ }
+ };
} else if (constant instanceof SerializableConstant) {
SerializableConstant s = (SerializableConstant) constant;
return new SerializableData(s);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,15 +22,15 @@
*/
package org.graalvm.compiler.hotspot;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.util.EconomicSet;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.code.CallingConvention;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Sat Feb 10 09:25:35 2018 +0100
@@ -44,10 +44,10 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
public final class HotSpotGraalMBean implements javax.management.DynamicMBean {
private static Object mBeanServerField;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
import java.util.Map;
import java.util.Properties;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
@@ -37,7 +38,6 @@
import org.graalvm.compiler.options.OptionValuesAccess;
import org.graalvm.compiler.options.OptionsParser;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.common.InitTimer;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,8 @@
import java.util.List;
import java.util.Map;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.runtime.GraalRuntime;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
@@ -57,8 +59,6 @@
import org.graalvm.compiler.replacements.SnippetCounter;
import org.graalvm.compiler.replacements.SnippetCounter.Group;
import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.stack.StackIntrospection;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.hotspot;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.lir.LIR;
@@ -29,8 +31,6 @@
import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.StackSlot;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
@@ -42,7 +43,6 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.util.EconomicMap;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.code.CallingConvention;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,6 +31,7 @@
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MutableCallSite;
import java.lang.invoke.VolatileCallSite;
+import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
@@ -39,17 +40,20 @@
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions;
+import org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions;
import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions;
-import org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions;
import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode;
import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions;
import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode;
+import org.graalvm.compiler.hotspot.replacements.HotSpotArraySubstitutions;
import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions;
import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode;
import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode;
@@ -68,7 +72,6 @@
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NamedLocationIdentity;
import org.graalvm.compiler.nodes.NodeView;
-import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.IntegerConvertNode;
@@ -83,8 +86,10 @@
import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
+import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.StampProvider;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
@@ -123,12 +128,12 @@
* @param stampProvider
*/
public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess,
- ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider,
- ReplacementsImpl replacements) {
+ ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, LoweringProvider lowerer,
+ StampProvider stampProvider, ReplacementsImpl replacements) {
InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration);
Plugins plugins = new Plugins(invocationPlugins);
- NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes);
+ NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, lowerer, wordTypes);
HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes);
HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin);
@@ -171,6 +176,7 @@
registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider);
registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider);
StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true);
+ registerArrayPlugins(invocationPlugins, replacementBytecodeProvider);
for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) {
factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider);
@@ -401,19 +407,23 @@
});
}
+ private static void registerArrayPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) {
+ Registration r = new Registration(plugins, Array.class, bytecodeProvider);
+ r.setAllowOverwrite(true);
+ r.registerMethodSubstitution(HotSpotArraySubstitutions.class, "newInstance", Class.class, int.class);
+ }
+
private static void registerThreadPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, WordTypes wordTypes, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
Registration r = new Registration(plugins, Thread.class, bytecodeProvider);
r.register0("currentThread", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(wordTypes.getWordKind()));
- boolean compressible = false;
ValueNode offset = b.add(ConstantNode.forLong(config.threadObjectOffset));
AddressNode address = b.add(new OffsetAddressNode(thread, offset));
- ValueNode javaThread = WordOperationPlugin.readOp(b, JavaKind.Object, address, JAVA_THREAD_THREAD_OBJECT_LOCATION, BarrierType.NONE, compressible);
- boolean exactType = false;
- boolean nonNull = true;
- b.addPush(JavaKind.Object, new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull));
+ // JavaThread::_threadObj is never compressed
+ ObjectStamp stamp = StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), metaAccess.lookupJavaType(Thread.class)));
+ b.addPush(JavaKind.Object, new ReadNode(address, JAVA_THREAD_THREAD_OBJECT_LOCATION, stamp, BarrierType.NONE));
return true;
}
});
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -101,6 +101,7 @@
import java.util.EnumMap;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.debug.GraalError;
@@ -123,7 +124,6 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.util.EconomicMap;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.code.CodeCacheProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,6 +27,7 @@
import java.lang.reflect.Type;
import java.util.Set;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
@@ -42,7 +43,6 @@
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.replacements.nodes.MacroNode;
import org.graalvm.compiler.serviceprovider.JDK9Method;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import jdk.vm.ci.meta.JavaKind;
@@ -122,7 +122,7 @@
* of its module dependencies are trusted.
*/
@Override
- protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
+ public boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
if (declaringClass instanceof HotSpotResolvedJavaType) {
Class<?> javaClass = ((HotSpotResolvedJavaType) declaringClass).mirror();
if (Java8OrEarlier) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot.meta;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -104,4 +105,9 @@
}
return null;
}
+
+ @Override
+ public Class<?> originalClass(ResolvedJavaType type) {
+ return ((HotSpotResolvedJavaType) type).mirror();
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,34 +23,37 @@
package org.graalvm.compiler.hotspot.nodes;
import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
@NodeInfo
public abstract class ArrayRangeWriteBarrier extends WriteBarrier implements Lowerable {
public static final NodeClass<ArrayRangeWriteBarrier> TYPE = NodeClass.create(ArrayRangeWriteBarrier.class);
- @Input ValueNode object;
- @Input ValueNode startIndex;
+ @Input(InputType.Association) AddressNode address;
@Input ValueNode length;
- protected ArrayRangeWriteBarrier(NodeClass<? extends ArrayRangeWriteBarrier> c, ValueNode object, ValueNode startIndex, ValueNode length) {
+ private final int elementStride;
+
+ protected ArrayRangeWriteBarrier(NodeClass<? extends ArrayRangeWriteBarrier> c, AddressNode address, ValueNode length, int elementStride) {
super(c);
- this.object = object;
- this.startIndex = startIndex;
+ this.address = address;
this.length = length;
+ this.elementStride = elementStride;
}
- public ValueNode getObject() {
- return object;
- }
-
- public ValueNode getStartIndex() {
- return startIndex;
+ public AddressNode getAddress() {
+ return address;
}
public ValueNode getLength() {
return length;
}
+
+ public int getElementStride() {
+ return elementStride;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,13 +28,14 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier {
public static final NodeClass<G1ArrayRangePostWriteBarrier> TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class);
- public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
- super(TYPE, object, startIndex, length);
+ public G1ArrayRangePostWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
+ super(TYPE, address, length, elementStride);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,13 +28,14 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
public static final NodeClass<G1ArrayRangePreWriteBarrier> TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class);
- public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
- super(TYPE, object, startIndex, length);
+ public G1ArrayRangePreWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
+ super(TYPE, address, length, elementStride);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,14 +28,14 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier {
-
public static final NodeClass<SerialArrayRangeWriteBarrier> TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class);
- public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) {
- super(TYPE, object, startIndex, length);
+ public SerialArrayRangeWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
+ super(TYPE, address, length, elementStride);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,7 +34,7 @@
import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode;
+import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
import org.graalvm.compiler.nodes.memory.FixedAccessNode;
@@ -65,9 +65,9 @@
addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph);
} else if (n instanceof AbstractCompareAndSwapNode) {
addCASBarriers((AbstractCompareAndSwapNode) n, graph);
- } else if (n instanceof ArrayRangeWriteNode) {
- ArrayRangeWriteNode node = (ArrayRangeWriteNode) n;
- if (node.isObjectArray()) {
+ } else if (n instanceof ArrayRangeWrite) {
+ ArrayRangeWrite node = (ArrayRangeWrite) n;
+ if (node.writesObjectArray()) {
addArrayRangeBarriers(node, graph);
}
}
@@ -171,17 +171,17 @@
}
}
- private void addArrayRangeBarriers(ArrayRangeWriteNode node, StructuredGraph graph) {
+ private void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) {
if (config.useG1GC) {
- if (!node.isInitialization()) {
- G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
- graph.addBeforeFixed(node, g1ArrayRangePreWriteBarrier);
+ if (!write.isInitialization()) {
+ G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
+ graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier);
}
- G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
- graph.addAfterFixed(node, g1ArrayRangePostWriteBarrier);
+ G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
+ graph.addAfterFixed(write.asNode(), g1ArrayRangePostWriteBarrier);
} else {
- SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(node.getArray(), node.getIndex(), node.getLength()));
- graph.addAfterFixed(node, serialArrayRangeWriteBarrier);
+ SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
+ graph.addAfterFixed(write.asNode(), serialArrayRangeWriteBarrier);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -39,7 +39,7 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode;
+import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
import org.graalvm.compiler.nodes.memory.FixedAccessNode;
@@ -122,7 +122,7 @@
private boolean hasAttachedBarrier(FixedWithNextNode node) {
final Node next = node.next();
final Node previous = node.predecessor();
- boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization());
+ boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization());
if (node instanceof WriteNode) {
WriteNode writeNode = (WriteNode) node;
if (writeNode.getLocationIdentity().isInit()) {
@@ -143,7 +143,7 @@
}
private static boolean isArrayBarrier(FixedWithNextNode node, final Node next) {
- return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWriteNode) node).getArray() == ((ArrayRangeWriteBarrier) next).getObject();
+ return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWrite) node).getAddress() == ((ArrayRangeWriteBarrier) next).getAddress();
}
private static boolean isObjectWrite(Node node) {
@@ -152,7 +152,7 @@
}
private static boolean isObjectArrayRangeWrite(Node node) {
- return node instanceof ArrayRangeWriteNode && ((ArrayRangeWriteNode) node).isObjectArray();
+ return node instanceof ArrayRangeWrite && ((ArrayRangeWrite) node).writesObjectArray();
}
private static void expandFrontier(NodeFlood frontier, Node node) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,11 @@
import java.util.Iterator;
import java.util.List;
+import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
@@ -40,11 +45,6 @@
import org.graalvm.compiler.phases.graph.MergeableState;
import org.graalvm.compiler.phases.graph.PostOrderNodeIterator;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicSet;
-
-import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
-import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.ResolvedJavaType;
public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContext> {
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,6 +29,7 @@
import java.util.HashSet;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -64,7 +65,6 @@
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,10 +25,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
@@ -56,7 +53,9 @@
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;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
@@ -169,8 +168,8 @@
}
@Override
- public boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) {
- assert op == Condition.EQ || op == Condition.NE;
+ public boolean preservesOrder(CanonicalCondition op, Constant value, ConstantReflectionProvider constantReflection) {
+ assert op == CanonicalCondition.EQ;
ResolvedJavaType exactType = constantReflection.asJavaType(value);
return !exactType.isPrimitive();
}
--- /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/replacements/HotSpotArraySubstitutions.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.replacements;
+
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayKlassOffset;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassFromObject;
+
+import java.lang.reflect.Array;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
+
+// JaCoCo Exclude
+
+/**
+ * Substitutions for {@link Array} methods.
+ */
+@ClassSubstitution(Array.class)
+public class HotSpotArraySubstitutions {
+
+ @MethodSubstitution
+ public static Object newInstance(Class<?> componentType, int length) {
+ if (componentType == null || loadKlassFromObject(componentType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION).isNull()) {
+ // Exit the intrinsic here for the case where the array class does not exist
+ return newInstance(componentType, length);
+ }
+ return DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(componentType), length);
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Sat Feb 10 09:25:35 2018 +0100
@@ -303,7 +303,11 @@
return result;
}
- public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj");
+ /*
+ * As far as Java code is concerned this can be considered immutable: it is set just after the
+ * JavaThread is created, before it is published. After that, it is never changed.
+ */
+ public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.immutable("JavaThread::_threadObj");
@Fold
public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) {
@@ -565,9 +569,20 @@
return WordFactory.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int)));
}
+ /**
+ * Idiom for making {@link GraalHotSpotVMConfig} a constant.
+ */
@Fold
- public static int objectAlignment(@InjectedParameter GraalHotSpotVMConfig config) {
- return config.objectAlignment;
+ public static GraalHotSpotVMConfig getConfig(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config;
+ }
+
+ /**
+ * Calls {@link #arrayAllocationSize(int, int, int, GraalHotSpotVMConfig)} using an injected VM
+ * configuration object.
+ */
+ public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize) {
+ return arrayAllocationSize(length, headerSize, log2ElementSize, getConfig(INJECTED_VMCONFIG));
}
/**
@@ -578,10 +593,12 @@
* @param length the number of elements in the array
* @param headerSize the size of the array header
* @param log2ElementSize log2 of the size of an element in the array
+ * @param config the VM configuration providing the
+ * {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment requirement}
* @return the size of the memory chunk
*/
- public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize) {
- int alignment = objectAlignment(INJECTED_VMCONFIG);
+ public static int arrayAllocationSize(int length, int headerSize, int log2ElementSize, GraalHotSpotVMConfig config) {
+ int alignment = config.objectAlignment;
int size = (length << log2ElementSize) + headerSize + (alignment - 1);
int mask = ~(alignment - 1);
return size & mask;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Sat Feb 10 09:25:35 2018 +0100
@@ -62,6 +62,7 @@
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
import static org.graalvm.compiler.replacements.ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED;
+import static org.graalvm.compiler.replacements.ReplacementsUtil.runtimeAssert;
import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert;
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
@@ -378,7 +379,13 @@
if (length < 0) {
DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
}
- int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(nonNullKlass);
+ int layoutHelper;
+ if (knownElementKind == JavaKind.Illegal) {
+ layoutHelper = readLayoutHelper(nonNullKlass);
+ } else {
+ runtimeAssert(knownLayoutHelper == readLayoutHelper(nonNullKlass), "layout mismatch");
+ layoutHelper = knownLayoutHelper;
+ }
//@formatter:off
// from src/share/vm/oops/klass.hpp:
//
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,6 @@
import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.cardTableShift;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.dirtyCardValue;
@@ -59,7 +58,6 @@
import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
-import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode;
import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier;
@@ -152,18 +150,14 @@
}
@Snippet
- public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) {
+ public static void serialArrayRangeWriteBarrier(Address address, int length, @ConstantParameter int elementStride) {
if (length == 0) {
return;
}
- Object dest = FixedValueAnchorNode.getObject(object);
int cardShift = cardTableShift(INJECTED_VMCONFIG);
final long cardStart = GraalHotSpotVMConfigNode.cardTableAddress();
- final int scale = arrayIndexScale(JavaKind.Object);
- int header = arrayBaseOffset(JavaKind.Object);
- long dstAddr = GetObjectAddressNode.get(dest);
- long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift;
- long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift;
+ long start = getPointerToFirstArrayElement(address, length, elementStride) >>> cardShift;
+ long end = getPointerToLastArrayElement(address, length, elementStride) >>> cardShift;
long count = end - start + 1;
while (count-- > 0) {
DirectStoreNode.storeBoolean((start + cardStart) + count, false, JavaKind.Boolean);
@@ -305,24 +299,22 @@
}
@Snippet
- public static void g1ArrayRangePreWriteBarrier(Object object, int startIndex, int length, @ConstantParameter Register threadRegister) {
+ public static void g1ArrayRangePreWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) {
Word thread = registerAsWord(threadRegister);
byte markingValue = thread.readByte(g1SATBQueueMarkingOffset(INJECTED_VMCONFIG));
// If the concurrent marker is not enabled or the vector length is zero, return.
if (markingValue == (byte) 0 || length == 0) {
return;
}
- Object dest = FixedValueAnchorNode.getObject(object);
Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset(INJECTED_VMCONFIG));
Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG));
- long dstAddr = GetObjectAddressNode.get(dest);
long indexValue = indexAddress.readWord(0).rawValue();
final int scale = arrayIndexScale(JavaKind.Object);
- int header = arrayBaseOffset(JavaKind.Object);
+ long start = getPointerToFirstArrayElement(address, length, elementStride);
- for (int i = startIndex; i < length; i++) {
- Word address = WordFactory.pointer(dstAddr + header + (i * scale));
- Pointer oop = Word.objectToTrackedPointer(address.readObject(0, BarrierType.NONE));
+ for (int i = 0; i < length; i++) {
+ Word arrElemPtr = WordFactory.pointer(start + i * scale);
+ Pointer oop = Word.objectToTrackedPointer(arrElemPtr.readObject(0, BarrierType.NONE));
verifyOop(oop.toObject());
if (oop.notEqual(0)) {
if (indexValue != 0) {
@@ -339,11 +331,10 @@
}
@Snippet
- public static void g1ArrayRangePostWriteBarrier(Object object, int startIndex, int length, @ConstantParameter Register threadRegister) {
+ public static void g1ArrayRangePostWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) {
if (length == 0) {
return;
}
- Object dest = FixedValueAnchorNode.getObject(object);
Word thread = registerAsWord(threadRegister);
Word bufferAddress = thread.readWord(g1CardQueueBufferOffset(INJECTED_VMCONFIG));
Word indexAddress = thread.add(g1CardQueueIndexOffset(INJECTED_VMCONFIG));
@@ -351,11 +342,8 @@
int cardShift = cardTableShift(INJECTED_VMCONFIG);
final long cardStart = GraalHotSpotVMConfigNode.cardTableAddress();
- final int scale = arrayIndexScale(JavaKind.Object);
- int header = arrayBaseOffset(JavaKind.Object);
- long dstAddr = GetObjectAddressNode.get(dest);
- long start = (dstAddr + header + (long) startIndex * scale) >>> cardShift;
- long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift;
+ long start = getPointerToFirstArrayElement(address, length, elementStride) >>> cardShift;
+ long end = getPointerToLastArrayElement(address, length, elementStride) >>> cardShift;
long count = end - start + 1;
while (count-- > 0) {
@@ -384,6 +372,26 @@
}
}
+ private static long getPointerToFirstArrayElement(Address address, int length, int elementStride) {
+ long result = Word.fromAddress(address).rawValue();
+ if (elementStride < 0) {
+ // the address points to the place after the last array element
+ result = result + elementStride * length;
+ }
+ return result;
+ }
+
+ private static long getPointerToLastArrayElement(Address address, int length, int elementStride) {
+ long result = Word.fromAddress(address).rawValue();
+ if (elementStride < 0) {
+ // the address points to the place after the last array element
+ result = result + elementStride;
+ } else {
+ result = result + (length - 1) * elementStride;
+ }
+ return result;
+ }
+
public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
@NodeIntrinsic(ForeignCallNode.class)
@@ -431,9 +439,9 @@
public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) {
Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("object", arrayRangeWriteBarrier.getObject());
- args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+ args.add("address", arrayRangeWriteBarrier.getAddress());
args.add("length", arrayRangeWriteBarrier.getLength());
+ args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
}
@@ -519,18 +527,18 @@
public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("object", arrayRangeWriteBarrier.getObject());
- args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+ args.add("address", arrayRangeWriteBarrier.getAddress());
args.add("length", arrayRangeWriteBarrier.getLength());
+ args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
args.addConst("threadRegister", registers.getThreadRegister());
template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
}
public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("object", arrayRangeWriteBarrier.getObject());
- args.add("startIndex", arrayRangeWriteBarrier.getStartIndex());
+ args.add("address", arrayRangeWriteBarrier.getAddress());
args.add("length", arrayRangeWriteBarrier.getLength());
+ args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
args.addConst("threadRegister", registers.getThreadRegister());
template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Sat Feb 10 09:25:35 2018 +0100
@@ -40,6 +40,7 @@
import java.lang.reflect.Method;
import java.util.EnumMap;
+import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.Snippet;
@@ -76,7 +77,6 @@
import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.util.UnmodifiableEconomicMap;
import org.graalvm.word.LocationIdentity;
import org.graalvm.word.WordFactory;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,21 @@
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.site.Call;
+import jdk.vm.ci.code.site.ConstantReference;
+import jdk.vm.ci.code.site.DataPatch;
+import jdk.vm.ci.code.site.Infopoint;
+import jdk.vm.ci.hotspot.HotSpotCompiledCode;
+import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
+import jdk.vm.ci.meta.DefaultProfilingInfo;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.TriState;
+
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.target.Backend;
@@ -54,21 +69,6 @@
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.tiers.Suites;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
-import org.graalvm.util.EconomicSet;
-
-import jdk.vm.ci.code.CodeCacheProvider;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.code.Register;
-import jdk.vm.ci.code.RegisterConfig;
-import jdk.vm.ci.code.site.Call;
-import jdk.vm.ci.code.site.ConstantReference;
-import jdk.vm.ci.code.site.DataPatch;
-import jdk.vm.ci.code.site.Infopoint;
-import jdk.vm.ci.hotspot.HotSpotCompiledCode;
-import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
-import jdk.vm.ci.meta.DefaultProfilingInfo;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.TriState;
//JaCoCo Exclude
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Sat Feb 10 09:25:35 2018 +0100
@@ -86,6 +86,8 @@
import java.util.List;
import java.util.TreeSet;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
import org.graalvm.compiler.bytecode.BytecodeStream;
@@ -95,8 +97,6 @@
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.ExceptionHandler;
@@ -415,9 +415,6 @@
}
public static class ExceptionDispatchBlock extends BciBlock {
-
- private EconomicMap<ExceptionHandler, ExceptionDispatchBlock> exceptionDispatch = EconomicMap.create(Equivalence.DEFAULT);
-
public ExceptionHandler handler;
public int deoptBci;
}
@@ -748,15 +745,6 @@
}
}
- private EconomicMap<ExceptionHandler, ExceptionDispatchBlock> initialExceptionDispatch;
-
- private EconomicMap<ExceptionHandler, ExceptionDispatchBlock> getInitialExceptionDispatch() {
- if (initialExceptionDispatch == null) {
- initialExceptionDispatch = EconomicMap.create(Equivalence.DEFAULT);
- }
- return initialExceptionDispatch;
- }
-
private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) {
ExceptionDispatchBlock lastHandler = null;
@@ -769,20 +757,17 @@
lastHandler = null;
}
- EconomicMap<ExceptionHandler, ExceptionDispatchBlock> exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : getInitialExceptionDispatch();
- ExceptionDispatchBlock curHandler = exceptionDispatch.get(h);
- if (curHandler == null) {
- curHandler = new ExceptionDispatchBlock();
- blocksNotYetAssignedId++;
- curHandler.startBci = -1;
- curHandler.endBci = -1;
- curHandler.deoptBci = bci;
- curHandler.handler = h;
- curHandler.addSuccessor(blockMap[h.getHandlerBCI()]);
- if (lastHandler != null) {
- curHandler.addSuccessor(lastHandler);
- }
- exceptionDispatch.put(h, curHandler);
+ // We do not reuse exception dispatch blocks, because nested exception handlers
+ // might have problems reasoning about the correct frame state.
+ ExceptionDispatchBlock curHandler = new ExceptionDispatchBlock();
+ blocksNotYetAssignedId++;
+ curHandler.startBci = -1;
+ curHandler.endBci = -1;
+ curHandler.deoptBci = bci;
+ curHandler.handler = h;
+ curHandler.addSuccessor(blockMap[h.getHandlerBCI()]);
+ if (lastHandler != null) {
+ curHandler.addSuccessor(lastHandler);
}
lastHandler = curHandler;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Sat Feb 10 09:25:35 2018 +0100
@@ -265,6 +265,8 @@
import java.util.Formatter;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
@@ -278,9 +280,12 @@
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
import org.graalvm.compiler.core.common.PermanentBailoutException;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
import org.graalvm.compiler.core.common.calc.FloatConvert;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -343,8 +348,8 @@
import org.graalvm.compiler.nodes.calc.AndNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
+import org.graalvm.compiler.nodes.calc.FloatConvertNode;
import org.graalvm.compiler.nodes.calc.FloatDivNode;
-import org.graalvm.compiler.nodes.calc.FloatConvertNode;
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
@@ -408,8 +413,6 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.util.ValueMergeUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.code.BailoutException;
@@ -436,7 +439,6 @@
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
import jdk.vm.ci.meta.TriState;
-import org.graalvm.compiler.core.common.type.IntegerStamp;
/**
* The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -577,10 +579,11 @@
// value on the stack on entry to an exception handler,
// namely the exception object.
assert frameState.rethrowException();
- ExceptionObjectNode exceptionObject = (ExceptionObjectNode) frameState.stackAt(0);
+ ValueNode exceptionValue = frameState.stackAt(0);
+ ExceptionObjectNode exceptionObject = (ExceptionObjectNode) GraphUtil.unproxify(exceptionValue);
FrameStateBuilder dispatchState = parser.frameState.copy();
dispatchState.clearStack();
- dispatchState.push(JavaKind.Object, exceptionObject);
+ dispatchState.push(JavaKind.Object, exceptionValue);
dispatchState.setRethrowException(true);
FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject);
frameState.replaceAndDelete(newFrameState);
@@ -700,6 +703,12 @@
assert code.getCode() != null : "method must contain bytecodes: " + method;
+ if (TraceBytecodeParserLevel.getValue(options) != 0) {
+ if (!Assertions.assertionsEnabled()) {
+ throw new IllegalArgumentException("A non-zero " + TraceBytecodeParserLevel.getName() + " value requires assertions to be enabled");
+ }
+ }
+
if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
lnt = code.getLineNumberTable();
previousLineNumber = -1;
@@ -1893,7 +1902,7 @@
LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
- LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected, NodeView.DEFAULT));
+ LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT));
JavaTypeProfile profile = null;
if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
@@ -2267,8 +2276,10 @@
}
protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
+ FixedWithNextNode calleeBeforeUnwindNode = null;
+ ValueNode calleeUnwindValue = null;
+
try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) {
-
BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph);
if (!targetMethod.isStatic()) {
@@ -2315,13 +2326,25 @@
}
}
- FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
+ calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
if (calleeBeforeUnwindNode != null) {
- ValueNode calleeUnwindValue = parser.getUnwindValue();
+ calleeUnwindValue = parser.getUnwindValue();
assert calleeUnwindValue != null;
- calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
}
}
+
+ /*
+ * Method handleException will call createTarget, which wires this exception edge to the
+ * corresponding exception dispatch block in the caller. In the case where it wires to the
+ * caller's unwind block, any FrameState created meanwhile, e.g., FrameState for
+ * LoopExitNode, would be instantiated with AFTER_EXCEPTION_BCI. Such frame states should
+ * not be fixed by IntrinsicScope.close, as they denote the states of the caller. Thus, the
+ * following code should be placed outside the IntrinsicScope, so that correctly created
+ * FrameStates are not replaced.
+ */
+ if (calleeBeforeUnwindNode != null) {
+ calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
+ }
}
public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
@@ -2773,6 +2796,10 @@
setCurrentFrameState(frameState);
currentBlock = block;
+ if (block != blockMap.getUnwindBlock() && !(block instanceof ExceptionDispatchBlock)) {
+ frameState.setRethrowException(false);
+ }
+
if (firstInstruction instanceof AbstractMergeNode) {
setMergeStateAfter(block, firstInstruction);
}
@@ -2782,7 +2809,6 @@
} else if (block instanceof ExceptionDispatchBlock) {
createExceptionDispatch((ExceptionDispatchBlock) block);
} else {
- frameState.setRethrowException(false);
iterateBytecodesForBlock(block);
}
}
@@ -3055,7 +3081,7 @@
}
private boolean traceState() {
- if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) {
+ if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) {
frameState.traceState();
}
return true;
@@ -3075,56 +3101,107 @@
ValueNode a = x;
ValueNode b = y;
+ BciBlock trueSuccessor = trueBlock;
+ BciBlock falseSuccessor = falseBlock;
+
+ CanonicalizedCondition canonicalizedCondition = cond.canonicalize();
// Check whether the condition needs to mirror the operands.
- if (cond.canonicalMirror()) {
+ if (canonicalizedCondition.mustMirror()) {
a = y;
b = x;
}
+ if (canonicalizedCondition.mustNegate()) {
+ trueSuccessor = falseBlock;
+ falseSuccessor = trueBlock;
+ }
// Create the logic node for the condition.
- LogicNode condition = createLogicNode(cond, a, b);
-
- // Check whether the condition needs to negate the result.
- boolean negate = cond.canonicalNegate();
- genIf(condition, negate, trueBlock, falseBlock);
- }
-
- protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) {
+ LogicNode condition = createLogicNode(canonicalizedCondition.getCanonicalCondition(), a, b);
+
+ double probability = -1;
+ if (condition instanceof IntegerEqualsNode) {
+ probability = extractInjectedProbability((IntegerEqualsNode) condition);
+ // the probability coming from here is about the actual condition
+ }
+
+ if (probability == -1) {
+ probability = getProfileProbability(canonicalizedCondition.mustNegate());
+ }
+
+ probability = clampProbability(probability);
+ genIf(condition, trueSuccessor, falseSuccessor, probability);
+ }
+
+ private double getProfileProbability(boolean negate) {
+ double probability;
+ if (profilingInfo == null) {
+ probability = 0.5;
+ } else {
+ assert assertAtIfBytecode();
+ probability = profilingInfo.getBranchTakenProbability(bci());
+ if (probability < 0) {
+ assert probability == -1 : "invalid probability";
+ debug.log("missing probability in %s at bci %d", code, bci());
+ probability = 0.5;
+ } else {
+ if (negate) {
+ // the probability coming from profile is about the original condition
+ probability = 1 - probability;
+ }
+ }
+ }
+ return probability;
+ }
+
+ private static double extractInjectedProbability(IntegerEqualsNode condition) {
+ // Propagate injected branch probability if any.
+ IntegerEqualsNode equalsNode = condition;
+ BranchProbabilityNode probabilityNode = null;
+ ValueNode other = null;
+ if (equalsNode.getX() instanceof BranchProbabilityNode) {
+ probabilityNode = (BranchProbabilityNode) equalsNode.getX();
+ other = equalsNode.getY();
+ } else if (equalsNode.getY() instanceof BranchProbabilityNode) {
+ probabilityNode = (BranchProbabilityNode) equalsNode.getY();
+ other = equalsNode.getX();
+ }
+
+ if (probabilityNode != null && probabilityNode.getProbability().isConstant() && other != null && other.isConstant()) {
+ double probabilityValue = probabilityNode.getProbability().asJavaConstant().asDouble();
+ return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue;
+ }
+ return -1;
+ }
+
+ protected void genIf(LogicNode conditionInput, BciBlock trueBlockInput, BciBlock falseBlockInput, double probabilityInput) {
BciBlock trueBlock = trueBlockInput;
BciBlock falseBlock = falseBlockInput;
LogicNode condition = conditionInput;
+ double probability = probabilityInput;
FrameState stateBefore = null;
ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
}
- // Remove a logic negation node and fold it into the negate boolean.
- boolean negate = negateCondition;
+ // Remove a logic negation node.
if (condition instanceof LogicNegationNode) {
LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
- negate = !negate;
+ BciBlock tmpBlock = trueBlock;
+ trueBlock = falseBlock;
+ falseBlock = tmpBlock;
+ probability = 1 - probability;
condition = logicNegationNode.getValue();
}
if (condition instanceof LogicConstantNode) {
- genConstantTargetIf(trueBlock, falseBlock, negate, condition);
+ genConstantTargetIf(trueBlock, falseBlock, condition);
} else {
if (condition.graph() == null) {
condition = genUnique(condition);
}
- // Need to get probability based on current bci.
- double probability = branchProbability(condition);
-
- if (negate) {
- BciBlock tmpBlock = trueBlock;
- trueBlock = falseBlock;
- falseBlock = tmpBlock;
- probability = 1 - probability;
- }
-
if (isNeverExecutedCode(probability)) {
append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
@@ -3200,28 +3277,26 @@
}
}
- private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) {
- LogicNode condition;
+ private LogicNode createLogicNode(CanonicalCondition cond, ValueNode a, ValueNode b) {
assert !a.getStackKind().isNumericFloat();
- if (cond == Condition.EQ || cond == Condition.NE) {
- if (a.getStackKind() == JavaKind.Object) {
- condition = genObjectEquals(a, b);
- } else {
- condition = genIntegerEquals(a, b);
- }
- } else {
- assert a.getStackKind() != JavaKind.Object && !cond.isUnsigned();
- condition = genIntegerLessThan(a, b);
+ switch (cond) {
+ case EQ:
+ if (a.getStackKind() == JavaKind.Object) {
+ return genObjectEquals(a, b);
+ } else {
+ return genIntegerEquals(a, b);
+ }
+ case LT:
+ assert a.getStackKind() != JavaKind.Object;
+ return genIntegerLessThan(a, b);
+ default:
+ throw GraalError.shouldNotReachHere("Unexpected condition: " + cond);
}
- return condition;
- }
-
- private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) {
+ }
+
+ private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition) {
LogicConstantNode constantLogicNode = (LogicConstantNode) condition;
boolean value = constantLogicNode.getValue();
- if (negate) {
- value = !value;
- }
BciBlock nextBlock = falseBlock;
if (value) {
nextBlock = trueBlock;
@@ -3775,7 +3850,13 @@
BciBlock firstSucc = currentBlock.getSuccessor(0);
BciBlock secondSucc = currentBlock.getSuccessor(1);
if (firstSucc != secondSucc) {
- genIf(instanceOfNode, value != Bytecodes.IFNE, firstSucc, secondSucc);
+ boolean negate = value != Bytecodes.IFNE;
+ if (negate) {
+ BciBlock tmp = firstSucc;
+ firstSucc = secondSucc;
+ secondSucc = tmp;
+ }
+ genIf(instanceOfNode, firstSucc, secondSucc, getProfileProbability(negate));
} else {
appendGoto(firstSucc);
}
@@ -4263,47 +4344,12 @@
return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions());
}
- private double rawBranchProbability(LogicNode conditionInput) {
- if (conditionInput instanceof IntegerEqualsNode) {
- // Propagate injected branch probability if any.
- IntegerEqualsNode condition = (IntegerEqualsNode) conditionInput;
- BranchProbabilityNode injectedProbability = null;
- ValueNode other = null;
- if (condition.getX() instanceof BranchProbabilityNode) {
- injectedProbability = (BranchProbabilityNode) condition.getX();
- other = condition.getY();
- } else if (condition.getY() instanceof BranchProbabilityNode) {
- injectedProbability = (BranchProbabilityNode) condition.getY();
- other = condition.getX();
- }
-
- if (injectedProbability != null && injectedProbability.getProbability().isConstant() && other != null && other.isConstant()) {
- double probabilityValue = injectedProbability.getProbability().asJavaConstant().asDouble();
- return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue;
- }
- }
-
- if (profilingInfo == null) {
- return 0.5;
- }
- assert assertAtIfBytecode();
-
- return profilingInfo.getBranchTakenProbability(bci());
- }
-
- protected double branchProbability(LogicNode conditionInput) {
- double probability = rawBranchProbability(conditionInput);
- if (probability < 0) {
- assert probability == -1 : "invalid probability";
- debug.log("missing probability in %s at bci %d", code, bci());
- probability = 0.5;
- }
-
+ private double clampProbability(double probability) {
if (!optimisticOpts.removeNeverExecutedCode(getOptions())) {
if (probability == 0) {
- probability = 0.0000001;
+ return 0.0000001;
} else if (probability == 1) {
- probability = 0.999999;
+ return 0.999999;
}
}
return probability;
@@ -4568,7 +4614,7 @@
}
protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
- if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) {
+ if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) {
traceInstructionHelper(bci, opcode, blockStart);
}
return true;
@@ -4589,7 +4635,7 @@
if (!currentBlock.getJsrScope().isEmpty()) {
sb.append(' ').append(currentBlock.getJsrScope());
}
- debug.log("%s", sb);
+ TTY.println("%s", sb);
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,7 +34,9 @@
*/
public class BytecodeParserOptions {
// @formatter:off
- @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug)
+ @Option(help = "The trace level for the bytecode parser. A value of 1 enables instruction tracing " +
+ "and any greater value emits a frame state trace just prior to an instruction trace. " +
+ "This option requires assertions to be enabled.", type = OptionType.Debug)
public static final OptionKey<Integer> TraceBytecodeParserLevel = new OptionKey<>(0);
@Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert)
@@ -56,7 +58,7 @@
public static final OptionKey<Boolean> TraceParserPlugins = new OptionKey<>(false);
@Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug)
- public static final OptionKey<Integer> InlineDuringParsingMaxDepth = new OptionKey<>(10);
+ public static final OptionKey<Integer> InlineDuringParsingMaxDepth = new OptionKey<>(3);
@Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug)
public static final OptionKey<Boolean> HideSubstitutionStates = new OptionKey<>(false);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,8 +22,11 @@
*/
package org.graalvm.compiler.java;
+import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities;
+
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.ControlSplitNode;
@@ -34,9 +37,6 @@
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
-import org.graalvm.util.EconomicMap;
-
-import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities;
public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure<Double> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -47,6 +47,7 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -999,15 +1000,14 @@
}
public void traceState() {
- DebugContext debug = graph.getDebug();
- debug.log("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod());
+ TTY.println("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod());
for (int i = 0; i < localsSize(); ++i) {
ValueNode value = locals[i];
- debug.log("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
+ TTY.println("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
}
for (int i = 0; i < stackSize(); ++i) {
ValueNode value = stack[i];
- debug.log("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
+ TTY.println("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,9 +26,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.AArch64Assembler.ConditionFlag;
@@ -43,7 +40,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 of the same length. If the CPU supports any vector
@@ -72,9 +68,8 @@
assert !kind.isNumericFloat() : "Float arrays comparison (bitwise_equal || both_NaN) isn't supported";
this.kind = kind;
- Class<?> arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass();
- this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass);
- this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass);
+ this.arrayBaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind);
+ this.arrayIndexScale = tool.getProviders().getArrayOffsetProvider().arrayScalingFactor(kind);
this.resultValue = result;
this.array1Value = array1;
@@ -218,20 +213,4 @@
masm.bind(end);
masm.mov(64, rscratch1, zr);
}
-
- 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 Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,12 +22,9 @@
*/
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 static jdk.vm.ci.code.ValueUtil.asRegister;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
@@ -50,7 +47,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 of the same length. If the CPU supports any vector
@@ -83,9 +79,8 @@
super(TYPE);
this.kind = kind;
- Class<?> arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass();
- this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass);
- this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass);
+ this.arrayBaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind);
+ this.arrayIndexScale = tool.getProviders().getArrayOffsetProvider().arrayScalingFactor(kind);
this.resultValue = result;
this.array1Value = array1;
@@ -531,20 +526,4 @@
// Floats within the range are equal, revert change to the register index
masm.subq(index, range);
}
-
- 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/AMD64Call.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java Sat Feb 10 09:25:35 2018 +0100
@@ -101,6 +101,10 @@
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
directCall(crb, masm, callTarget, null, true, state);
}
+
+ public int emitCall(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ return directCall(crb, masm, callTarget, null, true, state);
+ }
}
@Opcode("CALL_INDIRECT")
@@ -183,23 +187,27 @@
}
}
- public static void directCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) {
+ public static int directCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget callTarget, Register scratch, boolean align, LIRFrameState info) {
if (align) {
emitAlignmentForDirectCall(crb, masm);
}
int before = masm.position();
+ int callPCOffset;
if (scratch != null) {
// offset might not fit a 32-bit immediate, generate an
// indirect call with a 64-bit immediate
masm.movq(scratch, 0L);
+ callPCOffset = masm.position();
masm.call(scratch);
} else {
+ callPCOffset = masm.position();
masm.call();
}
int after = masm.position();
crb.recordDirectCall(before, after, callTarget, info);
crb.recordExceptionHandlers(after, info);
masm.ensureUniquePC();
+ return callPCOffset;
}
protected static void emitAlignmentForDirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
@@ -228,12 +236,13 @@
masm.ensureUniquePC();
}
- public static void indirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
+ public static int indirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
int before = masm.position();
masm.call(dst);
int after = masm.position();
crb.recordIndirectCall(before, after, callTarget, info);
crb.recordExceptionHandlers(after, info);
masm.ensureUniquePC();
+ return before;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,7 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Equal;
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
@@ -755,17 +756,18 @@
}
}
- public abstract static class Pointer extends AMD64LIRInstruction {
+ public abstract static class PointerCompressionOp extends AMD64LIRInstruction {
protected final LIRKindTool lirKindTool;
protected final CompressEncoding encoding;
protected final boolean nonNull;
@Def({REG, HINT}) private AllocatableValue result;
- @Use({REG}) private AllocatableValue input;
+ @Use({REG, CONST}) private Value input;
@Alive({REG, ILLEGAL}) private AllocatableValue baseRegister;
- protected Pointer(LIRInstructionClass<? extends Pointer> type, AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull,
- LIRKindTool lirKindTool) {
+ protected PointerCompressionOp(LIRInstructionClass<? extends PointerCompressionOp> type, AllocatableValue result, Value input,
+ AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+
super(type);
this.result = result;
this.input = input;
@@ -779,8 +781,12 @@
return GeneratePIC.getValue(crb.getOptions()) || encoding.hasBase();
}
- protected final Register getResultRegister() {
- return asRegister(result);
+ public final Value getInput() {
+ return input;
+ }
+
+ public final AllocatableValue getResult() {
+ return result;
}
protected final Register getBaseRegister() {
@@ -796,18 +802,24 @@
}
}
- public static final class CompressPointer extends Pointer {
- public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class);
+ public static class CompressPointerOp extends PointerCompressionOp {
+ public static final LIRInstructionClass<CompressPointerOp> TYPE = LIRInstructionClass.create(CompressPointerOp.class);
- public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
- super(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool);
+ public CompressPointerOp(AllocatableValue result, Value input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+ this(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool);
+ }
+
+ protected CompressPointerOp(LIRInstructionClass<? extends PointerCompressionOp> type, AllocatableValue result, Value input,
+ AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+
+ super(type, result, input, baseRegister, encoding, nonNull, lirKindTool);
}
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
move(lirKindTool.getObjectKind(), crb, masm);
- Register resReg = getResultRegister();
+ Register resReg = asRegister(getResult());
if (hasBase(crb)) {
Register baseReg = getBaseRegister();
if (!nonNull) {
@@ -824,18 +836,24 @@
}
}
- public static final class UncompressPointer extends Pointer {
- public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class);
+ public static class UncompressPointerOp extends PointerCompressionOp {
+ public static final LIRInstructionClass<UncompressPointerOp> TYPE = LIRInstructionClass.create(UncompressPointerOp.class);
- public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
- super(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool);
+ public UncompressPointerOp(AllocatableValue result, Value input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+ this(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool);
+ }
+
+ protected UncompressPointerOp(LIRInstructionClass<? extends PointerCompressionOp> type, AllocatableValue result, Value input,
+ AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+
+ super(type, result, input, baseRegister, encoding, nonNull, lirKindTool);
}
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
move(lirKindTool.getNarrowOopKind(), crb, masm);
- Register resReg = getResultRegister();
+ Register resReg = asRegister(getResult());
int shift = getShift();
if (shift != 0) {
masm.shlq(resReg, shift);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,11 +22,13 @@
*/
package org.graalvm.compiler.lir.amd64;
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static jdk.vm.ci.code.ValueUtil.asStackSlot;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import java.util.Arrays;
+
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.LIRValueUtil;
@@ -34,7 +36,6 @@
import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.framemap.FrameMap;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,13 +24,13 @@
import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.framemap.FrameMap;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterSaveLayout;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -36,9 +36,6 @@
import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual;
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.sparc.SPARCAddress;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
@@ -52,7 +49,6 @@
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.sparc.SPARCKind;
-import sun.misc.Unsafe;
/**
* Emits code which compares two arrays of the same length.
@@ -82,9 +78,8 @@
assert !kind.isNumericFloat() : "Float arrays comparison (bitwise_equal || both_NaN) isn't supported";
this.kind = kind;
- Class<?> arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass();
- this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass);
- this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass);
+ this.arrayBaseOffset = tool.getProviders().getArrayOffsetProvider().arrayBaseOffset(kind);
+ this.arrayIndexScale = tool.getProviders().getArrayOffsetProvider().arrayScalingFactor(kind);
this.resultValue = result;
this.array1Value = array1;
@@ -247,20 +242,4 @@
}
}
}
-
- 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.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Sat Feb 10 09:25:35 2018 +0100
@@ -78,6 +78,8 @@
import java.util.EnumSet;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Assembler.LabelHint;
import org.graalvm.compiler.asm.Label;
@@ -98,8 +100,6 @@
import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,12 +22,14 @@
*/
package org.graalvm.compiler.lir.sparc;
+import static jdk.vm.ci.code.ValueUtil.asStackSlot;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer.DUMMY;
-import static jdk.vm.ci.code.ValueUtil.asStackSlot;
-import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import java.util.Arrays;
+
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.sparc.SPARCAddress;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
@@ -36,7 +38,6 @@
import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.framemap.FrameMap;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterSaveLayout;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,15 +27,14 @@
import java.util.HashSet;
+import org.graalvm.collections.Pair;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue;
+import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
-import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue;
-import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase;
-import org.graalvm.util.Pair;
-
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.RegisterValue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Sat Feb 10 09:25:35 2018 +0100
@@ -33,14 +33,14 @@
import java.util.Arrays;
import java.util.EnumSet;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.core.common.FieldIntrospection;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.FieldsScanner;
import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
import jdk.vm.ci.code.RegisterValue;
import jdk.vm.ci.code.StackSlot;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,7 +30,8 @@
import java.util.Collections;
import java.util.EnumSet;
-import jdk.vm.ci.code.RegisterConfig;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.CounterKey;
@@ -43,11 +44,10 @@
import org.graalvm.compiler.lir.framemap.FrameMap;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterArray;
+import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.RegisterValue;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,12 +31,12 @@
import java.util.ArrayList;
import java.util.EnumSet;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.framemap.FrameMap;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterSaveLayout;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Sat Feb 10 09:25:35 2018 +0100
@@ -35,6 +35,7 @@
import java.util.BitSet;
import java.util.EnumSet;
+import org.graalvm.collections.Pair;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
@@ -60,7 +61,6 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.Pair;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterArray;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -35,6 +35,8 @@
import java.util.BitSet;
import java.util.EnumSet;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
@@ -56,8 +58,6 @@
import org.graalvm.compiler.lir.alloc.lsra.LinearScan.BlockData;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterArray;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,10 +22,10 @@
*/
package org.graalvm.compiler.lir.alloc.lsra;
+import org.graalvm.collections.Pair;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
-import org.graalvm.util.Pair;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,8 @@
import java.util.ArrayList;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
@@ -37,8 +39,6 @@
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LIRValueUtil;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.Constant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -32,13 +32,15 @@
import java.util.List;
import java.util.function.Consumer;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.asm.AbstractAddress;
import org.graalvm.compiler.asm.Assembler;
-import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
import org.graalvm.compiler.code.DataSection.Data;
import org.graalvm.compiler.code.DataSection.RawData;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.DataPointerConstant;
@@ -55,8 +57,6 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.DebugInfo;
@@ -324,12 +324,32 @@
}
/**
- * Notifies this object of a branch instruction at offset {@code pos} in the code.
+ * Notifies this object of a branch instruction at offset {@code pcOffset} in the code.
*
* @param isNegated negation status of the branch's condition.
*/
@SuppressWarnings("unused")
- public void recordBranch(int pos, boolean isNegated) {
+ public void recordBranch(int pcOffset, boolean isNegated) {
+ }
+
+ /**
+ * Notifies this object of a call instruction belonging to an INVOKEVIRTUAL or INVOKEINTERFACE
+ * at offset {@code pcOffset} in the code.
+ *
+ * @param nodeSourcePosition source position of the corresponding invoke.
+ */
+ @SuppressWarnings("unused")
+ public void recordInvokeVirtualOrInterfaceCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition) {
+ }
+
+ /**
+ * Notifies this object of a call instruction belonging to an INLINE_INVOKE at offset
+ * {@code pcOffset} in the code.
+ *
+ * @param nodeSourcePosition source position of the corresponding invoke.
+ */
+ @SuppressWarnings("unused")
+ public void recordInlineInvokeCallOp(int pcOffset, NodeSourcePosition nodeSourcePosition) {
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,8 @@
*/
package org.graalvm.compiler.lir.gen;
-import jdk.vm.ci.code.RegisterConfig;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
import org.graalvm.compiler.debug.DebugContext;
@@ -30,10 +31,9 @@
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.framemap.FrameMap;
import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.RegisterConfig;
public class LIRGenerationResult {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,20 +22,20 @@
*/
package org.graalvm.compiler.lir.gen;
-import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
import static jdk.vm.ci.code.ValueUtil.isIllegal;
import static jdk.vm.ci.code.ValueUtil.isLegal;
import static jdk.vm.ci.meta.Value.ILLEGAL;
+import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.lir.LIRInsertionBuffer;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/PreAllocationOptimizationStage.java Sat Feb 10 09:25:35 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 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
@@ -31,7 +31,7 @@
public PreAllocationOptimizationStage(OptionValues options) {
if (ConstantLoadOptimization.Options.LIROptConstantLoadOptimization.getValue(options)) {
appendPhase(new ConstantLoadOptimization());
- appendPhase(new SaveCalleeSaveRegisters());
}
+ appendPhase(new SaveCalleeSaveRegisters());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,6 +31,8 @@
import java.util.Deque;
import java.util.EnumSet;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.debug.CounterKey;
@@ -43,8 +45,6 @@
import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
import org.graalvm.compiler.lir.VirtualStackSlot;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Sat Feb 10 09:25:35 2018 +0100
@@ -35,6 +35,7 @@
import java.util.EnumSet;
import java.util.PriorityQueue;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
@@ -54,7 +55,6 @@
import org.graalvm.compiler.options.NestedBooleanOptionKey;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionType;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.lir.util;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,7 +31,7 @@
import java.util.List;
import org.graalvm.compiler.core.common.RetryableBailoutException;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph.Mark;
@@ -451,7 +451,7 @@
if (!(condition instanceof CompareNode)) {
return false;
}
- if (((CompareNode) condition).condition() == Condition.EQ || ((CompareNode) condition).condition() == Condition.NE) {
+ if (((CompareNode) condition).condition() == CanonicalCondition.EQ) {
condition.getDebug().log(DebugContext.VERBOSE_LEVEL, "isUnrollableLoop %s condition unsupported %s ", loopBegin, ((CompareNode) condition).condition());
return false;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -73,12 +73,18 @@
Stamp stamp = iv.valueNode().stamp(NodeView.DEFAULT);
ValueNode range = sub(graph, end, iv.initNode());
+ ValueNode max;
+ ValueNode min;
ValueNode oneDirection;
if (iv.direction() == Direction.Up) {
oneDirection = ConstantNode.forIntegerStamp(stamp, 1, graph);
+ max = end;
+ min = iv.initNode();
} else {
assert iv.direction() == Direction.Down;
oneDirection = ConstantNode.forIntegerStamp(stamp, -1, graph);
+ max = iv.initNode();
+ min = end;
}
if (oneOff) {
range = add(graph, range, oneDirection);
@@ -95,7 +101,7 @@
return div;
}
ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph);
- return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(zero, div)), div, zero));
+ return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(max, min)), zero, div));
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,13 @@
*/
package org.graalvm.compiler.loop;
-import jdk.vm.ci.code.BytecodeFrame;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.IntegerStamp;
@@ -67,13 +73,8 @@
import org.graalvm.compiler.nodes.debug.ControlFlowAnchored;
import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Queue;
+import jdk.vm.ci.code.BytecodeFrame;
public class LoopEx {
private final Loop<Block> loop;
@@ -236,13 +237,13 @@
if (isOutsideLoop(lessThan.getX())) {
iv = getInductionVariables().get(lessThan.getY());
if (iv != null) {
- condition = lessThan.condition().mirror();
+ condition = lessThan.condition().asCondition().mirror();
limit = lessThan.getX();
}
} else if (isOutsideLoop(lessThan.getY())) {
iv = getInductionVariables().get(lessThan.getX());
if (iv != null) {
- condition = lessThan.condition();
+ condition = lessThan.condition().asCondition();
limit = lessThan.getY();
}
}
@@ -393,8 +394,8 @@
} else {
boolean isValidConvert = op instanceof PiNode || op instanceof SignExtendNode;
if (!isValidConvert && op instanceof ZeroExtendNode) {
- IntegerStamp inputStamp = (IntegerStamp) ((ZeroExtendNode) op).getValue().stamp(NodeView.DEFAULT);
- isValidConvert = inputStamp.isPositive();
+ ZeroExtendNode zeroExtendNode = (ZeroExtendNode) op;
+ isValidConvert = zeroExtendNode.isInputAlwaysPositive() || ((IntegerStamp) zeroExtendNode.stamp(NodeView.DEFAULT)).isPositive();
}
if (isValidConvert) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,12 @@
*/
package org.graalvm.compiler.loop;
-import jdk.vm.ci.meta.TriState;
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.Iterator;
+
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
@@ -52,12 +57,8 @@
import org.graalvm.compiler.nodes.spi.NodeWithState;
import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.util.EconomicMap;
-import java.util.ArrayDeque;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.Iterator;
+import jdk.vm.ci.meta.TriState;
public abstract class LoopFragment {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,8 @@
import java.util.LinkedList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
@@ -62,8 +64,6 @@
import org.graalvm.compiler.nodes.calc.SubNode;
import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
public class LoopFragmentInside extends LoopFragment {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.loop;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph;
@@ -35,7 +36,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.cfg.Block;
-import org.graalvm.util.EconomicSet;
public class LoopFragmentWhole extends LoopFragment {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,6 +27,9 @@
import java.util.LinkedList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.LoopBeginNode;
@@ -34,9 +37,6 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
public class LoopsData {
private final EconomicMap<LoopBeginNode, LoopEx> loopBeginToEx = EconomicMap.create(Equivalence.IDENTITY);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/SchedulePhaseBenchmark.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,9 @@
import java.util.Arrays;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Warmup;
import org.graalvm.compiler.microbenchmarks.graal.util.MethodSpec;
@@ -32,7 +34,8 @@
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
-@Warmup(iterations = 15)
+@Warmup(iterations = 20)
+@Measurement(iterations = 10)
public class SchedulePhaseBenchmark extends GraalBenchmark {
@MethodSpec(declaringClass = String.class, name = "equals")
@@ -117,5 +120,67 @@
public void intersection_EARLIEST_OPTIMAL(IntersectionState_EARLIEST_OPTIMAL s) {
s.schedule.apply(s.graph);
}
+
+ @MethodSpec(declaringClass = SchedulePhaseBenchmark.class, name = "intersectionSnippet")
+ public static class IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL extends ScheduleState {
+ public IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL() {
+ super(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
+ }
+ }
+
+ @Benchmark
+ public void intersection_EARLIEST_WITH_GUARD_ORDER_OPTIMAL(IntersectionState_EARLIEST_WITH_GUARD_ORDER_OPTIMAL s) {
+ s.schedule.apply(s.graph);
+ }
+ // Checkstyle: resume method name check
+
+ // Checkstyle: stop method name check
+ @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative")
+ public static class ScheduleEarliestIterative_LATEST_OPTIMAL extends ScheduleState {
+ public ScheduleEarliestIterative_LATEST_OPTIMAL() {
+ super(SchedulingStrategy.LATEST);
+ }
+ }
+
+ @Benchmark
+ public void scheduleEarliestIterative_LATEST_OPTIMAL(ScheduleEarliestIterative_LATEST_OPTIMAL s) {
+ s.schedule.apply(s.graph);
+ }
+
+ @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative")
+ public static class ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL extends ScheduleState {
+ public ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL() {
+ super(SchedulingStrategy.LATEST_OUT_OF_LOOPS);
+ }
+ }
+
+ @Benchmark
+ public void scheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL(ScheduleEarliestIterative_LATEST_OUT_OF_LOOPS_OPTIMAL s) {
+ s.schedule.apply(s.graph);
+ }
+
+ @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative")
+ public static class ScheduleEarliestIterative_EARLIEST_OPTIMAL extends ScheduleState {
+ public ScheduleEarliestIterative_EARLIEST_OPTIMAL() {
+ super(SchedulingStrategy.EARLIEST);
+ }
+ }
+
+ @Benchmark
+ public void scheduleEarliestIterative_EARLIEST_OPTIMAL(ScheduleEarliestIterative_EARLIEST_OPTIMAL s) {
+ s.schedule.apply(s.graph);
+ }
+
+ @MethodSpec(declaringClass = SchedulePhase.Instance.class, name = "scheduleEarliestIterative")
+ public static class ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL extends ScheduleState {
+ public ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL() {
+ super(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
+ }
+ }
+
+ @Benchmark
+ public void scheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL(ScheduleEarliestIterative_EARLIEST_WITH_GUARD_ORDER_OPTIMAL s) {
+ s.schedule.apply(s.graph);
+ }
// Checkstyle: resume method name check
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/ScheduleState.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,8 +22,12 @@
*/
package org.graalvm.compiler.microbenchmarks.graal.util;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
public class ScheduleState extends GraphState {
@@ -36,7 +40,7 @@
}
public ScheduleState() {
- this(SchedulingStrategy.EARLIEST);
+ this(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
}
@Override
@@ -44,4 +48,13 @@
schedule = new SchedulePhase(selectedStrategy);
super.beforeInvocation();
}
+
+ @Override
+ protected StructuredGraph preprocessOriginal(StructuredGraph structuredGraph) {
+ StructuredGraph g = super.preprocessOriginal(structuredGraph);
+ GraalState graal = new GraalState();
+ PhaseSuite<HighTierContext> highTier = graal.backend.getSuites().getDefaultSuites(graal.options).getHighTier();
+ highTier.apply(g, new HighTierContext(graal.providers, graal.backend.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL));
+ return g;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -156,11 +156,11 @@
PhaseContext context = new PhaseContext(getProviders());
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+ new ConvertDeoptimizeToGuardPhase().apply(graph, context);
graph.clearAllStateAfter();
graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA);
canonicalizer.apply(graph, context);
- new ConvertDeoptimizeToGuardPhase().apply(graph, context);
// new DominatorConditionalEliminationPhase(true).apply(graph, context);
new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context);
canonicalizer.apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -129,10 +129,13 @@
if (ret == null) {
throw new NoSuchElementException();
}
- if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) {
+ if (current instanceof FixedWithNextNode) {
+ current = ((FixedWithNextNode) current).next();
+ if (current instanceof AbstractBeginNode) {
+ current = null;
+ }
+ } else {
current = null;
- } else {
- current = ((FixedWithNextNode) current).next();
}
return ret;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ControlSplitNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -49,7 +49,7 @@
/**
* Primary successor of the control split. Data dependencies on the node have to be scheduled in
- * the primary successor.
+ * the primary successor. Returns null if data dependencies are not expected.
*
* @return the primary successor
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -39,7 +39,7 @@
import jdk.vm.ci.meta.Value;
@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable {
+public final class DeoptimizeNode extends AbstractDeoptimizeNode implements Lowerable, LIRLowerable, StaticDeoptimizingNode {
public static final int DEFAULT_DEBUG_ID = 0;
public static final NodeClass<DeoptimizeNode> TYPE = NodeClass.create(DeoptimizeNode.class);
@@ -67,11 +67,13 @@
this.speculation = speculation;
}
- public DeoptimizationAction action() {
+ @Override
+ public DeoptimizationAction getAction() {
return action;
}
- public DeoptimizationReason reason() {
+ @Override
+ public DeoptimizationReason getReason() {
return reason;
}
@@ -115,6 +117,7 @@
return ConstantNode.forConstant(speculation, metaAccess, graph());
}
+ @Override
public JavaConstant getSpeculation() {
return speculation;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizingGuard.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,25 +24,15 @@
import org.graalvm.compiler.nodes.extended.GuardingNode;
-import jdk.vm.ci.meta.DeoptimizationAction;
-import jdk.vm.ci.meta.DeoptimizationReason;
-import jdk.vm.ci.meta.JavaConstant;
-
/**
* Shared interface to capture core methods of {@link AbstractFixedGuardNode} and {@link GuardNode}.
*
*/
-public interface DeoptimizingGuard extends ValueNodeInterface, GuardingNode {
+public interface DeoptimizingGuard extends GuardingNode, StaticDeoptimizingNode {
LogicNode getCondition();
void setCondition(LogicNode x, boolean negated);
- DeoptimizationReason getReason();
-
- DeoptimizationAction getAction();
-
- JavaConstant getSpeculation();
-
boolean isNegated();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -83,15 +83,7 @@
@Override
public void lower(LoweringTool tool) {
if (graph().getGuardsStage().allowsFloatingGuards()) {
- /*
- * Don't allow guards with action None and reason RuntimeConstraint to float. In cases
- * where 2 guards are testing equivalent conditions they might be lowered at the same
- * location. If the guard with the None action is lowered before the other guard then
- * the code will be stuck repeatedly deoptimizing without invalidating the code.
- * Conditional elimination will eliminate the guard if it's truly redundant in this
- * case.
- */
- if (getAction() != DeoptimizationAction.None || getReason() != DeoptimizationReason.RuntimeConstraint) {
+ if (getAction() != DeoptimizationAction.None) {
ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode();
this.replaceAtUsages(guard);
graph().removeFixed(this);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Sat Feb 10 09:25:35 2018 +0100
@@ -37,6 +37,9 @@
import java.util.SortedMap;
import java.util.TreeMap;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.util.TypeReader;
@@ -62,9 +65,6 @@
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.meta.DeoptimizationAction;
@@ -489,7 +489,8 @@
*/
LoopScope outerScope = loopScope.outer;
int nextIterationNumber = outerScope.nextIterations.isEmpty() ? outerScope.loopIteration + 1 : outerScope.nextIterations.getLast().loopIteration + 1;
- successorAddScope = new LoopScope(methodScope, outerScope.outer, outerScope.loopDepth, nextIterationNumber, outerScope.loopBeginOrderId, outerScope.initialCreatedNodes,
+ successorAddScope = new LoopScope(methodScope, outerScope.outer, outerScope.loopDepth, nextIterationNumber, outerScope.loopBeginOrderId,
+ outerScope.initialCreatedNodes == null ? null : Arrays.copyOf(outerScope.initialCreatedNodes, outerScope.initialCreatedNodes.length),
Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), outerScope.nextIterations, outerScope.iterationStates);
checkLoopExplosionIteration(methodScope, successorAddScope);
@@ -736,7 +737,8 @@
assert methodScope.loopExplosion != LoopExplosionKind.NONE;
if (methodScope.loopExplosion != LoopExplosionKind.FULL_UNROLL || loopScope.nextIterations.isEmpty()) {
int nextIterationNumber = loopScope.nextIterations.isEmpty() ? loopScope.loopIteration + 1 : loopScope.nextIterations.getLast().loopIteration + 1;
- LoopScope nextIterationScope = new LoopScope(methodScope, loopScope.outer, loopScope.loopDepth, nextIterationNumber, loopScope.loopBeginOrderId, loopScope.initialCreatedNodes,
+ LoopScope nextIterationScope = new LoopScope(methodScope, loopScope.outer, loopScope.loopDepth, nextIterationNumber, loopScope.loopBeginOrderId,
+ Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length),
Arrays.copyOf(loopScope.initialCreatedNodes, loopScope.initialCreatedNodes.length), loopScope.nextIterations, loopScope.iterationStates);
checkLoopExplosionIteration(methodScope, nextIterationScope);
loopScope.nextIterations.addLast(nextIterationScope);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,6 +27,8 @@
import java.util.Iterator;
import java.util.Objects;
+import org.graalvm.collections.Pair;
+import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.util.FrequencyEncoder;
import org.graalvm.compiler.core.common.util.TypeConversion;
@@ -42,8 +44,6 @@
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
-import org.graalvm.util.Pair;
-import org.graalvm.util.UnmodifiableMapCursor;
import jdk.vm.ci.code.Architecture;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,8 @@
import java.util.Iterator;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -59,8 +61,6 @@
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.JavaConstant;
@@ -557,7 +557,7 @@
} else if (next1 instanceof DeoptimizeNode && next2 instanceof DeoptimizeNode) {
DeoptimizeNode deopt1 = (DeoptimizeNode) next1;
DeoptimizeNode deopt2 = (DeoptimizeNode) next2;
- if (deopt1.reason() == deopt2.reason() && deopt1.action() == deopt2.action()) {
+ if (deopt1.getReason() == deopt2.getReason() && deopt1.getAction() == deopt2.getAction()) {
// Same deoptimization reason and action.
return true;
}
@@ -600,7 +600,7 @@
}
} else if (a instanceof CompareNode) {
CompareNode compareA = (CompareNode) a;
- Condition conditionA = compareA.condition();
+ Condition conditionA = compareA.condition().asCondition();
if (compareA.unorderedIsTrue()) {
return false;
}
@@ -614,7 +614,7 @@
return false;
}
Condition comparableCondition = null;
- Condition conditionB = compareB.condition();
+ Condition conditionB = compareB.condition().asCondition();
if (compareB.getX() == compareA.getX() && compareB.getY() == compareA.getY()) {
comparableCondition = conditionB;
} else if (compareB.getX() == compareA.getY() && compareB.getY() == compareA.getX()) {
@@ -1384,7 +1384,7 @@
@Override
public AbstractBeginNode getPrimarySuccessor() {
- return this.trueSuccessor();
+ return null;
}
public AbstractBeginNode getSuccessor(boolean result) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,278 @@
+/*
+ * 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.nodes;
+
+import jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class contains all inlining decisions performed on a graph during the compilation.
+ *
+ * Each inlining decision consists of:
+ *
+ * <ul>
+ * <li>a value indicating whether the decision was positive or negative</li>
+ * <li>the call target method</li>
+ * <li>the reason for the inlining decision</li>
+ * <li>the name of the phase in which the inlining decision took place</li>
+ * <li>the special {@link BytecodePositionWithId} value that describes the position in the bytecode
+ * together with the callsite-specific unique identifier</li>
+ * <li>the inlining log of the inlined graph, or {@code null} if the decision was negative</li>
+ * </ul>
+ *
+ * A phase that does inlining should use the instance of this class contained in the
+ * {@link StructuredGraph} by calling {@link #addDecision} whenever it decides to inline a method.
+ * If there are invokes in the graph at the end of the respective phase, then that phase must call
+ * {@link #addDecision} to log negative decisions.
+ *
+ * At the end of the compilation, the contents of the inlining log can be converted into a list of
+ * decisions by calling {@link #formatAsList} or into an inlining tree, by calling
+ * {@link #formatAsTree}.
+ */
+public class InliningLog {
+ /**
+ * A bytecode position with a unique identifier attached.
+ *
+ * The purpose of this class is to disambiguate callsites that are duplicated by a
+ * transformation (such as loop peeling or path duplication).
+ */
+ public static final class BytecodePositionWithId extends BytecodePosition implements Comparable<BytecodePositionWithId> {
+ private final int id;
+
+ public BytecodePositionWithId(BytecodePositionWithId caller, ResolvedJavaMethod method, int bci, int id) {
+ super(caller, method, bci);
+ this.id = id;
+ }
+
+ public BytecodePositionWithId addCallerWithId(BytecodePositionWithId caller) {
+ if (getCaller() == null) {
+ return new BytecodePositionWithId(caller, getMethod(), getBCI(), id);
+ } else {
+ return new BytecodePositionWithId(getCaller().addCallerWithId(caller), getMethod(), getBCI(), id);
+ }
+ }
+
+ public static BytecodePositionWithId create(FrameState state) {
+ return create(state, true);
+ }
+
+ @SuppressWarnings("deprecation")
+ private static BytecodePositionWithId create(FrameState state, boolean topLevel) {
+ if (state == null) {
+ return null;
+ }
+ ResolvedJavaMethod method = state.getMethod();
+ int bci = topLevel ? state.bci - 3 : state.bci;
+ int id = state.getId();
+ return new BytecodePositionWithId(create(state.outerFrameState(), false), method, bci, id);
+ }
+
+ @Override
+ public BytecodePositionWithId getCaller() {
+ return (BytecodePositionWithId) super.getCaller();
+ }
+
+ public BytecodePositionWithId withoutCaller() {
+ return new BytecodePositionWithId(null, getMethod(), getBCI(), id);
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ return super.equals(that) && this.id == ((BytecodePositionWithId) that).id;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() ^ (id << 16);
+ }
+
+ @Override
+ public int compareTo(BytecodePositionWithId that) {
+ int diff = this.getBCI() - that.getBCI();
+ if (diff != 0) {
+ return diff;
+ }
+ diff = (int) (this.getId() - that.getId());
+ return diff;
+ }
+ }
+
+ public static final class Decision {
+ private final boolean positive;
+ private final String reason;
+ private final String phase;
+ private final ResolvedJavaMethod target;
+ private final BytecodePositionWithId position;
+ private final InliningLog childLog;
+
+ private Decision(boolean positive, String reason, String phase, ResolvedJavaMethod target, BytecodePositionWithId position, InliningLog childLog) {
+ assert position != null;
+ this.positive = positive;
+ this.reason = reason;
+ this.phase = phase;
+ this.target = target;
+ this.position = position;
+ this.childLog = childLog;
+ }
+
+ public boolean isPositive() {
+ return positive;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getPhase() {
+ return phase;
+ }
+
+ public BytecodePositionWithId getPosition() {
+ return position;
+ }
+
+ public InliningLog getChildLog() {
+ return childLog;
+ }
+
+ public ResolvedJavaMethod getTarget() {
+ return target;
+ }
+ }
+
+ private static class Callsite {
+ public final List<String> decisions;
+ public final Map<BytecodePositionWithId, Callsite> children;
+ public final BytecodePositionWithId position;
+
+ Callsite(BytecodePositionWithId position) {
+ this.children = new HashMap<>();
+ this.position = position;
+ this.decisions = new ArrayList<>();
+ }
+
+ public Callsite getOrCreateChild(BytecodePositionWithId fromRootPosition) {
+ Callsite child = children.get(fromRootPosition.withoutCaller());
+ if (child == null) {
+ child = new Callsite(fromRootPosition);
+ children.put(fromRootPosition.withoutCaller(), child);
+ }
+ return child;
+ }
+
+ public Callsite createCallsite(BytecodePositionWithId fromRootPosition, String decision) {
+ Callsite parent = getOrCreateCallsite(fromRootPosition.getCaller());
+ Callsite callsite = parent.getOrCreateChild(fromRootPosition);
+ callsite.decisions.add(decision);
+ return null;
+ }
+
+ private Callsite getOrCreateCallsite(BytecodePositionWithId fromRootPosition) {
+ if (fromRootPosition == null) {
+ return this;
+ } else {
+ Callsite parent = getOrCreateCallsite(fromRootPosition.getCaller());
+ Callsite callsite = parent.getOrCreateChild(fromRootPosition);
+ return callsite;
+ }
+ }
+ }
+
+ private final List<Decision> decisions;
+
+ public InliningLog() {
+ this.decisions = new ArrayList<>();
+ }
+
+ public List<Decision> getDecisions() {
+ return decisions;
+ }
+
+ public void addDecision(boolean positive, String reason, String phase, ResolvedJavaMethod target, BytecodePositionWithId position,
+ InliningLog calleeLog) {
+ Decision decision = new Decision(positive, reason, phase, target, position, calleeLog);
+ decisions.add(decision);
+ }
+
+ public String formatAsList() {
+ StringBuilder builder = new StringBuilder();
+ formatAsList("", null, decisions, builder);
+ return builder.toString();
+ }
+
+ private void formatAsList(String phasePrefix, BytecodePositionWithId caller, List<Decision> subDecisions, StringBuilder builder) {
+ for (Decision decision : subDecisions) {
+ String phaseStack = phasePrefix.equals("") ? decision.getPhase() : phasePrefix + "-" + decision.getPhase();
+ String target = decision.getTarget().format("%H.%n(%p)");
+ String positive = decision.isPositive() ? "inline" : "do not inline";
+ BytecodePositionWithId absolutePosition = decision.getPosition().addCallerWithId(caller);
+ String position = " " + decision.getPosition().toString().replaceAll("\n", "\n ");
+ String line = String.format("<%s> %s %s: %s\n%s", phaseStack, positive, target, decision.getReason(), position);
+ builder.append(line).append(System.lineSeparator());
+ if (decision.getChildLog() != null) {
+ formatAsList(phaseStack, absolutePosition, decision.getChildLog().getDecisions(), builder);
+ }
+ }
+ }
+
+ public String formatAsTree() {
+ Callsite root = new Callsite(null);
+ createTree("", null, root, decisions);
+ StringBuilder builder = new StringBuilder();
+ formatAsTree(root, "", builder);
+ return builder.toString();
+ }
+
+ private void createTree(String phasePrefix, BytecodePositionWithId caller, Callsite root, List<Decision> subDecisions) {
+ for (Decision decision : subDecisions) {
+ String phaseStack = phasePrefix.equals("") ? decision.getPhase() : phasePrefix + "-" + decision.getPhase();
+ String target = decision.getTarget().format("%H.%n(%p)");
+ BytecodePositionWithId absolutePosition = decision.getPosition().addCallerWithId(caller);
+ String line = String.format("<%s> %s: %s", phaseStack, target, decision.getReason());
+ root.createCallsite(absolutePosition, line);
+ if (decision.getChildLog() != null) {
+ createTree(phaseStack, absolutePosition, root, decision.getChildLog().getDecisions());
+ }
+ }
+ }
+
+ private void formatAsTree(Callsite site, String indent, StringBuilder builder) {
+ String position = site.position != null ? site.position.withoutCaller().toString() : "<root>";
+ String decision = String.join("; ", site.decisions);
+ String line = String.format("%s%s; %s", indent, position, decision);
+ builder.append(line).append(System.lineSeparator());
+ String childIndent = indent + " ";
+ site.children.entrySet().stream().sorted((x, y) -> x.getKey().compareTo(y.getKey())).forEach(e -> {
+ formatAsTree(e.getValue(), childIndent, builder);
+ });
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,9 +24,9 @@
import java.util.EnumMap;
-import org.graalvm.util.Equivalence;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.word.LocationIdentity;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaKind.FormatWithToString;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StaticDeoptimizingNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.nodes;
+
+import org.graalvm.compiler.debug.GraalError;
+
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+
+public interface StaticDeoptimizingNode extends ValueNodeInterface {
+
+ DeoptimizationReason getReason();
+
+ DeoptimizationAction getAction();
+
+ JavaConstant getSpeculation();
+
+ /**
+ * Describes how much information is gathered when deoptimization triggers.
+ *
+ * This enum is {@link Comparable} and orders its element from highest priority to lowest
+ * priority.
+ */
+ enum GuardPriority {
+ Speculation,
+ Profile,
+ None;
+
+ public boolean isHigherPriorityThan(GuardPriority other) {
+ return this.compareTo(other) < 0;
+ }
+
+ public boolean isLowerPriorityThan(GuardPriority other) {
+ return this.compareTo(other) > 0;
+ }
+
+ public static GuardPriority highest() {
+ return Speculation;
+ }
+ }
+
+ default GuardPriority computePriority() {
+ if (getSpeculation() != null && getSpeculation().isNonNull()) {
+ return GuardNode.GuardPriority.Speculation;
+ }
+ switch (getAction()) {
+ case InvalidateReprofile:
+ case InvalidateRecompile:
+ return GuardNode.GuardPriority.Profile;
+ case RecompileIfTooManyDeopts:
+ case InvalidateStopCompiling:
+ case None:
+ return GuardNode.GuardPriority.None;
+ }
+ throw GraalError.shouldNotReachHere();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,10 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.core.common.CancellationBailoutException;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.GraalOptions;
@@ -38,6 +42,7 @@
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeMap;
+import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
@@ -45,10 +50,6 @@
import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.Assumptions.Assumption;
@@ -169,6 +170,7 @@
private final OptionValues options;
private Cancellable cancellable = null;
private final DebugContext debug;
+ private NodeSourcePosition callerContext;
/**
* Creates a builder for a graph.
@@ -255,8 +257,13 @@
return this;
}
+ public Builder callerContext(NodeSourcePosition context) {
+ this.callerContext = context;
+ return this;
+ }
+
public StructuredGraph build() {
- return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, compilationId, options, debug, cancellable);
+ return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, compilationId, options, debug, cancellable, callerContext);
}
}
@@ -284,6 +291,13 @@
private ScheduleResult lastSchedule;
+ private final InliningLog inliningLog;
+
+ /**
+ * Call stack (context) leading to construction of this graph.
+ */
+ private final NodeSourcePosition callerContext;
+
/**
* Records the methods that were used while constructing this graph, one entry for each time a
* specific method is used.
@@ -317,7 +331,8 @@
CompilationIdentifier compilationId,
OptionValues options,
DebugContext debug,
- Cancellable cancellable) {
+ Cancellable cancellable,
+ NodeSourcePosition context) {
super(name, options, debug);
this.setStart(add(new StartNode()));
this.rootMethod = method;
@@ -328,6 +343,8 @@
this.speculationLog = speculationLog;
this.useProfilingInfo = useProfilingInfo;
this.cancellable = cancellable;
+ this.inliningLog = new InliningLog();
+ this.callerContext = context;
}
public void setLastSchedule(ScheduleResult result) {
@@ -436,6 +453,10 @@
this.start = start;
}
+ public InliningLog getInliningLog() {
+ return inliningLog;
+ }
+
/**
* Creates a copy of this graph.
*
@@ -459,7 +480,7 @@
speculationLog,
useProfilingInfo,
newCompilationId,
- getOptions(), debugForCopy, null);
+ getOptions(), debugForCopy, null, callerContext);
if (allowAssumptions == AllowAssumptions.YES && assumptions != null) {
copy.assumptions.record(assumptions);
}
@@ -931,4 +952,8 @@
protected void afterRegister(Node node) {
assert hasValueProxies() || !(node instanceof ValueProxyNode);
}
+
+ public NodeSourcePosition getCallerContext() {
+ return callerContext;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
-import jdk.vm.ci.meta.MetaAccessProvider;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
@@ -42,17 +42,18 @@
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.PrimitiveConstant;
-import org.graalvm.compiler.options.OptionValues;
@NodeInfo(cycles = CYCLES_1)
public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode> {
public static final NodeClass<CompareNode> TYPE = NodeClass.create(CompareNode.class);
- protected final Condition condition;
+ protected final CanonicalCondition condition;
protected final boolean unorderedIsTrue;
/**
@@ -61,7 +62,7 @@
* @param x the instruction producing the first input to the instruction
* @param y the instruction that produces the second input to this instruction
*/
- protected CompareNode(NodeClass<? extends CompareNode> c, Condition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) {
+ protected CompareNode(NodeClass<? extends CompareNode> c, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) {
super(c, x, y);
this.condition = condition;
this.unorderedIsTrue = unorderedIsTrue;
@@ -72,7 +73,7 @@
*
* @return the condition
*/
- public final Condition condition() {
+ public final CanonicalCondition condition() {
return condition;
}
@@ -85,7 +86,7 @@
return this.unorderedIsTrue;
}
- public static LogicNode tryConstantFold(Condition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
+ public static LogicNode tryConstantFold(CanonicalCondition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
if (forX.isConstant() && forY.isConstant() && (constantReflection != null || forX.asConstant() instanceof PrimitiveConstant)) {
return LogicConstantNode.forBoolean(condition.foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue));
}
@@ -93,7 +94,7 @@
}
@SuppressWarnings("unused")
- public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) {
+ public static LogicNode tryConstantFoldPrimitive(CanonicalCondition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) {
if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) {
return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue));
}
@@ -107,11 +108,11 @@
* @return true for identity comparisons
*/
public boolean isIdentityComparison() {
- return condition == Condition.EQ;
+ return condition == CanonicalCondition.EQ;
}
public abstract static class CompareOp {
- public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
+ public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
LogicNode constantCondition = tryConstantFold(condition, forX, forY, constantReflection, unorderedIsTrue);
if (constantCondition != null) {
@@ -151,9 +152,13 @@
}
protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
- Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
+ CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
if (nonConstant instanceof ConditionalNode) {
- return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, mirrored ? condition.mirror() : condition, unorderedIsTrue);
+ Condition realCondition = condition.asCondition();
+ if (mirrored) {
+ realCondition = realCondition.mirror();
+ }
+ return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, realCondition, unorderedIsTrue);
} else if (nonConstant instanceof NormalizeCompareNode) {
return optimizeNormalizeCompare(constantReflection, metaAccess, options, smallestCompareWidth, constant, (NormalizeCompareNode) nonConstant, mirrored, view);
} else if (nonConstant instanceof ConvertNode) {
@@ -186,7 +191,7 @@
return null;
}
- private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Condition condition,
+ private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, CanonicalCondition condition,
ConvertNode convert, Constant constant, NodeView view) {
if (convert.preservesOrder(condition, constant, constantReflection)) {
Constant reverseConverted = convert.reverse(constant, constantReflection);
@@ -235,18 +240,17 @@
protected abstract LogicNode duplicateModified(ValueNode newW, ValueNode newY, boolean unorderedIsTrue, NodeView view);
}
- public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
+ public static LogicNode createCompareNode(StructuredGraph graph, CanonicalCondition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
LogicNode result = createCompareNode(condition, x, y, constantReflection, view);
return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
}
- public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
+ public static LogicNode createCompareNode(CanonicalCondition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
assert x.getStackKind() == y.getStackKind();
- assert condition.isCanonical();
assert !x.getStackKind().isNumericFloat();
LogicNode comparison;
- if (condition == Condition.EQ) {
+ if (condition == CanonicalCondition.EQ) {
if (x.stamp(view) instanceof AbstractObjectStamp) {
comparison = ObjectEqualsNode.create(x, y, constantReflection, view);
} else if (x.stamp(view) instanceof AbstractPointerStamp) {
@@ -255,11 +259,11 @@
assert x.getStackKind().isNumericInteger();
comparison = IntegerEqualsNode.create(x, y, view);
}
- } else if (condition == Condition.LT) {
+ } else if (condition == CanonicalCondition.LT) {
assert x.getStackKind().isNumericInteger();
comparison = IntegerLessThanNode.create(x, y, view);
} else {
- assert condition == Condition.BT;
+ assert condition == CanonicalCondition.BT;
assert x.getStackKind().isNumericInteger();
comparison = IntegerBelowNode.create(x, y, view);
}
@@ -268,19 +272,18 @@
}
public static LogicNode createCompareNode(StructuredGraph graph, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
- Condition condition, ValueNode x, ValueNode y, NodeView view) {
+ CanonicalCondition condition, ValueNode x, ValueNode y, NodeView view) {
LogicNode result = createCompareNode(constantReflection, metaAccess, options, smallestCompareWidth, condition, x, y, view);
return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
}
public static LogicNode createCompareNode(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
- Condition condition, ValueNode x, ValueNode y, NodeView view) {
+ CanonicalCondition condition, ValueNode x, ValueNode y, NodeView view) {
assert x.getStackKind() == y.getStackKind();
- assert condition.isCanonical();
assert !x.getStackKind().isNumericFloat();
LogicNode comparison;
- if (condition == Condition.EQ) {
+ if (condition == CanonicalCondition.EQ) {
if (x.stamp(view) instanceof AbstractObjectStamp) {
assert smallestCompareWidth == null;
comparison = ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, view);
@@ -290,11 +293,11 @@
assert x.getStackKind().isNumericInteger();
comparison = IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
}
- } else if (condition == Condition.LT) {
+ } else if (condition == CanonicalCondition.LT) {
assert x.getStackKind().isNumericInteger();
comparison = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
} else {
- assert condition == Condition.BT;
+ assert condition == CanonicalCondition.BT;
assert x.getStackKind().isNumericInteger();
comparison = IntegerBelowNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,7 +26,7 @@
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
import static org.graalvm.compiler.nodes.calc.CompareNode.createCompareNode;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -268,7 +268,7 @@
generator.emitConditional(this);
}
- public ConditionalNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
+ public ConditionalNode(StructuredGraph graph, CanonicalCondition condition, ValueNode x, ValueNode y) {
this(createCompareNode(graph, condition, x, y, null, NodeView.DEFAULT));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConvertNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.nodes.calc;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValueNodeInterface;
@@ -61,7 +61,7 @@
* @param op a comparison operator
* @return true iff (c1 op c2) == (convert(c1) op convert(c2)) for all c1, c2
*/
- default boolean preservesOrder(Condition op) {
+ default boolean preservesOrder(CanonicalCondition op) {
return isLossless();
}
@@ -73,7 +73,7 @@
* @param constantReflection
* @return true iff (c1 op value) == (convert(c1) op convert(value)) for value and all c1
*/
- default boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) {
+ default boolean preservesOrder(CanonicalCondition op, Constant value, ConstantReflectionProvider constantReflection) {
return preservesOrder(op);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatEqualsNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,10 +22,9 @@
*/
package org.graalvm.compiler.nodes.calc;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.TriState;
-import org.graalvm.compiler.core.common.calc.Condition;
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
+
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -42,7 +41,9 @@
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.TriState;
@NodeInfo(shortName = "==", cycles = CYCLES_2)
public final class FloatEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
@@ -50,13 +51,13 @@
private static final FloatEqualsOp OP = new FloatEqualsOp();
public FloatEqualsNode(ValueNode x, ValueNode y) {
- super(TYPE, Condition.EQ, false, x, y);
+ super(TYPE, CanonicalCondition.EQ, false, x, y);
assert x.stamp(NodeView.DEFAULT) instanceof FloatStamp && y.stamp(NodeView.DEFAULT) instanceof FloatStamp : x.stamp(NodeView.DEFAULT) + " " + y.stamp(NodeView.DEFAULT);
assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT));
}
public static LogicNode create(ValueNode x, ValueNode y, NodeView view) {
- LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false, view);
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(CanonicalCondition.EQ, x, y, false, view);
if (result != null) {
return result;
} else {
@@ -66,7 +67,7 @@
public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
ValueNode x, ValueNode y, NodeView view) {
- LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y, view);
+ LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, CanonicalCondition.EQ, false, x, y, view);
if (value != null) {
return value;
}
@@ -89,7 +90,7 @@
@Override
public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
NodeView view = NodeView.from(tool);
- ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, unorderedIsTrue, forX, forY, view);
+ ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, unorderedIsTrue, forX, forY, view);
if (value != null) {
return value;
}
@@ -99,7 +100,7 @@
public static class FloatEqualsOp extends CompareOp {
@Override
- public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
+ public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view);
if (result != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatLessThanNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,10 +22,9 @@
*/
package org.graalvm.compiler.nodes.calc;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.TriState;
-import org.graalvm.compiler.core.common.calc.Condition;
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
+
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -41,7 +40,9 @@
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.TriState;
@NodeInfo(shortName = "<", cycles = CYCLES_2)
public final class FloatLessThanNode extends CompareNode {
@@ -49,13 +50,13 @@
private static final FloatLessThanOp OP = new FloatLessThanOp();
public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) {
- super(TYPE, Condition.LT, unorderedIsTrue, x, y);
+ super(TYPE, CanonicalCondition.LT, unorderedIsTrue, x, y);
assert x.stamp(NodeView.DEFAULT) instanceof FloatStamp && y.stamp(NodeView.DEFAULT) instanceof FloatStamp;
assert x.stamp(NodeView.DEFAULT).isCompatible(y.stamp(NodeView.DEFAULT));
}
public static LogicNode create(ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) {
- LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.LT, x, y, unorderedIsTrue, view);
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(CanonicalCondition.LT, x, y, unorderedIsTrue, view);
if (result != null) {
return result;
}
@@ -64,7 +65,7 @@
public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) {
- LogicNode result = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.LT, unorderedIsTrue, x, y, view);
+ LogicNode result = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, CanonicalCondition.LT, unorderedIsTrue, x, y, view);
if (result != null) {
return result;
}
@@ -74,7 +75,7 @@
@Override
public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
NodeView view = NodeView.from(tool);
- ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.LT, unorderedIsTrue, forX, forY, view);
+ ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.LT, unorderedIsTrue, forX, forY, view);
if (value != null) {
return value;
}
@@ -84,7 +85,7 @@
public static class FloatLessThanOp extends CompareOp {
@Override
- public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
+ public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view);
if (result != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,10 +22,8 @@
*/
package org.graalvm.compiler.nodes.calc;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
@@ -35,9 +33,11 @@
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.code.CodeUtil;
-import org.graalvm.compiler.options.OptionValues;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
@NodeInfo(shortName = "|<|")
public final class IntegerBelowNode extends IntegerLowerThanNode {
@@ -126,8 +126,8 @@
}
@Override
- protected Condition getCondition() {
- return Condition.BT;
+ protected CanonicalCondition getCondition() {
+ return CanonicalCondition.BT;
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,9 +22,7 @@
*/
package org.graalvm.compiler.nodes.calc;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
@@ -42,12 +40,14 @@
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.PrimitiveConstant;
import jdk.vm.ci.meta.TriState;
-import org.graalvm.compiler.options.OptionValues;
@NodeInfo(shortName = "==")
public final class IntegerEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
@@ -55,13 +55,13 @@
private static final IntegerEqualsOp OP = new IntegerEqualsOp();
public IntegerEqualsNode(ValueNode x, ValueNode y) {
- super(TYPE, Condition.EQ, false, x, y);
+ super(TYPE, CanonicalCondition.EQ, false, x, y);
assert !x.getStackKind().isNumericFloat() && x.getStackKind() != JavaKind.Object;
assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object;
}
public static LogicNode create(ValueNode x, ValueNode y, NodeView view) {
- LogicNode result = CompareNode.tryConstantFoldPrimitive(Condition.EQ, x, y, false, view);
+ LogicNode result = CompareNode.tryConstantFoldPrimitive(CanonicalCondition.EQ, x, y, false, view);
if (result != null) {
return result;
}
@@ -87,7 +87,7 @@
public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, ValueNode x, ValueNode y,
NodeView view) {
- LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, Condition.EQ, false, x, y, view);
+ LogicNode value = OP.canonical(constantReflection, metaAccess, options, smallestCompareWidth, CanonicalCondition.EQ, false, x, y, view);
if (value != null) {
return value;
}
@@ -97,7 +97,7 @@
@Override
public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
NodeView view = NodeView.from(tool);
- ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view);
+ ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, false, forX, forY, view);
if (value != null) {
return value;
}
@@ -149,7 +149,7 @@
}
@Override
- public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
+ public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
return LogicConstantNode.tautology();
@@ -186,7 +186,7 @@
@Override
protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
- Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
+ CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
if (constant instanceof PrimitiveConstant) {
PrimitiveConstant primitiveConstant = (PrimitiveConstant) constant;
IntegerStamp nonConstantStamp = ((IntegerStamp) nonConstant.stamp(view));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,12 +22,10 @@
*/
package org.graalvm.compiler.nodes.calc;
-import static org.graalvm.compiler.core.common.calc.Condition.LT;
+import static org.graalvm.compiler.core.common.calc.CanonicalCondition.LT;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -42,13 +40,15 @@
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.options.OptionValues;
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;
import jdk.vm.ci.meta.PrimitiveConstant;
-import org.graalvm.compiler.options.OptionValues;
@NodeInfo(shortName = "<")
public final class IntegerLessThanNode extends IntegerLowerThanNode {
@@ -258,7 +258,7 @@
}
@Override
- protected Condition getCondition() {
+ protected CanonicalCondition getCondition() {
return LT;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,9 +22,7 @@
*/
package org.graalvm.compiler.nodes.calc;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
@@ -36,9 +34,11 @@
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.options.OptionValues;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.TriState;
-import org.graalvm.compiler.options.OptionValues;
/**
* Common super-class for "a < b" comparisons both {@linkplain IntegerLowerThanNode signed} and
@@ -117,7 +117,7 @@
public abstract static class LowerOp extends CompareOp {
@Override
- public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
+ public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
LogicNode result = super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY, view);
if (result != null) {
@@ -156,7 +156,7 @@
protected abstract IntegerStamp forInteger(int bits, long min, long max);
- protected abstract Condition getCondition();
+ protected abstract CanonicalCondition getCondition();
protected abstract IntegerLowerThanNode createNode(ValueNode x, ValueNode y);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NarrowNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -112,9 +112,9 @@
// ==> sxxx -(sign-extend)-> sssssxxx
return SignExtendNode.create(other.getValue(), other.getInputBits(), getResultBits(), view);
} else if (other instanceof ZeroExtendNode) {
- // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx
+ // xxxx -(zero-extend)-> 00000000 0000xxxx -(narrow)-> 0000xxxx
// ==> xxxx -(zero-extend)-> 0000xxxx
- return new ZeroExtendNode(other.getValue(), other.getInputBits(), getResultBits());
+ return new ZeroExtendNode(other.getValue(), other.getInputBits(), getResultBits(), ((ZeroExtendNode) other).isInputAlwaysPositive());
}
}
} else if (forValue instanceof AndNode) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/NormalizeCompareNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.IterableNodeType;
@@ -67,10 +67,10 @@
}
protected static ValueNode tryConstantFold(ValueNode x, ValueNode y, boolean isUnorderedLess, JavaKind kind, ConstantReflectionProvider constantReflection) {
- LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, null, false);
+ LogicNode result = CompareNode.tryConstantFold(CanonicalCondition.EQ, x, y, null, false);
if (result instanceof LogicConstantNode) {
LogicConstantNode logicConstantNode = (LogicConstantNode) result;
- LogicNode resultLT = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, isUnorderedLess);
+ LogicNode resultLT = CompareNode.tryConstantFold(CanonicalCondition.LT, x, y, constantReflection, isUnorderedLess);
if (resultLT instanceof LogicConstantNode) {
LogicConstantNode logicConstantNodeLT = (LogicConstantNode) resultLT;
if (logicConstantNodeLT.getValue()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ObjectEqualsNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.nodes.calc;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
@@ -42,6 +42,7 @@
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
+import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -49,7 +50,6 @@
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;
-import org.graalvm.compiler.options.OptionValues;
@NodeInfo(shortName = "==")
public final class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable {
@@ -64,7 +64,7 @@
}
public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
- LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false);
+ LogicNode result = CompareNode.tryConstantFold(CanonicalCondition.EQ, x, y, constantReflection, false);
if (result != null) {
return result;
} else {
@@ -77,7 +77,7 @@
}
public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, ValueNode x, ValueNode y, NodeView view) {
- LogicNode result = OP.canonical(constantReflection, metaAccess, options, null, Condition.EQ, false, x, y, view);
+ LogicNode result = OP.canonical(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, false, x, y, view);
if (result != null) {
return result;
}
@@ -87,7 +87,7 @@
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
NodeView view = NodeView.from(tool);
- ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view);
+ ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, false, forX, forY, view);
if (value != null) {
return value;
}
@@ -98,7 +98,7 @@
@Override
protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
- Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
+ CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
ResolvedJavaType type = constantReflection.asJavaType(constant);
if (type != null && nonConstant instanceof GetClassNode) {
GetClassNode getClassNode = (GetClassNode) nonConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/PointerEqualsNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,9 +22,7 @@
*/
package org.graalvm.compiler.nodes.calc;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -41,11 +39,13 @@
import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.options.OptionValues;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.TriState;
-import org.graalvm.compiler.options.OptionValues;
@NodeInfo(shortName = "==")
public class PointerEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
@@ -66,7 +66,7 @@
}
protected PointerEqualsNode(NodeClass<? extends PointerEqualsNode> c, ValueNode x, ValueNode y) {
- super(c, Condition.EQ, false, x, y);
+ super(c, CanonicalCondition.EQ, false, x, y);
assert x.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp;
assert y.stamp(NodeView.DEFAULT) instanceof AbstractPointerStamp;
}
@@ -74,7 +74,7 @@
@Override
public Node canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
NodeView view = NodeView.from(tool);
- ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), Condition.EQ, false, forX, forY, view);
+ ValueNode value = OP.canonical(tool.getConstantReflection(), tool.getMetaAccess(), tool.getOptions(), tool.smallestCompareWidth(), CanonicalCondition.EQ, false, forX, forY, view);
if (value != null) {
return value;
}
@@ -88,9 +88,9 @@
* could select a certain method and if so, returns {@code true} if the answer is guaranteed
* to be false. Otherwise, returns {@code false}.
*/
- private static boolean isAlwaysFailingVirtualDispatchTest(Condition condition, ValueNode forX, ValueNode forY) {
+ private static boolean isAlwaysFailingVirtualDispatchTest(CanonicalCondition condition, ValueNode forX, ValueNode forY) {
if (forY.isConstant()) {
- if (forX instanceof LoadMethodNode && condition == Condition.EQ) {
+ if (forX instanceof LoadMethodNode && condition == CanonicalCondition.EQ) {
LoadMethodNode lm = ((LoadMethodNode) forX);
if (lm.getMethod().getEncoding().equals(forY.asConstant())) {
if (lm.getHub() instanceof LoadHubNode) {
@@ -112,7 +112,7 @@
}
@Override
- public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
+ public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
LogicNode result = findSynonym(forX, forY, view);
if (result != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignExtendNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -95,7 +95,7 @@
if (other.getResultBits() > other.getInputBits()) {
// sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx
// ==> sxxx -(zero-extend)-> 00000000 0000sxxx
- return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits, view);
+ return ZeroExtendNode.create(other.getValue(), other.getInputBits(), resultBits, view, other.isInputAlwaysPositive());
}
}
@@ -104,7 +104,7 @@
if ((inputStamp.upMask() & (1L << (inputBits - 1))) == 0L) {
// 0xxx -(sign-extend)-> 0000 0xxx
// ==> 0xxx -(zero-extend)-> 0000 0xxx
- return ZeroExtendNode.create(forValue, inputBits, resultBits, view);
+ return ZeroExtendNode.create(forValue, inputBits, resultBits, view, true);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ZeroExtendNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
@@ -50,26 +50,33 @@
public static final NodeClass<ZeroExtendNode> TYPE = NodeClass.create(ZeroExtendNode.class);
+ private final boolean inputAlwaysPositive;
+
public ZeroExtendNode(ValueNode input, int resultBits) {
- this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits);
+ this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits, false);
assert 0 < PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) && PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) <= resultBits;
}
- public ZeroExtendNode(ValueNode input, int inputBits, int resultBits) {
+ public ZeroExtendNode(ValueNode input, int inputBits, int resultBits, boolean inputAlwaysPositive) {
super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input);
+ this.inputAlwaysPositive = inputAlwaysPositive;
}
public static ValueNode create(ValueNode input, int resultBits, NodeView view) {
- return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view);
+ return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view, false);
}
public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) {
+ return create(input, inputBits, resultBits, view, false);
+ }
+
+ public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view, boolean alwaysPositive) {
IntegerConvertOp<ZeroExtend> signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getZeroExtend();
ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view)));
if (synonym != null) {
return synonym;
}
- return canonical(null, input, inputBits, resultBits, view);
+ return canonical(null, input, inputBits, resultBits, view, alwaysPositive);
}
@Override
@@ -77,12 +84,13 @@
return true;
}
+ public boolean isInputAlwaysPositive() {
+ return inputAlwaysPositive;
+ }
+
@Override
- public boolean preservesOrder(Condition cond) {
+ public boolean preservesOrder(CanonicalCondition cond) {
switch (cond) {
- case GE:
- case GT:
- case LE:
case LT:
return false;
default:
@@ -98,16 +106,16 @@
return ret;
}
- return canonical(this, forValue, getInputBits(), getResultBits(), view);
+ return canonical(this, forValue, getInputBits(), getResultBits(), view, inputAlwaysPositive);
}
- private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view) {
+ private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view, boolean alwaysPositive) {
ZeroExtendNode self = zeroExtendNode;
if (forValue instanceof ZeroExtendNode) {
// xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx
// ==> xxxx -(zero-extend)-> 00000000 0000xxxx
ZeroExtendNode other = (ZeroExtendNode) forValue;
- return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits);
+ return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits, other.isInputAlwaysPositive());
}
if (forValue instanceof NarrowNode) {
NarrowNode narrow = (NarrowNode) forValue;
@@ -135,7 +143,7 @@
}
if (self == null) {
- self = new ZeroExtendNode(forValue, inputBits, resultBits);
+ self = new ZeroExtendNode(forValue, inputBits, resultBits, alwaysPositive);
}
return self;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Sat Feb 10 09:25:35 2018 +0100
@@ -42,7 +42,6 @@
import org.graalvm.word.LocationIdentity;
public final class Block extends AbstractBlockBase<Block> {
-
public static final Block[] EMPTY_ARRAY = new Block[0];
protected final AbstractBeginNode beginNode;
@@ -53,7 +52,6 @@
private Loop<Block> loop;
protected Block postdominator;
- protected Block distancedDominatorCache;
private LocationSet killLocations;
private LocationSet killLocationsBetweenThisAndDominator;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,54 @@
+/*
+ * 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.nodes.extended;
+
+import org.graalvm.compiler.graph.NodeInterface;
+import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+public interface ArrayRangeWrite extends NodeInterface {
+ AddressNode getAddress();
+
+ /**
+ * The length of the modified range.
+ */
+ ValueNode getLength();
+
+ /**
+ * Return true if the written array is an object array, false if it is a primitive array.
+ */
+ boolean writesObjectArray();
+
+ /**
+ * Returns whether this write is the initialization of the written location. If it is true, the
+ * old value of the memory location is either uninitialized or zero. If it is false, the memory
+ * location is guaranteed to contain a valid value or zero.
+ */
+ boolean isInitialization();
+
+ int getElementStride();
+
+ @Override
+ FixedWithNextNode asNode();
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWriteNode.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * 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.nodes.extended;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
-
-import org.graalvm.compiler.core.common.type.Stamp;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
-
-/**
- * Base class for nodes that modify a range of an array.
- */
-@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
-public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint {
-
- public static final NodeClass<ArrayRangeWriteNode> TYPE = NodeClass.create(ArrayRangeWriteNode.class);
-
- protected ArrayRangeWriteNode(NodeClass<? extends ArrayRangeWriteNode> c, Stamp stamp) {
- super(c, stamp);
- }
-
- /**
- * The array that is written to.
- */
- public abstract ValueNode getArray();
-
- /**
- * The first modified index.
- */
- public abstract ValueNode getIndex();
-
- /**
- * The length of the modified range.
- */
- public abstract ValueNode getLength();
-
- /**
- * Return true if the written array is an object array, false if it is a primitive array.
- */
- public abstract boolean isObjectArray();
-
- /**
- * Returns whether this write is the initialization of the written location. If it is true, the
- * old value of the memory location is either uninitialized or zero. If it is false, the memory
- * location is guaranteed to contain a valid value or zero.
- */
- public abstract boolean isInitialization();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.iterators.NodePredicates;
@@ -101,7 +101,7 @@
}
boolean usageFound = false;
for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) {
- assert node.condition() == Condition.EQ;
+ assert node.condition() == CanonicalCondition.EQ;
ValueNode other = node.getX();
if (node.getX() == this) {
other = node.getY();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -97,7 +97,7 @@
ValueNode offsetValue = tool.getAlias(offset());
if (offsetValue.isConstant()) {
long off = offsetValue.asJavaConstant().asLong();
- int entryIndex = virtual.entryIndexForOffset(off, accessKind());
+ int entryIndex = virtual.entryIndexForOffset(tool.getArrayOffsetProvider(), off, accessKind());
if (entryIndex != -1) {
ValueNode entry = tool.getEntry(virtual, entryIndex);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -119,7 +119,7 @@
ValueNode indexValue = tool.getAlias(offset());
if (indexValue.isConstant()) {
long off = indexValue.asJavaConstant().asLong();
- int entryIndex = virtual.entryIndexForOffset(off, accessKind());
+ int entryIndex = virtual.entryIndexForOffset(tool.getArrayOffsetProvider(), off, accessKind());
if (entryIndex != -1 && tool.setVirtualEntry(virtual, entryIndex, value(), accessKind(), off)) {
tool.delete();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -228,7 +228,7 @@
@Override
public AbstractBeginNode getPrimarySuccessor() {
- return this.defaultSuccessor();
+ return null;
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java Sat Feb 10 09:25:35 2018 +0100
@@ -82,6 +82,10 @@
return methodToInline;
}
+ public boolean allowsInlining() {
+ return methodToInline != null;
+ }
+
/**
* Gets the provider of bytecode to be parsed for {@link #getMethodToInline()} if is is an
* intrinsic for the original method (i.e., the {@code method} passed to
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Sat Feb 10 09:25:35 2018 +0100
@@ -35,6 +35,12 @@
import java.util.List;
import java.util.Map;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
+import org.graalvm.collections.Pair;
+import org.graalvm.collections.UnmodifiableEconomicMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry;
import org.graalvm.compiler.bytecode.BytecodeProvider;
@@ -44,12 +50,6 @@
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
-import org.graalvm.util.Pair;
-import org.graalvm.util.UnmodifiableEconomicMap;
-import org.graalvm.util.UnmodifiableMapCursor;
import jdk.vm.ci.meta.MetaUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -112,6 +112,26 @@
}
/**
+ * A symbol for an already resolved method.
+ */
+ public static class ResolvedJavaSymbol implements Type {
+ private final ResolvedJavaType resolved;
+
+ public ResolvedJavaSymbol(ResolvedJavaType type) {
+ this.resolved = type;
+ }
+
+ public ResolvedJavaType getResolved() {
+ return resolved;
+ }
+
+ @Override
+ public String toString() {
+ return resolved.toJavaName();
+ }
+ }
+
+ /**
* A symbol that is lazily {@linkplain OptionalLazySymbol#resolve() resolved} to a {@link Type}.
*/
static class OptionalLazySymbol implements Type {
@@ -696,7 +716,7 @@
*
* @param declaringClass the class to test
*/
- protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
+ public boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
return true;
}
@@ -1150,6 +1170,9 @@
}
static boolean checkResolvable(boolean isOptional, Type declaringType, Binding binding) {
+ if (declaringType instanceof ResolvedJavaSymbol) {
+ return checkResolvable(isOptional, ((ResolvedJavaSymbol) declaringType).getResolved(), binding);
+ }
Class<?> declaringClass = InvocationPlugins.resolveType(declaringType, isOptional);
if (declaringClass == null) {
return true;
@@ -1165,6 +1188,13 @@
}
return true;
}
+
+ private static boolean checkResolvable(boolean isOptional, ResolvedJavaType declaringType, Binding binding) {
+ if (resolveJavaMethod(declaringType, binding) == null && !isOptional) {
+ throw new AssertionError(String.format("Method not found: %s.%s%s", declaringType.toJavaName(), binding.name, binding.argumentsDescriptor));
+ }
+ return true;
+ }
}
/**
@@ -1235,7 +1265,7 @@
* {@link NoSuchMethodError} is thrown.
*
* @param declaringClass the class to search for a method matching {@code binding}
- * @return the method (if any) in {@code declaringClass} matching binding
+ * @return the method (if any) in {@code declaringClass} matching {@code binding}
*/
public static Method resolveMethod(Class<?> declaringClass, Binding binding) {
if (binding.name.equals("<init>")) {
@@ -1243,32 +1273,70 @@
}
Method[] methods = declaringClass.getDeclaredMethods();
List<String> parameterTypeNames = parseParameters(binding.argumentsDescriptor);
+ Method match = null;
for (int i = 0; i < methods.length; ++i) {
Method m = methods[i];
- if (binding.isStatic == Modifier.isStatic(m.getModifiers()) && m.getName().equals(binding.name)) {
- if (parameterTypeNames.equals(toInternalTypeNames(m.getParameterTypes()))) {
- for (int j = i + 1; j < methods.length; ++j) {
- Method other = methods[j];
- if (binding.isStatic == Modifier.isStatic(other.getModifiers()) && other.getName().equals(binding.name)) {
- if (parameterTypeNames.equals(toInternalTypeNames(other.getParameterTypes()))) {
- if (m.getReturnType().isAssignableFrom(other.getReturnType())) {
- // `other` has a more specific return type - choose it
- // (m is most likely a bridge method)
- m = other;
- } else {
- if (!other.getReturnType().isAssignableFrom(m.getReturnType())) {
- throw new NoSuchMethodError(String.format(
- "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", m, other));
- }
- }
- }
- }
+ if (binding.isStatic == Modifier.isStatic(m.getModifiers()) &&
+ m.getName().equals(binding.name) &&
+ parameterTypeNames.equals(toInternalTypeNames(m.getParameterTypes()))) {
+ if (match == null) {
+ match = m;
+ } else if (match.getReturnType().isAssignableFrom(m.getReturnType())) {
+ // `m` has a more specific return type - choose it
+ // (`match` is most likely a bridge method)
+ match = m;
+ } else {
+ if (!m.getReturnType().isAssignableFrom(match.getReturnType())) {
+ throw new NoSuchMethodError(String.format(
+ "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", match, m));
}
+ }
+ }
+ }
+ return match;
+ }
+
+ /**
+ * Same as {@link #resolveMethod(Class, Binding)} and
+ * {@link #resolveConstructor(Class, Binding)} except in terms of {@link ResolvedJavaType} and
+ * {@link ResolvedJavaMethod}.
+ */
+ public static ResolvedJavaMethod resolveJavaMethod(ResolvedJavaType declaringClass, Binding binding) {
+ ResolvedJavaMethod[] methods = declaringClass.getDeclaredMethods();
+ if (binding.name.equals("<init>")) {
+ for (ResolvedJavaMethod m : methods) {
+ if (m.getName().equals("<init>") && m.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) {
return m;
}
}
+ return null;
}
- return null;
+
+ ResolvedJavaMethod match = null;
+ for (int i = 0; i < methods.length; ++i) {
+ ResolvedJavaMethod m = methods[i];
+ if (binding.isStatic == m.isStatic() &&
+ m.getName().equals(binding.name) &&
+ m.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) {
+ if (match == null) {
+ match = m;
+ } else {
+ final ResolvedJavaType matchReturnType = (ResolvedJavaType) match.getSignature().getReturnType(declaringClass);
+ final ResolvedJavaType mReturnType = (ResolvedJavaType) m.getSignature().getReturnType(declaringClass);
+ if (matchReturnType.isAssignableFrom(mReturnType)) {
+ // `m` has a more specific return type - choose it
+ // (`match` is most likely a bridge method)
+ match = m;
+ } else {
+ if (!mReturnType.isAssignableFrom(matchReturnType)) {
+ throw new NoSuchMethodError(String.format(
+ "Found 2 methods with same name and parameter types but unrelated return types:%n %s%n %s", match, m));
+ }
+ }
+ }
+ }
+ }
+ return match;
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -39,10 +39,10 @@
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.Value;
-import sun.misc.Unsafe;
/**
- * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}.
+ * Represents an atomic read-and-add operation like
+ * {@link sun.misc.Unsafe#getAndAddInt(Object, long, int)}.
*/
@NodeInfo(allowedUsageTypes = Memory, cycles = CYCLES_8, size = SIZE_2)
public final class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -36,11 +36,10 @@
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
-import sun.misc.Unsafe;
/**
- * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)}
- * .
+ * Represents an atomic read-and-write operation like
+ * {@link sun.misc.Unsafe#getAndSetInt(Object, long, int)}.
*/
@NodeInfo(cycles = CYCLES_8, size = SIZE_2)
public final class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -125,6 +125,13 @@
}
@NodeIntrinsic
+ private static native Object newArray(Class<?> componentType, int length, @ConstantNodeParameter boolean fillContents);
+
+ public static Object newArray(Class<?> componentType, int length) {
+ return newArray(componentType, length, true);
+ }
+
+ @NodeIntrinsic
private static native Object newArray(Class<?> componentType, int length, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter JavaKind knownElementKind);
public static Object newArray(Class<?> componentType, int length, JavaKind knownElementKind) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -42,11 +42,10 @@
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.Value;
-import sun.misc.Unsafe;
/**
* Represents the lowered version of an atomic read-and-write operation like
- * {@link Unsafe#getAndSetInt(Object, long, int)} .
+ * {@link sun.misc.Unsafe#getAndSetInt(Object, long, int)}.
*/
@NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_8, size = SIZE_2)
public final class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerableAccess, MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import java.util.Collections;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -132,7 +132,7 @@
// Should be areFrameStatesAtSideEffects but currently SVM will complain about
// RuntimeConstraint
if (graph().getGuardsStage().allowsFloatingGuards()) {
- LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), Condition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view);
+ LogicNode lengthNegativeCondition = CompareNode.createCompareNode(graph(), CanonicalCondition.LT, length(), ConstantNode.forInt(0, graph()), tool.getConstantReflection(), view);
// we do not have a non-deopting path for that at the moment so action=None.
FixedGuardNode guard = graph().add(new FixedGuardNode(lengthNegativeCondition, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, true));
graph().replaceFixedWithFixed(this, guard);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -32,6 +32,9 @@
import java.util.Collection;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
@@ -41,9 +44,6 @@
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
import org.graalvm.word.LocationIdentity;
@NodeInfo(allowedUsageTypes = {Extension, Memory}, cycles = CYCLES_0, size = SIZE_0)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.nodes.spi;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
@@ -31,7 +32,7 @@
/**
* Provides a capability for replacing a higher node with one or more lower level nodes.
*/
-public interface LoweringProvider {
+public interface LoweringProvider extends ArrayOffsetProvider {
void lower(Node n, LoweringTool tool);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import java.util.List;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
@@ -56,6 +57,8 @@
*/
ConstantReflectionProvider getConstantReflectionProvider();
+ ArrayOffsetProvider getArrayOffsetProvider();
+
/**
* This method should be used to query the maximum size of virtualized objects before attempting
* virtualization.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,10 @@
import java.util.List;
import java.util.function.BiFunction;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
@@ -76,10 +80,6 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodePosition;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import java.nio.ByteOrder;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -35,7 +36,6 @@
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaType;
-import sun.misc.Unsafe;
@NodeInfo(nameTemplate = "VirtualArray({p#objectId}) {p#componentType/s}[{p#length}]")
public class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthProvider {
@@ -88,53 +88,14 @@
}
@Override
- public int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind) {
- return entryIndexForOffset(constantOffset, expectedEntryKind, componentType, length);
+ public int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind) {
+ return entryIndexForOffset(arrayOffsetProvider, constantOffset, expectedEntryKind, componentType, length);
}
- public static int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind, ResolvedJavaType componentType, int length) {
- int baseOffset;
- int indexScale;
- switch (componentType.getJavaKind()) {
- case Boolean:
- baseOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
- break;
- case Byte:
- baseOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_BYTE_INDEX_SCALE;
- break;
- case Short:
- baseOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_SHORT_INDEX_SCALE;
- break;
- case Char:
- baseOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_CHAR_INDEX_SCALE;
- break;
- case Int:
- baseOffset = Unsafe.ARRAY_INT_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_INT_INDEX_SCALE;
- break;
- case Long:
- baseOffset = Unsafe.ARRAY_LONG_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_LONG_INDEX_SCALE;
- break;
- case Float:
- baseOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_FLOAT_INDEX_SCALE;
- break;
- case Double:
- baseOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
- break;
- case Object:
- baseOffset = Unsafe.ARRAY_OBJECT_BASE_OFFSET;
- indexScale = Unsafe.ARRAY_OBJECT_INDEX_SCALE;
- break;
- default:
- return -1;
- }
+ public static int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind, ResolvedJavaType componentType, int length) {
+ int baseOffset = arrayOffsetProvider.arrayBaseOffset(componentType.getJavaKind());
+ int indexScale = arrayOffsetProvider.arrayScalingFactor(componentType.getJavaKind());
+
long offset;
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN && componentType.isPrimitive()) {
// On big endian, we expect the value to be correctly aligned in memory
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.nodes.virtual;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -100,7 +101,7 @@
}
@Override
- public int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind) {
+ public int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind) {
return fieldIndex(type.findInstanceFieldWithOffset(constantOffset, expectedEntryKind));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualObjectNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.graph.IterableNodeType;
@@ -95,7 +96,7 @@
* @param expectedEntryKind Specifies which type is expected at this offset (Is important when
* doing implicit casts, especially on big endian systems.
*/
- public abstract int entryIndexForOffset(long constantOffset, JavaKind expectedEntryKind);
+ public abstract int entryIndexForOffset(ArrayOffsetProvider arrayOffsetProvider, long constantOffset, JavaKind expectedEntryKind);
/**
* Returns the {@link JavaKind} of the entry at the given index.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import java.util.EnumSet;
-import org.graalvm.util.EconomicMap;
+import org.graalvm.collections.EconomicMap;
public class EnumOptionKey<T extends Enum<T>> extends OptionKey<T> {
final Class<T> enumClass;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,10 +24,10 @@
import java.util.concurrent.atomic.AtomicReference;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
-import org.graalvm.util.UnmodifiableMapCursor;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
/**
* A context for obtaining values for {@link OptionKey}s that allows for key/value pairs to be
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,7 @@
import java.util.Formatter;
-import org.graalvm.util.EconomicMap;
+import org.graalvm.collections.EconomicMap;
/**
* A key for an option. The value for an option is obtained from an {@link OptionValues} object.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,10 +30,10 @@
import java.util.SortedMap;
import java.util.TreeMap;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
-import org.graalvm.util.UnmodifiableMapCursor;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
/**
* A context for obtaining values for {@link OptionKey}s.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,9 +28,9 @@
import java.util.List;
import java.util.ServiceLoader;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.MapCursor;
import org.graalvm.util.CollectionsUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
/**
* This class contains methods for parsing Graal options and matching them against a set of
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -33,6 +33,15 @@
public class AddressLoweringPhase extends Phase {
public abstract static class AddressLowering {
+
+ @SuppressWarnings("unused")
+ public void preProcess(StructuredGraph graph) {
+ }
+
+ @SuppressWarnings("unused")
+ public void postProcess(AddressNode lowered) {
+ }
+
public abstract AddressNode lower(ValueNode base, ValueNode offset);
}
@@ -45,11 +54,13 @@
@Override
protected void run(StructuredGraph graph) {
+ lowering.preProcess(graph);
for (Node node : graph.getNodes()) {
AddressNode lowered;
if (node instanceof OffsetAddressNode) {
OffsetAddressNode address = (OffsetAddressNode) node;
lowered = lowering.lower(address.getBase(), address.getOffset());
+ lowering.postProcess(lowered);
} else {
continue;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,10 @@
import java.util.Deque;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
+import org.graalvm.collections.Pair;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
@@ -87,10 +91,6 @@
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
-import org.graalvm.util.Pair;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.TriState;
@@ -124,7 +124,11 @@
if (moveGuards) {
cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.hasValueProxies());
}
- SchedulePhase.run(graph, SchedulingStrategy.EARLIEST, cfg);
+ try (DebugContext.Scope scheduleScope = graph.getDebug().scope(SchedulePhase.class)) {
+ SchedulePhase.run(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, cfg);
+ } catch (Throwable t) {
+ throw graph.getDebug().handle(t);
+ }
ScheduleResult r = graph.getLastSchedule();
blockToNodes = r.getBlockToNodesMap();
nodeToBlock = r.getNodeToBlockMap();
@@ -662,7 +666,7 @@
*/
InputFilter v = new InputFilter(original);
thisGuard.getCondition().applyInputs(v);
- if (v.ok && foldGuard(thisGuard, pendingGuard, newStamp, rewireGuardFunction)) {
+ if (v.ok && foldGuard(thisGuard, pendingGuard, result.toBoolean(), newStamp, rewireGuardFunction)) {
return true;
}
}
@@ -670,19 +674,34 @@
return false;
}
- protected boolean foldGuard(DeoptimizingGuard thisGuard, DeoptimizingGuard otherGuard, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) {
+ protected boolean foldGuard(DeoptimizingGuard thisGuard, DeoptimizingGuard otherGuard, boolean outcome, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) {
if (otherGuard.getAction() == thisGuard.getAction() && otherGuard.getSpeculation() == thisGuard.getSpeculation()) {
LogicNode condition = (LogicNode) thisGuard.getCondition().copyWithInputs();
+ /*
+ * We have ...; guard(C1); guard(C2);...
+ *
+ * Where the first guard is `otherGuard` and the second one `thisGuard`.
+ *
+ * Depending on `outcome`, we have C2 => C1 or C2 => !C1.
+ *
+ * - If C2 => C1, `mustDeopt` below is false and we transform to ...; guard(C2); ...
+ *
+ * - If C2 => !C1, `mustDeopt` is true and we transform to ..; guard(C1); deopt;
+ */
GuardRewirer rewirer = (guard, result, innerGuardedValueStamp, newInput) -> {
- if (rewireGuardFunction.rewire(guard, result, innerGuardedValueStamp, newInput)) {
- otherGuard.setCondition(condition, thisGuard.isNegated());
+ // `result` is `outcome`, `guard` is `otherGuard`
+ boolean mustDeopt = result == otherGuard.isNegated();
+ if (rewireGuardFunction.rewire(guard, mustDeopt == thisGuard.isNegated(), innerGuardedValueStamp, newInput)) {
+ if (!mustDeopt) {
+ otherGuard.setCondition(condition, thisGuard.isNegated());
+ }
return true;
}
condition.safeDelete();
return false;
};
// Move the later test up
- return rewireGuards(otherGuard, !thisGuard.isNegated(), null, guardedValueStamp, rewirer);
+ return rewireGuards(otherGuard, outcome, null, guardedValueStamp, rewirer);
}
return false;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,8 @@
import java.util.List;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.debug.DebugCloseable;
-import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.InputType;
@@ -46,6 +46,8 @@
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.LoopExitNode;
import org.graalvm.compiler.nodes.ProxyNode;
+import org.graalvm.compiler.nodes.StartNode;
+import org.graalvm.compiler.nodes.StaticDeoptimizingNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValuePhiNode;
@@ -57,8 +59,6 @@
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.DeoptimizationAction;
-import jdk.vm.ci.meta.DeoptimizationReason;
-import jdk.vm.ci.meta.JavaConstant;
/**
* This phase will find branches which always end with a {@link DeoptimizeNode} and replace their
@@ -77,18 +77,16 @@
@SuppressWarnings("try")
protected void run(final StructuredGraph graph, PhaseContext context) {
assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies";
+ assert !graph.getGuardsStage().areFrameStatesAtDeopts() : graph.getGuardsStage();
for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.TYPE)) {
assert d.isAlive();
- // Can only aggressively move deoptimization point if their action implies that
- // the deoptimization will not be triggered again. Example for such action is
- // reprofiling or recompiling with less aggressive options.
- if (d.action() != DeoptimizationAction.None) {
- try (DebugCloseable closable = d.withNodeSourcePosition()) {
- visitDeoptBegin(AbstractBeginNode.prevBegin(d), d.action(), d.reason(), d.getSpeculation(), graph, context != null ? context.getLowerer() : null);
- }
+ if (d.getAction() == DeoptimizationAction.None) {
+ continue;
}
-
+ try (DebugCloseable closable = d.withNodeSourcePosition()) {
+ propagateFixed(d, d, context != null ? context.getLowerer() : null);
+ }
}
if (context != null) {
@@ -154,71 +152,73 @@
ys = yPhi.valueAt(mergePredecessor).asConstant();
}
if (xs != null && ys != null && compare.condition().foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) {
- visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.getSpeculation(), fixedGuard.graph(), context.getLowerer());
+ propagateFixed(mergePredecessor, fixedGuard, context.getLowerer());
}
}
}
- private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, JavaConstant speculation, StructuredGraph graph,
- LoweringProvider loweringProvider) {
- if (deoptBegin.predecessor() instanceof AbstractBeginNode) {
- /*
- * Walk up chains of LoopExitNodes to the "real" BeginNode that leads to deoptimization.
- */
- visitDeoptBegin((AbstractBeginNode) deoptBegin.predecessor(), deoptAction, deoptReason, speculation, graph, loweringProvider);
- return;
- }
+ private void propagateFixed(FixedNode from, StaticDeoptimizingNode deopt, LoweringProvider loweringProvider) {
+ Node current = from;
+ while (current != null) {
+ if (GraalOptions.GuardPriorities.getValue(from.getOptions()) && current instanceof FixedGuardNode) {
+ FixedGuardNode otherGuard = (FixedGuardNode) current;
+ if (otherGuard.computePriority().isHigherPriorityThan(deopt.computePriority())) {
+ moveAsDeoptAfter(otherGuard, deopt);
+ return;
+ }
+ } else if (current instanceof AbstractBeginNode) {
+ if (current instanceof AbstractMergeNode) {
+ AbstractMergeNode mergeNode = (AbstractMergeNode) current;
+ FixedNode next = mergeNode.next();
+ while (mergeNode.isAlive()) {
+ AbstractEndNode end = mergeNode.forwardEnds().first();
+ propagateFixed(end, deopt, loweringProvider);
+ }
+ assert next.isAlive();
+ propagateFixed(next, deopt, loweringProvider);
+ return;
+ } else if (current.predecessor() instanceof IfNode) {
+ IfNode ifNode = (IfNode) current.predecessor();
+ StructuredGraph graph = ifNode.graph();
+ LogicNode conditionNode = ifNode.condition();
+ boolean negateGuardCondition = current == ifNode.trueSuccessor();
+ FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition));
+ FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
+ AbstractBeginNode survivingSuccessor;
+ if (negateGuardCondition) {
+ survivingSuccessor = ifNode.falseSuccessor();
+ } else {
+ survivingSuccessor = ifNode.trueSuccessor();
+ }
+ graph.removeSplitPropagate(ifNode, survivingSuccessor);
- DebugContext debug = deoptBegin.getDebug();
- if (deoptBegin instanceof AbstractMergeNode) {
- AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
- debug.log("Visiting %s", mergeNode);
- FixedNode next = mergeNode.next();
- while (mergeNode.isAlive()) {
- AbstractEndNode end = mergeNode.forwardEnds().first();
- AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(end);
- visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider);
+ Node newGuard = guard;
+ if (survivingSuccessor instanceof LoopExitNode) {
+ newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
+ }
+ survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);
+
+ graph.getDebug().log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", negateGuardCondition, ifNode, survivingSuccessor);
+ FixedNode next = pred.next();
+ pred.setNext(guard);
+ guard.setNext(next);
+ SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider);
+ survivingSuccessor.simplify(simplifierTool);
+ return;
+ } else if (current.predecessor() == null || current.predecessor() instanceof ControlSplitNode) {
+ assert current.predecessor() != null || (current instanceof StartNode && current == ((AbstractBeginNode) current).graph().start());
+ moveAsDeoptAfter((AbstractBeginNode) current, deopt);
+ return;
+ }
}
- assert next.isAlive();
- AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(next);
- visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider);
- return;
- } else if (deoptBegin.predecessor() instanceof IfNode) {
- IfNode ifNode = (IfNode) deoptBegin.predecessor();
- LogicNode conditionNode = ifNode.condition();
- FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, speculation, deoptBegin == ifNode.trueSuccessor()));
- FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
- AbstractBeginNode survivingSuccessor;
- if (deoptBegin == ifNode.trueSuccessor()) {
- survivingSuccessor = ifNode.falseSuccessor();
- } else {
- survivingSuccessor = ifNode.trueSuccessor();
- }
- graph.removeSplitPropagate(ifNode, survivingSuccessor);
+ current = current.predecessor();
+ }
+ }
- Node newGuard = guard;
- if (survivingSuccessor instanceof LoopExitNode) {
- newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
- }
- survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);
-
- debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor);
- FixedNode next = pred.next();
- pred.setNext(guard);
- guard.setNext(next);
- SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider);
- survivingSuccessor.simplify(simplifierTool);
- return;
- }
-
- // We could not convert the control split - at least cut off control flow after the split.
- FixedWithNextNode deoptPred = deoptBegin;
- FixedNode next = deoptPred.next();
-
- if (!(next instanceof DeoptimizeNode)) {
- DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason, speculation));
- deoptPred.setNext(newDeoptNode);
- assert deoptPred == newDeoptNode.predecessor();
+ private static void moveAsDeoptAfter(FixedWithNextNode node, StaticDeoptimizingNode deopt) {
+ FixedNode next = node.next();
+ if (next != deopt.asNode()) {
+ node.setNext(node.graph().add(new DeoptimizeNode(deopt.getAction(), deopt.getReason(), deopt.getSpeculation())));
GraphUtil.killCFG(next);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.phases.common;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.FloatStamp;
@@ -70,8 +72,6 @@
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
import org.graalvm.compiler.phases.tiers.LowTierContext;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.MetaAccessProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,10 @@
import java.util.Iterator;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
@@ -67,10 +71,6 @@
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.LoopInfo;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.UnmodifiableMapCursor;
import org.graalvm.word.LocationIdentity;
public class FloatingReadPhase extends Phase {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import java.util.List;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -40,7 +41,6 @@
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.BytecodeFrame;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -120,7 +120,7 @@
@Override
protected void run(StructuredGraph graph, MidTierContext context) {
if (graph.getGuardsStage().allowsFloatingGuards()) {
- SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST);
+ SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
schedulePhase.apply(graph);
ScheduleResult schedule = graph.getLastSchedule();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,9 @@
*/
package org.graalvm.compiler.phases.common;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.graph.NodeStack;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractDeoptimizeNode;
@@ -32,9 +35,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.MapCursor;
/**
* This phase will make sure that the branch leading towards this deopt has 0.0 probability.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -50,6 +50,9 @@
import org.graalvm.compiler.nodes.memory.FixedAccessNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.tiers.LowTierContext;
@@ -64,16 +67,24 @@
private static final CounterKey counterTrappingNullCheckUnreached = DebugContext.counter("TrappingNullCheckUnreached");
private static final CounterKey counterTrappingNullCheckDynamicDeoptimize = DebugContext.counter("TrappingNullCheckDynamicDeoptimize");
+ public static class Options {
+
+ // @formatter:off
+ @Option(help = "Use traps for null checks instead of explicit null-checks", type = OptionType.Expert)
+ public static final OptionKey<Boolean> UseTrappingNullChecks = new OptionKey<>(true);
+ // @formatter:on
+ }
+
@Override
protected void run(StructuredGraph graph, LowTierContext context) {
- if (context.getTarget().implicitNullCheckLimit <= 0) {
+ if (!Options.UseTrappingNullChecks.getValue(graph.getOptions()) || context.getTarget().implicitNullCheckLimit <= 0) {
return;
}
assert graph.getGuardsStage().areFrameStatesAtDeopts();
long implicitNullCheckLimit = context.getTarget().implicitNullCheckLimit;
for (DeoptimizeNode deopt : graph.getNodes(DeoptimizeNode.TYPE)) {
- tryUseTrappingNullCheck(deopt, deopt.predecessor(), deopt.reason(), deopt.getSpeculation(), implicitNullCheckLimit);
+ tryUseTrappingNullCheck(deopt, deopt.predecessor(), deopt.getReason(), deopt.getSpeculation(), implicitNullCheckLimit);
}
for (DynamicDeoptimizeNode deopt : graph.getNodes(DynamicDeoptimizeNode.TYPE)) {
tryUseTrappingNullCheck(context.getMetaAccess(), deopt, implicitNullCheckLimit);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Sat Feb 10 09:25:35 2018 +0100
@@ -33,6 +33,11 @@
import java.util.Objects;
import java.util.function.Consumer;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -92,11 +97,6 @@
import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener;
import org.graalvm.compiler.phases.util.ValueMergeUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
-import org.graalvm.util.UnmodifiableMapCursor;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.Assumptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -31,7 +32,6 @@
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.common.inlining.info.elem.InlineableGraph;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,12 +22,12 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,11 +22,11 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -30,7 +31,6 @@
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,8 @@
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -54,8 +56,6 @@
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.DeoptimizationAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,7 +22,8 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ConstantNode;
@@ -37,7 +38,6 @@
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
@@ -114,7 +114,7 @@
LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph);
- LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT);
+ LogicNode typeCheck = CompareNode.createCompareNode(graph, CanonicalCondition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT);
FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
assert invoke.predecessor() != null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,8 @@
import java.util.LinkedList;
import java.util.function.ToDoubleFunction;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.ParameterNode;
@@ -33,8 +35,6 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.phases.common.inlining.policy.AbstractInliningPolicy;
import org.graalvm.compiler.phases.graph.FixedNodeProbabilityCache;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicSet;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,8 @@
import java.util.ArrayList;
import java.util.function.ToDoubleFunction;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeWorkList;
@@ -43,8 +45,6 @@
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
public class ComputeInliningRelevance {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,8 @@
import java.util.LinkedList;
import java.util.List;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
@@ -64,8 +66,6 @@
import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,12 +26,12 @@
import java.util.HashSet;
import java.util.Set;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.graph.Graph.NodeEvent;
import org.graalvm.compiler.graph.Graph.NodeEventListener;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.Node.IndirectCanonicalization;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicSet;
/**
* A simple {@link NodeEventListener} implementation that accumulates event nodes in a
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,8 +22,12 @@
*/
package org.graalvm.compiler.phases.graph;
+import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities;
+
import java.util.function.ToDoubleFunction;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
@@ -36,10 +40,6 @@
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.StartNode;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
-
-import static org.graalvm.compiler.nodes.cfg.ControlFlowGraph.multiplyProbabilities;
/**
* Compute probabilities for fixed nodes on the fly and cache them at {@link AbstractBeginNode}s.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,6 +27,8 @@
import java.util.Deque;
import java.util.Set;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -41,8 +43,6 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.LoopEndNode;
import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
/**
* A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,8 @@
import java.util.List;
import java.util.function.Predicate;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.RetryableBailoutException;
import org.graalvm.compiler.core.common.cfg.Loop;
@@ -38,8 +40,6 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.cfg.Block;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
public final class ReentrantBlockIterator {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,9 @@
import java.util.Iterator;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
@@ -38,9 +41,6 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.LoopEndNode;
import org.graalvm.compiler.nodes.LoopExitNode;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.MapCursor;
public final class ReentrantNodeIterator {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,6 +27,8 @@
import java.util.Deque;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -42,8 +44,6 @@
import org.graalvm.compiler.nodes.LoopEndNode;
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
/**
* A SinglePassNodeIterator iterates the fixed nodes of the graph in post order starting from its
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,8 @@
import java.util.List;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugContext;
@@ -40,8 +42,6 @@
import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import org.graalvm.word.LocationIdentity;
public final class MemoryScheduleVerification extends BlockIteratorClosure<EconomicSet<FloatingReadNode>> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,14 +22,23 @@
*/
package org.graalvm.compiler.phases.schedule;
+import static org.graalvm.collections.Equivalence.IDENTITY;
+import static org.graalvm.compiler.core.common.GraalOptions.GuardPriorities;
import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops;
import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
+import java.util.EnumMap;
import java.util.Formatter;
+import java.util.Iterator;
import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Function;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
import org.graalvm.compiler.core.common.cfg.BlockMap;
@@ -48,7 +57,6 @@
import org.graalvm.compiler.nodes.ControlSplitNode;
import org.graalvm.compiler.nodes.DeoptimizeNode;
import org.graalvm.compiler.nodes.FixedNode;
-import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.GuardNode;
import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.KillingBeginNode;
@@ -57,6 +65,8 @@
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.ProxyNode;
import org.graalvm.compiler.nodes.StartNode;
+import org.graalvm.compiler.nodes.StaticDeoptimizingNode;
+import org.graalvm.compiler.nodes.StaticDeoptimizingNode.GuardPriority;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
@@ -78,10 +88,19 @@
public final class SchedulePhase extends Phase {
public enum SchedulingStrategy {
+ EARLIEST_WITH_GUARD_ORDER,
EARLIEST,
LATEST,
LATEST_OUT_OF_LOOPS,
- FINAL_SCHEDULE
+ FINAL_SCHEDULE;
+
+ public boolean isEarliest() {
+ return this == EARLIEST || this == EARLIEST_WITH_GUARD_ORDER;
+ }
+
+ public boolean isLatest() {
+ return !isEarliest();
+ }
}
private final SchedulingStrategy selectedStrategy;
@@ -164,13 +183,13 @@
this.nodeToBlockMap = currentNodeMap;
this.blockToNodesMap = earliestBlockToNodesMap;
- scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, immutableGraph);
+ scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, immutableGraph, selectedStrategy == SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER);
- if (selectedStrategy != SchedulingStrategy.EARLIEST) {
+ if (!selectedStrategy.isEarliest()) {
// For non-earliest schedules, we need to do a second pass.
BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg);
for (Block b : cfg.getBlocks()) {
- latestBlockToNodesMap.put(b, new ArrayList<Node>());
+ latestBlockToNodesMap.put(b, new ArrayList<>());
}
BlockMap<ArrayList<FloatingReadNode>> watchListMap = calcLatestBlocks(selectedStrategy, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, immutableGraph);
@@ -181,8 +200,8 @@
this.blockToNodesMap = latestBlockToNodesMap;
- cfg.setNodeToBlock(currentNodeMap);
}
+ cfg.setNodeToBlock(currentNodeMap);
graph.setLastSchedule(new ScheduleResult(this.cfg, this.nodeToBlockMap, this.blockToNodesMap));
}
@@ -524,7 +543,6 @@
assert latestBlock != null : currentNode;
if (strategy == SchedulingStrategy.FINAL_SCHEDULE || strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS) {
- assert latestBlock != null;
Block currentBlock = latestBlock;
while (currentBlock.getLoopDepth() > earliestBlock.getLoopDepth() && currentBlock != earliestBlock.getDominator()) {
Block previousCurrentBlock = currentBlock;
@@ -645,7 +663,7 @@
*/
public void add(Node node) {
assert !(node instanceof FixedNode) : node;
- NodeEntry newTail = new NodeEntry(node, null);
+ NodeEntry newTail = new NodeEntry(node);
if (tail == null) {
tail = head = newTail;
} else {
@@ -659,9 +677,18 @@
* Number of nodes in this micro block.
*/
public int getNodeCount() {
+ assert getActualNodeCount() == nodeCount : getActualNodeCount() + " != " + nodeCount;
return nodeCount;
}
+ private int getActualNodeCount() {
+ int count = 0;
+ for (NodeEntry e = head; e != null; e = e.next) {
+ count++;
+ }
+ return count;
+ }
+
/**
* The id of the micro block, with a block always associated with a lower id than its
* successors.
@@ -685,6 +712,7 @@
*/
public void prependChildrenTo(MicroBlock newBlock) {
if (tail != null) {
+ assert head != null;
tail.next = newBlock.head;
newBlock.head = head;
head = tail = null;
@@ -697,6 +725,11 @@
public String toString() {
return String.format("MicroBlock[id=%d]", id);
}
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
}
/**
@@ -706,9 +739,9 @@
private final Node node;
private NodeEntry next;
- NodeEntry(Node node, NodeEntry next) {
+ NodeEntry(Node node) {
this.node = node;
- this.next = next;
+ this.next = null;
}
public NodeEntry getNext() {
@@ -720,7 +753,8 @@
}
}
- private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph) {
+ private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph,
+ boolean withGuardOrder) {
NodeMap<MicroBlock> entries = graph.createNodeMap();
NodeStack stack = new NodeStack();
@@ -729,62 +763,44 @@
MicroBlock startBlock = null;
int nextId = 1;
for (Block b : cfg.reversePostOrder()) {
- FixedNode current = b.getBeginNode();
- while (true) {
+ for (FixedNode current : b.getBeginNode().getBlockNodes()) {
MicroBlock microBlock = new MicroBlock(nextId++);
- entries.put(current, microBlock);
- visited.checkAndMarkInc(current);
-
+ entries.set(current, microBlock);
+ boolean isNew = visited.checkAndMarkInc(current);
+ assert isNew;
if (startBlock == null) {
startBlock = microBlock;
}
-
- // Process inputs of this fixed node.
- for (Node input : current.inputs()) {
- if (entries.get(input) == null) {
- processStack(input, startBlock, entries, visited, stack);
- }
- }
-
- if (current == b.getEndNode()) {
- // Break loop when reaching end node.
- break;
- }
-
- current = ((FixedWithNextNode) current).next();
}
}
- // Now process guards.
- for (GuardNode guardNode : graph.getNodes(GuardNode.TYPE)) {
- if (entries.get(guardNode) == null) {
- processStack(guardNode, startBlock, entries, visited, stack);
+ if (graph.getGuardsStage().allowsFloatingGuards() && graph.getNodes(GuardNode.TYPE).isNotEmpty()) {
+ // Now process guards.
+ if (GuardPriorities.getValue(graph.getOptions()) && withGuardOrder) {
+ EnumMap<GuardPriority, List<GuardNode>> guardsByPriority = new EnumMap<>(GuardPriority.class);
+ for (GuardNode guard : graph.getNodes(GuardNode.TYPE)) {
+ guardsByPriority.computeIfAbsent(guard.computePriority(), p -> new ArrayList<>()).add(guard);
+ }
+ // `EnumMap.values` returns values in "natural" key order
+ for (List<GuardNode> guards : guardsByPriority.values()) {
+ processNodes(visited, entries, stack, startBlock, guards);
+ }
+ GuardOrder.resortGuards(graph, entries, stack);
+ } else {
+ processNodes(visited, entries, stack, startBlock, graph.getNodes(GuardNode.TYPE));
}
+ } else {
+ assert graph.getNodes(GuardNode.TYPE).isEmpty();
}
// Now process inputs of fixed nodes.
for (Block b : cfg.reversePostOrder()) {
- FixedNode current = b.getBeginNode();
- while (true) {
-
- // Process inputs of this fixed node.
- for (Node input : current.inputs()) {
- if (entries.get(input) == null) {
- processStack(input, startBlock, entries, visited, stack);
- }
- }
-
- if (current == b.getEndNode()) {
- // Break loop when reaching end node.
- break;
- }
-
- current = ((FixedWithNextNode) current).next();
+ for (FixedNode current : b.getBeginNode().getBlockNodes()) {
+ processNodes(visited, entries, stack, startBlock, current.inputs());
}
}
if (visited.getCounter() < graph.getNodeCount()) {
-
// Visit back input edges of loop phis.
boolean changed;
boolean unmarkedPhi;
@@ -829,36 +845,29 @@
if (fixedNode instanceof ControlSplitNode) {
ControlSplitNode controlSplitNode = (ControlSplitNode) fixedNode;
MicroBlock endBlock = entries.get(fixedNode);
- MicroBlock primarySuccessor = entries.get(controlSplitNode.getPrimarySuccessor());
- endBlock.prependChildrenTo(primarySuccessor);
+ AbstractBeginNode primarySuccessor = controlSplitNode.getPrimarySuccessor();
+ if (primarySuccessor != null) {
+ endBlock.prependChildrenTo(entries.get(primarySuccessor));
+ } else {
+ assert endBlock.tail == null;
+ }
}
}
- // Initialize with begin nodes
+ // Create lists for each block
for (Block b : cfg.reversePostOrder()) {
-
- FixedNode current = b.getBeginNode();
+ // Count nodes in block
int totalCount = 0;
- while (true) {
-
+ for (FixedNode current : b.getBeginNode().getBlockNodes()) {
MicroBlock microBlock = entries.get(current);
totalCount += microBlock.getNodeCount() + 1;
-
- if (current == b.getEndNode()) {
- // Break loop when reaching end node.
- break;
- }
-
- current = ((FixedWithNextNode) current).next();
}
// Initialize with begin node, it is always the first node.
ArrayList<Node> nodes = new ArrayList<>(totalCount);
blockToNodes.put(b, nodes);
- current = b.getBeginNode();
- while (true) {
-
+ for (FixedNode current : b.getBeginNode().getBlockNodes()) {
MicroBlock microBlock = entries.get(current);
nodeToBlock.set(current, b);
nodes.add(current);
@@ -869,19 +878,20 @@
nodes.add(nextNode);
next = next.getNext();
}
-
- if (current == b.getEndNode()) {
- // Break loop when reaching end node.
- break;
- }
-
- current = ((FixedWithNextNode) current).next();
}
}
assert (!Assertions.detailedAssertionsEnabled(cfg.graph.getOptions())) || MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes);
}
+ private static void processNodes(NodeBitMap visited, NodeMap<MicroBlock> entries, NodeStack stack, MicroBlock startBlock, Iterable<? extends Node> nodes) {
+ for (Node node : nodes) {
+ if (entries.get(node) == null) {
+ processStack(node, startBlock, entries, visited, stack);
+ }
+ }
+ }
+
private static void processStackPhi(NodeStack stack, PhiNode phiNode, NodeMap<MicroBlock> nodeToBlock, NodeBitMap visited) {
stack.pop();
if (visited.checkAndMarkInc(phiNode)) {
@@ -944,6 +954,166 @@
}
}
+ private static class GuardOrder {
+ /**
+ * After an earliest schedule, this will re-sort guards to honor their
+ * {@linkplain StaticDeoptimizingNode#computePriority() priority}.
+ *
+ * Note that this only changes the order of nodes within {@linkplain MicroBlock
+ * micro-blocks}, nodes will not be moved from one micro-block to another.
+ */
+ private static void resortGuards(StructuredGraph graph, NodeMap<MicroBlock> entries, NodeStack stack) {
+ assert stack.isEmpty();
+ EconomicSet<MicroBlock> blocksWithGuards = EconomicSet.create(IDENTITY);
+ for (GuardNode guard : graph.getNodes(GuardNode.TYPE)) {
+ MicroBlock block = entries.get(guard);
+ assert block != null : guard + "should already be scheduled to a micro-block";
+ blocksWithGuards.add(block);
+ }
+ assert !blocksWithGuards.isEmpty();
+ NodeMap<GuardPriority> priorities = graph.createNodeMap();
+ NodeBitMap blockNodes = graph.createNodeBitMap();
+ for (MicroBlock block : blocksWithGuards) {
+ MicroBlock newBlock = resortGuards(block, stack, blockNodes, priorities);
+ assert stack.isEmpty();
+ assert blockNodes.isEmpty();
+ if (newBlock != null) {
+ assert block.getNodeCount() == newBlock.getNodeCount();
+ block.head = newBlock.head;
+ block.tail = newBlock.tail;
+ }
+ }
+ }
+
+ /**
+ * This resorts guards within one micro-block.
+ *
+ * {@code stack}, {@code blockNodes} and {@code priorities} are just temporary
+ * data-structures which are allocated once by the callers of this method. They should
+ * be in their "initial"/"empty" state when calling this method and when it returns.
+ */
+ private static MicroBlock resortGuards(MicroBlock block, NodeStack stack, NodeBitMap blockNodes, NodeMap<GuardPriority> priorities) {
+ if (!propagatePriority(block, stack, priorities, blockNodes)) {
+ return null;
+ }
+
+ Function<GuardNode, GuardPriority> transitiveGuardPriorityGetter = priorities::get;
+ Comparator<GuardNode> globalGuardPriorityComparator = Comparator.comparing(transitiveGuardPriorityGetter).thenComparing(GuardNode::computePriority).thenComparingInt(Node::hashCode);
+
+ SortedSet<GuardNode> availableGuards = new TreeSet<>(globalGuardPriorityComparator);
+ MicroBlock newBlock = new MicroBlock(block.getId());
+
+ NodeBitMap sorted = blockNodes;
+ sorted.invert();
+
+ for (NodeEntry e = block.head; e != null; e = e.next) {
+ checkIfAvailable(e.node, stack, sorted, newBlock, availableGuards, false);
+ }
+ do {
+ while (!stack.isEmpty()) {
+ checkIfAvailable(stack.pop(), stack, sorted, newBlock, availableGuards, true);
+ }
+ Iterator<GuardNode> iterator = availableGuards.iterator();
+ if (iterator.hasNext()) {
+ addNodeToResort(iterator.next(), stack, sorted, newBlock, true);
+ iterator.remove();
+ }
+ } while (!stack.isEmpty() || !availableGuards.isEmpty());
+
+ blockNodes.clearAll();
+ return newBlock;
+ }
+
+ /**
+ * This checks if {@code n} can be scheduled, if it is the case, it schedules it now by
+ * calling {@link #addNodeToResort(Node, NodeStack, NodeBitMap, MicroBlock, boolean)}.
+ */
+ private static void checkIfAvailable(Node n, NodeStack stack, NodeBitMap sorted, Instance.MicroBlock newBlock, SortedSet<GuardNode> availableGuardNodes, boolean pushUsages) {
+ if (sorted.isMarked(n)) {
+ return;
+ }
+ for (Node in : n.inputs()) {
+ if (!sorted.isMarked(in)) {
+ return;
+ }
+ }
+ if (n instanceof GuardNode) {
+ availableGuardNodes.add((GuardNode) n);
+ } else {
+ addNodeToResort(n, stack, sorted, newBlock, pushUsages);
+ }
+ }
+
+ /**
+ * Add a node to the re-sorted micro-block. This also pushes nodes that need to be
+ * (re-)examined on the stack.
+ */
+ private static void addNodeToResort(Node n, NodeStack stack, NodeBitMap sorted, MicroBlock newBlock, boolean pushUsages) {
+ sorted.mark(n);
+ newBlock.add(n);
+ if (pushUsages) {
+ for (Node u : n.usages()) {
+ if (!sorted.isMarked(u)) {
+ stack.push(u);
+ }
+ }
+ }
+ }
+
+ /**
+ * This fills in a map of transitive priorities ({@code priorities}). It also marks the
+ * nodes from this micro-block in {@code blockNodes}.
+ *
+ * The transitive priority of a guard is the highest of its priority and the priority of
+ * the guards that depend on it (transitively).
+ *
+ * This method returns {@code false} if no re-ordering is necessary in this micro-block.
+ */
+ private static boolean propagatePriority(MicroBlock block, NodeStack stack, NodeMap<GuardPriority> priorities, NodeBitMap blockNodes) {
+ assert stack.isEmpty();
+ assert blockNodes.isEmpty();
+ GuardPriority lowestPriority = GuardPriority.highest();
+ for (NodeEntry e = block.head; e != null; e = e.next) {
+ blockNodes.mark(e.node);
+ if (e.node instanceof GuardNode) {
+ GuardNode guard = (GuardNode) e.node;
+ GuardPriority priority = guard.computePriority();
+ if (lowestPriority != null) {
+ if (priority.isLowerPriorityThan(lowestPriority)) {
+ lowestPriority = priority;
+ } else if (priority.isHigherPriorityThan(lowestPriority)) {
+ lowestPriority = null;
+ }
+ }
+ stack.push(guard);
+ priorities.set(guard, priority);
+ }
+ }
+ if (lowestPriority != null) {
+ stack.clear();
+ blockNodes.clearAll();
+ return false;
+ }
+
+ do {
+ Node current = stack.pop();
+ assert blockNodes.isMarked(current);
+ GuardPriority priority = priorities.get(current);
+ for (Node input : current.inputs()) {
+ if (!blockNodes.isMarked(input)) {
+ continue;
+ }
+ GuardPriority inputPriority = priorities.get(input);
+ if (inputPriority == null || inputPriority.isLowerPriorityThan(priority)) {
+ priorities.set(input, priority);
+ stack.push(input);
+ }
+ }
+ } while (!stack.isEmpty());
+ return true;
+ }
+ }
+
/**
* Processes the inputs of given block. Pushes unprocessed inputs onto the stack. Returns
* null if there were still unprocessed inputs, otherwise returns the earliest block given
@@ -960,7 +1130,7 @@
if (inputBlock == null) {
earliestBlock = null;
stack.push(input);
- } else if (earliestBlock != null && inputBlock.getId() >= earliestBlock.getId()) {
+ } else if (earliestBlock != null && inputBlock.getId() > earliestBlock.getId()) {
earliestBlock = inputBlock;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,8 @@
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.GraalGraphError;
@@ -55,8 +57,6 @@
import org.graalvm.compiler.phases.graph.StatelessPostOrderNodeIterator;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
public final class GraphOrder {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.phases.util;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.core.common.spi.CodeGenProviders;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
@@ -90,6 +91,11 @@
}
@Override
+ public ArrayOffsetProvider getArrayOffsetProvider() {
+ return lowerer;
+ }
+
+ @Override
public ConstantReflectionProvider getConstantReflection() {
return constantReflection;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java Sat Feb 10 09:25:35 2018 +0100
@@ -143,9 +143,9 @@
"org.graalvm.compiler.phases.BasePhase.dumpAfter",
"org.graalvm.compiler.phases.BasePhase.dumpBefore",
"org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
- "org.graalvm.compiler.truffle.PartialEvaluator.fastPartialEvaluation",
- "org.graalvm.compiler.truffle.PartialEvaluator$PerformanceInformationHandler.reportPerformanceWarnings",
- "org.graalvm.compiler.truffle.TruffleCompiler.compileMethodHelper",
+ "org.graalvm.compiler.truffle.compiler.PartialEvaluator.fastPartialEvaluation",
+ "org.graalvm.compiler.truffle.compiler.PartialEvaluator$PerformanceInformationHandler.reportPerformanceWarnings",
+ "org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph",
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run",
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run",
"org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run"));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,8 +22,10 @@
*/
package org.graalvm.compiler.phases.verify;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
@@ -40,10 +42,9 @@
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.phases.VerifyPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicSet;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
public class VerifyGraphAddUsage extends VerifyPhase<PhaseContext> {
private static final Method ADD_OR_UNIQUE;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java Sat Feb 10 09:25:35 2018 +0100
@@ -33,6 +33,7 @@
import java.util.Map;
import java.util.TreeMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.core.common.alloc.Trace;
@@ -66,7 +67,6 @@
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
-import org.graalvm.util.UnmodifiableMapCursor;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,12 +23,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.graph.Node.ConstantNodeParameter;
import org.graalvm.compiler.word.Word;
import org.graalvm.word.Pointer;
-import sun.misc.Unsafe;
+import jdk.vm.ci.meta.JavaKind;
// JaCoCo Exclude
@@ -38,6 +41,19 @@
@ClassSubstitution(String.class)
public class AMD64StringSubstitutions {
+ @Fold
+ static int charArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
+ return arrayOffsetProvider.arrayBaseOffset(JavaKind.Char);
+ }
+
+ @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;
+
// Only exists in JDK <= 8
@MethodSubstitution(isStatic = true, optional = true)
public static int indexOf(char[] source, int sourceOffset, int sourceCount,
@@ -62,8 +78,8 @@
}
assert sourceCount - fromIndex > 0 && targetCount > 0;
- Pointer sourcePointer = Word.objectToTrackedPointer(source).add(Unsafe.ARRAY_CHAR_BASE_OFFSET).add(totalOffset * Unsafe.ARRAY_CHAR_INDEX_SCALE);
- Pointer targetPointer = Word.objectToTrackedPointer(target).add(Unsafe.ARRAY_CHAR_BASE_OFFSET).add(targetOffset * Unsafe.ARRAY_CHAR_INDEX_SCALE);
+ Pointer sourcePointer = Word.objectToTrackedPointer(source).add(charArrayBaseOffset(INJECTED)).add(totalOffset * charArrayIndexScale(INJECTED));
+ Pointer targetPointer = Word.objectToTrackedPointer(target).add(charArrayBaseOffset(INJECTED)).add(targetOffset * charArrayIndexScale(INJECTED));
int result = AMD64StringIndexOfNode.optimizedStringIndexPointer(sourcePointer, sourceCount - fromIndex, targetPointer, targetCount);
if (result >= 0) {
return result + totalOffset;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -79,7 +79,7 @@
@Override
protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
- InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null);
+ InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), getProviders().getLowerer(), null);
new PluginFactory_FoldTest().registerPlugins(invocationPlugins, injection);
BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider();
Registration r = new Registration(invocationPlugins, TestMethod.class, replacementBytecodeProvider);
--- /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/NestedExceptionHandlerTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -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.
+ */
+package org.graalvm.compiler.replacements.test;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.core.phases.HighTier;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.options.OptionValues;
+import org.junit.Test;
+
+public class NestedExceptionHandlerTest extends GraalCompilerTest {
+
+ @BytecodeParserNeverInline(invokeWithException = true)
+ public static void foo() {
+ }
+
+ @BytecodeParserNeverInline(invokeWithException = true)
+ public static void bar() {
+ throw new NegativeArraySizeException();
+ }
+
+ public static int nestedExceptionHandler() {
+ int flag = 0;
+ try {
+ try {
+ try {
+ foo();
+ } catch (NegativeArraySizeException e) {
+ flag = -1;
+ }
+ bar();
+ } catch (NullPointerException e) {
+ flag = -2;
+ }
+ } catch (Throwable e) {
+ GraalDirectives.deoptimize();
+ }
+ return flag;
+ }
+
+ @Test
+ public void testNestedExceptionHandler() {
+ test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "nestedExceptionHandler");
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
+import org.graalvm.collections.EconomicMap;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.java.GraphBuilderPhase;
@@ -43,7 +44,6 @@
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.util.EconomicMap;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,10 +24,13 @@
import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
+import org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.debug.DebugHandlersFactory;
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues;
@@ -38,7 +41,7 @@
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import jdk.vm.ci.code.TargetDescription;
-import sun.misc.Unsafe;
+import jdk.vm.ci.meta.JavaKind;
public class ConstantStringIndexOfSnippets implements Snippets {
public static class Templates extends AbstractTemplates {
@@ -91,6 +94,14 @@
return cache;
}
+ @Fold
+ static int charArrayBaseOffset(@InjectedParameter ArrayOffsetProvider arrayOffsetProvider) {
+ return arrayOffsetProvider.arrayBaseOffset(JavaKind.Char);
+ }
+
+ /** Marker value for the {@link InjectedParameter} injected parameter. */
+ static final ArrayOffsetProvider INJECTED = null;
+
@Snippet
public static int indexOfConstant(char[] source, int sourceOffset, int sourceCount,
@ConstantParameter char[] target, int targetOffset, int targetCount,
@@ -109,7 +120,7 @@
int targetCountLess1 = targetCount - 1;
int sourceEnd = sourceCount - targetCountLess1;
- long base = Unsafe.ARRAY_CHAR_BASE_OFFSET;
+ long base = charArrayBaseOffset(INJECTED);
int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2);
outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -921,8 +921,7 @@
public abstract int arrayLengthOffset();
- public abstract int arrayBaseOffset(JavaKind elementKind);
-
+ @Override
public int arrayScalingFactor(JavaKind elementKind) {
return target.arch.getPlatformKind(elementKind).getSizeInBytes();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java Sat Feb 10 09:25:35 2018 +0100
@@ -27,7 +27,7 @@
import java.util.List;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
-import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.ConditionAnchorNode;
@@ -184,7 +184,7 @@
}
if (condition == null || (!(condition instanceof CompareNode)) || ((CompareNode) condition).getY() != testValue) {
// Re-use previously generated condition if the trueValue for the test is the same
- condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null, NodeView.DEFAULT);
+ condition = createCompareNode(result.graph(), CanonicalCondition.EQ, result, testValue, null, NodeView.DEFAULT);
}
return condition;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,6 +23,7 @@
package org.graalvm.compiler.replacements;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -40,12 +41,15 @@
private final MetaAccessProvider metaAccess;
private final SnippetReflectionProvider snippetReflection;
private final ForeignCallsProvider foreignCalls;
+ private final ArrayOffsetProvider arrayOffsetProvider;
private final WordTypes wordTypes;
- public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, WordTypes wordTypes) {
+ public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, ArrayOffsetProvider arrayOffsetProvider,
+ WordTypes wordTypes) {
this.metaAccess = metaAccess;
this.snippetReflection = snippetReflection;
this.foreignCalls = foreignCalls;
+ this.arrayOffsetProvider = arrayOffsetProvider;
this.wordTypes = wordTypes;
}
@@ -73,6 +77,8 @@
return type.cast(foreignCalls);
} else if (type.equals(SnippetReflectionProvider.class)) {
return type.cast(snippetReflection);
+ } else if (type.equals(ArrayOffsetProvider.class)) {
+ return type.cast(arrayOffsetProvider);
} else {
throw new GraalError("Cannot handle injected argument of type %s.", type.getName());
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Sat Feb 10 09:25:35 2018 +0100
@@ -32,6 +32,8 @@
import java.util.List;
import java.util.Map;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.PermanentBailoutException;
@@ -102,8 +104,6 @@
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.BailoutException;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -36,6 +36,8 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.api.replacements.Snippet;
@@ -47,9 +49,9 @@
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.debug.DebugCloseable;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Description;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.graph.Node;
@@ -81,8 +83,6 @@
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordOperationPlugin;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -274,10 +274,13 @@
if (plugin instanceof MethodSubstitutionPlugin) {
MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin;
ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess);
- StructuredGraph graph = graphs.get(substitute);
+ StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(substitute) : null;
if (graph == null) {
try (DebugContext debug = openDebugContext("Substitution_", method)) {
graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method);
+ if (!UseSnippetGraphCache.getValue(options)) {
+ return graph;
+ }
graph.freeze();
graphs.putIfAbsent(substitute, graph);
graph = graphs.get(substitute);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Sat Feb 10 09:25:35 2018 +0100
@@ -47,11 +47,27 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Local;
+import jdk.vm.ci.meta.LocalVariableTable;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter;
+
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter;
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -59,15 +75,15 @@
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugHandlersFactory;
-import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.DebugContext.Description;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TimerKey;
-import org.graalvm.compiler.graph.Graph.Mark;
+import org.graalvm.compiler.debug.DebugContext.Description;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.Position;
+import org.graalvm.compiler.graph.Graph.Mark;
import org.graalvm.compiler.loop.LoopEx;
import org.graalvm.compiler.loop.LoopsData;
import org.graalvm.compiler.loop.phases.LoopTransformations;
@@ -86,15 +102,15 @@
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.PhiNode;
-import org.graalvm.compiler.nodes.PiNode.Placeholder;
-import org.graalvm.compiler.nodes.PiNode.PlaceholderStamp;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.ValueNodeUtil;
+import org.graalvm.compiler.nodes.PiNode.Placeholder;
+import org.graalvm.compiler.nodes.PiNode.PlaceholderStamp;
+import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.java.LoadIndexedNode;
import org.graalvm.compiler.nodes.java.StoreIndexedNode;
@@ -115,35 +131,19 @@
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
-import org.graalvm.compiler.phases.common.FloatingReadPhase.MemoryMapImpl;
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
+import org.graalvm.compiler.phases.common.FloatingReadPhase.MemoryMapImpl;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode;
import org.graalvm.util.CollectionsUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.UnmodifiableEconomicMap;
import org.graalvm.word.LocationIdentity;
import org.graalvm.word.WordBase;
-import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.Local;
-import jdk.vm.ci.meta.LocalVariableTable;
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter;
-import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.meta.Signature;
-
/**
* A snippet template is a graph created by parsing a snippet method and then specialized by binding
* constants to the snippet's {@link ConstantParameter} parameters.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Sat Feb 10 09:25:35 2018 +0100
@@ -37,10 +37,13 @@
import java.lang.reflect.Field;
import java.util.Arrays;
+import jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.meta.SpeculationLog;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
import org.graalvm.compiler.core.common.calc.UnsignedMath;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -456,23 +459,16 @@
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- // the mirroring and negation operations get the condition into canonical form
- boolean mirror = condition.canonicalMirror();
- boolean negate = condition.canonicalNegate();
+ CanonicalizedCondition canonical = condition.canonicalize();
StructuredGraph graph = b.getGraph();
- ValueNode lhs = mirror ? y : x;
- ValueNode rhs = mirror ? x : y;
-
- ValueNode trueValue = ConstantNode.forBoolean(!negate, graph);
- ValueNode falseValue = ConstantNode.forBoolean(negate, graph);
+ ValueNode lhs = canonical.mustMirror() ? y : x;
+ ValueNode rhs = canonical.mustMirror() ? x : y;
- Condition cond = mirror ? condition.mirror() : condition;
- if (negate) {
- cond = cond.negate();
- }
+ ValueNode trueValue = ConstantNode.forBoolean(!canonical.mustNegate(), graph);
+ ValueNode falseValue = ConstantNode.forBoolean(canonical.mustNegate(), graph);
- LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, cond, lhs, rhs, NodeView.DEFAULT);
+ LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, canonical.getCanonicalCondition(), lhs, rhs, NodeView.DEFAULT);
b.addPush(JavaKind.Boolean, new ConditionalNode(compare, trueValue, falseValue));
return true;
}
@@ -728,6 +724,24 @@
}
}
+ private static final class DirectiveSpeculationReason implements SpeculationLog.SpeculationReason {
+ private final BytecodePosition pos;
+
+ private DirectiveSpeculationReason(BytecodePosition pos) {
+ this.pos = pos;
+ }
+
+ @Override
+ public int hashCode() {
+ return pos.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof DirectiveSpeculationReason && ((DirectiveSpeculationReason) obj).pos.equals(this.pos);
+ }
+ }
+
private static void registerGraalDirectivesPlugins(InvocationPlugins plugins) {
Registration r = new Registration(plugins, GraalDirectives.class);
r.register0("deoptimize", new InvocationPlugin() {
@@ -746,6 +760,23 @@
}
});
+ r.register0("deoptimizeAndInvalidateWithSpeculation", new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
+ GraalError.guarantee(b.getGraph().getSpeculationLog() != null, "A speculation log is need to use `deoptimizeAndInvalidateWithSpeculation`");
+ BytecodePosition pos = new BytecodePosition(null, b.getMethod(), b.bci());
+ DirectiveSpeculationReason reason = new DirectiveSpeculationReason(pos);
+ JavaConstant speculation;
+ if (b.getGraph().getSpeculationLog().maySpeculate(reason)) {
+ speculation = b.getGraph().getSpeculationLog().speculate(reason);
+ } else {
+ speculation = JavaConstant.defaultForKind(JavaKind.Object);
+ }
+ b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter, speculation));
+ return true;
+ }
+ });
+
r.register0("inCompiledCode", new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/Classfile.java Sat Feb 10 09:25:35 2018 +0100
@@ -46,8 +46,8 @@
private final ResolvedJavaType type;
private final List<ClassfileBytecode> codeAttributes;
- private static final int MAJOR_VERSION_JAVA_MIN = 51;
- private static final int MAJOR_VERSION_JAVA_MAX = 55;
+ private static final int MAJOR_VERSION_JAVA_MIN = 51; // JDK7
+ private static final int MAJOR_VERSION_JAVA_MAX = 55; // JDK11
private static final int MAGIC = 0xCAFEBABE;
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,12 +29,12 @@
import java.io.IOException;
import java.io.InputStream;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.serviceprovider.JDK9Method;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java Sat Feb 10 09:25:35 2018 +0100
@@ -54,6 +54,7 @@
public static final byte CONSTANT_NameAndType = 12;
public static final byte CONSTANT_MethodHandle = 15;
public static final byte CONSTANT_MethodType = 16;
+ public static final byte CONSTANT_Dynamic = 17;
public static final byte CONSTANT_InvokeDynamic = 18;
// @formatter:on
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java Sat Feb 10 09:25:35 2018 +0100
@@ -112,6 +112,9 @@
case ClassfileConstant.CONSTANT_MethodType:
skipFully(stream, 2); // descriptor_index
return new ClassfileConstant.Unsupported(tag, "CONSTANT_MethodType_info");
+ case ClassfileConstant.CONSTANT_Dynamic:
+ skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index
+ return new ClassfileConstant.Unsupported(tag, "CONSTANT_Dynamic_info");
case ClassfileConstant.CONSTANT_InvokeDynamic:
skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index
return new ClassfileConstant.Unsupported(tag, "CONSTANT_InvokeDynamic_info");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Sat Feb 10 09:25:35 2018 +0100
@@ -62,7 +62,7 @@
@Override
public boolean inferStamp() {
- return updateStamp(computeStamp(getObject()));
+ return updateStamp(stamp.improveWith(computeStamp(getObject())));
}
protected Stamp computeStamp(ValueNode object) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider.processor/src/org/graalvm/compiler/serviceprovider/processor/ServiceProviderProcessor.java Sat Feb 10 09:25:35 2018 +0100
@@ -37,6 +37,8 @@
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
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.type.MirroredTypeException;
import javax.lang.model.type.TypeMirror;
@@ -84,8 +86,8 @@
try {
annotation.value();
} catch (MirroredTypeException ex) {
- TypeMirror serviceInterface = ex.getTypeMirror();
- if (verifyAnnotation(serviceInterface, serviceProvider)) {
+ TypeMirror service = ex.getTypeMirror();
+ if (verifyAnnotation(service, serviceProvider)) {
if (serviceProvider.getNestingKind().isNested()) {
/*
* This is a simplifying constraint that means we don't have to process the
@@ -94,7 +96,30 @@
String msg = String.format("Service provider class %s must be a top level class", serviceProvider.getSimpleName());
processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
} else {
- serviceProviders.put(serviceProvider, ex.getTypeMirror().toString());
+ /*
+ * Since the definition of the service class is not necessarily modifiable,
+ * we need to support a non-top-level service class and ensure its name is
+ * properly expressed with '$' separating nesting levels instead of '.'.
+ */
+ TypeElement serviceElement = (TypeElement) processingEnv.getTypeUtils().asElement(service);
+ String serviceName = serviceElement.getSimpleName().toString();
+ Element enclosing = serviceElement.getEnclosingElement();
+ while (enclosing != null) {
+ final ElementKind kind = enclosing.getKind();
+ if (kind == ElementKind.PACKAGE) {
+ serviceName = ((PackageElement) enclosing).getQualifiedName().toString() + "." + serviceName;
+ break;
+ } else if (kind == ElementKind.CLASS || kind == ElementKind.INTERFACE) {
+ serviceName = ((TypeElement) enclosing).getSimpleName().toString() + "$" + serviceName;
+ enclosing = enclosing.getEnclosingElement();
+ } else {
+ String msg = String.format("Cannot generate provider descriptor for service class %s as it is not nested in a package, class or interface",
+ serviceElement.getQualifiedName());
+ processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
+ return;
+ }
+ }
+ serviceProviders.put(serviceProvider, serviceName);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,7 +24,6 @@
import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION;
-import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES;
import java.io.PrintStream;
import java.io.PrintWriter;
@@ -36,16 +35,17 @@
import java.util.Collections;
import java.util.List;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugDumpHandler;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.debug.GlobalMetrics;
import org.graalvm.compiler.options.OptionValues;
import org.junit.After;
import org.junit.Assert;
import org.junit.internal.ComparisonCriteria;
import org.junit.internal.ExactComparisonCriteria;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
import sun.misc.Unsafe;
/**
@@ -398,7 +398,7 @@
/**
* Gets a {@link DebugContext} object corresponding to {@code options}, creating a new one if
- * none currently exists.Debug contexts created by this method will have their
+ * none currently exists. Debug contexts created by this method will have their
* {@link DebugDumpHandler}s closed in {@link #afterTest()}.
*
* @param options currently active options
@@ -423,11 +423,21 @@
} else {
descr = new DebugContext.Description(method, id == null ? method.getName() : id);
}
- DebugContext debug = DebugContext.create(options, descr, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, getDebugHandlersFactories());
+ DebugContext debug = DebugContext.create(options, descr, globalMetrics, DEFAULT_LOG_STREAM, getDebugHandlersFactories());
cached.add(debug);
return debug;
}
+ private static final GlobalMetrics globalMetrics = new GlobalMetrics();
+
+ static {
+ Runtime.getRuntime().addShutdownHook(new Thread("GlobalMetricsPrinter") {
+ @Override
+ public void run() {
+ globalMetrics.print(new OptionValues(OptionValues.newOptionMap()));
+ }
+ });
+ }
private final ThreadLocal<List<DebugContext>> cachedDebugs = new ThreadLocal<>();
@After
@@ -435,6 +445,7 @@
List<DebugContext> cached = cachedDebugs.get();
if (cached != null) {
for (DebugContext debug : cached) {
+ debug.close();
debug.closeDumpHandlers(true);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Sat Feb 10 09:25:35 2018 +0100
@@ -22,8 +22,6 @@
*/
package org.graalvm.compiler.test;
-import org.graalvm.util.CollectionsUtil;
-
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -37,6 +35,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.graalvm.util.CollectionsUtil;
+
/**
* Utility methods for spawning a VM in a subprocess during unit tests.
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,8 +25,8 @@
import java.util.Iterator;
import java.util.Map;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.UnmodifiableMapCursor;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.UnmodifiableMapCursor;
public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,9 @@
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -59,9 +62,6 @@
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.LoopInfo;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import org.graalvm.word.LocationIdentity;
public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.util.CompilationAlarm;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
@@ -39,7 +40,6 @@
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicSet;
public abstract class EffectsPhase<PhaseContextT extends PhaseContext> extends BasePhase<PhaseContextT> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,8 @@
import java.util.Iterator;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.DebugContext;
@@ -35,8 +37,6 @@
import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,6 +29,11 @@
import java.util.Iterator;
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
+import org.graalvm.collections.Pair;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.graph.Node;
@@ -61,11 +66,6 @@
import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
-import org.graalvm.util.Pair;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -186,7 +186,7 @@
JavaKind accessKind = load.accessKind();
JavaKind componentKind = type.getComponentType().getJavaKind();
long offset = load.offset().asJavaConstant().asLong();
- int index = VirtualArrayNode.entryIndexForOffset(offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
+ int index = VirtualArrayNode.entryIndexForOffset(tool.getArrayOffsetProvider(), offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
ValueNode object = GraphUtil.unproxify(load.object());
LocationIdentity location = NamedLocationIdentity.getArrayLocation(componentKind);
ValueNode cachedValue = state.getReadCache(object, location, index, accessKind, this);
@@ -212,7 +212,7 @@
if (store.offset().isConstant()) {
long offset = store.offset().asJavaConstant().asLong();
boolean overflowAccess = isOverflowAccess(accessKind, componentKind);
- int index = overflowAccess ? -1 : VirtualArrayNode.entryIndexForOffset(offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
+ int index = overflowAccess ? -1 : VirtualArrayNode.entryIndexForOffset(tool.getArrayOffsetProvider(), offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
return processStore(store, store.object(), location, index, accessKind, overflowAccess, store.value(), state, effects);
} else {
processIdentity(state, location);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,6 +28,9 @@
import java.util.List;
import java.util.function.IntUnaryOperator;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
@@ -68,9 +71,6 @@
import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.virtual.nodes.VirtualObjectState;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalysisIterations;
import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalyzeOnly;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
@@ -37,7 +38,6 @@
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.util.EconomicSet;
public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,10 +24,10 @@
import java.util.Iterator;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.util.Equivalence;
import org.graalvm.word.LocationIdentity;
-import org.graalvm.util.EconomicMap;
/**
* This class maintains a set of known values, identified by base object, locations and offset.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Sat Feb 10 09:25:35 2018 +0100
@@ -28,7 +28,10 @@
import java.util.Iterator;
import java.util.List;
-import jdk.vm.ci.meta.ResolvedJavaType;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.EconomicSet;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.collections.MapCursor;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
@@ -60,13 +63,10 @@
import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
/**
* This closure initially handled a set of nodes that is disjunct from
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,8 @@
import java.util.List;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TTY;
@@ -35,8 +37,6 @@
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.Equivalence;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,7 @@
import java.util.List;
+import org.graalvm.compiler.core.common.spi.ArrayOffsetProvider;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
@@ -108,6 +109,11 @@
return constantFieldProvider;
}
+ @Override
+ public ArrayOffsetProvider getArrayOffsetProvider() {
+ return loweringProvider;
+ }
+
public void reset(PartialEscapeBlockState<?> newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
deleted = false;
state = newState;
@@ -160,7 +166,7 @@
* Special case: Allow storing a single long or double value into two consecutive
* int slots.
*/
- int nextIndex = virtual.entryIndexForOffset(offset + 4, JavaKind.Int);
+ int nextIndex = virtual.entryIndexForOffset(getArrayOffsetProvider(), offset + 4, JavaKind.Int);
if (nextIndex != -1) {
canVirtualize = true;
assert nextIndex == index + 1 : "expected to be sequential";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Sat Feb 10 09:25:35 2018 +0100
@@ -31,7 +31,9 @@
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BridgeMethodUtils;
+import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
@@ -409,31 +411,30 @@
private ValueNode comparisonOp(GraphBuilderContext graph, Condition condition, ValueNode left, ValueNode right) {
assert left.getStackKind() == wordKind && right.getStackKind() == wordKind;
- // mirroring gets the condition into canonical form
- boolean mirror = condition.canonicalMirror();
+ CanonicalizedCondition canonical = condition.canonicalize();
- ValueNode a = mirror ? right : left;
- ValueNode b = mirror ? left : right;
+ ValueNode a = canonical.mustMirror() ? right : left;
+ ValueNode b = canonical.mustMirror() ? left : right;
CompareNode comparison;
- if (condition == Condition.EQ || condition == Condition.NE) {
+ if (canonical.getCanonicalCondition() == CanonicalCondition.EQ) {
comparison = new IntegerEqualsNode(a, b);
- } else if (condition.isUnsigned()) {
+ } else if (canonical.getCanonicalCondition() == CanonicalCondition.BT) {
comparison = new IntegerBelowNode(a, b);
} else {
+ assert canonical.getCanonicalCondition() == CanonicalCondition.LT;
comparison = new IntegerLessThanNode(a, b);
}
ConstantNode trueValue = graph.add(forInt(1));
ConstantNode falseValue = graph.add(forInt(0));
- if (condition.canonicalNegate()) {
+ if (canonical.mustNegate()) {
ConstantNode temp = trueValue;
trueValue = falseValue;
falseValue = temp;
}
- ConditionalNode materialize = graph.add(new ConditionalNode(graph.add(comparison), trueValue, falseValue));
- return materialize;
+ return graph.add(new ConditionalNode(graph.add(comparison), trueValue, falseValue));
}
protected ValueNode readOp(GraphBuilderContext b, JavaKind readKind, AddressNode address, LocationIdentity location, Opcode op) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphJavadocSnippets.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.graalvm.graphio;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+final class GraphJavadocSnippets {
+ static GraphStructure<AcmeGraph, AcmeNode, AcmeNodeType, AcmePorts> acmeGraphStructure() {
+ // @formatter:off
+ // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure
+ class AcmeGraphStructure implements
+ GraphStructure<AcmeGraph, AcmeNode, AcmeNodeType, AcmePorts> {
+
+ @Override
+ public AcmeGraph graph(AcmeGraph currentGraph, Object obj) {
+ return obj instanceof AcmeGraph ? (AcmeGraph) obj : null;
+ }
+
+ @Override
+ public Iterable<? extends AcmeNode> nodes(AcmeGraph graph) {
+ return graph.allNodes();
+ }
+
+ @Override
+ public int nodesCount(AcmeGraph graph) {
+ return graph.allNodes().size();
+ }
+
+ @Override
+ public int nodeId(AcmeNode node) {
+ return node.id;
+ }
+
+ @Override
+ public boolean nodeHasPredecessor(AcmeNode node) {
+ return node.id > 0;
+ }
+
+ @Override
+ public void nodeProperties(
+ AcmeGraph graph, AcmeNode node, Map<String, ? super Object> properties
+ ) {
+ properties.put("id", node.id);
+ }
+
+ @Override
+ public AcmeNodeType nodeClass(Object obj) {
+ return obj instanceof AcmeNodeType ? (AcmeNodeType) obj : null;
+ }
+
+ @Override
+ public AcmeNode node(Object obj) {
+ return obj instanceof AcmeNode ? (AcmeNode) obj : null;
+ }
+
+ @Override
+ public AcmeNodeType classForNode(AcmeNode node) {
+ // we have only one type of nodes
+ return AcmeNodeType.STANDARD;
+ }
+
+
+ @Override
+ public String nameTemplate(AcmeNodeType nodeClass) {
+ return "Acme ({p#id})";
+ }
+
+ @Override
+ public Object nodeClassType(AcmeNodeType nodeClass) {
+ return nodeClass.getClass();
+ }
+
+ @Override
+ public AcmePorts portInputs(AcmeNodeType nodeClass) {
+ return AcmePorts.INPUT;
+ }
+
+ @Override
+ public AcmePorts portOutputs(AcmeNodeType nodeClass) {
+ return AcmePorts.OUTPUT;
+ }
+
+ @Override
+ public int portSize(AcmePorts port) {
+ return port == AcmePorts.OUTPUT ? 1 : 0;
+ }
+
+ @Override
+ public boolean edgeDirect(AcmePorts port, int index) {
+ return false;
+ }
+
+ @Override
+ public String edgeName(AcmePorts port, int index) {
+ return port.name();
+ }
+
+ @Override
+ public Object edgeType(AcmePorts port, int index) {
+ return port;
+ }
+
+ @Override
+ public Collection<? extends AcmeNode> edgeNodes(
+ AcmeGraph graph, AcmeNode node, AcmePorts port, int index
+ ) {
+ if (port == AcmePorts.OUTPUT) {
+ return node.outgoing.targets;
+ }
+ return null;
+ }
+ }
+
+ // END: org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure
+
+ return new AcmeGraphStructure();
+ }
+
+ // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#buildOutput
+ static GraphOutput<AcmeGraph, ?> buildOutput(WritableByteChannel channel)
+ throws IOException {
+ return GraphOutput.newBuilder(acmeGraphStructure()).
+ // use the latest version; currently 5.0
+ protocolVersion(5, 0).
+ build(channel);
+ }
+ // END: org.graalvm.graphio.GraphJavadocSnippets#buildOutput
+
+ // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#buildAll
+ static GraphOutput<AcmeGraph, ?> buildAll(WritableByteChannel channel)
+ throws IOException {
+ GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> graphBlocks = acmeBlocks();
+ GraphElements<AcmeMethod, AcmeField,
+ AcmeSignature, AcmeCodePosition> graphElements = acmeElements();
+ GraphTypes graphTypes = acmeTypes();
+
+ return GraphOutput.newBuilder(acmeGraphStructure()).
+ protocolVersion(5, 0).
+ blocks(graphBlocks).
+ elements(graphElements).
+ types(graphTypes).
+ build(channel);
+ }
+ // END: org.graalvm.graphio.GraphJavadocSnippets#buildAll
+
+ private static GraphTypes acmeTypes() {
+ GraphTypes graphTypes = null;
+ // in real world don't return null
+ return graphTypes;
+ }
+
+ private static GraphElements<AcmeMethod, AcmeField, AcmeSignature, AcmeCodePosition> acmeElements() {
+ GraphElements<AcmeMethod, AcmeField, AcmeSignature, AcmeCodePosition> graphElements = null;
+ // in real world don't return null
+ return graphElements;
+ }
+
+ private static GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> acmeBlocks() {
+ GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> graphBlocks = null;
+ // in real world don't return null
+ return graphBlocks;
+ }
+
+ private static class AcmeGraph {
+ final AcmeNode root;
+
+ AcmeGraph(AcmeNode root) {
+ this.root = root;
+ }
+
+ Set<AcmeNode> allNodes() {
+ return allNodes(root, new LinkedHashSet<>());
+ }
+
+ private static Set<AcmeNode> allNodes(AcmeNode node, Set<AcmeNode> collectTo) {
+ if (collectTo.add(node)) {
+ for (AcmeNode target : node.outgoing.targets) {
+ allNodes(target, collectTo);
+ }
+ }
+ return collectTo;
+ }
+ }
+
+ private static class AcmeNode {
+ final int id;
+ final AcmeEdges outgoing;
+
+ AcmeNode(int id) {
+ this.id = id;
+ this.outgoing = new AcmeEdges();
+ }
+
+ void linkTo(AcmeNode target) {
+ outgoing.targets.add(target);
+ }
+ }
+
+ private enum AcmeNodeType {
+ STANDARD
+ }
+
+ private enum AcmePorts {
+ INPUT,
+ OUTPUT;
+ }
+
+ private static class AcmeEdges {
+ final Set<AcmeNode> targets;
+
+ AcmeEdges() {
+ this.targets = new LinkedHashSet<>();
+ }
+ }
+
+ private static class AcmeBlocks {
+ }
+
+ private static class AcmeMethod {
+ }
+
+ private static class AcmeField {
+ }
+
+ private static class AcmeSignature {
+ }
+
+ private static class AcmeCodePosition {
+ }
+
+ // BEGIN: org.graalvm.graphio.GraphJavadocSnippets#dump
+ static void dump(File toFile) throws IOException {
+ try (
+ FileChannel ch = new FileOutputStream(toFile).getChannel();
+ GraphOutput<AcmeGraph, ?> output = buildOutput(ch);
+ ) {
+ AcmeNode root = new AcmeNode(0);
+ AcmeNode n1 = new AcmeNode(1);
+ AcmeNode n2 = new AcmeNode(2);
+ AcmeNode n3 = new AcmeNode(3);
+
+ root.linkTo(n1);
+ root.linkTo(n2);
+ n1.linkTo(n3);
+ n2.linkTo(n3);
+
+ AcmeGraph diamondGraph = new AcmeGraph(root);
+
+ output.beginGroup(diamondGraph, "Diamond", "dia", null, 0, null);
+ output.print(diamondGraph, null, 0, "Diamond graph #%d", 1);
+ output.endGroup();
+ }
+ }
+ // END: org.graalvm.graphio.GraphJavadocSnippets#dump
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.graalvm.graphio;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.channels.FileChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-final class GraphSnippets {
- static GraphStructure<AcmeGraph, AcmeNode, AcmeNodeType, AcmePorts> acmeGraphStructure() {
- // @formatter:off
- // BEGIN: org.graalvm.graphio.GraphSnippets#acmeGraphStructure
- class AcmeGraphStructure implements
- GraphStructure<AcmeGraph, AcmeNode, AcmeNodeType, AcmePorts> {
-
- @Override
- public AcmeGraph graph(AcmeGraph currentGraph, Object obj) {
- return obj instanceof AcmeGraph ? (AcmeGraph) obj : null;
- }
-
- @Override
- public Iterable<? extends AcmeNode> nodes(AcmeGraph graph) {
- return graph.allNodes();
- }
-
- @Override
- public int nodesCount(AcmeGraph graph) {
- return graph.allNodes().size();
- }
-
- @Override
- public int nodeId(AcmeNode node) {
- return node.id;
- }
-
- @Override
- public boolean nodeHasPredecessor(AcmeNode node) {
- return node.id > 0;
- }
-
- @Override
- public void nodeProperties(
- AcmeGraph graph, AcmeNode node, Map<String, ? super Object> properties
- ) {
- properties.put("id", node.id);
- }
-
- @Override
- public AcmeNodeType nodeClass(Object obj) {
- return obj instanceof AcmeNodeType ? (AcmeNodeType) obj : null;
- }
-
- @Override
- public AcmeNode node(Object obj) {
- return obj instanceof AcmeNode ? (AcmeNode) obj : null;
- }
-
- @Override
- public AcmeNodeType classForNode(AcmeNode node) {
- // we have only one type of nodes
- return AcmeNodeType.STANDARD;
- }
-
-
- @Override
- public String nameTemplate(AcmeNodeType nodeClass) {
- return "Acme ({p#id})";
- }
-
- @Override
- public Object nodeClassType(AcmeNodeType nodeClass) {
- return nodeClass.getClass();
- }
-
- @Override
- public AcmePorts portInputs(AcmeNodeType nodeClass) {
- return AcmePorts.INPUT;
- }
-
- @Override
- public AcmePorts portOutputs(AcmeNodeType nodeClass) {
- return AcmePorts.OUTPUT;
- }
-
- @Override
- public int portSize(AcmePorts port) {
- return port == AcmePorts.OUTPUT ? 1 : 0;
- }
-
- @Override
- public boolean edgeDirect(AcmePorts port, int index) {
- return false;
- }
-
- @Override
- public String edgeName(AcmePorts port, int index) {
- return port.name();
- }
-
- @Override
- public Object edgeType(AcmePorts port, int index) {
- return port;
- }
-
- @Override
- public Collection<? extends AcmeNode> edgeNodes(
- AcmeGraph graph, AcmeNode node, AcmePorts port, int index
- ) {
- if (port == AcmePorts.OUTPUT) {
- return node.outgoing.targets;
- }
- return null;
- }
- }
-
- // END: org.graalvm.graphio.GraphSnippets#acmeGraphStructure
-
- return new AcmeGraphStructure();
- }
-
- // BEGIN: org.graalvm.graphio.GraphSnippets#buildOutput
- static GraphOutput<AcmeGraph, ?> buildOutput(WritableByteChannel channel)
- throws IOException {
- return GraphOutput.newBuilder(acmeGraphStructure()).
- // use the latest version; currently 5.0
- protocolVersion(5, 0).
- build(channel);
- }
- // END: org.graalvm.graphio.GraphSnippets#buildOutput
-
- // BEGIN: org.graalvm.graphio.GraphSnippets#buildAll
- static GraphOutput<AcmeGraph, ?> buildAll(WritableByteChannel channel)
- throws IOException {
- GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> graphBlocks = acmeBlocks();
- GraphElements<AcmeMethod, AcmeField,
- AcmeSignature, AcmeCodePosition> graphElements = acmeElements();
- GraphTypes graphTypes = acmeTypes();
-
- return GraphOutput.newBuilder(acmeGraphStructure()).
- protocolVersion(5, 0).
- blocks(graphBlocks).
- elements(graphElements).
- types(graphTypes).
- build(channel);
- }
- // END: org.graalvm.graphio.GraphSnippets#buildAll
-
- private static GraphTypes acmeTypes() {
- GraphTypes graphTypes = null;
- // in real world don't return null
- return graphTypes;
- }
-
- private static GraphElements<AcmeMethod, AcmeField, AcmeSignature, AcmeCodePosition> acmeElements() {
- GraphElements<AcmeMethod, AcmeField, AcmeSignature, AcmeCodePosition> graphElements = null;
- // in real world don't return null
- return graphElements;
- }
-
- private static GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> acmeBlocks() {
- GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> graphBlocks = null;
- // in real world don't return null
- return graphBlocks;
- }
-
- private static class AcmeGraph {
- final AcmeNode root;
-
- AcmeGraph(AcmeNode root) {
- this.root = root;
- }
-
- Set<AcmeNode> allNodes() {
- return allNodes(root, new LinkedHashSet<>());
- }
-
- private static Set<AcmeNode> allNodes(AcmeNode node, Set<AcmeNode> collectTo) {
- if (collectTo.add(node)) {
- for (AcmeNode target : node.outgoing.targets) {
- allNodes(target, collectTo);
- }
- }
- return collectTo;
- }
- }
-
- private static class AcmeNode {
- final int id;
- final AcmeEdges outgoing;
-
- AcmeNode(int id) {
- this.id = id;
- this.outgoing = new AcmeEdges();
- }
-
- void linkTo(AcmeNode target) {
- outgoing.targets.add(target);
- }
- }
-
- private enum AcmeNodeType {
- STANDARD
- }
-
- private enum AcmePorts {
- INPUT,
- OUTPUT;
- }
-
- private static class AcmeEdges {
- final Set<AcmeNode> targets;
-
- AcmeEdges() {
- this.targets = new LinkedHashSet<>();
- }
- }
-
- private static class AcmeBlocks {
- }
-
- private static class AcmeMethod {
- }
-
- private static class AcmeField {
- }
-
- private static class AcmeSignature {
- }
-
- private static class AcmeCodePosition {
- }
-
- // BEGIN: org.graalvm.graphio.GraphSnippets#dump
- static void dump(File toFile) throws IOException {
- try (
- FileChannel ch = new FileOutputStream(toFile).getChannel();
- GraphOutput<AcmeGraph, ?> output = buildOutput(ch);
- ) {
- AcmeNode root = new AcmeNode(0);
- AcmeNode n1 = new AcmeNode(1);
- AcmeNode n2 = new AcmeNode(2);
- AcmeNode n3 = new AcmeNode(3);
-
- root.linkTo(n1);
- root.linkTo(n2);
- n1.linkTo(n3);
- n2.linkTo(n3);
-
- AcmeGraph diamondGraph = new AcmeGraph(root);
-
- output.beginGroup(diamondGraph, "Diamond", "dia", null, 0, null);
- output.print(diamondGraph, null, 0, "Diamond graph #%d", 1);
- output.endGroup();
- }
- }
- // END: org.graalvm.graphio.GraphSnippets#dump
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,13 +24,12 @@
/**
* Send your graphs to <b>IGV</b> via a socket or a file. This package allows one to easily encode
- * any graph-like data structure and send it for visualization to
- * <em>OracleLab's Ideal Graph Visualizer</em> tool. Assuming you already have your own data
- * structure that contains <b>nodes</b> and <b>edges</b> among them, creating a
- * {@link org.graalvm.graphio.GraphOutput} specialized for your data is a matter of implementing a
- * single interface:
+ * any graph-like data structure and send it for visualization to <em>OracleLab's Ideal Graph
+ * Visualizer</em> tool. Assuming you already have your own data structure that contains
+ * <b>nodes</b> and <b>edges</b> among them, creating a {@link org.graalvm.graphio.GraphOutput}
+ * specialized for your data is a matter of implementing a single interface:
*
- * {@link org.graalvm.graphio.GraphSnippets#acmeGraphStructure}
+ * {@link org.graalvm.graphio.GraphJavadocSnippets#acmeGraphStructure}
*
* The {@link org.graalvm.graphio.GraphStructure} interface defines the set of operations that are
* needed by the <em>graph protocol</em> to encode a graph into the <b>IGV</b> expected format. The
@@ -43,7 +42,7 @@
* {@link org.graalvm.graphio.GraphOutput}. To do so use the associated
* {@link org.graalvm.graphio.GraphOutput.Builder builder} just like shown in the following method:
*
- * {@link org.graalvm.graphio.GraphSnippets#buildOutput}
+ * {@link org.graalvm.graphio.GraphJavadocSnippets#buildOutput}
*
* Now you are ready to dump your graph into <b>IGV</b>. Where to obtain the right channel? One
* option is to create a {@link java.nio.channels.FileChannel} and dump the data into a file
@@ -51,7 +50,7 @@
* <code>4445</code> (the default port <b>IGV</b> listens to) and dump the data there. Here is an
* example:
*
- * {@link org.graalvm.graphio.GraphSnippets#dump}
+ * {@link org.graalvm.graphio.GraphJavadocSnippets#dump}
*
* Call the {@code dump} method with pointer to file {@code diamond.bgv} and then you can open the
* file in <b>IGV</b>. The result will look like this:
@@ -75,7 +74,7 @@
* {@link org.graalvm.graphio.GraphOutput.Builder} instance methods, which may, but need not be
* called at all. Here is an example:
*
- * {@link org.graalvm.graphio.GraphSnippets#buildAll}
+ * {@link org.graalvm.graphio.GraphJavadocSnippets#buildAll}
*
* All these interfaces follow the
* <a href="http://wiki.apidesign.org/wiki/Singletonizer">singletonizer</a> API pattern again - e.g.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.util.test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+import org.graalvm.compiler.test.GraalTest;
+import org.graalvm.util.ObjectSizeEstimate;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class CollectionSizeTest {
+
+ /**
+ * Tests the memory size of an empty map and a map with only one or two entries.
+ */
+ @Test
+ public void testSize() {
+ Assume.assumeTrue("Not working in JDK9 due to module visibility.", GraalTest.Java8OrEarlier);
+ EconomicMap<Object, Object> map = EconomicMap.create(Equivalence.IDENTITY);
+ assertEquals(49, ObjectSizeEstimate.forObject(map).getTotalBytes());
+
+ Integer value = 1;
+ map.put(value, value);
+ assertEquals(153, ObjectSizeEstimate.forObject(map).getTotalBytes());
+
+ Integer secondValue = 2;
+ map.put(secondValue, secondValue);
+ assertEquals(153 + 20, ObjectSizeEstimate.forObject(map).getTotalBytes());
+ }
+
+ /**
+ * Tests whether the map actually compresses the entries array when a large number of entries
+ * are deleted.
+ */
+ @Test
+ public void testCompress() {
+ Assume.assumeTrue("Not working in JDK9 due to module visibility.", GraalTest.Java8OrEarlier);
+ EconomicMap<Object, Object> map = EconomicMap.create();
+
+ // Measuring size of map with one entry.
+ Object firstValue = 0;
+ map.put(firstValue, firstValue);
+ ObjectSizeEstimate afterFirstValue = ObjectSizeEstimate.forObject(map);
+
+ // Add 999 more entries.
+ for (int i = 1; i < 1000; ++i) {
+ Object value = i;
+ map.put(value, value);
+ }
+ ObjectSizeEstimate beforeRemove = ObjectSizeEstimate.forObject(map);
+
+ // Remove 999 first entries.
+ for (int i = 0; i < 999; ++i) {
+ map.removeKey(i);
+ }
+ ObjectSizeEstimate afterRemove = ObjectSizeEstimate.forObject(map);
+
+ // Check that size is same size as with one entry.
+ assertEquals(afterFirstValue, afterRemove);
+
+ // Add 999 new entries.
+ for (int i = 0; i < 999; ++i) {
+ Object value = i;
+ map.put(value, value);
+ }
+ ObjectSizeEstimate afterAdd = ObjectSizeEstimate.forObject(map);
+
+ // Check that entries array is same size again.
+ assertEquals(beforeRemove.getPointerCount(), afterAdd.getPointerCount());
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionTest.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,536 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util.test;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Random;
-import java.util.function.BiFunction;
-
-import org.graalvm.util.CollectionsUtil;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.MapCursor;
-import org.graalvm.util.ObjectSizeEstimate;
-import org.graalvm.util.UnmodifiableMapCursor;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class CollectionTest {
-
- /**
- * Tests the memory size of an empty map and a map with only one or two entries.
- */
- @Test
- public void testSize() {
- EconomicMap<Object, Object> map = EconomicMap.create(Equivalence.IDENTITY);
- assertEquals(48, ObjectSizeEstimate.forObject(map).getTotalBytes());
-
- Integer value = 1;
- map.put(value, value);
- assertEquals(152, ObjectSizeEstimate.forObject(map).getTotalBytes());
-
- Integer secondValue = 2;
- map.put(secondValue, secondValue);
- assertEquals(152 + 20, ObjectSizeEstimate.forObject(map).getTotalBytes());
- }
-
- /**
- * Tests whether the map actually compresses the entries array when a large number of entries
- * are deleted.
- */
- @Test
- public void testCompress() {
- EconomicMap<Object, Object> map = EconomicMap.create();
-
- // Measuring size of map with one entry.
- Object firstValue = 0;
- map.put(firstValue, firstValue);
- ObjectSizeEstimate afterFirstValue = ObjectSizeEstimate.forObject(map);
-
- // Add 999 more entries.
- for (int i = 1; i < 1000; ++i) {
- Object value = i;
- map.put(value, value);
- }
- ObjectSizeEstimate beforeRemove = ObjectSizeEstimate.forObject(map);
-
- // Remove 999 first entries.
- for (int i = 0; i < 999; ++i) {
- map.removeKey(i);
- }
- ObjectSizeEstimate afterRemove = ObjectSizeEstimate.forObject(map);
-
- // Check that size is same size as with one entry.
- assertEquals(afterFirstValue, afterRemove);
-
- // Add 999 new entries.
- for (int i = 0; i < 999; ++i) {
- Object value = i;
- map.put(value, value);
- }
- ObjectSizeEstimate afterAdd = ObjectSizeEstimate.forObject(map);
-
- // Check that entries array is same size again.
- assertEquals(beforeRemove.getPointerCount(), afterAdd.getPointerCount());
- }
-
- private static int[] createRandomRange(Random random, int count) {
- int[] result = new int[count];
- for (int i = 0; i < count; ++i) {
- int range = random.nextInt(14);
- if (range == 0 || range > 10) {
- range = Integer.MAX_VALUE;
- } else if (range == 10) {
- range = 100;
- }
- result[i] = range;
- }
- return result;
- }
-
- private static final class BadHashClass {
- private int value;
-
- BadHashClass(int randomInt) {
- this.value = randomInt;
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof BadHashClass) {
- BadHashClass badHashClass = (BadHashClass) other;
- return badHashClass.value == value;
- }
- return false;
- }
- }
-
- interface MapAction {
- Object perform(EconomicMap<Object, Object> map, int randomInt);
- }
-
- static final Object EXISTING_VALUE = new Object();
-
- static final MapAction[] INCREASE_ACTIONS = new MapAction[]{
- (map, randomInt) -> map.put(randomInt, "value"),
- (map, randomInt) -> map.get(randomInt)
- };
-
- static final MapAction[] ACTIONS = new MapAction[]{
- (map, randomInt) -> map.removeKey(randomInt),
- (map, randomInt) -> map.put(randomInt, "value"),
- (map, randomInt) -> map.put(randomInt, null),
- (map, randomInt) -> map.put(EXISTING_VALUE, randomInt),
- (map, randomInt) -> {
- if (randomInt == 0) {
- map.clear();
- }
- return map.isEmpty();
- },
- (map, randomInt) -> map.containsKey(randomInt),
- (map, randomInt) -> map.get(randomInt),
- (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"),
- (map, randomInt) -> {
- if (randomInt == 0) {
- map.replaceAll((key, value) -> Objects.toString(value) + "!");
- }
- return map.isEmpty();
- }
-
- };
-
- @Test
- public void testVeryLarge() {
- EconomicMap<Object, Object> map = EconomicMap.create();
- EconomicMap<Object, Object> referenceMap = createDebugMap();
-
- Random random = new Random(0);
- for (int i = 0; i < 200000; ++i) {
- for (int j = 0; j < INCREASE_ACTIONS.length; ++j) {
- int nextInt = random.nextInt(10000000);
- MapAction action = INCREASE_ACTIONS[j];
- Object result = action.perform(map, nextInt);
- Object referenceResult = action.perform(referenceMap, nextInt);
- Assert.assertEquals(result, referenceResult);
- }
- }
- }
-
- /**
- * Tests a sequence of random operations on the map.
- */
- @Test
- public void testAddRemove() {
- EconomicMap<Object, Object> map = EconomicMap.create();
- EconomicMap<Object, Object> referenceMap = createDebugMap();
-
- for (int seed = 0; seed < 10; ++seed) {
- Random random = new Random(seed);
- int[] ranges = createRandomRange(random, ACTIONS.length);
- int value = random.nextInt(10000);
- for (int i = 0; i < value; ++i) {
- for (int j = 0; j < ACTIONS.length; ++j) {
- if (random.nextInt(ranges[j]) == 0) {
- int nextInt = random.nextInt(100);
- MapAction action = ACTIONS[j];
- Object result = action.perform(map, nextInt);
- Object referenceResult = action.perform(referenceMap, nextInt);
- Assert.assertEquals(result, referenceResult);
- if (j % 100 == 0) {
- checkEquality(map, referenceMap);
- }
- }
- }
-
- if (random.nextInt(20) == 0) {
- removeElement(random.nextInt(100), map, referenceMap);
- }
- }
- }
- }
-
- private static void removeElement(int index, EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
- Assert.assertEquals(referenceMap.size(), map.size());
- MapCursor<?, ?> cursor = map.getEntries();
- MapCursor<?, ?> referenceCursor = referenceMap.getEntries();
- int z = 0;
- while (cursor.advance()) {
- Assert.assertTrue(referenceCursor.advance());
- Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
- Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
- if (index == z) {
- cursor.remove();
- referenceCursor.remove();
- }
- ++z;
- }
-
- Assert.assertFalse(referenceCursor.advance());
- }
-
- private static void checkEquality(EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
- Assert.assertEquals(referenceMap.size(), map.size());
-
- // Check entries.
- UnmodifiableMapCursor<?, ?> cursor = map.getEntries();
- UnmodifiableMapCursor<?, ?> referenceCursor = referenceMap.getEntries();
- while (cursor.advance()) {
- Assert.assertTrue(referenceCursor.advance());
- Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
- Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
- }
-
- // Check keys.
- Iterator<?> iterator = map.getKeys().iterator();
- Iterator<?> referenceIterator = referenceMap.getKeys().iterator();
- while (iterator.hasNext()) {
- Assert.assertTrue(referenceIterator.hasNext());
- Assert.assertEquals(iterator.next(), referenceIterator.next());
- }
-
- // Check values.
- iterator = map.getValues().iterator();
- referenceIterator = referenceMap.getValues().iterator();
- while (iterator.hasNext()) {
- Assert.assertTrue(referenceIterator.hasNext());
- Assert.assertEquals(iterator.next(), referenceIterator.next());
- }
- Assert.assertFalse(referenceIterator.hasNext());
- }
-
- public static <K, V> EconomicMap<K, V> createDebugMap() {
- final LinkedHashMap<K, V> linkedMap = new LinkedHashMap<>();
- final EconomicMap<K, V> sparseMap = EconomicMap.create();
- return new EconomicMap<K, V>() {
-
- @Override
- public V get(K key) {
- V result = linkedMap.get(key);
- V sparseResult = sparseMap.get(key);
- assert Objects.equals(result, sparseResult);
- return result;
- }
-
- @Override
- public V put(K key, V value) {
- V result = linkedMap.put(key, value);
- assert Objects.equals(result, sparseMap.put(key, value));
- return result;
- }
-
- @Override
- public int size() {
- int result = linkedMap.size();
- assert result == sparseMap.size();
- return result;
- }
-
- @Override
- public boolean containsKey(K key) {
- boolean result = linkedMap.containsKey(key);
- assert result == sparseMap.containsKey(key);
- return result;
- }
-
- @Override
- public void clear() {
- linkedMap.clear();
- sparseMap.clear();
- }
-
- @Override
- public V removeKey(K key) {
- V result = linkedMap.remove(key);
- assert Objects.equals(result, sparseMap.removeKey(key));
- return result;
- }
-
- @Override
- public Iterable<V> getValues() {
-
- Iterator<V> iterator = linkedMap.values().iterator();
- Iterator<V> sparseIterator = sparseMap.getValues().iterator();
- return new Iterable<V>() {
-
- @Override
- public Iterator<V> iterator() {
- return new Iterator<V>() {
-
- @Override
- public boolean hasNext() {
- boolean result = iterator.hasNext();
- boolean otherResult = sparseIterator.hasNext();
- assert result == otherResult;
- return result;
- }
-
- @Override
- public V next() {
- V sparseNext = sparseIterator.next();
- V next = iterator.next();
- assert Objects.equals(sparseNext, next);
- return next;
- }
-
- @Override
- public void remove() {
- iterator.remove();
- sparseIterator.remove();
- }
- };
- }
-
- };
- }
-
- @Override
- public Iterable<K> getKeys() {
-
- Iterator<K> iterator = linkedMap.keySet().iterator();
- Iterator<K> sparseIterator = sparseMap.getKeys().iterator();
- return new Iterable<K>() {
-
- @Override
- public Iterator<K> iterator() {
- return new Iterator<K>() {
-
- @Override
- public boolean hasNext() {
- boolean result = iterator.hasNext();
- boolean otherResult = sparseIterator.hasNext();
- assert result == otherResult;
- return result;
- }
-
- @Override
- public K next() {
- K sparseNext = sparseIterator.next();
- K next = iterator.next();
- assert Objects.equals(sparseNext, next);
- return next;
- }
-
- @Override
- public void remove() {
- iterator.remove();
- sparseIterator.remove();
- }
- };
- }
-
- };
- }
-
- @Override
- public boolean isEmpty() {
- boolean result = linkedMap.isEmpty();
- assert result == sparseMap.isEmpty();
- return result;
- }
-
- @Override
- public MapCursor<K, V> getEntries() {
- Iterator<java.util.Map.Entry<K, V>> iterator = linkedMap.entrySet().iterator();
- MapCursor<K, V> cursor = sparseMap.getEntries();
- return new MapCursor<K, V>() {
-
- private Map.Entry<K, V> current;
-
- @Override
- public boolean advance() {
- boolean result = iterator.hasNext();
- boolean otherResult = cursor.advance();
- assert result == otherResult;
- if (result) {
- current = iterator.next();
- }
-
- return result;
- }
-
- @Override
- public K getKey() {
- K key = current.getKey();
- assert key == cursor.getKey();
- return key;
- }
-
- @Override
- public V getValue() {
- V value = current.getValue();
- assert Objects.equals(value, cursor.getValue());
- return value;
- }
-
- @Override
- public void remove() {
- iterator.remove();
- cursor.remove();
- }
- };
- }
-
- @Override
- public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
- linkedMap.replaceAll(function);
- sparseMap.replaceAll(function);
- }
- };
- }
-
- @Test
- public void testIterableConcat() {
- List<String> i1 = Arrays.asList("1", "2", "3");
- List<String> i2 = Arrays.asList();
- List<String> i3 = Arrays.asList("4", "5");
- List<String> i4 = Arrays.asList();
- List<String> i5 = Arrays.asList("6");
- List<String> iNull = null;
-
- List<String> actual = new ArrayList<>();
- List<String> expected = new ArrayList<>();
- expected.addAll(i1);
- expected.addAll(i2);
- expected.addAll(i3);
- expected.addAll(i4);
- expected.addAll(i5);
- Iterable<String> iterable = CollectionsUtil.concat(Arrays.asList(i1, i2, i3, i4, i5));
- for (String s : iterable) {
- actual.add(s);
- }
- Assert.assertEquals(expected, actual);
-
- Iterator<String> iter = iterable.iterator();
- while (iter.hasNext()) {
- iter.next();
- }
- try {
- iter.next();
- Assert.fail("Expected NoSuchElementException");
- } catch (NoSuchElementException e) {
- // Expected
- }
- try {
- CollectionsUtil.concat(i1, iNull);
- Assert.fail("Expected NullPointerException");
- } catch (NullPointerException e) {
- // Expected
- }
-
- Iterable<Object> emptyIterable = CollectionsUtil.concat(Collections.emptyList());
- Assert.assertFalse(emptyIterable.iterator().hasNext());
- }
-
- @Test
- public void testSetRemoval() {
- ArrayList<Integer> initialList = new ArrayList<>();
- ArrayList<Integer> removalList = new ArrayList<>();
- ArrayList<Integer> finalList = new ArrayList<>();
- EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
- set.add(1);
- set.add(2);
- set.add(3);
- set.add(4);
- set.add(5);
- set.add(6);
- set.add(7);
- set.add(8);
- set.add(9);
- Iterator<Integer> i1 = set.iterator();
- while (i1.hasNext()) {
- initialList.add(i1.next());
- }
- int size = 0;
- Iterator<Integer> i2 = set.iterator();
- while (i2.hasNext()) {
- Integer elem = i2.next();
- if (size++ < 8) {
- i2.remove();
- }
- removalList.add(elem);
- }
- Iterator<Integer> i3 = set.iterator();
- while (i3.hasNext()) {
- finalList.add(i3.next());
- }
- Assert.assertEquals(initialList, removalList);
- Assert.assertEquals(1, finalList.size());
- Assert.assertEquals(new Integer(9), finalList.get(0));
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionUtilTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.util.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.graalvm.util.CollectionsUtil;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CollectionUtilTest {
+
+ private static int sum(Iterable<Integer> iterable) {
+ int sum = 0;
+ for (int i : iterable) {
+ sum += i;
+ }
+ return sum;
+ }
+
+ private static int indexOf(Iterable<Integer> iterable, int element) {
+ int index = 0;
+ for (int i : iterable) {
+ if (i == element) {
+ return index;
+ }
+ index++;
+ }
+ return -1;
+ }
+
+ @Test
+ public void testConcat() {
+ List<Integer> a = Arrays.asList(1, 2);
+ List<Integer> b = Arrays.asList(3, 4, 5);
+ Assert.assertEquals(sum(CollectionsUtil.concat(a, b)), 15);
+ Assert.assertEquals(sum(CollectionsUtil.concat(b, a)), 15);
+ Assert.assertEquals(indexOf(CollectionsUtil.concat(a, b), 5), 4);
+ Assert.assertEquals(indexOf(CollectionsUtil.concat(b, a), 5), 2);
+ }
+
+ @Test
+ public void testMatch() {
+ String[] array = {"a", "b", "c", "d", "e"};
+ Assert.assertTrue(CollectionsUtil.allMatch(array, s -> !s.isEmpty()));
+ Assert.assertFalse(CollectionsUtil.allMatch(array, s -> !s.startsWith("c")));
+ Assert.assertFalse(CollectionsUtil.anyMatch(array, String::isEmpty));
+ Assert.assertTrue(CollectionsUtil.anyMatch(array, s -> s.startsWith("c")));
+ }
+
+ @Test
+ public void testFilterToList() {
+ String[] array = {"a", "b", "", "d", "e"};
+ Assert.assertEquals(CollectionsUtil.filterToList(Arrays.asList(array), String::isEmpty).size(), 1);
+ }
+
+ @Test
+ public void testFilterAndMapToArray() {
+ String[] array = {"a", "b", "", "d", "e"};
+ String[] newArray = CollectionsUtil.filterAndMapToArray(array, s -> !s.isEmpty(), String::toUpperCase, String[]::new);
+ Assert.assertArrayEquals(newArray, new String[]{"A", "B", "D", "E"});
+ }
+
+ @Test
+ public void testMapToArray() {
+ String[] array = {"a", "b", "c", "d", "e"};
+ String[] newArray = CollectionsUtil.mapToArray(array, String::toUpperCase, String[]::new);
+ Assert.assertArrayEquals(newArray, new String[]{"A", "B", "C", "D", "E"});
+ }
+
+ @Test
+ public void testMapAndJoin() {
+ String[] array = {"a", "b", "c", "d", "e"};
+ Assert.assertEquals(CollectionsUtil.mapAndJoin(array, String::toUpperCase, ", "), "A, B, C, D, E");
+ Assert.assertEquals(CollectionsUtil.mapAndJoin(array, String::toUpperCase, ", ", "'"), "'A, 'B, 'C, 'D, 'E");
+ Assert.assertEquals(CollectionsUtil.mapAndJoin(array, String::toUpperCase, ", ", "'", "'"), "'A', 'B', 'C', 'D', 'E'");
+
+ Assert.assertEquals(CollectionsUtil.mapAndJoin(Arrays.asList(array), String::toUpperCase, ", "), "A, B, C, D, E");
+ Assert.assertEquals(CollectionsUtil.mapAndJoin(Arrays.asList(array), String::toUpperCase, ", ", "'"), "'A, 'B, 'C, 'D, 'E");
+ }
+
+ @Test
+ public void testIterableConcat() {
+ List<String> i1 = Arrays.asList("1", "2", "3");
+ List<String> i2 = Arrays.asList();
+ List<String> i3 = Arrays.asList("4", "5");
+ List<String> i4 = Arrays.asList();
+ List<String> i5 = Arrays.asList("6");
+ List<String> iNull = null;
+
+ List<String> actual = new ArrayList<>();
+ List<String> expected = new ArrayList<>();
+ expected.addAll(i1);
+ expected.addAll(i2);
+ expected.addAll(i3);
+ expected.addAll(i4);
+ expected.addAll(i5);
+ Iterable<String> iterable = CollectionsUtil.concat(Arrays.asList(i1, i2, i3, i4, i5));
+ for (String s : iterable) {
+ actual.add(s);
+ }
+ Assert.assertEquals(expected, actual);
+
+ Iterator<String> iter = iterable.iterator();
+ while (iter.hasNext()) {
+ iter.next();
+ }
+ try {
+ iter.next();
+ Assert.fail("Expected NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+ try {
+ CollectionsUtil.concat(i1, iNull);
+ Assert.fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected
+ }
+
+ Iterable<Object> emptyIterable = CollectionsUtil.concat(Collections.emptyList());
+ Assert.assertFalse(emptyIterable.iterator().hasNext());
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/CollectionsUtil.java Sat Feb 10 09:25:35 2018 +0100
@@ -37,7 +37,10 @@
/**
* This class contains utility methods for commonly used functional patterns for collections.
*/
-public class CollectionsUtil {
+public final class CollectionsUtil {
+
+ private CollectionsUtil() {
+ }
/**
* Concatenates two iterables into a single iterable. The iterator exposed by the returned
@@ -93,10 +96,26 @@
};
}
+ /**
+ * Returns whether all elements in {@code inputs} match {@code predicate}. May not evaluate
+ * {@code predicate} on all elements if not necessary for determining the result. If
+ * {@code inputs} is empty then {@code true} is returned and {@code predicate} is not evaluated.
+ *
+ * @return {@code true} if either all elements in {@code inputs} match {@code predicate} or
+ * {@code inputs} is empty, otherwise {@code false}.
+ */
public static <T> boolean allMatch(T[] inputs, Predicate<T> predicate) {
return allMatch(Arrays.asList(inputs), predicate);
}
+ /**
+ * Returns whether all elements in {@code inputs} match {@code predicate}. May not evaluate
+ * {@code predicate} on all elements if not necessary for determining the result. If
+ * {@code inputs} is empty then {@code true} is returned and {@code predicate} is not evaluated.
+ *
+ * @return {@code true} if either all elements in {@code inputs} match {@code predicate} or
+ * {@code inputs} is empty, otherwise {@code false}.
+ */
public static <T> boolean allMatch(Iterable<T> inputs, Predicate<T> predicate) {
for (T t : inputs) {
if (!predicate.test(t)) {
@@ -106,10 +125,28 @@
return true;
}
+ /**
+ * Returns whether any elements in {@code inputs} match {@code predicate}. May not evaluate
+ * {@code predicate} on all elements if not necessary for determining the result. If
+ * {@code inputs} is empty then {@code false} is returned and {@code predicate} is not
+ * evaluated.
+ *
+ * @return {@code true} if any elements in {@code inputs} match {@code predicate}, otherwise
+ * {@code false}.
+ */
public static <T> boolean anyMatch(T[] inputs, Predicate<T> predicate) {
return anyMatch(Arrays.asList(inputs), predicate);
}
+ /**
+ * Returns whether any elements in {@code inputs} match {@code predicate}. May not evaluate
+ * {@code predicate} on all elements if not necessary for determining the result. If
+ * {@code inputs} is empty then {@code false} is returned and {@code predicate} is not
+ * evaluated.
+ *
+ * @return {@code true} if any elements in {@code inputs} match {@code predicate}, otherwise
+ * {@code false}.
+ */
public static <T> boolean anyMatch(Iterable<T> inputs, Predicate<T> predicate) {
for (T t : inputs) {
if (predicate.test(t)) {
@@ -119,10 +156,21 @@
return false;
}
+ /**
+ * Returns a new list consisting of the elements in {@code inputs} that match {@code predicate}.
+ *
+ * @return the new list.
+ */
public static <T> List<T> filterToList(List<T> inputs, Predicate<? super T> predicate) {
return filterToList(inputs, predicate, ArrayList::new);
}
+ /**
+ * Appends elements of {@code inputs} that match {@code predicate} to the list generated by
+ * {@code listGenerator}.
+ *
+ * @return the list generated by {@code listGenerator}.
+ */
public static <T> List<T> filterToList(List<T> inputs, Predicate<? super T> predicate, Supplier<List<T>> listGenerator) {
List<T> resultList = listGenerator.get();
for (T t : inputs) {
@@ -134,8 +182,10 @@
}
/**
- * Filters the inputs, maps them given the mapping function and adds them in the array provided
- * by the generator.
+ * Filters {@code inputs} with {@code predicate}, applies {@code mapper} and adds them in the
+ * array provided by {@code arrayGenerator}.
+ *
+ * @return the array provided by {@code arrayGenerator}.
*/
public static <T, R> R[] filterAndMapToArray(T[] inputs, Predicate<? super T> predicate, Function<? super T, ? extends R> mapper, IntFunction<R[]> arrayGenerator) {
List<R> resultList = new ArrayList<>();
@@ -148,13 +198,21 @@
}
/**
- * Maps the inputs given the mapping function and adds them in the array provided by the
- * generator.
+ * Applies {@code mapper} on the elements in {@code inputs} and adds them in the array provided
+ * by {@code arrayGenerator}.
+ *
+ * @return the array provided by {@code arrayGenerator}.
*/
public static <T, R> R[] mapToArray(T[] inputs, Function<? super T, ? extends R> mapper, IntFunction<R[]> arrayGenerator) {
return mapToArray(Arrays.asList(inputs), mapper, arrayGenerator);
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs} and adds them in the array provided
+ * by {@code arrayGenerator}.
+ *
+ * @return the array provided by {@code arrayGenerator}.
+ */
public static <T, R> R[] mapToArray(Collection<T> inputs, Function<? super T, ? extends R> mapper, IntFunction<R[]> arrayGenerator) {
R[] result = arrayGenerator.apply(inputs.size());
int idx = 0;
@@ -164,26 +222,62 @@
return result;
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated
+ * by {@code delimiter}.
+ *
+ * @return a new String that is composed from {@code inputs}.
+ */
public static <T, R> String mapAndJoin(T[] inputs, Function<? super T, ? extends R> mapper, String delimiter) {
return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, "", "");
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated
+ * by {@code delimiter} and starting with {@code prefix}.
+ *
+ * @return a new String that is composed from {@code inputs}.
+ */
public static <T, R> String mapAndJoin(T[] inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix) {
return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, prefix, "");
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated
+ * by {@code delimiter} and starting with {@code prefix} and ending with {@code suffix}.
+ *
+ * @return a new String that is composed from {@code inputs}.
+ */
public static <T, R> String mapAndJoin(T[] inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix, String suffix) {
return mapAndJoin(Arrays.asList(inputs), mapper, delimiter, prefix, suffix);
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated
+ * by {@code delimiter}.
+ *
+ * @return a new String that is composed from {@code inputs}.
+ */
public static <T, R> String mapAndJoin(Iterable<T> inputs, Function<? super T, ? extends R> mapper, String delimiter) {
return mapAndJoin(inputs, mapper, delimiter, "", "");
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated
+ * by {@code delimiter} and starting with {@code prefix}.
+ *
+ * @return a new String that is composed from {@code inputs}.
+ */
public static <T, R> String mapAndJoin(Iterable<T> inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix) {
return mapAndJoin(inputs, mapper, delimiter, prefix, "");
}
+ /**
+ * Applies {@code mapper} on the elements in {@code inputs}, and joins them together separated
+ * by {@code delimiter} and starting with {@code prefix} and ending with {@code suffix}.
+ *
+ * @return a new String that is composed from {@code inputs}.
+ */
public static <T, R> String mapAndJoin(Iterable<T> inputs, Function<? super T, ? extends R> mapper, String delimiter, String prefix, String suffix) {
StringBuilder strb = new StringBuilder();
String sep = "";
@@ -193,4 +287,5 @@
}
return strb.toString();
}
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicMap.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.function.BiFunction;
-
-import org.graalvm.util.impl.EconomicMapImpl;
-
-/**
- * Memory efficient map data structure.
- */
-public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
-
- V put(K key, V value);
-
- default void putAll(EconomicMap<K, V> other) {
- MapCursor<K, V> e = other.getEntries();
- while (e.advance()) {
- put(e.getKey(), e.getValue());
- }
- }
-
- void clear();
-
- V removeKey(K key);
-
- @Override
- MapCursor<K, V> getEntries();
-
- void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
-
- default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
- UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
- while (entry.advance()) {
- put(entry.getKey(), entry.getValue());
- }
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the default
- * {@link Equivalence#DEFAULT} comparison strategy for keys.
- */
- static <K, V> EconomicMap<K, V> create() {
- return EconomicMap.create(Equivalence.DEFAULT);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the default
- * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
- * capacity.
- */
- static <K, V> EconomicMap<K, V> create(int initialCapacity) {
- return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the given comparison
- * strategy for keys.
- */
- static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
- return EconomicMapImpl.create(strategy);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the default
- * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
- * specified existing map.
- */
- static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
- return EconomicMap.create(Equivalence.DEFAULT, m);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set and copies all elements from
- * the specified existing map.
- */
- static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
- return EconomicMapImpl.create(strategy, m);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set and initializes with a
- * specified capacity.
- */
- static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
- return EconomicMapImpl.create(strategy, initialCapacity);
- }
-
- /**
- * Wraps an existing {@link java.util.Map} as an {@link org.graalvm.util.EconomicMap}.
- */
- static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
- return new EconomicMap<K, V>() {
-
- @Override
- public V get(K key) {
- V result = map.get(key);
- return result;
- }
-
- @Override
- public V put(K key, V value) {
- V result = map.put(key, value);
- return result;
- }
-
- @Override
- public int size() {
- int result = map.size();
- return result;
- }
-
- @Override
- public boolean containsKey(K key) {
- return map.containsKey(key);
- }
-
- @Override
- public void clear() {
- map.clear();
- }
-
- @Override
- public V removeKey(K key) {
- V result = map.remove(key);
- return result;
- }
-
- @Override
- public Iterable<V> getValues() {
- return map.values();
- }
-
- @Override
- public Iterable<K> getKeys() {
- return map.keySet();
- }
-
- @Override
- public boolean isEmpty() {
- return map.isEmpty();
- }
-
- @Override
- public MapCursor<K, V> getEntries() {
- Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
- return new MapCursor<K, V>() {
-
- private Map.Entry<K, V> current;
-
- @Override
- public boolean advance() {
- boolean result = iterator.hasNext();
- if (result) {
- current = iterator.next();
- }
-
- return result;
- }
-
- @Override
- public K getKey() {
- return current.getKey();
- }
-
- @Override
- public V getValue() {
- return current.getValue();
- }
-
- @Override
- public void remove() {
- iterator.remove();
- }
- };
- }
-
- @Override
- public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
- map.replaceAll(function);
- }
- };
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/EconomicSet.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-import java.util.Iterator;
-
-import org.graalvm.util.impl.EconomicMapImpl;
-
-/**
- * Memory efficient set data structure.
- */
-public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
-
- boolean add(E element);
-
- void remove(E element);
-
- void clear();
-
- default void addAll(EconomicSet<E> values) {
- addAll(values.iterator());
- }
-
- default void addAll(Iterable<E> values) {
- addAll(values.iterator());
- }
-
- default void addAll(Iterator<E> values) {
- while (values.hasNext()) {
- add(values.next());
- }
- }
-
- default void removeAll(EconomicSet<E> values) {
- removeAll(values.iterator());
- }
-
- default void removeAll(Iterable<E> values) {
- removeAll(values.iterator());
- }
-
- default void removeAll(Iterator<E> values) {
- while (values.hasNext()) {
- remove(values.next());
- }
- }
-
- default void retainAll(EconomicSet<E> values) {
- Iterator<E> iterator = iterator();
- while (iterator.hasNext()) {
- E key = iterator.next();
- if (!values.contains(key)) {
- iterator.remove();
- }
- }
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements with the
- * default {@link Equivalence#DEFAULT} comparison strategy.
- */
- static <E> EconomicSet<E> create() {
- return EconomicSet.create(Equivalence.DEFAULT);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements.
- */
- static <E> EconomicSet<E> create(Equivalence strategy) {
- return EconomicMapImpl.create(strategy);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements with the
- * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
- * specified collection.
- */
- static <E> EconomicSet<E> create(int initialCapacity) {
- return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements with the
- * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
- * specified collection.
- */
- static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
- return EconomicSet.create(Equivalence.DEFAULT, c);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements and
- * initializes with the given capacity.
- */
- static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
- return EconomicMapImpl.create(strategy, initialCapacity);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements and inserts
- * all elements of the specified collection.
- */
- static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E> c) {
- return EconomicMapImpl.create(strategy, c);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Equivalence.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-/**
- * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
- * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
- */
-public abstract class Equivalence {
-
- /**
- * Default equivalence calling {@link #equals(Object)} to check equality and {@link #hashCode()}
- * for obtaining hash values. Do not change the logic of this class as it may be inlined in
- * other places.
- */
- public static final Equivalence DEFAULT = new Equivalence() {
-
- @Override
- public boolean equals(Object a, Object b) {
- return a.equals(b);
- }
-
- @Override
- public int hashCode(Object o) {
- return o.hashCode();
- }
- };
-
- /**
- * Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining
- * hash values. Do not change the logic of this class as it may be inlined in other places.
- */
- public static final Equivalence IDENTITY = new Equivalence() {
-
- @Override
- public boolean equals(Object a, Object b) {
- return a == b;
- }
-
- @Override
- public int hashCode(Object o) {
- return o.hashCode();
- }
- };
-
- /**
- * Identity equivalence using {@code ==} to check equality and
- * {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of
- * this class as it may be inlined in other places.
- */
- public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
-
- @Override
- public boolean equals(Object a, Object b) {
- return a == b;
- }
-
- @Override
- public int hashCode(Object o) {
- return System.identityHashCode(o);
- }
- };
-
- /**
- * Subclass for creating custom equivalence definitions.
- */
- protected Equivalence() {
- }
-
- public abstract boolean equals(Object a, Object b);
-
- public abstract int hashCode(Object o);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/MapCursor.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-/**
- * Cursor to iterate over a mutable map.
- */
-public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
- /**
- * Remove the current entry from the map. May only be called once. After calling
- * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
- * the current entry.
- */
- void remove();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,6 +26,9 @@
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import org.graalvm.collections.EconomicMap;
+import org.graalvm.collections.Equivalence;
+
/**
* Calculates approximate estimates of the size of an object graph.
*
@@ -193,8 +196,8 @@
} else {
size.recordPointer();
if (maxDepth > 1) {
- f.setAccessible(true);
try {
+ f.setAccessible(true);
Object inner = f.get(o);
if (inner != null) {
if (depth < maxDepth && !identityHashMap.containsKey(inner)) {
@@ -205,6 +208,14 @@
}
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new UnsupportedOperationException("Must have access privileges to traverse object graph");
+ } catch (RuntimeException e) {
+ if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) {
+ // This is a newly introduced exception in JDK9 and thus
+ // cannot be declared in the catch clause.
+ throw new UnsupportedOperationException("Target class is not exported to the current module.", e);
+ } else {
+ throw e;
+ }
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/Pair.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-import java.util.Objects;
-
-/**
- * Utility class representing a pair of values.
- */
-public final class Pair<L, R> {
- private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);
-
- private final L left;
- private final R right;
-
- @SuppressWarnings("unchecked")
- public static <L, R> Pair<L, R> empty() {
- return (Pair<L, R>) EMPTY;
- }
-
- public static <L, R> Pair<L, R> createLeft(L left) {
- if (left == null) {
- return empty();
- } else {
- return new Pair<>(left, null);
- }
- }
-
- public static <L, R> Pair<L, R> createRight(R right) {
- if (right == null) {
- return empty();
- } else {
- return new Pair<>(null, right);
- }
- }
-
- public static <L, R> Pair<L, R> create(L left, R right) {
- if (right == null && left == null) {
- return empty();
- } else {
- return new Pair<>(left, right);
- }
- }
-
- private Pair(L left, R right) {
- this.left = left;
- this.right = right;
- }
-
- public L getLeft() {
- return left;
- }
-
- public R getRight() {
- return right;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(left) + 31 * Objects.hashCode(right);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof Pair) {
- Pair<L, R> pair = (Pair<L, R>) obj;
- return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
- }
-
- return false;
- }
-
- @Override
- public String toString() {
- return String.format("(%s, %s)", left, right);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicMap.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-/**
- * Unmodifiable memory efficient map data structure.
- */
-public interface UnmodifiableEconomicMap<K, V> {
-
- V get(K key);
-
- default V get(K key, V defaultValue) {
- V v = get(key);
- if (v == null) {
- return defaultValue;
- }
- return v;
- }
-
- boolean containsKey(K key);
-
- int size();
-
- boolean isEmpty();
-
- Iterable<V> getValues();
-
- Iterable<K> getKeys();
-
- UnmodifiableMapCursor<K, V> getEntries();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableEconomicSet.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-/**
- * Unmodifiable memory efficient set data structure.
- */
-public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
-
- boolean contains(E element);
-
- int size();
-
- boolean isEmpty();
-
- default E[] toArray(E[] target) {
- if (target.length != size()) {
- throw new UnsupportedOperationException("Length of target array must equal the size of the set.");
- }
-
- int index = 0;
- for (E element : this) {
- target[index++] = element;
- }
-
- return target;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/UnmodifiableMapCursor.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util;
-
-/**
- * Cursor to iterate over a map without changing its contents.
- */
-public interface UnmodifiableMapCursor<K, V> {
- /**
- * Advances to the next entry.
- *
- * @return {@code true} if a next entry exists, {@code false} if there is no next entry.
- */
- boolean advance();
-
- /**
- * The key of the current entry.
- */
- K getKey();
-
- /**
- * The value of the current entry.
- */
- V getValue();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/impl/EconomicMapImpl.java Tue Feb 13 14:41:54 2018 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,852 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.util.impl;
-
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.function.BiFunction;
-
-import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicMap;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.UnmodifiableEconomicMap;
-import org.graalvm.util.UnmodifiableEconomicSet;
-import org.graalvm.util.MapCursor;
-
-/**
- * Implementation of a map with a memory-efficient structure that always preserves insertion order
- * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal
- * {@link #INITIAL_CAPACITY} or smaller 256.
- *
- * The key/value pairs are kept in an expanding flat object array with keys at even indices and
- * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there
- * is no additional hash data structure and comparisons are done via linear checking of the
- * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an
- * object identity comparison), this limit below which the map is without an actual hash table is
- * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}.
- *
- * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash
- * array where an entry of 0 means no hit and otherwise denotes the entry number in the
- * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit
- * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of
- * integer values in other cases.
- *
- * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take
- * the place of the values in the {@link #entries} array.
- *
- * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the
- * map falls below a specific threshold, the map will be compressed via the
- * {@link #maybeCompress(int)} method.
- */
-public final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
-
- /**
- * Initial number of key/value pair entries that is allocated in the first entries array.
- */
- private static final int INITIAL_CAPACITY = 4;
-
- /**
- * Maximum number of entries that are moved linearly forward if a key is removed.
- */
- private static final int COMPRESS_IMMEDIATE_CAPACITY = 8;
-
- /**
- * Minimum number of key/value pair entries added when the entries array is increased in size.
- */
- private static final int MIN_CAPACITY_INCREASE = 8;
-
- /**
- * Number of entries above which a hash table is created.
- */
- private static final int HASH_THRESHOLD = 4;
-
- /**
- * Number of entries above which a hash table is created when equality can be checked with
- * object identity.
- */
- private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8;
-
- /**
- * Maximum number of entries allowed in the map.
- */
- private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1;
-
- /**
- * Number of entries above which more than 1 byte is necessary for the hash index.
- */
- private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1);
-
- /**
- * Number of entries above which more than 2 bytes are are necessary for the hash index.
- */
- private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE);
-
- /**
- * Total number of entries (actual entries plus deleted entries).
- */
- private int totalEntries;
-
- /**
- * Number of deleted entries.
- */
- private int deletedEntries;
-
- /**
- * Entries array with even indices storing keys and odd indices storing values.
- */
- private Object[] entries;
-
- /**
- * Hash array that is interpreted either as byte or short or int array depending on number of
- * map entries.
- */
- private byte[] hashArray;
-
- /**
- * The strategy used for comparing keys or {@code null} for denoting special strategy
- * {@link Equivalence#IDENTITY}.
- */
- private final Equivalence strategy;
-
- /**
- * Intercept method for debugging purposes.
- */
- private static <K, V> EconomicMapImpl<K, V> intercept(EconomicMapImpl<K, V> map) {
- return map;
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy) {
- return intercept(new EconomicMapImpl<>(strategy));
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, int initialCapacity) {
- return intercept(new EconomicMapImpl<>(strategy, initialCapacity));
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> other) {
- return intercept(new EconomicMapImpl<>(strategy, other));
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other) {
- return intercept(new EconomicMapImpl<>(strategy, other));
- }
-
- private EconomicMapImpl(Equivalence strategy) {
- if (strategy == Equivalence.IDENTITY) {
- this.strategy = null;
- } else {
- this.strategy = strategy;
- }
- }
-
- private EconomicMapImpl(Equivalence strategy, int initialCapacity) {
- this(strategy);
- init(initialCapacity);
- }
-
- private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap<K, V> other) {
- this(strategy);
- if (!initFrom(other)) {
- init(other.size());
- putAll(other);
- }
- }
-
- private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet<K> other) {
- this(strategy);
- if (!initFrom(other)) {
- init(other.size());
- addAll(other);
- }
- }
-
- @SuppressWarnings("unchecked")
- private boolean initFrom(Object o) {
- if (o instanceof EconomicMapImpl) {
- EconomicMapImpl<K, V> otherMap = (EconomicMapImpl<K, V>) o;
- // We are only allowed to directly copy if the strategies of the two maps are the same.
- if (strategy == otherMap.strategy) {
- totalEntries = otherMap.totalEntries;
- deletedEntries = otherMap.deletedEntries;
- if (otherMap.entries != null) {
- entries = otherMap.entries.clone();
- }
- if (otherMap.hashArray != null) {
- hashArray = otherMap.hashArray.clone();
- }
- return true;
- }
- }
- return false;
- }
-
- private void init(int size) {
- if (size > INITIAL_CAPACITY) {
- entries = new Object[size << 1];
- }
- }
-
- /**
- * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from
- * other map on construction.
- */
- private static final class CollisionLink {
-
- CollisionLink(Object value, int next) {
- this.value = value;
- this.next = next;
- }
-
- final Object value;
-
- /**
- * Index plus one of the next entry in the collision link chain.
- */
- final int next;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V get(K key) {
- Objects.requireNonNull(key);
-
- int index = find(key);
- if (index != -1) {
- return (V) getValue(index);
- }
- return null;
- }
-
- private int find(K key) {
- if (hasHashArray()) {
- return findHash(key);
- } else {
- return findLinear(key);
- }
- }
-
- private int findLinear(K key) {
- for (int i = 0; i < totalEntries; i++) {
- Object entryKey = entries[i << 1];
- if (entryKey != null && compareKeys(key, entryKey)) {
- return i;
- }
- }
- return -1;
- }
-
- private boolean compareKeys(Object key, Object entryKey) {
- if (key == entryKey) {
- return true;
- }
- if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
- if (strategy == Equivalence.DEFAULT) {
- return key.equals(entryKey);
- } else {
- return strategy.equals(key, entryKey);
- }
- }
- return false;
- }
-
- private int findHash(K key) {
- int index = getHashArray(getHashIndex(key)) - 1;
- if (index != -1) {
- Object entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- return index;
- } else {
- Object entryValue = getRawValue(index);
- if (entryValue instanceof CollisionLink) {
- return findWithCollision(key, (CollisionLink) entryValue);
- }
- }
- }
-
- return -1;
- }
-
- private int findWithCollision(K key, CollisionLink initialEntryValue) {
- int index;
- Object entryKey;
- CollisionLink entryValue = initialEntryValue;
- while (true) {
- CollisionLink collisionLink = entryValue;
- index = collisionLink.next;
- entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- return index;
- } else {
- Object value = getRawValue(index);
- if (value instanceof CollisionLink) {
- entryValue = (CollisionLink) getRawValue(index);
- } else {
- return -1;
- }
- }
- }
- }
-
- private int getHashArray(int index) {
- if (entries.length < LARGE_HASH_THRESHOLD) {
- return (hashArray[index] & 0xFF);
- } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
- int adjustedIndex = index << 1;
- return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8);
- } else {
- int adjustedIndex = index << 2;
- return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24);
- }
- }
-
- private void setHashArray(int index, int value) {
- if (entries.length < LARGE_HASH_THRESHOLD) {
- hashArray[index] = (byte) value;
- } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
- int adjustedIndex = index << 1;
- hashArray[adjustedIndex] = (byte) value;
- hashArray[adjustedIndex + 1] = (byte) (value >> 8);
- } else {
- int adjustedIndex = index << 2;
- hashArray[adjustedIndex] = (byte) value;
- hashArray[adjustedIndex + 1] = (byte) (value >> 8);
- hashArray[adjustedIndex + 2] = (byte) (value >> 16);
- hashArray[adjustedIndex + 3] = (byte) (value >> 24);
- }
- }
-
- private int findAndRemoveHash(Object key) {
- int hashIndex = getHashIndex(key);
- int index = getHashArray(hashIndex) - 1;
- if (index != -1) {
- Object entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- Object value = getRawValue(index);
- int nextIndex = -1;
- if (value instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) value;
- nextIndex = collisionLink.next;
- }
- setHashArray(hashIndex, nextIndex + 1);
- return index;
- } else {
- Object entryValue = getRawValue(index);
- if (entryValue instanceof CollisionLink) {
- return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index);
- }
- }
- }
-
- return -1;
- }
-
- private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) {
- int index;
- Object entryKey;
- CollisionLink entryValue = initialEntryValue;
- int lastIndex = initialIndexValue;
- while (true) {
- CollisionLink collisionLink = entryValue;
- index = collisionLink.next;
- entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- Object value = getRawValue(index);
- if (value instanceof CollisionLink) {
- CollisionLink thisCollisionLink = (CollisionLink) value;
- setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next));
- } else {
- setRawValue(lastIndex, collisionLink.value);
- }
- return index;
- } else {
- Object value = getRawValue(index);
- if (value instanceof CollisionLink) {
- entryValue = (CollisionLink) getRawValue(index);
- lastIndex = index;
- } else {
- return -1;
- }
- }
- }
- }
-
- private int getHashIndex(Object key) {
- int hash;
- if (strategy != null && strategy != Equivalence.DEFAULT) {
- if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
- hash = System.identityHashCode(key);
- } else {
- hash = strategy.hashCode(key);
- }
- } else {
- hash = key.hashCode();
- }
- hash = hash ^ (hash >>> 16);
- return hash & (getHashTableSize() - 1);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V put(K key, V value) {
- if (key == null) {
- throw new UnsupportedOperationException("null not supported as key!");
- }
- int index = find(key);
- if (index != -1) {
- Object oldValue = getValue(index);
- setValue(index, value);
- return (V) oldValue;
- }
-
- int nextEntryIndex = totalEntries;
- if (entries == null) {
- entries = new Object[INITIAL_CAPACITY << 1];
- } else if (entries.length == nextEntryIndex << 1) {
- grow();
-
- assert entries.length > totalEntries << 1;
- // Can change if grow is actually compressing.
- nextEntryIndex = totalEntries;
- }
-
- setKey(nextEntryIndex, key);
- setValue(nextEntryIndex, value);
- totalEntries++;
-
- if (hasHashArray()) {
- // Rehash on collision if hash table is more than three quarters full.
- boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1)));
- putHashEntry(key, nextEntryIndex, rehashOnCollision);
- } else if (totalEntries > getHashThreshold()) {
- createHash();
- }
-
- return null;
- }
-
- /**
- * Number of entries above which a hash table should be constructed.
- */
- private int getHashThreshold() {
- if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
- return HASH_THRESHOLD_IDENTITY_COMPARE;
- } else {
- return HASH_THRESHOLD;
- }
- }
-
- private void grow() {
- int entriesLength = entries.length;
- int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2);
- if (newSize > MAX_ELEMENT_COUNT) {
- throw new UnsupportedOperationException("map grown too large!");
- }
- Object[] newEntries = new Object[newSize << 1];
- System.arraycopy(entries, 0, newEntries, 0, entriesLength);
- entries = newEntries;
- if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) ||
- (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) {
- // Rehash in order to change number of bits reserved for hash indices.
- createHash();
- }
- }
-
- /**
- * Compresses the graph if there is a large number of deleted entries and returns the translated
- * new next index.
- */
- private int maybeCompress(int nextIndex) {
- if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) {
- return compressLarge(nextIndex);
- }
- return nextIndex;
- }
-
- /**
- * Compresses the graph and returns the translated new next index.
- */
- private int compressLarge(int nextIndex) {
- int size = INITIAL_CAPACITY;
- int remaining = totalEntries - deletedEntries;
-
- while (size <= remaining) {
- size += Math.max(MIN_CAPACITY_INCREASE, size >> 1);
- }
-
- Object[] newEntries = new Object[size << 1];
- int z = 0;
- int newNextIndex = remaining;
- for (int i = 0; i < totalEntries; ++i) {
- Object key = getKey(i);
- if (i == nextIndex) {
- newNextIndex = z;
- }
- if (key != null) {
- newEntries[z << 1] = key;
- newEntries[(z << 1) + 1] = getValue(i);
- z++;
- }
- }
-
- this.entries = newEntries;
- totalEntries = z;
- deletedEntries = 0;
- if (z <= getHashThreshold()) {
- this.hashArray = null;
- } else {
- createHash();
- }
- return newNextIndex;
- }
-
- private int getHashTableSize() {
- if (entries.length < LARGE_HASH_THRESHOLD) {
- return hashArray.length;
- } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
- return hashArray.length >> 1;
- } else {
- return hashArray.length >> 2;
- }
- }
-
- private void createHash() {
- int entryCount = size();
-
- // Calculate smallest 2^n that is greater number of entries.
- int size = getHashThreshold();
- while (size <= entryCount) {
- size <<= 1;
- }
-
- // Give extra size to avoid collisions.
- size <<= 1;
-
- if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) {
- // Every entry has 4 bytes.
- size <<= 2;
- } else if (this.entries.length >= LARGE_HASH_THRESHOLD) {
- // Every entry has 2 bytes.
- size <<= 1;
- } else {
- // Entries are very small => give extra size to further reduce collisions.
- size <<= 1;
- }
-
- hashArray = new byte[size];
- for (int i = 0; i < totalEntries; i++) {
- Object entryKey = getKey(i);
- if (entryKey != null) {
- putHashEntry(entryKey, i, false);
- }
- }
- }
-
- private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) {
- int hashIndex = getHashIndex(key);
- int oldIndex = getHashArray(hashIndex) - 1;
- if (oldIndex != -1 && rehashOnCollision) {
- this.createHash();
- return;
- }
- setHashArray(hashIndex, entryIndex + 1);
- Object value = getRawValue(entryIndex);
- if (oldIndex != -1) {
- assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle";
- if (value instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) value;
- setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex));
- } else {
- setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex));
- }
- } else {
- if (value instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) value;
- setRawValue(entryIndex, collisionLink.value);
- }
- }
- }
-
- @Override
- public int size() {
- return totalEntries - deletedEntries;
- }
-
- @Override
- public boolean containsKey(K key) {
- return find(key) != -1;
- }
-
- @Override
- public void clear() {
- entries = null;
- hashArray = null;
- totalEntries = deletedEntries = 0;
- }
-
- private boolean hasHashArray() {
- return hashArray != null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V removeKey(K key) {
- if (key == null) {
- throw new UnsupportedOperationException("null not supported as key!");
- }
- int index;
- if (hasHashArray()) {
- index = this.findAndRemoveHash(key);
- } else {
- index = this.findLinear(key);
- }
-
- if (index != -1) {
- Object value = getValue(index);
- remove(index);
- return (V) value;
- }
- return null;
- }
-
- /**
- * Removes the element at the specific index and returns the index of the next element. This can
- * be a different value if graph compression was triggered.
- */
- private int remove(int indexToRemove) {
- int index = indexToRemove;
- int entriesAfterIndex = totalEntries - index - 1;
- int result = index + 1;
-
- // Without hash array, compress immediately.
- if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) {
- while (index < totalEntries - 1) {
- setKey(index, getKey(index + 1));
- setRawValue(index, getRawValue(index + 1));
- index++;
- }
- result--;
- }
-
- setKey(index, null);
- setRawValue(index, null);
- if (index == totalEntries - 1) {
- // Make sure last element is always non-null.
- totalEntries--;
- while (index > 0 && getKey(index - 1) == null) {
- totalEntries--;
- deletedEntries--;
- index--;
- }
- } else {
- deletedEntries++;
- result = maybeCompress(result);
- }
-
- return result;
- }
-
- private abstract class SparseMapIterator<E> implements Iterator<E> {
-
- protected int current;
-
- @Override
- public boolean hasNext() {
- return current < totalEntries;
- }
-
- @Override
- public void remove() {
- if (hasHashArray()) {
- EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1));
- }
- current = EconomicMapImpl.this.remove(current - 1);
- }
- }
-
- @Override
- public Iterable<V> getValues() {
- return new Iterable<V>() {
- @Override
- public Iterator<V> iterator() {
- return new SparseMapIterator<V>() {
- @SuppressWarnings("unchecked")
- @Override
- public V next() {
- Object result;
- while (true) {
- result = getValue(current);
- if (result == null && getKey(current) == null) {
- // values can be null, double-check if key is also null
- current++;
- } else {
- current++;
- break;
- }
- }
- return (V) result;
- }
- };
- }
- };
- }
-
- @Override
- public Iterable<K> getKeys() {
- return this;
- }
-
- @Override
- public boolean isEmpty() {
- return this.size() == 0;
- }
-
- @Override
- public MapCursor<K, V> getEntries() {
- return new MapCursor<K, V>() {
- int current = -1;
-
- @Override
- public boolean advance() {
- current++;
- if (current >= totalEntries) {
- return false;
- } else {
- while (EconomicMapImpl.this.getKey(current) == null) {
- // Skip over null entries
- current++;
- }
- return true;
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public K getKey() {
- return (K) EconomicMapImpl.this.getKey(current);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V getValue() {
- return (V) EconomicMapImpl.this.getValue(current);
- }
-
- @Override
- public void remove() {
- if (hasHashArray()) {
- EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current));
- }
- current = EconomicMapImpl.this.remove(current) - 1;
- }
- };
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
- for (int i = 0; i < totalEntries; i++) {
- Object entryKey = getKey(i);
- if (entryKey != null) {
- Object newValue = function.apply((K) entryKey, (V) getValue(i));
- setValue(i, newValue);
- }
- }
- }
-
- private Object getKey(int index) {
- return entries[index << 1];
- }
-
- private void setKey(int index, Object newValue) {
- entries[index << 1] = newValue;
- }
-
- private void setValue(int index, Object newValue) {
- Object oldValue = getRawValue(index);
- if (oldValue instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) oldValue;
- setRawValue(index, new CollisionLink(newValue, collisionLink.next));
- } else {
- setRawValue(index, newValue);
- }
- }
-
- private void setRawValue(int index, Object newValue) {
- entries[(index << 1) + 1] = newValue;
- }
-
- private Object getRawValue(int index) {
- return entries[(index << 1) + 1];
- }
-
- private Object getValue(int index) {
- Object object = getRawValue(index);
- if (object instanceof CollisionLink) {
- return ((CollisionLink) object).value;
- }
- return object;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("map(size=").append(size()).append(", {");
- MapCursor<K, V> cursor = getEntries();
- while (cursor.advance()) {
- builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append("),");
- }
- builder.append("})");
- return builder.toString();
- }
-
- @Override
- public Iterator<K> iterator() {
- return new SparseMapIterator<K>() {
- @SuppressWarnings("unchecked")
- @Override
- public K next() {
- Object result;
- while ((result = getKey(current++)) == null) {
- // skip null entries
- }
- return (K) result;
- }
- };
- }
-
- @Override
- public boolean contains(K element) {
- return containsKey(element);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean add(K element) {
- return put(element, (V) element) == null;
- }
-
- @Override
- public void remove(K element) {
- removeKey(element);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml Tue Feb 13 14:41:54 2018 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml Sat Feb 10 09:25:35 2018 +0100
@@ -40,7 +40,7 @@
<property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
</module>
<module name="NoWhitespaceBefore">
- <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+ <property name="tokens" value="SEMI,POST_DEC,POST_INC"/>
</module>
<module name="ParenPad"/>
<module name="TypecastParenPad">
--- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp Sat Feb 10 09:25:35 2018 +0100
@@ -70,6 +70,10 @@
return storage._allocate_mutex;
}
+ static bool reduce_deferred_updates(OopStorage& storage) {
+ return storage.reduce_deferred_updates();
+ }
+
static bool block_is_empty(const Block& block) {
return block.is_empty();
}
@@ -127,9 +131,31 @@
return list.chead() == NULL;
}
-static void release_entry(OopStorage& storage, oop* entry) {
+static bool process_deferred_updates(OopStorage& storage) {
+ MutexLockerEx ml(TestAccess::allocate_mutex(storage), Mutex::_no_safepoint_check_flag);
+ bool result = false;
+ while (TestAccess::reduce_deferred_updates(storage)) {
+ result = true;
+ }
+ return result;
+}
+
+static void release_entry(OopStorage& storage, oop* entry, bool process_deferred = true) {
*entry = NULL;
storage.release(entry);
+ if (process_deferred) {
+ process_deferred_updates(storage);
+ }
+}
+
+static size_t empty_block_count(const OopStorage& storage) {
+ const TestAccess::BlockList& list = TestAccess::allocate_list(storage);
+ size_t count = 0;
+ for (const OopBlock* block = list.ctail();
+ (block != NULL) && block->is_empty();
+ ++count, block = list.prev(*block))
+ {}
+ return count;
}
class OopStorageTest : public ::testing::Test {
@@ -188,31 +214,22 @@
class OopStorageTestWithAllocation::VM_DeleteBlocksAtSafepoint
: public VM_GTestExecuteAtSafepoint {
public:
- VM_DeleteBlocksAtSafepoint(OopStorage* storage, size_t retain) :
- _storage(storage), _retain(retain)
- {}
+ VM_DeleteBlocksAtSafepoint(OopStorage* storage) : _storage(storage) {}
void doit() {
- _storage->delete_empty_blocks_safepoint(_retain);
+ _storage->delete_empty_blocks_safepoint();
}
private:
OopStorage* _storage;
- size_t _retain;
};
static bool is_allocate_list_sorted(const OopStorage& storage) {
// The allocate_list isn't strictly sorted. Rather, all empty
- // blocks are segregated to the end of the list. And the number of
- // empty blocks should match empty_block_count().
- size_t expected_empty = storage.empty_block_count();
+ // blocks are segregated to the end of the list.
const TestAccess::BlockList& list = TestAccess::allocate_list(storage);
const OopBlock* block = list.ctail();
- for (size_t i = 0; i < expected_empty; ++i, block = list.prev(*block)) {
- if ((block == NULL) || !block->is_empty()) {
- return false;
- }
- }
+ for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {}
for ( ; block != NULL; block = list.prev(*block)) {
if (block->is_empty()) {
return false;
@@ -243,7 +260,7 @@
EXPECT_EQ(1u, _storage.block_count());
EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage)));
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
const OopBlock* block = TestAccess::allocate_list(_storage).chead();
EXPECT_NE(block, (OopBlock*)NULL);
@@ -259,7 +276,7 @@
EXPECT_EQ(1u, _storage.block_count());
EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage)));
- EXPECT_EQ(1u, _storage.empty_block_count());
+ EXPECT_EQ(1u, empty_block_count(_storage));
const OopBlock* new_block = TestAccess::allocate_list(_storage).chead();
EXPECT_EQ(block, new_block);
@@ -322,14 +339,14 @@
TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
entries[0] = _storage.allocate();
ASSERT_TRUE(entries[0] != NULL);
EXPECT_EQ(1u, list_length(active_list));
EXPECT_EQ(1u, _storage.block_count());
EXPECT_EQ(1u, list_length(allocate_list));
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
const OopBlock* block = active_list.chead();
EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
@@ -339,7 +356,7 @@
entries[i] = _storage.allocate();
EXPECT_EQ(i + 1, _storage.allocation_count());
ASSERT_TRUE(entries[i] != NULL);
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
if (block == NULL) {
ASSERT_FALSE(is_list_empty(allocate_list));
@@ -374,7 +391,7 @@
EXPECT_EQ(list_length(active_list), list_length(allocate_list));
EXPECT_EQ(list_length(active_list), _storage.block_count());
- EXPECT_EQ(list_length(active_list), _storage.empty_block_count());
+ EXPECT_EQ(list_length(active_list), empty_block_count(_storage));
for (const OopBlock* block = allocate_list.chead();
block != NULL;
block = allocate_list.next(*block)) {
@@ -386,7 +403,7 @@
static const size_t step = 11;
ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
@@ -409,7 +426,7 @@
EXPECT_EQ(list_length(active_list), list_length(allocate_list));
EXPECT_EQ(list_length(active_list), _storage.block_count());
EXPECT_EQ(0u, total_allocation_count(active_list));
- EXPECT_EQ(list_length(allocate_list), _storage.empty_block_count());
+ EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage));
}
TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) {
@@ -417,7 +434,7 @@
static const size_t allocate_step = 5;
ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage);
@@ -449,7 +466,7 @@
EXPECT_EQ(list_length(active_list), list_length(allocate_list));
EXPECT_EQ(list_length(active_list), _storage.block_count());
EXPECT_EQ(0u, total_allocation_count(active_list));
- EXPECT_EQ(list_length(allocate_list), _storage.empty_block_count());
+ EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage));
}
template<bool sorted>
@@ -471,11 +488,12 @@
EXPECT_EQ(_max_entries - nrelease, _storage.allocation_count());
for (size_t i = 0; i < nrelease; ++i) {
- release_entry(_storage, _entries[2 * i + 1]);
+ release_entry(_storage, _entries[2 * i + 1], false);
EXPECT_EQ(_max_entries - nrelease - (i + 1), _storage.allocation_count());
}
+ EXPECT_TRUE(process_deferred_updates(_storage));
- EXPECT_EQ(_storage.block_count(), _storage.empty_block_count());
+ EXPECT_EQ(_storage.block_count(), empty_block_count(_storage));
FREE_C_HEAP_ARRAY(oop*, to_release);
}
@@ -607,8 +625,9 @@
}
while (allocated > 0) {
- release_entry(_storage, entries[--allocated]);
+ release_entry(_storage, entries[--allocated], false);
}
+ process_deferred_updates(_storage);
}
class OopStorageTestIteration : public OopStorageTestWithAllocation {
@@ -627,16 +646,17 @@
memset(_states, 0, sizeof(_states));
size_t initial_release = 0;
- for ( ; _storage.empty_block_count() < 2; ++initial_release) {
+ for ( ; empty_block_count(_storage) < 2; ++initial_release) {
ASSERT_GT(_max_entries, initial_release);
release_entry(_storage, _entries[initial_release]);
_states[0][initial_release] = mark_released;
}
for (size_t i = initial_release; i < _max_entries; i += 3) {
- release_entry(_storage, _entries[i]);
+ release_entry(_storage, _entries[i], false);
_states[0][i] = mark_released;
}
+ process_deferred_updates(_storage);
}
class VerifyState;
@@ -1006,30 +1026,21 @@
EXPECT_EQ(initial_active_size, _storage.block_count());
ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test
- for (size_t i = 0; _storage.empty_block_count() < 3; ++i) {
+ for (size_t i = 0; empty_block_count(_storage) < 3; ++i) {
ASSERT_GT(_max_entries, i);
release_entry(_storage, _entries[i]);
}
EXPECT_EQ(initial_active_size, list_length(active_list));
EXPECT_EQ(initial_active_size, _storage.block_count());
- EXPECT_EQ(3u, _storage.empty_block_count());
+ EXPECT_EQ(3u, empty_block_count(_storage));
{
ThreadInVMfromNative invm(JavaThread::current());
- VM_DeleteBlocksAtSafepoint op(&_storage, 2);
+ VM_DeleteBlocksAtSafepoint op(&_storage);
VMThread::execute(&op);
}
- EXPECT_EQ(2u, _storage.empty_block_count());
- EXPECT_EQ(initial_active_size - 1, list_length(active_list));
- EXPECT_EQ(initial_active_size - 1, _storage.block_count());
-
- {
- ThreadInVMfromNative invm(JavaThread::current());
- VM_DeleteBlocksAtSafepoint op(&_storage, 0);
- VMThread::execute(&op);
- }
- EXPECT_EQ(0u, _storage.empty_block_count());
+ EXPECT_EQ(0u, empty_block_count(_storage));
EXPECT_EQ(initial_active_size - 3, list_length(active_list));
EXPECT_EQ(initial_active_size - 3, _storage.block_count());
}
@@ -1041,22 +1052,17 @@
EXPECT_EQ(initial_active_size, _storage.block_count());
ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test
- for (size_t i = 0; _storage.empty_block_count() < 3; ++i) {
+ for (size_t i = 0; empty_block_count(_storage) < 3; ++i) {
ASSERT_GT(_max_entries, i);
release_entry(_storage, _entries[i]);
}
EXPECT_EQ(initial_active_size, list_length(active_list));
EXPECT_EQ(initial_active_size, _storage.block_count());
- EXPECT_EQ(3u, _storage.empty_block_count());
+ EXPECT_EQ(3u, empty_block_count(_storage));
- _storage.delete_empty_blocks_concurrent(2);
- EXPECT_EQ(2u, _storage.empty_block_count());
- EXPECT_EQ(initial_active_size - 1, list_length(active_list));
- EXPECT_EQ(initial_active_size - 1, _storage.block_count());
-
- _storage.delete_empty_blocks_concurrent(0);
- EXPECT_EQ(0u, _storage.empty_block_count());
+ _storage.delete_empty_blocks_concurrent();
+ EXPECT_EQ(0u, empty_block_count(_storage));
EXPECT_EQ(initial_active_size - 3, list_length(active_list));
EXPECT_EQ(initial_active_size - 3, _storage.block_count());
}
@@ -1075,13 +1081,14 @@
for (size_t i = 0; i < _max_entries; ++i) {
if ((_entries[i] != retained) && (_entries[i] != released)) {
- release_entry(_storage, _entries[i]);
+ // Leave deferred release updates to block deletion.
+ release_entry(_storage, _entries[i], false);
}
}
{
ThreadInVMfromNative invm(JavaThread::current());
- VM_DeleteBlocksAtSafepoint op(&_storage, 0);
+ VM_DeleteBlocksAtSafepoint op(&_storage);
VMThread::execute(&op);
}
EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained));
@@ -1121,12 +1128,14 @@
TEST_VM_F(OopStorageTestWithAllocation, print_storage) {
// Release the first 1/2
for (size_t i = 0; i < (_max_entries / 2); ++i) {
- release_entry(_storage, _entries[i]);
+ // Deferred updates don't affect print output.
+ release_entry(_storage, _entries[i], false);
_entries[i] = NULL;
}
// Release every other remaining
for (size_t i = _max_entries / 2; i < _max_entries; i += 2) {
- release_entry(_storage, _entries[i]);
+ // Deferred updates don't affect print output.
+ release_entry(_storage, _entries[i], false);
_entries[i] = NULL;
}
@@ -1137,24 +1146,17 @@
size_t expected_blocks = (_max_entries + entries_per_block - 1) / entries_per_block;
EXPECT_EQ(expected_blocks, _storage.block_count());
- size_t expected_empties = (_max_entries / 2) / entries_per_block;
- EXPECT_EQ(expected_empties, _storage.empty_block_count());
-
- size_t expected_used = expected_blocks - expected_empties;
-
- double expected_usage = (100.0 * expected_entries) / (expected_used * entries_per_block);
+ double expected_usage = (100.0 * expected_entries) / (expected_blocks * entries_per_block);
{
ResourceMark rm;
stringStream expected_st;
expected_st.print("Test Storage: " SIZE_FORMAT
" entries in " SIZE_FORMAT
- " blocks (%.F%%), " SIZE_FORMAT
- " empties, " SIZE_FORMAT " bytes",
+ " blocks (%.F%%), " SIZE_FORMAT " bytes",
expected_entries,
- expected_used,
+ expected_blocks,
expected_usage,
- expected_empties,
_storage.total_memory_usage());
stringStream st;
_storage.print_on(&st);
--- a/test/hotspot/jtreg/compiler/uncommontrap/TestUnstableIfTrap.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/compiler/uncommontrap/TestUnstableIfTrap.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
/*
* @test
* @bug 8030976 8059226
+ * @requires !vm.graal.enabled
* @library /test/lib /
* @modules java.base/jdk.internal.org.objectweb.asm
* java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/TestNUMAPageSize.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/TestNUMAPageSize.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,11 +23,10 @@
/**
* @test TestNUMAPageSize
+ * @key gc regression
* @summary Make sure that start up with NUMA support does not cause problems.
* @bug 8061467
* @requires (vm.opt.AggressiveOpts == null) | (vm.opt.AggressiveOpts == false)
- * @key gc
- * @key regression
* @run main/othervm -Xmx8M -XX:+UseNUMA TestNUMAPageSize
*/
--- a/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,11 +23,10 @@
/**
* @test TestAlignmentToUseLargePages
+ * @key gc regression
* @summary All parallel GC variants may use large pages without the requirement that the
* heap alignment is large page aligned. Other collectors also need to start up with odd sized heaps.
* @bug 8024396
- * @key gc
- * @key regression
* @requires vm.gc=="null"
* @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages
* @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages
--- a/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,10 +23,9 @@
/**
* @test GuardShrinkWarning
+ * @key gc regression
* @summary Remove warning about CMS generation shrinking.
* @bug 8012111
- * @key gc
- * @key regression
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
--- a/test/hotspot/jtreg/gc/g1/Test2GbHeap.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/g1/Test2GbHeap.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,13 +23,12 @@
/*
* @test Test2GbHeap
+ * @key gc regression
* @bug 8031686
* @summary Regression test to ensure we can start G1 with 2gb heap.
* Skip test on 32 bit system: it typically does not support the many and large virtual memory reservations needed.
* @requires vm.gc.G1
* @requires vm.bits != "32"
- * @key gc
- * @key regression
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
--- a/test/hotspot/jtreg/gc/g1/TestHumongousCodeCacheRoots.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/g1/TestHumongousCodeCacheRoots.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,8 +23,7 @@
/*
* @test
- * @key regression
- * @key gc
+ * @key regression gc
* @bug 8027756
* @requires vm.gc.G1
* @library /test/lib
--- a/test/hotspot/jtreg/gc/g1/TestParallelAlwaysPreTouch.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/g1/TestParallelAlwaysPreTouch.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,13 +23,12 @@
/*
* @test
+ * @key gc regression
* @bug 8169703
* @summary Regression test to ensure AlwaysPreTouch with multiple threads works at mutator time.
* Allocates a few humongous objects that will be allocated by expanding the heap, causing concurrent parallel
* pre-touch.
* @requires vm.gc.G1
- * @key gc
- * @key regression
* @run main/othervm -XX:+UseG1GC -Xms10M -Xmx100m -XX:G1HeapRegionSize=1M -XX:+AlwaysPreTouch -XX:PreTouchParallelChunkSize=512k -Xlog:gc+ergo+heap=debug,gc+heap=debug,gc=debug TestParallelAlwaysPreTouch
*/
--- a/test/hotspot/jtreg/gc/logging/TestUnifiedLoggingSwitchStress.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/logging/TestUnifiedLoggingSwitchStress.java Sat Feb 10 09:25:35 2018 +0100
@@ -39,9 +39,8 @@
/**
* @test TestUnifiedLoggingSwitchStress
+ * @key gc stress
* @summary Switches gc log level on fly while stressing memory/gc
- * @key gc
- * @key stress
* @requires !vm.flightRecorder
* @library /test/lib /
* @modules java.management java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/parallel/AdaptiveGCBoundary.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/parallel/AdaptiveGCBoundary.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,10 +23,9 @@
/**
* @test AdaptiveGCBoundary
+ * @key gc regression
* @summary UseAdaptiveGCBoundary is broken
* @bug 8014546
- * @key gc
- * @key regression
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
--- a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java Sat Feb 10 09:25:35 2018 +0100
@@ -23,8 +23,7 @@
/*
* @test TestStressG1Humongous
- * @key gc
- * @key stress
+ * @key gc stress
* @summary Stress G1 by humongous allocations in situation near OOM
* @requires vm.gc.G1
* @requires !vm.flightRecorder
--- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithAllocateHeapAt.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithAllocateHeapAt.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,7 @@
/*
* @test TestGCBasherWithAllocateHeapAt
- * @key gc
- * @key stress
+ * @key gc stress
* @requires vm.gc.G1
* @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress Java heap allocation with AllocateHeapAt flag using GC basher.
--- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithCMS.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithCMS.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,7 @@
/*
* @test TestGCBasherWithCMS
- * @key gc
- * @key stress
+ * @key gc stress
* @requires vm.gc.ConcMarkSweep
* @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the CMS GC by trying to make old objects more likely to be garbage than young objects.
--- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithG1.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithG1.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,7 @@
/*
* @test TestGCBasherWithG1
- * @key gc
- * @key stress
+ * @key gc stress
* @requires vm.gc.G1
* @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the G1 GC by trying to make old objects more likely to be garbage than young objects.
--- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithParallel.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithParallel.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,7 @@
/*
* @test TestGCBasherWithParallel
- * @key gc
- * @key stress
+ * @key gc stress
* @requires vm.gc.Parallel
* @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the Parallel GC by trying to make old objects more likely to be garbage than young objects.
--- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithSerial.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithSerial.java Sat Feb 10 09:25:35 2018 +0100
@@ -26,8 +26,7 @@
/*
* @test TestGCBasherWithSerial
- * @key gc
- * @key stress
+ * @key gc stress
* @requires vm.gc.Serial
* @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the Serial GC by trying to make old objects more likely to be garbage than young objects.
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,9 +24,8 @@
/*
* @test TestSystemGCWithCMS
+ * @key gc stress
* @bug 8190703
- * @key gc
- * @key stress
* @requires vm.gc.ConcMarkSweep
* @summary Stress the CMS GC full GC by allocating objects of different lifetimes concurrently with System.gc().
* @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseConcMarkSweepGC TestSystemGCWithCMS 270
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithG1.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithG1.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,9 +24,8 @@
/*
* @test TestSystemGCWithG1
+ * @key gc stress
* @bug 8190703
- * @key gc
- * @key stress
* @requires vm.gc.G1
* @summary Stress the G1 GC full GC by allocating objects of different lifetimes concurrently with System.gc().
* @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseG1GC TestSystemGCWithG1 270
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithParallel.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithParallel.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,9 +24,8 @@
/*
* @test TestSystemGCWithParallel
+ * @key gc stress
* @bug 8190703
- * @key gc
- * @key stress
* @requires vm.gc.Parallel
* @summary Stress the Parallel GC full GC by allocating objects of different lifetimes concurrently with System.gc().
* @run main/othervm/timeout=300 -Xlog:gc=info -Xmx512m -XX:+UseParallelGC TestSystemGCWithParallel 270
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithSerial.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithSerial.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,9 +24,8 @@
/*
* @test TestSystemGCWithSerial
+ * @key gc stress
* @bug 8190703
- * @key gc
- * @key stress
* @requires vm.gc.Serial
* @summary Stress the Serial GC full GC by allocating objects of different lifetimes concurrently with System.gc().
* @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseSerialGC TestSystemGCWithSerial 270
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -47,6 +47,8 @@
{"InitialRAMFraction", "64"},
{"AssumeMP", "false"},
{"UseMembar", "true"},
+ {"CompilerThreadHintNoPreempt", "true"},
+ {"VMThreadHintNoPreempt", "false"},
// deprecated alias flags (see also aliased_jvm_flags):
{"DefaultMaxRAMFraction", "4"},
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/NMT/JcmdSummaryClass.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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 8193184
+ * @key nmt
+ * @summary Check class counters in summary report
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run main/othervm -Xbootclasspath/a:. -XX:NativeMemoryTracking=summary JcmdSummaryClass
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.JDKToolFinder;
+
+
+import java.util.regex.*;
+
+public class JcmdSummaryClass {
+
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = new ProcessBuilder();
+ OutputAnalyzer output;
+ // Grab my own PID
+ String pid = Long.toString(ProcessTools.getProcessId());
+
+ // Run 'jcmd <pid> VM.native_memory baseline=true'
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory"});
+ pb.start().waitFor();
+
+ String classes_line = "classes #\\d+";
+ String instance_array_classes_line = "instance classes #\\d+, array classes #\\d+";
+ output = new OutputAnalyzer(pb.start());
+ output.shouldMatch(classes_line);
+ output.shouldMatch(instance_array_classes_line);
+ }
+}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java Sat Feb 10 09:25:35 2018 +0100
@@ -29,6 +29,7 @@
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
* @requires vm.cds
* @requires vm.flavor != "minimal"
+ * @requires !vm.graal.enabled
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* java.management
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
* @requires vm.cds
* @requires vm.flavor != "minimal"
+ * @requires !vm.graal.enabled
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* java.management
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
* @requires vm.cds
* @requires vm.flavor != "minimal"
+ * @requires !vm.graal.enabled
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* java.management
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelLoadAndTransformTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/parallelLoad/ParallelLoadAndTransformTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -30,6 +30,7 @@
* /test/hotspot/jtreg/runtime/appcds/test-classes /test/hotspot/jtreg/runtime/appcds/jvmti
* /test/hotspot/jtreg/testlibrary/jvmti
* @requires vm.cds
+ * @requires !vm.graal.enabled
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformInterfaceImplementorAppCDS.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformInterfaceImplementorAppCDS.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,7 @@
* /test/hotspot/jtreg/runtime/appcds/customLoader/test-classes
* @requires vm.cds
* @requires vm.flavor != "minimal"
+ * @requires !vm.graal.enabled
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* java.management
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformSuperSubAppCDS.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformSuperSubAppCDS.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,7 @@
* /test/hotspot/jtreg/runtime/appcds/customLoader/test-classes
* @requires vm.cds
* @requires vm.flavor != "minimal"
+ * @requires !vm.graal.enabled
* @modules java.base/jdk.internal.misc
* jdk.jartool/sun.tools.jar
* java.management
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/Dockerfile-BasicTest-ppc64le Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,10 @@
+# test on x86_64 uses Oracle Linux but we do not have this for ppc64le
+# so use some other Linux where OpenJDK works
+# FROM oraclelinux:7.2
+FROM ppc64le/ubuntu
+
+COPY /jdk /jdk
+
+ENV JAVA_HOME=/jdk
+
+CMD ["/bin/bash"]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/CanGenerateAllClassHook/CanGenerateAllClassHook.java Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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 8161605
+ * @summary Tests that jvmtiEnv::GetPotentialCapabilities reports
+ * can_generate_all_class_hook_events capability with CDS (-Xshare:on)
+ * at ONLOAD and LIVE phases
+ * @library /test/lib
+ * @compile CanGenerateAllClassHook.java
+ * @run main/othervm/native CanGenerateAllClassHook
+ */
+
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import java.io.File;
+import java.io.IOException;
+
+/*
+ * The simplest way to test is to use system classes.jsa,
+ * but we cannot rely on tested JRE/JDK has it.
+ * So the test runs 2 java processes -
+ * 1st to generate custom shared archive file:
+ * java -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=<jsa_file> -Xshare:dump
+ * and 2nd to perform the actual testing using generated shared archive:
+ * java -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=<jsa_file> -Xshare:on
+ * -agentlib:<agent> CanGenerateAllClassHook
+ */
+public class CanGenerateAllClassHook {
+
+ private static final String agentLib = "CanGenerateAllClassHook";
+
+ private static native int getClassHookAvail();
+ private static native int getOnLoadClassHookAvail();
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ // this is master run
+
+ final File jsaFile = File.createTempFile(agentLib, ".jsa");
+ jsaFile.deleteOnExit();
+ final String jsaPath = jsaFile.getAbsolutePath();
+
+ log("generating CDS archive...");
+ execJava(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + jsaPath,
+ "-Xshare:dump")
+ .shouldHaveExitValue(0);
+ log("CDS generation completed.");
+
+ OutputAnalyzer output = execJava(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + jsaPath,
+ "-Xshare:on",
+ "-agentlib:" + agentLib,
+ // copy java.library.path
+ "-Djava.library.path=" + System.getProperty("java.library.path"),
+ // specify "-showversion" to ensure the test runs in shared mode
+ "-showversion",
+ // class to run
+ CanGenerateAllClassHook.class.getCanonicalName(),
+ // and arg
+ "test");
+ // Xshare:on can cause intermittent failure
+ // checkExec handles this.
+ CDSTestUtils.checkExec(output);
+
+ log("Test PASSED.");
+ } else {
+ // this is test run
+ try {
+ System.loadLibrary(agentLib);
+ } catch (UnsatisfiedLinkError ex) {
+ System.err.println("Failed to load " + agentLib + " lib");
+ System.err.println("java.library.path: " + System.getProperty("java.library.path"));
+ throw ex;
+ }
+
+ final int onLoadValue = getOnLoadClassHookAvail();
+ final int liveValue = getClassHookAvail();
+ // Possible values returned:
+ // 1 - the capability is supported;
+ // 0 - the capability is not supported;
+ // -1 - error occured.
+
+ log("can_generate_all_class_hook_events value capability:");
+ log("ONLOAD phase: " + (onLoadValue < 0 ? "Failed to read" : onLoadValue));
+ log("LIVE phase: " + (liveValue < 0 ? "Failed to read" : liveValue));
+ if (onLoadValue != 1 || liveValue != 1) {
+ throw new RuntimeException("The can_generate_all_class_hook_events capability "
+ + " is expected to be available in both ONLOAD and LIVE phases");
+ }
+ }
+ }
+
+ private static void log(String msg) {
+ System.out.println(msg);
+ System.out.flush();
+ }
+
+ private static OutputAnalyzer execJava(String... args) throws IOException {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ log("[STDERR]\n" + output.getStderr());
+ log("[STDOUT]\n" + output.getStdout());
+
+ return output;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/CanGenerateAllClassHook/libCanGenerateAllClassHook.c Sat Feb 10 09:25:35 2018 +0100
@@ -0,0 +1,126 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+
+static jvmtiEnv *jvmti = NULL;
+
+typedef enum {
+ Yes = 1,
+ No = 0,
+ Error = -1
+} IsAvail;
+
+static IsAvail onLoadIsAvail = Error;
+
+void reportError(const char *msg, int err) {
+ printf("%s, error: %d\n", msg, err);
+}
+
+static IsAvail isClassHookAvail() {
+ IsAvail result = Error;
+ do {
+ jvmtiCapabilities caps;
+ jvmtiPhase phase;
+ jvmtiError err;
+
+ if (jvmti == NULL) {
+ reportError("jvmti is NULL", -1);
+ break;
+ }
+
+ err = (*jvmti)->GetPhase(jvmti, &phase);
+ if (err != JVMTI_ERROR_NONE) {
+ reportError("GetPhase failed", err);
+ break;
+ }
+
+ err = (*jvmti)->GetPotentialCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ reportError("GetPotentialCapabilities failed", err);
+ break;
+ }
+
+ result = caps.can_generate_all_class_hook_events ? Yes : No;
+
+ printf("isClassHookAvail: phase=%d, value=%d\n", phase, result);
+ } while (0);
+ return result;
+}
+
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
+{
+ jint res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ reportError("GetEnv failed", res);
+ return JNI_ERR;
+ }
+
+ // check and save can_generate_all_class_hook_events for ONLOAD phase
+ onLoadIsAvail = isClassHookAvail();
+
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_9;
+}
+
+
+JNIEXPORT jint JNICALL
+Java_CanGenerateAllClassHook_getClassHookAvail(JNIEnv *env, jclass cls) {
+ return isClassHookAvail();
+}
+
+JNIEXPORT jint JNICALL
+Java_CanGenerateAllClassHook_getOnLoadClassHookAvail(JNIEnv *env, jclass cls) {
+ return onLoadIsAvail;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -48,9 +48,9 @@
LingeredApp.startApp(null, theApp);
System.out.println("Started LingeredApp with pid " + theApp.getPid());
- // Run the 'jstack -v' command to get the address of a Method*
- // and the oop address of a java.lang.ref.ReferenceQueue$Lock
- // object
+ // Run the 'jstack -v' command to get the address of a Method*,
+ // the oop address of a java.lang.ref.ReferenceQueue$Lock
+ // and the oop address of a java.lang.Class object
List<String> cmds = List.of("jstack -v");
String jstackOutput = test.run(theApp.getPid(), cmds, null, null);
@@ -62,26 +62,37 @@
return;
}
- String addressString = null;
Map<String, String> tokensMap = new HashMap<>();
- tokensMap.put("waiting to lock",
+ tokensMap.put("(a java.lang.Class for LingeredAppWithLock)",
"instance of Oop for java/lang/Class");
- tokensMap.put("Method\\*=", "Type is Method");
- tokensMap.put("waiting to re-lock in wait",
+ tokensMap.put("Method*=", "Type is Method");
+ tokensMap.put("(a java.lang.ref.ReferenceQueue$Lock)",
"instance of Oop for java/lang/ref/ReferenceQueue$Lock");
+ String[] lines = jstackOutput.split("\\R");
+
for (String key: tokensMap.keySet()) {
cmds = new ArrayList<String>();
Map<String, List<String>> expStrMap = new HashMap<>();
- String[] snippets = jstackOutput.split(key);
- String[] tokens = snippets[1].split(" ");
- for (String token: tokens) {
- if (token.contains("0x")) {
- addressString = token.replace("<", "").replace(">", "");
- break;
- }
- }
+ String addressString = null;
+ for (String line : lines) {
+ if (line.contains(key)) {
+ // Escape the token "Method*=" because the split method uses
+ // a regex, not just a straight String.
+ String escapedKey = key.replace("*","\\*");
+ String[] words = line.split(escapedKey+"|[ ]");
+ for (String word : words) {
+ word = word.replace("<","").replace(">","");
+ if (word.startsWith("0x")) {
+ addressString = word;
+ break;
+ }
+ }
+ if (addressString != null)
+ break;
+ }
+ }
String cmd = "inspect " + addressString;
cmds.add(cmd);
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java Sat Feb 10 09:25:35 2018 +0100
@@ -56,9 +56,8 @@
"Java Stack Trace for Sweeper thread",
"CompilerThread",
"Java Stack Trace for Finalizer",
- "java.lang.ref.Reference",
- "private static void processPendingReferences",
- "private static native void waitForReferencePendingList",
+ "Java Stack Trace for Signal Dispatcher",
+ "Java Stack Trace for Reference Handler",
"Java Stack Trace for main",
"public static void main"));
--- a/test/hotspot/jtreg/testlibrary/jvmti/TransformerAgent.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/hotspot/jtreg/testlibrary/jvmti/TransformerAgent.java Sat Feb 10 09:25:35 2018 +0100
@@ -57,17 +57,25 @@
static class SimpleTransformer implements ClassFileTransformer {
- public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined,
- ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException {
+ public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined,
+ ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException {
+ try {
+ log("SimpleTransformer called for: " + name + "@" + incrCounter(name));
+ if (!shouldTransform(name))
+ return null;
- log("SimpleTransformer called for: " + name + "@" + incrCounter(name));
- if (!shouldTransform(name))
- return null;
-
- log("transforming: class name = " + name);
- int nrOfReplacements = TransformUtil.replace(buffer, TransformUtil.BeforePattern,
- TransformUtil.AfterPattern);
- log("replaced the string, nrOfReplacements = " + nrOfReplacements);
+ log("transforming: class name = " + name);
+ int nrOfReplacements = TransformUtil.replace(buffer, TransformUtil.BeforePattern,
+ TransformUtil.AfterPattern);
+ log("replaced the string, nrOfReplacements = " + nrOfReplacements);
+ } catch (Throwable t) {
+ // The retransform native code that called this method does not propagate
+ // exceptions. Instead of getting an uninformative generic error, catch
+ // problems here and print it, then exit.
+ log("Transformation failed!");
+ t.printStackTrace();
+ System.exit(1);
+ }
return buffer;
}
--- a/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -24,6 +24,7 @@
/*
* @test
* @bug 8164512 8191360
+ * @requires vm.compMode != "Xcomp"
* @summary verify if the native library is unloaded when the class loader is GC'ed
* @build p.Test
* @run main/othervm/native -Xcheck:jni NativeLibraryTest
--- a/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/jdk/java/lang/invoke/condy/ConstantBootstrapsTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -25,6 +25,7 @@
* @test
* @bug 8186046 8195694
* @summary Test dynamic constant bootstraps
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
* @run testng ConstantBootstrapsTest
--- a/test/jdk/sun/misc/SunMiscSignalTest.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/jdk/sun/misc/SunMiscSignalTest.java Sat Feb 10 09:25:35 2018 +0100
@@ -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
@@ -112,7 +112,6 @@
Object[][] posixSignals = {
{"HUP", IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
{"QUIT", IsSupported.YES, CanRegister.NO, CanRaise.NO, Invoked.NO},
- {"BUS", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
{"USR1", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
{"USR2", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
{"PIPE", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
@@ -132,6 +131,14 @@
{"SYS", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
};
+ Object[][] posixNonOSXSignals = {
+ {"BUS", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
+ };
+
+ Object[][] posixOSXSignals = {
+ {"BUS", IsSupported.YES, CanRegister.NO, CanRaise.NO, Invoked.NO},
+ };
+
Object[][] windowsSignals = {
{"HUP", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
{"QUIT", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
@@ -155,7 +162,9 @@
{"SYS", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
};
- return concatArrays(commonSignals, (Platform.isWindows() ? windowsSignals : posixSignals));
+ Object[][] combinedPosixSignals = concatArrays(posixSignals,
+ (Platform.isOSX() ? posixOSXSignals : posixNonOSXSignals));
+ return concatArrays(commonSignals, (Platform.isWindows() ? windowsSignals : combinedPosixSignals));
}
// Provider of invalid signal names
--- a/test/jtreg-ext/requires/VMProps.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/jtreg-ext/requires/VMProps.java Sat Feb 10 09:25:35 2018 +0100
@@ -352,9 +352,11 @@
* @return true if docker is supported in a given environment
*/
protected String dockerSupport() {
- // currently docker testing is only supported for Linux-x64
- if (! ( Platform.isLinux() && Platform.isX64() ) )
+ // currently docker testing is only supported for Linux-x64 and Linux-ppc64le
+ String arch = System.getProperty("os.arch");
+ if (! (Platform.isLinux() && (Platform.isX64() || arch.equals("ppc64le")))) {
return "false";
+ }
boolean isSupported;
try {
--- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Tue Feb 13 14:41:54 2018 -0500
+++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Sat Feb 10 09:25:35 2018 +0100
@@ -34,6 +34,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import jdk.test.lib.Platform;
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
@@ -109,7 +110,9 @@
* The jdk will be placed under the "/jdk/" folder inside the docker file system.
*
* @param imageName name of the image to be created, including version tag
- * @param dockerfile name of the dockerfile residing in the test source
+ * @param dockerfile name of the dockerfile residing in the test source;
+ * we check for a platform specific dockerfile as well
+ * and use this one in case it exists
* @param buildDirName name of the docker build/staging directory, which will
* be created in the jtreg's scratch folder
* @throws Exception
@@ -122,6 +125,11 @@
if (Files.exists(buildDir)) {
throw new RuntimeException("The docker build directory already exists: " + buildDir);
}
+ // check for the existance of a platform specific docker file as well
+ String platformSpecificDockerfile = dockerfile + "-" + Platform.getOsArch();
+ if (Files.exists(Paths.get(Utils.TEST_SRC, platformSpecificDockerfile))) {
+ dockerfile = platformSpecificDockerfile;
+ }
Path jdkSrcDir = Paths.get(Utils.TEST_JDK);
Path jdkDstDir = buildDir.resolve("jdk");