# HG changeset patch
# User herrick
# Date 1535400175 14400
# Node ID 6668bbc41155232521ab09f3750099a2f84a8d3b
# Parent 41e17fe9fbeb7962c143aa0af9e74677878f62d2# Parent f23312250f25a4ce975a9cdc819cd3fde4ac2c97
Merge
diff -r 41e17fe9fbeb -r 6668bbc41155 doc/building.html
--- a/doc/building.html Mon Aug 27 16:01:38 2018 -0400
+++ b/doc/building.html Mon Aug 27 16:02:55 2018 -0400
@@ -72,6 +72,7 @@
Specifying the Target Platform
Toolchain Considerations
Native Libraries
+Creating And Using Sysroots With qemu-deboostrap
Building for ARM/aarch64
Verifying the Build
@@ -634,6 +635,72 @@
cp: cannot stat `arm-linux-gnueabihf/libXt.so': No such file or directory
If the X11 libraries are not properly detected by configure
, you can point them out by --with-x
.
+Creating And Using Sysroots With qemu-deboostrap
+Fortunately, you can create sysroots for foreign architectures with tools provided by your OS. On Debian/Ubuntu systems, one could use qemu-deboostrap
to create the target system chroot, which would have the native libraries and headers specific to that target system. After that, we can use the cross-compiler on the build system, pointing into chroot to get the build dependencies right. This allows building for foreign architectures with native compilation speed.
+For example, cross-compiling to AArch64 from x86_64 could be done like this:
+
+Install cross-compiler on the build system:
+apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
+Create chroot on the build system, configuring it for target system:
+sudo qemu-debootstrap --arch=arm64 --verbose \
+ --include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \
+ --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/
+Configure and build with newly created chroot as sysroot/toolchain-path:
+CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ sh ./configure --openjdk-target=aarch64-linux-gnu --with-sysroot=/chroots/arm64/ --with-toolchain-path=/chroots/arm64/
+make images
+ls build/linux-aarch64-normal-server-release/
+
+The build does not create new files in that chroot, so it can be reused for multiple builds without additional cleanup.
+Architectures that are known to successfully cross-compile like this are:
+
+
+
+
+
+
+x86 |
+default |
+default |
+i386 |
+i386-linux-gnu |
+
+
+armhf |
+gcc-arm-linux-gnueabihf |
+g++-arm-linux-gnueabihf |
+armhf |
+arm-linux-gnueabihf |
+
+
+aarch64 |
+gcc-aarch64-linux-gnu |
+g++-aarch64-linux-gnu |
+arm64 |
+aarch64-linux-gnu |
+
+
+ppc64el |
+gcc-powerpc64le-linux-gnu |
+g++-powerpc64le-linux-gnu |
+ppc64el |
+powerpc64le-linux-gnu |
+
+
+s390x |
+gcc-s390x-linux-gnu |
+g++-s390x-linux-gnu |
+s390x |
+s390x-linux-gnu |
+
+
+
+Additional architectures might be supported by Debian/Ubuntu Ports.
Building for ARM/aarch64
A common cross-compilation target is the ARM CPU. When building for ARM, it is useful to set the ABI profile. A number of pre-defined ABI profiles are available using --with-abi-profile
: arm-vfp-sflt, arm-vfp-hflt, arm-sflt, armv5-vfp-sflt, armv6-vfp-hflt. Note that soft-float ABIs are no longer properly supported by the JDK.
The JDK contains two different ports for the aarch64 platform, one is the original aarch64 port from the AArch64 Port Project and one is a 64-bit version of the Oracle contributed ARM port. When targeting aarch64, by the default the original aarch64 port is used. To select the Oracle ARM 64 port, use --with-cpu-port=arm64
. Also set the corresponding value (aarch64
or arm64
) to --with-abi-profile, to ensure a consistent build.
diff -r 41e17fe9fbeb -r 6668bbc41155 doc/building.md
--- a/doc/building.md Mon Aug 27 16:01:38 2018 -0400
+++ b/doc/building.md Mon Aug 27 16:02:55 2018 -0400
@@ -1018,6 +1018,51 @@
* If the X11 libraries are not properly detected by `configure`, you can
point them out by `--with-x`.
+### Creating And Using Sysroots With qemu-deboostrap
+
+Fortunately, you can create sysroots for foreign architectures with tools
+provided by your OS. On Debian/Ubuntu systems, one could use `qemu-deboostrap` to
+create the *target* system chroot, which would have the native libraries and headers
+specific to that *target* system. After that, we can use the cross-compiler on the *build*
+system, pointing into chroot to get the build dependencies right. This allows building
+for foreign architectures with native compilation speed.
+
+For example, cross-compiling to AArch64 from x86_64 could be done like this:
+
+ * Install cross-compiler on the *build* system:
+```
+apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
+```
+
+ * Create chroot on the *build* system, configuring it for *target* system:
+```
+sudo qemu-debootstrap --arch=arm64 --verbose \
+ --include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \
+ --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/
+```
+
+ * Configure and build with newly created chroot as sysroot/toolchain-path:
+```
+CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ sh ./configure --openjdk-target=aarch64-linux-gnu --with-sysroot=/chroots/arm64/ --with-toolchain-path=/chroots/arm64/
+make images
+ls build/linux-aarch64-normal-server-release/
+```
+
+The build does not create new files in that chroot, so it can be reused for multiple builds
+without additional cleanup.
+
+Architectures that are known to successfully cross-compile like this are:
+
+ Target `CC` `CXX` `--arch=...` `--openjdk-target=...`
+ ------------ ------------------------- --------------------------- ------------ ----------------------
+ x86 default default i386 i386-linux-gnu
+ armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf
+ aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu
+ ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu
+ s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu
+
+Additional architectures might be supported by Debian/Ubuntu Ports.
+
### Building for ARM/aarch64
A common cross-compilation target is the ARM CPU. When building for ARM, it is
diff -r 41e17fe9fbeb -r 6668bbc41155 make/common/TestFilesCompilation.gmk
--- a/make/common/TestFilesCompilation.gmk Mon Aug 27 16:01:38 2018 -0400
+++ b/make/common/TestFilesCompilation.gmk Mon Aug 27 16:02:55 2018 -0400
@@ -94,7 +94,7 @@
CFLAGS := $$($1_CFLAGS) $$($1_CFLAGS_$$(name)), \
LDFLAGS := $$($1_LDFLAGS) $$($1_LDFLAGS_$$(name)), \
LIBS := $$($1_LIBS_$$(name)), \
- OPTIMIZATION := LOW, \
+ OPTIMIZATION := $$(if $$($1_OPTIMIZATION_$$(name)),$$($1_OPTIMIZATION_$$(name)),LOW), \
COPY_DEBUG_SYMBOLS := false, \
STRIP_SYMBOLS := false, \
)) \
diff -r 41e17fe9fbeb -r 6668bbc41155 make/test/JtregNativeHotspot.gmk
--- a/make/test/JtregNativeHotspot.gmk Mon Aug 27 16:01:38 2018 -0400
+++ b/make/test/JtregNativeHotspot.gmk Mon Aug 27 16:02:55 2018 -0400
@@ -139,6 +139,15 @@
-I$(VM_TESTBASE_DIR)/nsk/share/native \
-I$(VM_TESTBASE_DIR)/nsk/share/jni
+NO_FRAMEPOINTER_CFLAGS :=
+ifeq ($(OPENJDK_TARGET_OS),linux)
+ NO_FRAMEPOINTER_CFLAGS := -fomit-frame-pointer
+endif
+
+BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libNoFramePointer := $(NO_FRAMEPOINTER_CFLAGS)
+# Optimization -O3 needed, HIGH == -O3
+BUILD_HOTSPOT_JTREG_LIBRARIES_OPTIMIZATION_libNoFramePointer := HIGH
+
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES)
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libThreadController := $(NSK_MONITORING_INCLUDES)
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/c1/c1_LIRAssembler.cpp
--- a/src/hotspot/share/c1/c1_LIRAssembler.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -112,6 +112,9 @@
LIR_Assembler::~LIR_Assembler() {
+ // The unwind handler label may be unnbound if this destructor is invoked because of a bail-out.
+ // Reset it here to avoid an assertion.
+ _unwind_handler_entry.reset();
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/c1/c1_LIRAssembler.hpp
--- a/src/hotspot/share/c1/c1_LIRAssembler.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/c1/c1_LIRAssembler.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -71,11 +71,7 @@
void record_non_safepoint_debug_info();
// unified bailout support
- void bailout(const char* msg) {
- // reset the label in case it hits assertion in destructor.
- _unwind_handler_entry.reset();
- compilation()->bailout(msg);
- }
+ void bailout(const char* msg) const { compilation()->bailout(msg); }
bool bailed_out() const { return compilation()->bailed_out(); }
// code emission patterns and accessors
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/classLoaderData.cpp
--- a/src/hotspot/share/classfile/classLoaderData.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -655,7 +655,7 @@
size = _default_loader_dictionary_size;
resizable = true;
}
- if (!DynamicallyResizeSystemDictionaries || DumpSharedSpaces || UseSharedSpaces) {
+ if (!DynamicallyResizeSystemDictionaries || DumpSharedSpaces) {
resizable = false;
}
return new Dictionary(this, size, resizable);
@@ -1254,15 +1254,6 @@
}
}
-// Walks all entries in the dictionary including entries initiated by this class loader.
-void ClassLoaderDataGraph::dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
- Thread* thread = Thread::current();
- FOR_ALL_DICTIONARY(cld) {
- Handle holder(thread, cld->holder_phantom());
- cld->dictionary()->all_entries_do(f);
- }
-}
-
void ClassLoaderDataGraph::verify_dictionary() {
FOR_ALL_DICTIONARY(cld) {
cld->dictionary()->verify();
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/classLoaderData.hpp
--- a/src/hotspot/share/classfile/classLoaderData.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -134,9 +134,6 @@
// Added for initialize_itable_for_klass to handle exceptions.
static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
- // Iterate all classes and their class loaders, including initiating class loaders.
- static void dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
-
// VM_CounterDecay iteration support
static InstanceKlass* try_get_next_class();
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/dictionary.cpp
--- a/src/hotspot/share/classfile/dictionary.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/dictionary.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -330,13 +330,13 @@
}
// All classes, and their class loaders, including initiating class loaders
-void Dictionary::all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
+void Dictionary::all_entries_do(KlassClosure* closure) {
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
InstanceKlass* k = probe->instance_klass();
- f(k, loader_data());
+ closure->do_klass(k);
}
}
}
@@ -592,8 +592,8 @@
ResourceMark rm;
assert(loader_data() != NULL, "loader data should not be null");
- st->print_cr("Java dictionary (table_size=%d, classes=%d)",
- table_size(), number_of_entries());
+ st->print_cr("Java dictionary (table_size=%d, classes=%d, resizable=%s)",
+ table_size(), number_of_entries(), BOOL_TO_STR(_resizable));
st->print_cr("^ indicates that initiating loader is different from defining loader");
for (int index = 0; index < table_size(); index++) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/dictionary.hpp
--- a/src/hotspot/share/classfile/dictionary.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/dictionary.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -74,7 +74,7 @@
void classes_do(void f(InstanceKlass*));
void classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
- void all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
+ void all_entries_do(KlassClosure* closure);
void classes_do(MetaspaceClosure* it);
void unlink();
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/javaClasses.cpp
--- a/src/hotspot/share/classfile/javaClasses.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/javaClasses.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -1271,6 +1271,13 @@
return size;
}
+int java_lang_Class::oop_size_raw(oop java_class) {
+ assert(_oop_size_offset != 0, "must be set");
+ int size = java_class->int_field_raw(_oop_size_offset);
+ assert(size > 0, "Oop size must be greater than zero, not %d", size);
+ return size;
+}
+
void java_lang_Class::set_oop_size(HeapWord* java_class, int size) {
assert(_oop_size_offset != 0, "must be set");
assert(size > 0, "Oop size must be greater than zero, not %d", size);
@@ -1281,6 +1288,12 @@
assert(_static_oop_field_count_offset != 0, "must be set");
return java_class->int_field(_static_oop_field_count_offset);
}
+
+int java_lang_Class::static_oop_field_count_raw(oop java_class) {
+ assert(_static_oop_field_count_offset != 0, "must be set");
+ return java_class->int_field_raw(_static_oop_field_count_offset);
+}
+
void java_lang_Class::set_static_oop_field_count(oop java_class, int size) {
assert(_static_oop_field_count_offset != 0, "must be set");
java_class->int_field_put(_static_oop_field_count_offset, size);
@@ -1370,6 +1383,14 @@
return k;
}
+Klass* java_lang_Class::as_Klass_raw(oop java_class) {
+ //%note memory_2
+ assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+ Klass* k = ((Klass*)java_class->metadata_field_raw(_klass_offset));
+ assert(k == NULL || k->is_klass(), "type check");
+ return k;
+}
+
void java_lang_Class::set_klass(oop java_class, Klass* klass) {
assert(java_lang_Class::is_instance(java_class), "must be a Class object");
@@ -4007,6 +4028,11 @@
return HeapAccess<>::load_at(loader, _loader_data_offset);
}
+ClassLoaderData* java_lang_ClassLoader::loader_data_raw(oop loader) {
+ assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop");
+ return RawAccess<>::load_at(loader, _loader_data_offset);
+}
+
ClassLoaderData* java_lang_ClassLoader::cmpxchg_loader_data(ClassLoaderData* new_data, oop loader, ClassLoaderData* expected_data) {
assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop");
return HeapAccess<>::atomic_cmpxchg_at(new_data, loader, _loader_data_offset, expected_data);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/javaClasses.hpp
--- a/src/hotspot/share/classfile/javaClasses.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/javaClasses.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -277,6 +277,7 @@
// Conversion
static Klass* as_Klass(oop java_class);
+ static Klass* as_Klass_raw(oop java_class);
static void set_klass(oop java_class, Klass* klass);
static BasicType as_BasicType(oop java_class, Klass** reference_klass = NULL);
static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS);
@@ -310,8 +311,10 @@
static oop module(oop java_class);
static int oop_size(oop java_class);
+ static int oop_size_raw(oop java_class);
static void set_oop_size(HeapWord* java_class, int size);
static int static_oop_field_count(oop java_class);
+ static int static_oop_field_count_raw(oop java_class);
static void set_static_oop_field_count(oop java_class, int size);
static GrowableArray* fixup_mirror_list() {
@@ -1320,6 +1323,7 @@
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
static ClassLoaderData* loader_data(oop loader);
+ static ClassLoaderData* loader_data_raw(oop loader);
static ClassLoaderData* cmpxchg_loader_data(ClassLoaderData* new_data, oop loader, ClassLoaderData* expected_data);
static oop parent(oop loader);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/symbolTable.cpp
--- a/src/hotspot/share/classfile/symbolTable.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/symbolTable.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -134,7 +134,7 @@
void SymbolTable::delete_symbol(Symbol* sym) {
if (sym->refcount() == PERM_REFCOUNT) {
- MutexLocker ml(SymbolTable_lock); // Protect arena
+ MutexLockerEx ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
// Deleting permanent symbol should not occur very often (insert race condition),
// so log it.
log_trace_symboltable_helper(sym, "Freeing permanent symbol");
@@ -197,7 +197,7 @@
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
} else {
// Allocate to global arena
- MutexLocker ml(SymbolTable_lock); // Protect arena
+ MutexLockerEx ml(SymbolArena_lock, Mutex::_no_safepoint_check_flag); // Protect arena
sym = new (len, arena(), THREAD) Symbol((const u1*)name, len, PERM_REFCOUNT);
}
return sym;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/classfile/systemDictionary.cpp
--- a/src/hotspot/share/classfile/systemDictionary.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -1160,10 +1160,12 @@
#if INCLUDE_CDS
void SystemDictionary::set_shared_dictionary(HashtableBucket* t, int length,
int number_of_entries) {
+ assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces");
assert(length == _shared_dictionary_size * sizeof(HashtableBucket),
"bad shared dictionary size.");
_shared_dictionary = new Dictionary(ClassLoaderData::the_null_class_loader_data(),
- _shared_dictionary_size, t, number_of_entries);
+ _shared_dictionary_size, t, number_of_entries,
+ false /* explicitly set _resizable to false */);
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/gc/g1/g1CollectedHeap.cpp
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -70,6 +70,7 @@
#include "gc/shared/generationSpec.hpp"
#include "gc/shared/isGCActiveMark.hpp"
#include "gc/shared/oopStorageParState.hpp"
+#include "gc/shared/parallelCleaning.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/shared/referenceProcessor.inline.hpp"
@@ -3298,334 +3299,12 @@
undo_waste * HeapWordSize / K);
}
-class G1StringCleaningTask : public AbstractGangTask {
-private:
- BoolObjectClosure* _is_alive;
- G1StringDedupUnlinkOrOopsDoClosure _dedup_closure;
- OopStorage::ParState _par_state_string;
-
- int _initial_string_table_size;
-
- bool _process_strings;
- int _strings_processed;
- int _strings_removed;
-
- bool _process_string_dedup;
-
-public:
- G1StringCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_string_dedup) :
- AbstractGangTask("String Unlinking"),
- _is_alive(is_alive),
- _dedup_closure(is_alive, NULL, false),
- _par_state_string(StringTable::weak_storage()),
- _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
- _process_string_dedup(process_string_dedup) {
-
- _initial_string_table_size = (int) StringTable::the_table()->table_size();
- if (process_strings) {
- StringTable::reset_dead_counter();
- }
- }
-
- ~G1StringCleaningTask() {
- log_info(gc, stringtable)(
- "Cleaned string table, "
- "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
- strings_processed(), strings_removed());
- if (_process_strings) {
- StringTable::finish_dead_counter();
- }
- }
-
- void work(uint worker_id) {
- int strings_processed = 0;
- int strings_removed = 0;
- if (_process_strings) {
- StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed);
- Atomic::add(strings_processed, &_strings_processed);
- Atomic::add(strings_removed, &_strings_removed);
- }
- if (_process_string_dedup) {
- G1StringDedup::parallel_unlink(&_dedup_closure, worker_id);
- }
- }
-
- size_t strings_processed() const { return (size_t)_strings_processed; }
- size_t strings_removed() const { return (size_t)_strings_removed; }
-};
-
-class G1CodeCacheUnloadingTask {
-private:
- static Monitor* _lock;
-
- BoolObjectClosure* const _is_alive;
- const bool _unloading_occurred;
- const uint _num_workers;
-
- // Variables used to claim nmethods.
- CompiledMethod* _first_nmethod;
- CompiledMethod* volatile _claimed_nmethod;
-
- // The list of nmethods that need to be processed by the second pass.
- CompiledMethod* volatile _postponed_list;
- volatile uint _num_entered_barrier;
-
- public:
- G1CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
- _is_alive(is_alive),
- _unloading_occurred(unloading_occurred),
- _num_workers(num_workers),
- _first_nmethod(NULL),
- _claimed_nmethod(NULL),
- _postponed_list(NULL),
- _num_entered_barrier(0)
- {
- CompiledMethod::increase_unloading_clock();
- // Get first alive nmethod
- CompiledMethodIterator iter = CompiledMethodIterator();
- if(iter.next_alive()) {
- _first_nmethod = iter.method();
- }
- _claimed_nmethod = _first_nmethod;
- }
-
- ~G1CodeCacheUnloadingTask() {
- CodeCache::verify_clean_inline_caches();
-
- CodeCache::set_needs_cache_clean(false);
- guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
-
- CodeCache::verify_icholder_relocations();
- }
-
- private:
- void add_to_postponed_list(CompiledMethod* nm) {
- CompiledMethod* old;
- do {
- old = _postponed_list;
- nm->set_unloading_next(old);
- } while (Atomic::cmpxchg(nm, &_postponed_list, old) != old);
- }
-
- void clean_nmethod(CompiledMethod* nm) {
- bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred);
-
- if (postponed) {
- // This nmethod referred to an nmethod that has not been cleaned/unloaded yet.
- add_to_postponed_list(nm);
- }
-
- // Mark that this nmethod has been cleaned/unloaded.
- // After this call, it will be safe to ask if this nmethod was unloaded or not.
- nm->set_unloading_clock(CompiledMethod::global_unloading_clock());
- }
-
- void clean_nmethod_postponed(CompiledMethod* nm) {
- nm->do_unloading_parallel_postponed();
- }
-
- static const int MaxClaimNmethods = 16;
-
- void claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
- CompiledMethod* first;
- CompiledMethodIterator last;
-
- do {
- *num_claimed_nmethods = 0;
-
- first = _claimed_nmethod;
- last = CompiledMethodIterator(first);
-
- if (first != NULL) {
-
- for (int i = 0; i < MaxClaimNmethods; i++) {
- if (!last.next_alive()) {
- break;
- }
- claimed_nmethods[i] = last.method();
- (*num_claimed_nmethods)++;
- }
- }
-
- } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
- }
-
- CompiledMethod* claim_postponed_nmethod() {
- CompiledMethod* claim;
- CompiledMethod* next;
-
- do {
- claim = _postponed_list;
- if (claim == NULL) {
- return NULL;
- }
-
- next = claim->unloading_next();
-
- } while (Atomic::cmpxchg(next, &_postponed_list, claim) != claim);
-
- return claim;
- }
-
- public:
- // Mark that we're done with the first pass of nmethod cleaning.
- void barrier_mark(uint worker_id) {
- MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
- _num_entered_barrier++;
- if (_num_entered_barrier == _num_workers) {
- ml.notify_all();
- }
- }
-
- // See if we have to wait for the other workers to
- // finish their first-pass nmethod cleaning work.
- void barrier_wait(uint worker_id) {
- if (_num_entered_barrier < _num_workers) {
- MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
- while (_num_entered_barrier < _num_workers) {
- ml.wait(Mutex::_no_safepoint_check_flag, 0, false);
- }
- }
- }
-
- // Cleaning and unloading of nmethods. Some work has to be postponed
- // to the second pass, when we know which nmethods survive.
- void work_first_pass(uint worker_id) {
- // The first nmethods is claimed by the first worker.
- if (worker_id == 0 && _first_nmethod != NULL) {
- clean_nmethod(_first_nmethod);
- _first_nmethod = NULL;
- }
-
- int num_claimed_nmethods;
- CompiledMethod* claimed_nmethods[MaxClaimNmethods];
-
- while (true) {
- claim_nmethods(claimed_nmethods, &num_claimed_nmethods);
-
- if (num_claimed_nmethods == 0) {
- break;
- }
-
- for (int i = 0; i < num_claimed_nmethods; i++) {
- clean_nmethod(claimed_nmethods[i]);
- }
- }
- }
-
- void work_second_pass(uint worker_id) {
- CompiledMethod* nm;
- // Take care of postponed nmethods.
- while ((nm = claim_postponed_nmethod()) != NULL) {
- clean_nmethod_postponed(nm);
- }
- }
-};
-
-Monitor* G1CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never);
-
-class G1KlassCleaningTask : public StackObj {
- volatile int _clean_klass_tree_claimed;
- ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator;
-
- public:
- G1KlassCleaningTask() :
- _clean_klass_tree_claimed(0),
- _klass_iterator() {
- }
-
- private:
- bool claim_clean_klass_tree_task() {
- if (_clean_klass_tree_claimed) {
- return false;
- }
-
- return Atomic::cmpxchg(1, &_clean_klass_tree_claimed, 0) == 0;
- }
-
- InstanceKlass* claim_next_klass() {
- Klass* klass;
- do {
- klass =_klass_iterator.next_klass();
- } while (klass != NULL && !klass->is_instance_klass());
-
- // this can be null so don't call InstanceKlass::cast
- return static_cast(klass);
- }
-
-public:
-
- void clean_klass(InstanceKlass* ik) {
- ik->clean_weak_instanceklass_links();
- }
-
- void work() {
- ResourceMark rm;
-
- // One worker will clean the subklass/sibling klass tree.
- if (claim_clean_klass_tree_task()) {
- Klass::clean_subklass_tree();
- }
-
- // All workers will help cleaning the classes,
- InstanceKlass* klass;
- while ((klass = claim_next_klass()) != NULL) {
- clean_klass(klass);
- }
- }
-};
-
-// To minimize the remark pause times, the tasks below are done in parallel.
-class G1ParallelCleaningTask : public AbstractGangTask {
-private:
- bool _unloading_occurred;
- G1StringCleaningTask _string_task;
- G1CodeCacheUnloadingTask _code_cache_task;
- G1KlassCleaningTask _klass_cleaning_task;
-
-public:
- // The constructor is run in the VMThread.
- G1ParallelCleaningTask(BoolObjectClosure* is_alive, uint num_workers, bool unloading_occurred) :
- AbstractGangTask("Parallel Cleaning"),
- _unloading_occurred(unloading_occurred),
- _string_task(is_alive, true, G1StringDedup::is_enabled()),
- _code_cache_task(num_workers, is_alive, unloading_occurred),
- _klass_cleaning_task() {
- }
-
- // The parallel work done by all worker threads.
- void work(uint worker_id) {
- // Do first pass of code cache cleaning.
- _code_cache_task.work_first_pass(worker_id);
-
- // Let the threads mark that the first pass is done.
- _code_cache_task.barrier_mark(worker_id);
-
- // Clean the Strings.
- _string_task.work(worker_id);
-
- // Wait for all workers to finish the first code cache cleaning pass.
- _code_cache_task.barrier_wait(worker_id);
-
- // Do the second code cache cleaning work, which realize on
- // the liveness information gathered during the first pass.
- _code_cache_task.work_second_pass(worker_id);
-
- // Clean all klasses that were not unloaded.
- // The weak metadata in klass doesn't need to be
- // processed if there was no unloading.
- if (_unloading_occurred) {
- _klass_cleaning_task.work();
- }
- }
-};
-
-
void G1CollectedHeap::complete_cleaning(BoolObjectClosure* is_alive,
bool class_unloading_occurred) {
uint n_workers = workers()->active_workers();
- G1ParallelCleaningTask g1_unlink_task(is_alive, n_workers, class_unloading_occurred);
+ G1StringDedupUnlinkOrOopsDoClosure dedup_closure(is_alive, NULL, false);
+ ParallelCleaningTask g1_unlink_task(is_alive, &dedup_closure, n_workers, class_unloading_occurred);
workers()->run_task(&g1_unlink_task);
}
@@ -3637,7 +3316,8 @@
return;
}
- G1StringCleaningTask g1_unlink_task(is_alive, process_strings, process_string_dedup);
+ G1StringDedupUnlinkOrOopsDoClosure dedup_closure(is_alive, NULL, false);
+ StringCleaningTask g1_unlink_task(is_alive, process_string_dedup ? &dedup_closure : NULL, process_strings);
workers()->run_task(&g1_unlink_task);
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/gc/shared/oopStorage.cpp
--- a/src/hotspot/share/gc/shared/oopStorage.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -43,7 +43,6 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
-#include "utilities/spinYield.hpp"
OopStorage::AllocationListEntry::AllocationListEntry() : _prev(NULL), _next(NULL) {}
@@ -495,48 +494,6 @@
return true;
}
-OopStorage::ProtectActive::ProtectActive() : _enter(0), _exit() {}
-
-// Begin read-side critical section.
-uint OopStorage::ProtectActive::read_enter() {
- return Atomic::add(2u, &_enter);
-}
-
-// End read-side critical section.
-void OopStorage::ProtectActive::read_exit(uint enter_value) {
- Atomic::add(2u, &_exit[enter_value & 1]);
-}
-
-// Wait until all readers that entered the critical section before
-// synchronization have exited that critical section.
-void OopStorage::ProtectActive::write_synchronize() {
- SpinYield spinner;
- // Determine old and new exit counters, based on bit0 of the
- // on-entry _enter counter.
- uint value = OrderAccess::load_acquire(&_enter);
- volatile uint* new_ptr = &_exit[(value + 1) & 1];
- // Atomically change the in-use exit counter to the new counter, by
- // adding 1 to the _enter counter (flipping bit0 between 0 and 1)
- // and initializing the new exit counter to that enter value. Note:
- // The new exit counter is not being used by read operations until
- // this change succeeds.
- uint old;
- do {
- old = value;
- *new_ptr = ++value;
- value = Atomic::cmpxchg(value, &_enter, old);
- } while (old != value);
- // Readers that entered the critical section before we changed the
- // selected exit counter will use the old exit counter. Readers
- // entering after the change will use the new exit counter. Wait
- // for all the critical sections started before the change to
- // complete, e.g. for the value of old_ptr to catch up with old.
- volatile uint* old_ptr = &_exit[old & 1];
- while (old != OrderAccess::load_acquire(old_ptr)) {
- spinner.wait();
- }
-}
-
// Make new_array the _active_array. Increments new_array's refcount
// to account for the new reference. The assignment is atomic wrto
// obtain_active_array; once this function returns, it is safe for the
@@ -548,7 +505,10 @@
// Install new_array, ensuring its initialization is complete first.
OrderAccess::release_store(&_active_array, new_array);
// Wait for any readers that could read the old array from _active_array.
- _protect_active.write_synchronize();
+ // Can't use GlobalCounter here, because this is called from allocate(),
+ // which may be called in the scope of a GlobalCounter critical section
+ // when inserting a StringTable entry.
+ _protect_active.synchronize();
// All obtain critical sections that could see the old array have
// completed, having incremented the refcount of the old array. The
// caller can now safely relinquish the old array.
@@ -560,10 +520,9 @@
// _active_array. The caller must relinquish the array when done
// using it.
OopStorage::ActiveArray* OopStorage::obtain_active_array() const {
- uint enter_value = _protect_active.read_enter();
+ SingleWriterSynchronizer::CriticalSection cs(&_protect_active);
ActiveArray* result = OrderAccess::load_acquire(&_active_array);
result->increment_refcount();
- _protect_active.read_exit(enter_value);
return result;
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/gc/shared/oopStorage.hpp
--- a/src/hotspot/share/gc/shared/oopStorage.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/gc/shared/oopStorage.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -29,6 +29,7 @@
#include "oops/oop.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
+#include "utilities/singleWriterSynchronizer.hpp"
class Mutex;
class outputStream;
@@ -203,19 +204,6 @@
void unlink(const Block& block);
};
- // RCU-inspired protection of access to _active_array.
- class ProtectActive {
- volatile uint _enter;
- volatile uint _exit[2];
-
- public:
- ProtectActive();
-
- uint read_enter();
- void read_exit(uint enter_value);
- void write_synchronize();
- };
-
private:
const char* _name;
ActiveArray* _active_array;
@@ -229,7 +217,7 @@
volatile size_t _allocation_count;
// Protection for _active_array.
- mutable ProtectActive _protect_active;
+ mutable SingleWriterSynchronizer _protect_active;
// mutable because this gets set even for const iteration.
mutable bool _concurrent_iteration_active;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/gc/shared/parallelCleaning.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/stringTable.hpp"
+#include "code/codeCache.hpp"
+#include "gc/shared/parallelCleaning.hpp"
+#include "memory/resourceArea.hpp"
+#include "logging/log.hpp"
+
+StringCleaningTask::StringCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure, bool process_strings) :
+ AbstractGangTask("String Unlinking"),
+ _is_alive(is_alive),
+ _dedup_closure(dedup_closure),
+ _par_state_string(StringTable::weak_storage()),
+ _initial_string_table_size((int) StringTable::the_table()->table_size()),
+ _process_strings(process_strings), _strings_processed(0), _strings_removed(0) {
+
+ if (process_strings) {
+ StringTable::reset_dead_counter();
+ }
+}
+
+StringCleaningTask::~StringCleaningTask() {
+ log_info(gc, stringtable)(
+ "Cleaned string table, "
+ "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
+ strings_processed(), strings_removed());
+ if (_process_strings) {
+ StringTable::finish_dead_counter();
+ }
+}
+
+void StringCleaningTask::work(uint worker_id) {
+ int strings_processed = 0;
+ int strings_removed = 0;
+ if (_process_strings) {
+ StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed);
+ Atomic::add(strings_processed, &_strings_processed);
+ Atomic::add(strings_removed, &_strings_removed);
+ }
+ if (_dedup_closure != NULL) {
+ StringDedup::parallel_unlink(_dedup_closure, worker_id);
+ }
+}
+
+CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
+ _is_alive(is_alive),
+ _unloading_occurred(unloading_occurred),
+ _num_workers(num_workers),
+ _first_nmethod(NULL),
+ _claimed_nmethod(NULL),
+ _postponed_list(NULL),
+ _num_entered_barrier(0) {
+ CompiledMethod::increase_unloading_clock();
+ // Get first alive nmethod
+ CompiledMethodIterator iter = CompiledMethodIterator();
+ if(iter.next_alive()) {
+ _first_nmethod = iter.method();
+ }
+ _claimed_nmethod = _first_nmethod;
+}
+
+CodeCacheUnloadingTask::~CodeCacheUnloadingTask() {
+ CodeCache::verify_clean_inline_caches();
+
+ CodeCache::set_needs_cache_clean(false);
+ guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
+
+ CodeCache::verify_icholder_relocations();
+}
+
+Monitor* CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never);
+
+void CodeCacheUnloadingTask::add_to_postponed_list(CompiledMethod* nm) {
+ CompiledMethod* old;
+ do {
+ old = _postponed_list;
+ nm->set_unloading_next(old);
+ } while (Atomic::cmpxchg(nm, &_postponed_list, old) != old);
+}
+
+void CodeCacheUnloadingTask::clean_nmethod(CompiledMethod* nm) {
+ bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred);
+
+ if (postponed) {
+ // This nmethod referred to an nmethod that has not been cleaned/unloaded yet.
+ add_to_postponed_list(nm);
+ }
+
+ // Mark that this nmethod has been cleaned/unloaded.
+ // After this call, it will be safe to ask if this nmethod was unloaded or not.
+ nm->set_unloading_clock(CompiledMethod::global_unloading_clock());
+}
+
+void CodeCacheUnloadingTask::clean_nmethod_postponed(CompiledMethod* nm) {
+ nm->do_unloading_parallel_postponed();
+}
+
+void CodeCacheUnloadingTask::claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
+ CompiledMethod* first;
+ CompiledMethodIterator last;
+
+ do {
+ *num_claimed_nmethods = 0;
+
+ first = _claimed_nmethod;
+ last = CompiledMethodIterator(first);
+
+ if (first != NULL) {
+
+ for (int i = 0; i < MaxClaimNmethods; i++) {
+ if (!last.next_alive()) {
+ break;
+ }
+ claimed_nmethods[i] = last.method();
+ (*num_claimed_nmethods)++;
+ }
+ }
+
+ } while (Atomic::cmpxchg(last.method(), &_claimed_nmethod, first) != first);
+}
+
+CompiledMethod* CodeCacheUnloadingTask::claim_postponed_nmethod() {
+ CompiledMethod* claim;
+ CompiledMethod* next;
+
+ do {
+ claim = _postponed_list;
+ if (claim == NULL) {
+ return NULL;
+ }
+
+ next = claim->unloading_next();
+
+ } while (Atomic::cmpxchg(next, &_postponed_list, claim) != claim);
+
+ return claim;
+}
+
+void CodeCacheUnloadingTask::barrier_mark(uint worker_id) {
+ MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+ _num_entered_barrier++;
+ if (_num_entered_barrier == _num_workers) {
+ ml.notify_all();
+ }
+}
+
+void CodeCacheUnloadingTask::barrier_wait(uint worker_id) {
+ if (_num_entered_barrier < _num_workers) {
+ MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+ while (_num_entered_barrier < _num_workers) {
+ ml.wait(Mutex::_no_safepoint_check_flag, 0, false);
+ }
+ }
+}
+
+void CodeCacheUnloadingTask::work_first_pass(uint worker_id) {
+ // The first nmethods is claimed by the first worker.
+ if (worker_id == 0 && _first_nmethod != NULL) {
+ clean_nmethod(_first_nmethod);
+ _first_nmethod = NULL;
+ }
+
+ int num_claimed_nmethods;
+ CompiledMethod* claimed_nmethods[MaxClaimNmethods];
+
+ while (true) {
+ claim_nmethods(claimed_nmethods, &num_claimed_nmethods);
+
+ if (num_claimed_nmethods == 0) {
+ break;
+ }
+
+ for (int i = 0; i < num_claimed_nmethods; i++) {
+ clean_nmethod(claimed_nmethods[i]);
+ }
+ }
+}
+
+void CodeCacheUnloadingTask::work_second_pass(uint worker_id) {
+ CompiledMethod* nm;
+ // Take care of postponed nmethods.
+ while ((nm = claim_postponed_nmethod()) != NULL) {
+ clean_nmethod_postponed(nm);
+ }
+}
+
+KlassCleaningTask::KlassCleaningTask() :
+ _clean_klass_tree_claimed(0),
+ _klass_iterator() {
+}
+
+bool KlassCleaningTask::claim_clean_klass_tree_task() {
+ if (_clean_klass_tree_claimed) {
+ return false;
+ }
+
+ return Atomic::cmpxchg(1, &_clean_klass_tree_claimed, 0) == 0;
+}
+
+InstanceKlass* KlassCleaningTask::claim_next_klass() {
+ Klass* klass;
+ do {
+ klass =_klass_iterator.next_klass();
+ } while (klass != NULL && !klass->is_instance_klass());
+
+ // this can be null so don't call InstanceKlass::cast
+ return static_cast(klass);
+}
+
+void KlassCleaningTask::work() {
+ ResourceMark rm;
+
+ // One worker will clean the subklass/sibling klass tree.
+ if (claim_clean_klass_tree_task()) {
+ Klass::clean_subklass_tree();
+ }
+
+ // All workers will help cleaning the classes,
+ InstanceKlass* klass;
+ while ((klass = claim_next_klass()) != NULL) {
+ clean_klass(klass);
+ }
+}
+
+ParallelCleaningTask::ParallelCleaningTask(BoolObjectClosure* is_alive,
+ StringDedupUnlinkOrOopsDoClosure* dedup_closure, uint num_workers, bool unloading_occurred) :
+ AbstractGangTask("Parallel Cleaning"),
+ _unloading_occurred(unloading_occurred),
+ _string_task(is_alive, StringDedup::is_enabled() ? dedup_closure : NULL, true),
+ _code_cache_task(num_workers, is_alive, unloading_occurred),
+ _klass_cleaning_task() {
+}
+
+// The parallel work done by all worker threads.
+void ParallelCleaningTask::work(uint worker_id) {
+ // Do first pass of code cache cleaning.
+ _code_cache_task.work_first_pass(worker_id);
+
+ // Let the threads mark that the first pass is done.
+ _code_cache_task.barrier_mark(worker_id);
+
+ // Clean the Strings and Symbols.
+ _string_task.work(worker_id);
+
+ // Wait for all workers to finish the first code cache cleaning pass.
+ _code_cache_task.barrier_wait(worker_id);
+
+ // Do the second code cache cleaning work, which realize on
+ // the liveness information gathered during the first pass.
+ _code_cache_task.work_second_pass(worker_id);
+
+ // Clean all klasses that were not unloaded.
+ // The weak metadata in klass doesn't need to be
+ // processed if there was no unloading.
+ if (_unloading_occurred) {
+ _klass_cleaning_task.work();
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/gc/shared/parallelCleaning.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/parallelCleaning.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
+#define SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
+
+#include "gc/shared/oopStorageParState.hpp"
+#include "gc/shared/stringdedup/stringDedup.hpp"
+#include "gc/shared/workgroup.hpp"
+
+class ParallelCleaningTask;
+
+class StringCleaningTask : public AbstractGangTask {
+private:
+ BoolObjectClosure* _is_alive;
+ StringDedupUnlinkOrOopsDoClosure * const _dedup_closure;
+
+ OopStorage::ParState _par_state_string;
+
+ int _initial_string_table_size;
+
+ bool _process_strings;
+ int _strings_processed;
+ int _strings_removed;
+
+public:
+ StringCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure, bool process_strings);
+ ~StringCleaningTask();
+
+ void work(uint worker_id);
+
+ size_t strings_processed() const { return (size_t)_strings_processed; }
+ size_t strings_removed() const { return (size_t)_strings_removed; }
+};
+
+class CodeCacheUnloadingTask {
+private:
+ static Monitor* _lock;
+
+ BoolObjectClosure* const _is_alive;
+ const bool _unloading_occurred;
+ const uint _num_workers;
+
+ // Variables used to claim nmethods.
+ CompiledMethod* _first_nmethod;
+ CompiledMethod* volatile _claimed_nmethod;
+
+ // The list of nmethods that need to be processed by the second pass.
+ CompiledMethod* volatile _postponed_list;
+ volatile uint _num_entered_barrier;
+
+public:
+ CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred);
+ ~CodeCacheUnloadingTask();
+
+private:
+ void add_to_postponed_list(CompiledMethod* nm);
+ void clean_nmethod(CompiledMethod* nm);
+ void clean_nmethod_postponed(CompiledMethod* nm);
+
+ static const int MaxClaimNmethods = 16;
+
+ void claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods);
+ CompiledMethod* claim_postponed_nmethod();
+public:
+ // Mark that we're done with the first pass of nmethod cleaning.
+ void barrier_mark(uint worker_id);
+
+ // See if we have to wait for the other workers to
+ // finish their first-pass nmethod cleaning work.
+ void barrier_wait(uint worker_id);
+
+ // Cleaning and unloading of nmethods. Some work has to be postponed
+ // to the second pass, when we know which nmethods survive.
+ void work_first_pass(uint worker_id);
+ void work_second_pass(uint worker_id);
+};
+
+
+class KlassCleaningTask : public StackObj {
+ volatile int _clean_klass_tree_claimed;
+ ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator;
+
+public:
+ KlassCleaningTask();
+
+private:
+ bool claim_clean_klass_tree_task();
+ InstanceKlass* claim_next_klass();
+
+public:
+
+ void clean_klass(InstanceKlass* ik) {
+ ik->clean_weak_instanceklass_links();
+ }
+
+ void work();
+};
+
+// To minimize the remark pause times, the tasks below are done in parallel.
+class ParallelCleaningTask : public AbstractGangTask {
+private:
+ bool _unloading_occurred;
+ StringCleaningTask _string_task;
+ CodeCacheUnloadingTask _code_cache_task;
+ KlassCleaningTask _klass_cleaning_task;
+
+public:
+ // The constructor is run in the VMThread.
+ ParallelCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure,
+ uint num_workers, bool unloading_occurred);
+
+ void work(uint worker_id);
+};
+
+#endif // SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/memory/metaspace/virtualSpaceList.cpp
--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -1,8 +1,25 @@
/*
- * virtualSpaceList.cpp
+ * 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.
*
- * Created on: May 6, 2018
- * Author: thomas
+ * 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.
+ *
*/
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/memory/universe.cpp
--- a/src/hotspot/share/memory/universe.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/memory/universe.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -165,14 +165,15 @@
uint64_t Universe::_narrow_klass_range = (uint64_t(max_juint)+1);
void Universe::basic_type_classes_do(void f(Klass*)) {
- f(boolArrayKlassObj());
- f(byteArrayKlassObj());
- f(charArrayKlassObj());
- f(intArrayKlassObj());
- f(shortArrayKlassObj());
- f(longArrayKlassObj());
- f(singleArrayKlassObj());
- f(doubleArrayKlassObj());
+ for (int i = T_BOOLEAN; i < T_LONG+1; i++) {
+ f(_typeArrayKlassObjs[i]);
+ }
+}
+
+void Universe::basic_type_classes_do(KlassClosure *closure) {
+ for (int i = T_BOOLEAN; i < T_LONG+1; i++) {
+ closure->do_klass(_typeArrayKlassObjs[i]);
+ }
}
void Universe::oops_do(OopClosure* f, bool do_all) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/memory/universe.hpp
--- a/src/hotspot/share/memory/universe.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/memory/universe.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -486,6 +486,7 @@
// Apply "f" to all klasses for basic types (classes not present in
// SystemDictionary).
static void basic_type_classes_do(void f(Klass*));
+ static void basic_type_classes_do(KlassClosure* closure);
static void metaspace_pointers_do(MetaspaceClosure* it);
// Debugging
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp
--- a/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -39,7 +39,7 @@
InstanceKlass::oop_oop_iterate(obj, closure);
if (Devirtualizer::do_metadata(closure)) {
- ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
+ ClassLoaderData* cld = java_lang_ClassLoader::loader_data_raw(obj);
// cld can be null if we have a non-registered class loader.
if (cld != NULL) {
Devirtualizer::do_cld(closure, cld);
@@ -61,7 +61,7 @@
if (Devirtualizer::do_metadata(closure)) {
if (mr.contains(obj)) {
- ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
+ ClassLoaderData* cld = java_lang_ClassLoader::loader_data_raw(obj);
// cld can be null if we have a non-registered class loader.
if (cld != NULL) {
Devirtualizer::do_cld(closure, cld);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/instanceMirrorKlass.cpp
--- a/src/hotspot/share/oops/instanceMirrorKlass.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/instanceMirrorKlass.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -56,7 +56,7 @@
}
int InstanceMirrorKlass::oop_size(oop obj) const {
- return java_lang_Class::oop_size(obj);
+ return java_lang_Class::oop_size_raw(obj);
}
int InstanceMirrorKlass::compute_static_oop_field_count(oop obj) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/instanceMirrorKlass.inline.hpp
--- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -36,7 +36,7 @@
template
void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closure) {
T* p = (T*)start_of_static_fields(obj);
- T* const end = p + java_lang_Class::static_oop_field_count(obj);
+ T* const end = p + java_lang_Class::static_oop_field_count_raw(obj);
for (; p < end; ++p) {
Devirtualizer::do_oop(closure, p);
@@ -48,7 +48,7 @@
InstanceKlass::oop_oop_iterate(obj, closure);
if (Devirtualizer::do_metadata(closure)) {
- Klass* klass = java_lang_Class::as_Klass(obj);
+ Klass* klass = java_lang_Class::as_Klass_raw(obj);
// We'll get NULL for primitive mirrors.
if (klass != NULL) {
if (klass->is_instance_klass() &&
@@ -90,7 +90,7 @@
OopClosureType* closure,
MemRegion mr) {
T* p = (T*)start_of_static_fields(obj);
- T* end = p + java_lang_Class::static_oop_field_count(obj);
+ T* end = p + java_lang_Class::static_oop_field_count_raw(obj);
T* const l = (T*)mr.start();
T* const h = (T*)mr.end();
@@ -116,7 +116,7 @@
if (Devirtualizer::do_metadata(closure)) {
if (mr.contains(obj)) {
- Klass* klass = java_lang_Class::as_Klass(obj);
+ Klass* klass = java_lang_Class::as_Klass_raw(obj);
// We'll get NULL for primitive mirrors.
if (klass != NULL) {
Devirtualizer::do_klass(closure, klass);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/instanceRefKlass.inline.hpp
--- a/src/hotspot/share/oops/instanceRefKlass.inline.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/instanceRefKlass.inline.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -183,8 +183,13 @@
T* discovered_addr = (T*) java_lang_ref_Reference::discovered_addr_raw(obj);
log_develop_trace(gc, ref)("InstanceRefKlass %s for obj " PTR_FORMAT, s, p2i(obj));
- log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT,
- p2i(referent_addr), p2i((oop)HeapAccess::oop_load_at(obj, java_lang_ref_Reference::referent_offset)));
+ if (java_lang_ref_Reference::is_phantom(obj)) {
+ log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT,
+ p2i(referent_addr), p2i((oop)HeapAccess::oop_load(referent_addr)));
+ } else {
+ log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT,
+ p2i(referent_addr), p2i((oop)HeapAccess::oop_load(referent_addr)));
+ }
log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT,
p2i(discovered_addr), p2i((oop)HeapAccess::oop_load(discovered_addr)));
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/oop.cpp
--- a/src/hotspot/share/oops/oop.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/oop.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -177,6 +177,7 @@
void oopDesc::release_address_field_put(int offset, address value) { HeapAccess::store_at(as_oop(), offset, value); }
Metadata* oopDesc::metadata_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); }
+Metadata* oopDesc::metadata_field_raw(int offset) const { return RawAccess<>::load_at(as_oop(), offset); }
void oopDesc::metadata_field_put(int offset, Metadata* value) { HeapAccess<>::store_at(as_oop(), offset, value); }
Metadata* oopDesc::metadata_field_acquire(int offset) const { return HeapAccess::load_at(as_oop(), offset); }
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/oop.hpp
--- a/src/hotspot/share/oops/oop.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/oop.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -163,6 +163,7 @@
void obj_field_put_volatile(int offset, oop value);
Metadata* metadata_field(int offset) const;
+ Metadata* metadata_field_raw(int offset) const;
void metadata_field_put(int offset, Metadata* value);
Metadata* metadata_field_acquire(int offset) const;
@@ -178,6 +179,7 @@
void bool_field_put(int offset, jboolean contents);
jint int_field(int offset) const;
+ jint int_field_raw(int offset) const;
void int_field_put(int offset, jint contents);
jshort short_field(int offset) const;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/oops/oop.inline.hpp
--- a/src/hotspot/share/oops/oop.inline.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/oops/oop.inline.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -306,6 +306,7 @@
inline void oopDesc::short_field_put(int offset, jshort value) { HeapAccess<>::store_at(as_oop(), offset, value); }
inline jint oopDesc::int_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); }
+inline jint oopDesc::int_field_raw(int offset) const { return RawAccess<>::load_at(as_oop(), offset); }
inline void oopDesc::int_field_put(int offset, jint value) { HeapAccess<>::store_at(as_oop(), offset, value); }
inline jlong oopDesc::long_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); }
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/opto/coalesce.cpp
--- a/src/hotspot/share/opto/coalesce.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/opto/coalesce.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/block.hpp"
+#include "opto/c2compiler.hpp"
#include "opto/cfgnode.hpp"
#include "opto/chaitin.hpp"
#include "opto/coalesce.hpp"
@@ -294,9 +295,13 @@
} else {
uint ireg = m->ideal_reg();
if (ireg == 0 || ireg == Op_RegFlags) {
- assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %u, spill_type: %s",
- m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::PhiInput));
- C->record_method_not_compilable("attempted to spill a non-spillable item");
+ if (C->subsume_loads()) {
+ C->record_failure(C2Compiler::retry_no_subsuming_loads());
+ } else {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %u, spill_type: %s",
+ m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::PhiInput));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ }
return;
}
const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/opto/graphKit.cpp
--- a/src/hotspot/share/opto/graphKit.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/opto/graphKit.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -1772,7 +1772,7 @@
//return xcall; // no need, caller already has it
}
-Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj) {
+Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj, bool deoptimize) {
if (stopped()) return top(); // maybe the call folded up?
// Capture the return value, if any.
@@ -1785,7 +1785,7 @@
// Note: Since any out-of-line call can produce an exception,
// we always insert an I_O projection from the call into the result.
- make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj);
+ make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj, deoptimize);
if (separate_io_proj) {
// The caller requested separate projections be used by the fall
@@ -2571,7 +2571,7 @@
Deoptimization::Action_none);
} else {
// Create an exception state also.
- // Use an exact type if the caller has specified a specific exception.
+ // Use an exact type if the caller has a specific exception.
const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull);
Node* ex_oop = new CreateExNode(ex_type, control(), i_o);
add_exception_state(make_exception_state(_gvn.transform(ex_oop)));
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/opto/graphKit.hpp
--- a/src/hotspot/share/opto/graphKit.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/opto/graphKit.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -693,7 +693,7 @@
// Finish up a java call that was started by set_edges_for_java_call.
// Call add_exception on any throw arising from the call.
// Return the call result (transformed).
- Node* set_results_for_java_call(CallJavaNode* call, bool separate_io_proj = false);
+ Node* set_results_for_java_call(CallJavaNode* call, bool separate_io_proj = false, bool deoptimize = false);
// Similar to set_edges_for_java_call, but simplified for runtime calls.
void set_predefined_output_for_runtime_call(Node* call) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/opto/library_call.cpp
--- a/src/hotspot/share/opto/library_call.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/opto/library_call.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -4386,7 +4386,8 @@
if (!stopped()) {
PreserveJVMState pjvms(this);
CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_clone, is_virtual);
- Node* slow_result = set_results_for_java_call(slow_call);
+ // We need to deoptimize on exception (see comment above)
+ Node* slow_result = set_results_for_java_call(slow_call, false, /* deoptimize */ true);
// this->control() comes from set_results_for_java_call
result_reg->init_req(_slow_path, control());
result_val->init_req(_slow_path, slow_result);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/dictionary.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.hpp"
@@ -39,16 +40,7 @@
Stack _classStack;
JvmtiEnv* _env;
Thread* _cur_thread;
-
-public:
- LoadedClassesClosure(Thread* thread, JvmtiEnv* env) : _env(env), _cur_thread(thread) {
- assert(_cur_thread == Thread::current(), "must be current thread");
- }
-
- void do_klass(Klass* k) {
- // Collect all jclasses
- _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
- }
+ bool _dictionary_walk;
int extract(jclass* result_list) {
// The size of the Stack will be 0 after extract, so get it here
@@ -68,198 +60,46 @@
int get_count() {
return (int)_classStack.size();
}
-};
-// The closure for GetClassLoaderClasses
-class JvmtiGetLoadedClassesClosure : public StackObj {
- // Since the ClassLoaderDataGraph::dictionary_all_entries_do callback
- // doesn't pass a closureData pointer,
- // we use a thread-local slot to hold a pointer to
- // a stack allocated instance of this structure.
- private:
- jobject _initiatingLoader;
- int _count;
- Handle* _list;
- int _index;
-
- private:
- // Getting and setting the thread local pointer
- static JvmtiGetLoadedClassesClosure* get_this() {
- JvmtiGetLoadedClassesClosure* result = NULL;
- JavaThread* thread = JavaThread::current();
- result = thread->get_jvmti_get_loaded_classes_closure();
- return result;
- }
- static void set_this(JvmtiGetLoadedClassesClosure* that) {
- JavaThread* thread = JavaThread::current();
- thread->set_jvmti_get_loaded_classes_closure(that);
- }
-
- public:
- // Constructor/Destructor
- JvmtiGetLoadedClassesClosure() {
- JvmtiGetLoadedClassesClosure* that = get_this();
- assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
- _initiatingLoader = NULL;
- _count = 0;
- _list = NULL;
- _index = 0;
- set_this(this);
- }
-
- JvmtiGetLoadedClassesClosure(jobject initiatingLoader) {
- JvmtiGetLoadedClassesClosure* that = get_this();
- assert(that == NULL, "JvmtiGetLoadedClassesClosure in use");
- _initiatingLoader = initiatingLoader;
- _count = 0;
- _list = NULL;
- _index = 0;
- set_this(this);
- }
-
- ~JvmtiGetLoadedClassesClosure() {
- JvmtiGetLoadedClassesClosure* that = get_this();
- assert(that != NULL, "JvmtiGetLoadedClassesClosure not found");
- set_this(NULL);
- _initiatingLoader = NULL;
- _count = 0;
- if (_list != NULL) {
- FreeHeap(_list);
- _list = NULL;
- }
- _index = 0;
- }
-
- // Accessors.
- jobject get_initiatingLoader() {
- return _initiatingLoader;
- }
-
- int get_count() {
- return _count;
+public:
+ LoadedClassesClosure(JvmtiEnv* env, bool dictionary_walk) :
+ _env(env),
+ _cur_thread(Thread::current()),
+ _dictionary_walk(dictionary_walk) {
}
- void set_count(int value) {
- _count = value;
- }
-
- Handle* get_list() {
- return _list;
- }
-
- void set_list(Handle* value) {
- _list = value;
- }
-
- int get_index() {
- return _index;
- }
-
- void set_index(int value) {
- _index = value;
- }
-
- Handle get_element(int index) {
- if ((_list != NULL) && (index < _count)) {
- return _list[index];
- } else {
- assert(false, "empty get_element");
- return Handle();
- }
- }
-
- void set_element(int index, Handle value) {
- if ((_list != NULL) && (index < _count)) {
- _list[index] = value;
- } else {
- assert(false, "bad set_element");
- }
- }
-
- // Other predicates
- bool available() {
- return (_list != NULL);
- }
-
-#ifdef ASSERT
- // For debugging.
- void check(int limit) {
- for (int i = 0; i < limit; i += 1) {
- assert(Universe::heap()->is_in(get_element(i)()), "check fails");
- }
- }
-#endif
-
- // Public methods that get called within the scope of the closure
- void allocate() {
- _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
- assert(_list != NULL, "Out of memory");
- if (_list == NULL) {
- _count = 0;
- }
- }
-
- void extract(JvmtiEnv *env, jclass* result) {
- for (int index = 0; index < _count; index += 1) {
- result[index] = (jclass) env->jni_reference(get_element(index));
- }
- }
-
- static void increment_with_loader(InstanceKlass* k, ClassLoaderData* loader_data) {
- JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
- oop class_loader = loader_data->class_loader();
- if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
- for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
- that->set_count(that->get_count() + 1);
+ void do_klass(Klass* k) {
+ // Collect all jclasses
+ _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, k->java_mirror())));
+ if (_dictionary_walk) {
+ // Collect array classes this way when walking the dictionary (because array classes are
+ // not in the dictionary).
+ for (Klass* l = k->array_klass_or_null(); l != NULL; l = l->array_klass_or_null()) {
+ _classStack.push((jclass) _env->jni_reference(Handle(_cur_thread, l->java_mirror())));
}
}
}
- static void add_with_loader(InstanceKlass* k, ClassLoaderData* loader_data) {
- JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
- if (that->available()) {
- oop class_loader = loader_data->class_loader();
- if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
- Thread *thread = Thread::current();
- for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
- Handle mirror(thread, l->java_mirror());
- that->set_element(that->get_index(), mirror);
- that->set_index(that->get_index() + 1);
- }
- }
- }
- }
+ jvmtiError get_result(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
+ // Return results by extracting the collected contents into a list
+ // allocated via JvmtiEnv
+ jclass* result_list;
+ jvmtiError error = env->Allocate(get_count() * sizeof(jclass),
+ (unsigned char**)&result_list);
- // increment the count for the given basic type array class (and any
- // multi-dimensional arrays). For example, for [B we check for
- // [[B, [[[B, .. and the count is incremented for each one that exists.
- static void increment_for_basic_type_arrays(Klass* k) {
- JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
- assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
- for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
- that->set_count(that->get_count() + 1);
+ if (error == JVMTI_ERROR_NONE) {
+ int count = extract(result_list);
+ *classCountPtr = count;
+ *classesPtr = result_list;
}
- }
-
- // add the basic type array class and its multi-dimensional array classes to the list
- static void add_for_basic_type_arrays(Klass* k) {
- JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
- assert(that != NULL, "no JvmtiGetLoadedClassesClosure");
- assert(that->available(), "no list");
- Thread *thread = Thread::current();
- for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) {
- Handle mirror(thread, l->java_mirror());
- that->set_element(that->get_index(), mirror);
- that->set_index(that->get_index() + 1);
- }
+ return error;
}
};
-
jvmtiError
JvmtiGetLoadedClasses::getLoadedClasses(JvmtiEnv *env, jint* classCountPtr, jclass** classesPtr) {
- LoadedClassesClosure closure(Thread::current(), env);
+ LoadedClassesClosure closure(env, false);
{
// To get a consistent list of classes we need MultiArray_lock to ensure
// array classes aren't created.
@@ -270,56 +110,35 @@
ClassLoaderDataGraph::loaded_classes_do(&closure);
}
- // Return results by extracting the collected contents into a list
- // allocated via JvmtiEnv
- jclass* result_list;
- jvmtiError error = env->Allocate(closure.get_count() * sizeof(jclass),
- (unsigned char**)&result_list);
-
- if (error == JVMTI_ERROR_NONE) {
- int count = closure.extract(result_list);
- *classCountPtr = count;
- *classesPtr = result_list;
- }
- return error;
+ return closure.get_result(env, classCountPtr, classesPtr);
}
jvmtiError
JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
jint* classCountPtr, jclass** classesPtr) {
- // Since ClassLoaderDataGraph::dictionary_all_entries_do only takes a function pointer
- // and doesn't call back with a closure data pointer,
- // we can only pass static methods.
- JvmtiGetLoadedClassesClosure closure(initiatingLoader);
+
+ LoadedClassesClosure closure(env, true);
{
// To get a consistent list of classes we need MultiArray_lock to ensure
- // array classes aren't created, and SystemDictionary_lock to ensure that
- // classes aren't added to the class loader data dictionaries.
+ // array classes aren't created during this walk.
MutexLocker ma(MultiArray_lock);
MutexLocker sd(SystemDictionary_lock);
- // First, count the classes in the class loader data dictionaries which have this loader recorded
- // as an initiating loader. For basic type arrays this information is not recorded
- // so GetClassLoaderClasses will return all of the basic type arrays. This is okay
- // because the defining loader for basic type arrays is always the boot class loader
- // and these classes are "visible" to all loaders.
- ClassLoaderDataGraph::dictionary_all_entries_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
- Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
- // Next, fill in the classes
- closure.allocate();
- ClassLoaderDataGraph::dictionary_all_entries_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
- Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
- // Drop the SystemDictionary_lock, so the results could be wrong from here,
- // but we still have a snapshot.
+ oop loader = JNIHandles::resolve(initiatingLoader);
+ // All classes loaded from this loader as initiating loader are
+ // requested, so only need to walk this loader's ClassLoaderData
+ // dictionary, or the NULL ClassLoaderData dictionary for bootstrap loader.
+ if (loader != NULL) {
+ ClassLoaderData* data = java_lang_ClassLoader::loader_data(loader);
+ // ClassLoader may not be used yet for loading.
+ if (data != NULL && data->dictionary() != NULL) {
+ data->dictionary()->all_entries_do(&closure);
+ }
+ } else {
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->all_entries_do(&closure);
+ }
+ // Get basic arrays for all loaders.
+ Universe::basic_type_classes_do(&closure);
}
- // Post results
- jclass* result_list;
- jvmtiError err = env->Allocate(closure.get_count() * sizeof(jclass),
- (unsigned char**)&result_list);
- if (err != JVMTI_ERROR_NONE) {
- return err;
- }
- closure.extract(env, result_list);
- *classCountPtr = closure.get_count();
- *classesPtr = result_list;
- return JVMTI_ERROR_NONE;
+
+ return closure.get_result(env, classCountPtr, classesPtr);
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/runtime/deoptimization.cpp
--- a/src/hotspot/share/runtime/deoptimization.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/runtime/deoptimization.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -703,13 +703,12 @@
// a given bytecode or the state after, so we try both
if (!Bytecodes::is_invoke(cur_code) && cur_code != Bytecodes::_athrow) {
// Get expression stack size for the next bytecode
+ InterpreterOopMap next_mask;
+ OopMapCache::compute_one_oop_map(mh, str.bci(), &next_mask);
+ next_mask_expression_stack_size = next_mask.expression_stack_size();
if (Bytecodes::is_invoke(next_code)) {
Bytecode_invoke invoke(mh, str.bci());
- next_mask_expression_stack_size = invoke.size_of_parameters();
- } else {
- InterpreterOopMap next_mask;
- OopMapCache::compute_one_oop_map(mh, str.bci(), &next_mask);
- next_mask_expression_stack_size = next_mask.expression_stack_size();
+ next_mask_expression_stack_size += invoke.size_of_parameters();
}
// Need to subtract off the size of the result type of
// the bytecode because this is not described in the
@@ -739,28 +738,30 @@
(is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute || el->should_reexecute()) &&
(iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size))
)) {
- ttyLocker ttyl;
+ {
+ ttyLocker ttyl;
- // Print out some information that will help us debug the problem
- tty->print_cr("Wrong number of expression stack elements during deoptimization");
- tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1);
- tty->print_cr(" Fabricated interpreter frame had %d expression stack elements",
- iframe->interpreter_frame_expression_stack_size());
- tty->print_cr(" Interpreter oop map had %d expression stack elements", mask.expression_stack_size());
- tty->print_cr(" try_next_mask = %d", try_next_mask);
- tty->print_cr(" next_mask_expression_stack_size = %d", next_mask_expression_stack_size);
- tty->print_cr(" callee_size_of_parameters = %d", callee_size_of_parameters);
- tty->print_cr(" callee_max_locals = %d", callee_max_locals);
- tty->print_cr(" top_frame_expression_stack_adjustment = %d", top_frame_expression_stack_adjustment);
- tty->print_cr(" exec_mode = %d", exec_mode);
- tty->print_cr(" cur_invoke_parameter_size = %d", cur_invoke_parameter_size);
- tty->print_cr(" Thread = " INTPTR_FORMAT ", thread ID = %d", p2i(thread), thread->osthread()->thread_id());
- tty->print_cr(" Interpreted frames:");
- for (int k = 0; k < cur_array->frames(); k++) {
- vframeArrayElement* el = cur_array->element(k);
- tty->print_cr(" %s (bci %d)", el->method()->name_and_sig_as_C_string(), el->bci());
- }
- cur_array->print_on_2(tty);
+ // Print out some information that will help us debug the problem
+ tty->print_cr("Wrong number of expression stack elements during deoptimization");
+ tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1);
+ tty->print_cr(" Fabricated interpreter frame had %d expression stack elements",
+ iframe->interpreter_frame_expression_stack_size());
+ tty->print_cr(" Interpreter oop map had %d expression stack elements", mask.expression_stack_size());
+ tty->print_cr(" try_next_mask = %d", try_next_mask);
+ tty->print_cr(" next_mask_expression_stack_size = %d", next_mask_expression_stack_size);
+ tty->print_cr(" callee_size_of_parameters = %d", callee_size_of_parameters);
+ tty->print_cr(" callee_max_locals = %d", callee_max_locals);
+ tty->print_cr(" top_frame_expression_stack_adjustment = %d", top_frame_expression_stack_adjustment);
+ tty->print_cr(" exec_mode = %d", exec_mode);
+ tty->print_cr(" cur_invoke_parameter_size = %d", cur_invoke_parameter_size);
+ tty->print_cr(" Thread = " INTPTR_FORMAT ", thread ID = %d", p2i(thread), thread->osthread()->thread_id());
+ tty->print_cr(" Interpreted frames:");
+ for (int k = 0; k < cur_array->frames(); k++) {
+ vframeArrayElement* el = cur_array->element(k);
+ tty->print_cr(" %s (bci %d)", el->method()->name_and_sig_as_C_string(), el->bci());
+ }
+ cur_array->print_on_2(tty);
+ } // release tty lock before calling guarantee
guarantee(false, "wrong number of expression stack elements during deopt");
}
VerifyOopClosure verify;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/runtime/frame.cpp
--- a/src/hotspot/share/runtime/frame.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/runtime/frame.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -721,6 +721,14 @@
st->print("v ~ExceptionBlob");
} else if (_cb->is_safepoint_stub()) {
st->print("v ~SafepointBlob");
+ } else if (_cb->is_adapter_blob()) {
+ st->print("v ~AdapterBlob");
+ } else if (_cb->is_vtable_blob()) {
+ st->print("v ~VtableBlob");
+ } else if (_cb->is_method_handles_adapter_blob()) {
+ st->print("v ~MethodHandlesAdapterBlob");
+ } else if (_cb->is_uncommon_trap_stub()) {
+ st->print("v ~UncommonTrapBlob");
} else {
st->print("v blob " PTR_FORMAT, p2i(pc()));
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/runtime/mutexLocker.cpp
--- a/src/hotspot/share/runtime/mutexLocker.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -63,7 +63,7 @@
Mutex* AdapterHandlerLibrary_lock = NULL;
Mutex* SignatureHandlerLibrary_lock = NULL;
Mutex* VtableStubs_lock = NULL;
-Mutex* SymbolTable_lock = NULL;
+Mutex* SymbolArena_lock = NULL;
Mutex* StringTable_lock = NULL;
Monitor* StringDedupQueue_lock = NULL;
Mutex* StringDedupTable_lock = NULL;
@@ -76,6 +76,7 @@
Monitor* Safepoint_lock = NULL;
Monitor* SerializePage_lock = NULL;
Monitor* Threads_lock = NULL;
+Mutex* NamedThreadsList_lock = NULL;
Monitor* CGC_lock = NULL;
Monitor* STS_lock = NULL;
Monitor* FullGCCount_lock = NULL;
@@ -234,9 +235,9 @@
def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always);
def(VMStatistic_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always);
def(ExpandHeap_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // Used during compilation by VM thread
- def(JNIHandleBlockFreeList_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); // handles are used by VM thread
+ def(JNIHandleBlockFreeList_lock , PaddedMutex , leaf-1, true, Monitor::_safepoint_check_never); // handles are used by VM thread
def(SignatureHandlerLibrary_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always);
- def(SymbolTable_lock , PaddedMutex , leaf+2, true, Monitor::_safepoint_check_always);
+ def(SymbolArena_lock , PaddedMutex , leaf+2, true, Monitor::_safepoint_check_never);
def(StringTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always);
def(ProfilePrint_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
def(ExceptionCache_lock , PaddedMutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing
@@ -256,6 +257,7 @@
def(Safepoint_lock , PaddedMonitor, safepoint, true, Monitor::_safepoint_check_sometimes); // locks SnippetCache_lock/Threads_lock
def(Threads_lock , PaddedMonitor, barrier, true, Monitor::_safepoint_check_sometimes);
+ def(NamedThreadsList_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never);
def(VMOperationQueue_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_sometimes); // VM_thread allowed to block on these
def(VMOperationRequest_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_sometimes);
@@ -278,7 +280,7 @@
def(CompileTaskAlloc_lock , PaddedMutex , nonleaf+2, true, Monitor::_safepoint_check_always);
def(CompileStatistics_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always);
def(DirectivesStack_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never);
- def(MultiArray_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock
+ def(MultiArray_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always);
def(JvmtiThreadState_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController
def(Management_lock , PaddedMutex , nonleaf+2, false, Monitor::_safepoint_check_always); // used for JVM management
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/runtime/mutexLocker.hpp
--- a/src/hotspot/share/runtime/mutexLocker.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -57,7 +57,7 @@
extern Mutex* AdapterHandlerLibrary_lock; // a lock on the AdapterHandlerLibrary
extern Mutex* SignatureHandlerLibrary_lock; // a lock on the SignatureHandlerLibrary
extern Mutex* VtableStubs_lock; // a lock on the VtableStubs
-extern Mutex* SymbolTable_lock; // a lock on the symbol table
+extern Mutex* SymbolArena_lock; // a lock on the symbol table arena
extern Mutex* StringTable_lock; // a lock on the interned string table
extern Monitor* StringDedupQueue_lock; // a lock on the string deduplication queue
extern Mutex* StringDedupTable_lock; // a lock on the string deduplication table
@@ -72,6 +72,7 @@
extern Monitor* Safepoint_lock; // a lock used by the safepoint abstraction
extern Monitor* Threads_lock; // a lock on the Threads table of active Java threads
// (also used by Safepoints too to block threads creation/destruction)
+extern Mutex* NamedThreadsList_lock; // a lock on the NamedThreads list
extern Monitor* CGC_lock; // used for coordination between
// fore- & background GC threads.
extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet.
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/runtime/thread.cpp
--- a/src/hotspot/share/runtime/thread.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/runtime/thread.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -114,6 +114,7 @@
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
#include "utilities/preserveException.hpp"
+#include "utilities/singleWriterSynchronizer.hpp"
#include "utilities/vmError.hpp"
#if INCLUDE_JVMCI
#include "jvmci/jvmciCompiler.hpp"
@@ -1206,15 +1207,61 @@
THREAD);
}
+// List of all NamedThreads and safe iteration over that list.
+
+class NamedThread::List {
+public:
+ NamedThread* volatile _head;
+ SingleWriterSynchronizer _protect;
+
+ List() : _head(NULL), _protect() {}
+};
+
+NamedThread::List NamedThread::_the_list;
+
+NamedThread::Iterator::Iterator() :
+ _protect_enter(_the_list._protect.enter()),
+ _current(OrderAccess::load_acquire(&_the_list._head))
+{}
+
+NamedThread::Iterator::~Iterator() {
+ _the_list._protect.exit(_protect_enter);
+}
+
+void NamedThread::Iterator::step() {
+ assert(!end(), "precondition");
+ _current = OrderAccess::load_acquire(&_current->_next_named_thread);
+}
+
// NamedThread -- non-JavaThread subclasses with multiple
// uniquely named instances should derive from this.
-NamedThread::NamedThread() : Thread() {
- _name = NULL;
- _processed_thread = NULL;
- _gc_id = GCId::undefined();
+NamedThread::NamedThread() :
+ Thread(),
+ _name(NULL),
+ _processed_thread(NULL),
+ _gc_id(GCId::undefined()),
+ _next_named_thread(NULL)
+{
+ // Add this thread to _the_list.
+ MutexLockerEx lock(NamedThreadsList_lock, Mutex::_no_safepoint_check_flag);
+ _next_named_thread = _the_list._head;
+ OrderAccess::release_store(&_the_list._head, this);
}
NamedThread::~NamedThread() {
+ // Remove this thread from _the_list.
+ {
+ MutexLockerEx lock(NamedThreadsList_lock, Mutex::_no_safepoint_check_flag);
+ NamedThread* volatile* p = &_the_list._head;
+ for (NamedThread* t = *p; t != NULL; p = &t->_next_named_thread, t = *p) {
+ if (t == this) {
+ *p = this->_next_named_thread;
+ // Wait for any in-progress iterators.
+ _the_list._protect.synchronize();
+ break;
+ }
+ }
+ }
if (_name != NULL) {
FREE_C_HEAP_ARRAY(char, _name);
_name = NULL;
@@ -1520,7 +1567,6 @@
_is_method_handle_return = 0;
_jvmti_thread_state= NULL;
_should_post_on_exceptions_flag = JNI_FALSE;
- _jvmti_get_loaded_classes_closure = NULL;
_interp_only_mode = 0;
_special_runtime_exit_condition = _no_async_condition;
_pending_async_exception = NULL;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/runtime/thread.hpp
--- a/src/hotspot/share/runtime/thread.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/runtime/thread.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -63,7 +63,6 @@
class ThreadsSMRSupport;
class JvmtiThreadState;
-class JvmtiGetLoadedClassesClosure;
class ThreadStatistics;
class ConcurrentLocksDump;
class ParkEvent;
@@ -103,6 +102,7 @@
// - JavaThread
// - various subclasses eg CompilerThread, ServiceThread
// - WatcherThread
+// - JfrSamplerThread
class Thread: public ThreadShadow {
friend class VMStructs;
@@ -776,6 +776,10 @@
// log JavaThread being processed by oops_do
JavaThread* _processed_thread;
uint _gc_id; // The current GC id when a thread takes part in GC
+ NamedThread* volatile _next_named_thread;
+
+ class List;
+ static List _the_list;
public:
NamedThread();
@@ -791,6 +795,31 @@
void set_gc_id(uint gc_id) { _gc_id = gc_id; }
uint gc_id() { return _gc_id; }
+
+ class Iterator;
+};
+
+// Provides iteration over the list of NamedThreads. Because list
+// management occurs in the NamedThread constructor and destructor,
+// entries in the list may not be fully constructed instances of a
+// derived class. Threads created after an iterator is constructed
+// will not be visited by the iterator. The scope of an iterator is a
+// critical section; there must be no safepoint checks in that scope.
+class NamedThread::Iterator : public StackObj {
+ uint _protect_enter;
+ NamedThread* _current;
+
+ // Noncopyable.
+ Iterator(const Iterator&);
+ Iterator& operator=(const Iterator&);
+
+public:
+ Iterator();
+ ~Iterator();
+
+ bool end() const { return _current == NULL; }
+ NamedThread* current() const { return _current; }
+ void step();
};
// Worker threads are named and have an id of an assigned work.
@@ -1855,8 +1884,6 @@
// the specified JavaThread is exiting.
JvmtiThreadState *jvmti_thread_state() const { return _jvmti_thread_state; }
static ByteSize jvmti_thread_state_offset() { return byte_offset_of(JavaThread, _jvmti_thread_state); }
- void set_jvmti_get_loaded_classes_closure(JvmtiGetLoadedClassesClosure* value) { _jvmti_get_loaded_classes_closure = value; }
- JvmtiGetLoadedClassesClosure* get_jvmti_get_loaded_classes_closure() const { return _jvmti_get_loaded_classes_closure; }
// JVMTI PopFrame support
// Setting and clearing popframe_condition
@@ -1908,7 +1935,6 @@
private:
JvmtiThreadState *_jvmti_thread_state;
- JvmtiGetLoadedClassesClosure* _jvmti_get_loaded_classes_closure;
// Used by the interpreter in fullspeed mode for frame pop, method
// entry, method exit and single stepping support. This field is
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/utilities/globalCounter.cpp
--- a/src/hotspot/share/utilities/globalCounter.cpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/utilities/globalCounter.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -71,5 +71,7 @@
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
ctc.do_thread(thread);
}
- ctc.do_thread(VMThread::vm_thread());
+ for (NamedThread::Iterator nti; !nti.end(); nti.step()) {
+ ctc.do_thread(nti.current());
+ }
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/utilities/globalCounter.inline.hpp
--- a/src/hotspot/share/utilities/globalCounter.inline.hpp Mon Aug 27 16:01:38 2018 -0400
+++ b/src/hotspot/share/utilities/globalCounter.inline.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -31,16 +31,16 @@
inline void GlobalCounter::critical_section_begin(Thread *thread) {
assert(thread == Thread::current(), "must be current thread");
- assert(thread->is_VM_thread() || thread->is_Java_thread(), "must be VMThread or JavaThread");
- assert((*thread->get_rcu_counter() & COUNTER_ACTIVE) == 0x0, "nestled critical sections, not supported yet");
+ assert(thread->is_Named_thread() || thread->is_Java_thread(), "must be NamedThread or JavaThread");
+ assert((*thread->get_rcu_counter() & COUNTER_ACTIVE) == 0x0, "nested critical sections, not supported yet");
uintx gbl_cnt = OrderAccess::load_acquire(&_global_counter._counter);
OrderAccess::release_store_fence(thread->get_rcu_counter(), gbl_cnt | COUNTER_ACTIVE);
}
inline void GlobalCounter::critical_section_end(Thread *thread) {
assert(thread == Thread::current(), "must be current thread");
- assert(thread->is_VM_thread() || thread->is_Java_thread(), "must be VMThread or JavaThread");
- assert((*thread->get_rcu_counter() & COUNTER_ACTIVE) == COUNTER_ACTIVE, "must be in ctitical section");
+ assert(thread->is_Named_thread() || thread->is_Java_thread(), "must be NamedThread or JavaThread");
+ assert((*thread->get_rcu_counter() & COUNTER_ACTIVE) == COUNTER_ACTIVE, "must be in critical section");
// Mainly for debugging we set it to 'now'.
uintx gbl_cnt = OrderAccess::load_acquire(&_global_counter._counter);
OrderAccess::release_store(thread->get_rcu_counter(), gbl_cnt);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/utilities/singleWriterSynchronizer.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/utilities/singleWriterSynchronizer.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/singleWriterSynchronizer.hpp"
+#include "utilities/macros.hpp"
+
+SingleWriterSynchronizer::SingleWriterSynchronizer() :
+ _enter(0),
+ _exit(),
+ // The initial value of 1 for _waiting_for puts it on the inactive
+ // track, so no thread exiting a critical section will match it.
+ _waiting_for(1),
+ _wakeup()
+ DEBUG_ONLY(COMMA _writers(0))
+{}
+
+// Wait until all threads that entered a critical section before
+// synchronization have exited that critical section.
+void SingleWriterSynchronizer::synchronize() {
+ // Side-effect in assert balanced by debug-only dec at end.
+ assert(Atomic::add(1u, &_writers) == 1u, "multiple writers");
+ // We don't know anything about the muxing between this invocation
+ // and invocations in other threads. We must start with the latest
+ // _enter polarity, else we could clobber the wrong _exit value on
+ // the first iteration. So fence to ensure everything here follows
+ // whatever muxing was used.
+ OrderAccess::fence();
+ uint value = _enter;
+ // (1) Determine the old and new exit counters, based on the
+ // polarity (bit0 value) of the on-entry enter counter.
+ volatile uint* new_ptr = &_exit[(value + 1) & 1];
+ // (2) Change the in-use exit counter to the new counter, by adding
+ // 1 to the enter counter (flipping the polarity), meanwhile
+ // "simultaneously" initializing the new exit counter to that enter
+ // value. Note: The new exit counter is not being used by read
+ // operations until this change of _enter succeeds.
+ uint old;
+ do {
+ old = value;
+ *new_ptr = ++value;
+ value = Atomic::cmpxchg(value, &_enter, old);
+ } while (old != value);
+ // Critical sections entered before we changed the polarity will use
+ // the old exit counter. Critical sections entered after the change
+ // will use the new exit counter.
+ volatile uint* old_ptr = &_exit[old & 1];
+ assert(old_ptr != new_ptr, "invariant");
+ // (3) Inform threads in in-progress critical sections that there is
+ // a pending synchronize waiting. The thread that completes the
+ // request (_exit value == old) will signal the _wakeup semaphore to
+ // allow us to proceed.
+ _waiting_for = old;
+ // Write of _waiting_for must precede read of _exit and associated
+ // conditional semaphore wait. If they were re-ordered then a
+ // critical section exit could miss the wakeup request, failing to
+ // signal us while we're waiting.
+ OrderAccess::fence();
+ // (4) Wait for all the critical sections started before the change
+ // to complete, e.g. for the value of old_ptr to catch up with old.
+ // Loop because there could be pending wakeups unrelated to this
+ // synchronize request.
+ while (old != OrderAccess::load_acquire(old_ptr)) {
+ _wakeup.wait();
+ }
+ // (5) Drain any pending wakeups. A critical section exit may have
+ // completed our request and seen our _waiting_for before we checked
+ // for completion. There are also possible (though rare) spurious
+ // wakeup signals in the timing gap between changing the _enter
+ // polarity and setting _waiting_for. Enough of any of those could
+ // lead to semaphore overflow. This doesn't guarantee no unrelated
+ // wakeups for the next wait, but prevents unbounded accumulation.
+ while (_wakeup.trywait()) {}
+ DEBUG_ONLY(Atomic::dec(&_writers);)
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/hotspot/share/utilities/singleWriterSynchronizer.hpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/utilities/singleWriterSynchronizer.hpp Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP
+#define SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/semaphore.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+
+// Synchronization primitive inspired by RCU.
+//
+// Any number of threads may enter critical sections associated with a
+// synchronizer object. One (at a time) other thread may wait for the
+// completion of all critical sections for the synchronizer object
+// that were extent when the wait was initiated. Usage is that there
+// is some state that can be accessed either before or after some
+// change. An accessing thread performs the access within a critical
+// section. A writer thread performs the state change, and then waits
+// for critical sections to complete, thereby ensuring there are no
+// threads in a critical section that might have seen the old state.
+//
+// Generally, GlobalCounter should be used instead of this class, as
+// GlobalCounter has measurably better performance and doesn't have
+// the single writer at a time restriction. Use this only in
+// situations where GlobalCounter won't work for some reason, such as
+// nesting. But note that nesting often indicates other problems, and
+// may risk deadlock.
+class SingleWriterSynchronizer {
+ volatile uint _enter;
+ volatile uint _exit[2];
+ volatile uint _waiting_for;
+ Semaphore _wakeup;
+
+ DEBUG_ONLY(volatile uint _writers;)
+
+ // Noncopyable.
+ SingleWriterSynchronizer(const SingleWriterSynchronizer&);
+ SingleWriterSynchronizer& operator=(const SingleWriterSynchronizer&);
+
+public:
+ SingleWriterSynchronizer();
+
+ // Enter a critical section for this synchronizer. Entering a
+ // critical section never blocks. While in a critical section, a
+ // thread should avoid blocking, or even take a long time. In
+ // particular, a thread must never safepoint while in a critical
+ // section.
+ // Precondition: The current thread must not already be in a
+ // critical section for this synchronizer.
+ inline uint enter();
+
+ // Exit a critical section for this synchronizer.
+ // Precondition: enter_value must be the result of the corresponding
+ // enter() for the critical section.
+ inline void exit(uint enter_value);
+
+ // Wait until all threads currently in a critical section for this
+ // synchronizer have exited their critical section. Threads that
+ // enter a critical section after the synchronization has started
+ // are not considered in the wait.
+ // Precondition: No other thread may be synchronizing on this
+ // synchronizer.
+ void synchronize();
+
+ // RAII class for managing enter/exit pairs.
+ class CriticalSection;
+};
+
+inline uint SingleWriterSynchronizer::enter() {
+ return Atomic::add(2u, &_enter);
+}
+
+inline void SingleWriterSynchronizer::exit(uint enter_value) {
+ uint exit_value = Atomic::add(2u, &_exit[enter_value & 1]);
+ // If this exit completes a synchronize request, wakeup possibly
+ // waiting synchronizer. Read of _waiting_for must follow the _exit
+ // update.
+ if (exit_value == _waiting_for) {
+ _wakeup.signal();
+ }
+}
+
+class SingleWriterSynchronizer::CriticalSection : public StackObj {
+ SingleWriterSynchronizer* _synchronizer;
+ uint _enter_value;
+
+public:
+ // Enter synchronizer's critical section.
+ explicit CriticalSection(SingleWriterSynchronizer* synchronizer) :
+ _synchronizer(synchronizer),
+ _enter_value(synchronizer->enter())
+ {}
+
+ // Exit synchronizer's critical section.
+ ~CriticalSection() {
+ _synchronizer->exit(_enter_value);
+ }
+};
+
+#endif // SHARE_UTILITIES_SINGLEWRITERSYNCHRONIZER_HPP
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/share/classes/java/io/FileSystem.java
--- a/src/java.base/share/classes/java/io/FileSystem.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/share/classes/java/io/FileSystem.java Mon Aug 27 16:02:55 2018 -0400
@@ -231,18 +231,16 @@
// Flags for enabling/disabling performance optimizations for file
// name canonicalization
- static boolean useCanonCaches;
- static boolean useCanonPrefixCache;
+ static final boolean useCanonCaches;
+ static final boolean useCanonPrefixCache;
private static boolean getBooleanProperty(String prop, boolean defaultVal) {
- return Boolean.parseBoolean(System.getProperty(prop,
- String.valueOf(defaultVal)));
+ String value = System.getProperty(prop);
+ return (value != null) ? Boolean.parseBoolean(value) : defaultVal;
}
static {
- useCanonCaches = getBooleanProperty("sun.io.useCanonCaches",
- useCanonCaches);
- useCanonPrefixCache = getBooleanProperty("sun.io.useCanonPrefixCache",
- useCanonPrefixCache);
+ useCanonCaches = getBooleanProperty("sun.io.useCanonCaches", false);
+ useCanonPrefixCache = useCanonCaches && getBooleanProperty("sun.io.useCanonPrefixCache", false);
}
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/share/classes/java/lang/Integer.java
--- a/src/java.base/share/classes/java/lang/Integer.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Integer.java Mon Aug 27 16:02:55 2018 -0400
@@ -1654,15 +1654,15 @@
*/
@HotSpotIntrinsicCandidate
public static int numberOfTrailingZeros(int i) {
- // HD, Figure 5-14
- int y;
- if (i == 0) return 32;
- int n = 31;
- y = i <<16; if (y != 0) { n = n -16; i = y; }
- y = i << 8; if (y != 0) { n = n - 8; i = y; }
- y = i << 4; if (y != 0) { n = n - 4; i = y; }
- y = i << 2; if (y != 0) { n = n - 2; i = y; }
- return n - ((i << 1) >>> 31);
+ // HD, Count trailing 0's
+ i = ~i & (i - 1);
+ if (i <= 0) return i & 32;
+ int n = 1;
+ if (i > 1 << 16) { n += 16; i >>>= 16; }
+ if (i > 1 << 8) { n += 8; i >>>= 8; }
+ if (i > 1 << 4) { n += 4; i >>>= 4; }
+ if (i > 1 << 2) { n += 2; i >>>= 2; }
+ return n + (i >>> 1);
}
/**
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/share/classes/java/lang/Long.java
--- a/src/java.base/share/classes/java/lang/Long.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/share/classes/java/lang/Long.java Mon Aug 27 16:02:55 2018 -0400
@@ -1782,16 +1782,9 @@
*/
@HotSpotIntrinsicCandidate
public static int numberOfTrailingZeros(long i) {
- // HD, Figure 5-14
- int x, y;
- if (i == 0) return 64;
- int n = 63;
- y = (int)i; if (y != 0) { n = n -32; x = y; } else x = (int)(i>>>32);
- y = x <<16; if (y != 0) { n = n -16; x = y; }
- y = x << 8; if (y != 0) { n = n - 8; x = y; }
- y = x << 4; if (y != 0) { n = n - 4; x = y; }
- y = x << 2; if (y != 0) { n = n - 2; x = y; }
- return n - ((x << 1) >>> 31);
+ int x = (int)i;
+ return x == 0 ? 32 + Integer.numberOfTrailingZeros((int)(i >>> 32))
+ : Integer.numberOfTrailingZeros(x);
}
/**
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/share/classes/module-info.java
--- a/src/java.base/share/classes/module-info.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/share/classes/module-info.java Mon Aug 27 16:02:55 2018 -0400
@@ -284,8 +284,6 @@
java.naming;
exports sun.security.rsa to
jdk.crypto.cryptoki;
- exports sun.security.ssl to
- java.security.jgss;
exports sun.security.timestamp to
jdk.jartool;
exports sun.security.tools to
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/share/classes/sun/security/provider/DSA.java
--- a/src/java.base/share/classes/sun/security/provider/DSA.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/share/classes/sun/security/provider/DSA.java Mon Aug 27 16:02:55 2018 -0400
@@ -152,7 +152,7 @@
// check key size against hash output size for signing
// skip this check for verification to minimize impact on existing apps
- if (md.getAlgorithm() != "NullDigest20") {
+ if (!"NullDigest20".equals(md.getAlgorithm())) {
checkKey(params, md.getDigestLength()*8, md.getAlgorithm());
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/share/classes/sun/security/ssl/SSLExtensions.java
--- a/src/java.base/share/classes/sun/security/ssl/SSLExtensions.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SSLExtensions.java Mon Aug 27 16:02:55 2018 -0400
@@ -43,7 +43,7 @@
// Extension map for debug logging
private final Map logMap =
- SSLLogger.isOn ? null : new LinkedHashMap<>();
+ SSLLogger.isOn ? new LinkedHashMap<>() : null;
SSLExtensions(HandshakeMessage handshakeMessage) {
this.handshakeMessage = handshakeMessage;
@@ -65,38 +65,59 @@
"): no sufficient data");
}
+ boolean isSupported = true;
SSLHandshake handshakeType = hm.handshakeType();
if (SSLExtension.isConsumable(extId) &&
SSLExtension.valueOf(handshakeType, extId) == null) {
- hm.handshakeContext.conContext.fatal(
+ if (extId == SSLExtension.CH_SUPPORTED_GROUPS.id &&
+ handshakeType == SSLHandshake.SERVER_HELLO) {
+ // Note: It does not comply to the specification. However,
+ // there are servers that send the supported_groups
+ // extension in ServerHello handshake message.
+ //
+ // TLS 1.3 should not send this extension. We may want to
+ // limit the workaround for TLS 1.2 and prior version only.
+ // However, the implementation of the limit is complicated
+ // and inefficient, and may not worthy the maintenance.
+ isSupported = false;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.warning(
+ "Received buggy supported_groups extension " +
+ "in the ServerHello handshake message");
+ }
+ } else {
+ hm.handshakeContext.conContext.fatal(
Alert.UNSUPPORTED_EXTENSION,
"extension (" + extId +
") should not be presented in " + handshakeType.name);
+ }
}
- boolean isSupported = false;
- for (SSLExtension extension : extensions) {
- if ((extension.id != extId) ||
- (extension.onLoadConsumer == null)) {
- continue;
- }
+ if (isSupported) {
+ isSupported = false;
+ for (SSLExtension extension : extensions) {
+ if ((extension.id != extId) ||
+ (extension.onLoadConsumer == null)) {
+ continue;
+ }
- if (extension.handshakeType != handshakeType) {
- hm.handshakeContext.conContext.fatal(
- Alert.UNSUPPORTED_EXTENSION,
- "extension (" + extId + ") should not be " +
- "presented in " + handshakeType.name);
- }
+ if (extension.handshakeType != handshakeType) {
+ hm.handshakeContext.conContext.fatal(
+ Alert.UNSUPPORTED_EXTENSION,
+ "extension (" + extId + ") should not be " +
+ "presented in " + handshakeType.name);
+ }
- byte[] extData = new byte[extLen];
- m.get(extData);
- extMap.put(extension, extData);
- if (logMap != null) {
- logMap.put(extId, extData);
+ byte[] extData = new byte[extLen];
+ m.get(extData);
+ extMap.put(extension, extData);
+ if (logMap != null) {
+ logMap.put(extId, extData);
+ }
+
+ isSupported = true;
+ break;
}
-
- isSupported = true;
- break;
}
if (!isSupported) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/unix/classes/java/io/UnixFileSystem.java
--- a/src/java.base/unix/classes/java/io/UnixFileSystem.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/unix/classes/java/io/UnixFileSystem.java Mon Aug 27 16:02:55 2018 -0400
@@ -44,6 +44,8 @@
colon = props.getProperty("path.separator").charAt(0);
javaHome = StaticProperty.javaHome();
userDir = StaticProperty.userDir();
+ cache = useCanonCaches ? new ExpiringCache() : null;
+ javaHomePrefixCache = useCanonPrefixCache ? new ExpiringCache() : null;
}
@@ -145,11 +147,11 @@
// same directory, and must not create results differing from the true
// canonicalization algorithm in canonicalize_md.c. For this reason the
// prefix cache is conservative and is not used for complex path names.
- private ExpiringCache cache = new ExpiringCache();
+ private final ExpiringCache cache;
// On Unix symlinks can jump anywhere in the file system, so we only
// treat prefixes in java.home as trusted and cacheable in the
// canonicalization algorithm
- private ExpiringCache javaHomePrefixCache = new ExpiringCache();
+ private final ExpiringCache javaHomePrefixCache;
public String canonicalize(String path) throws IOException {
if (!useCanonCaches) {
@@ -158,7 +160,7 @@
String res = cache.get(path);
if (res == null) {
String dir = null;
- String resDir = null;
+ String resDir;
if (useCanonPrefixCache) {
// Note that this can cause symlinks that should
// be resolved to a destination directory to be
@@ -266,8 +268,12 @@
// (i.e., only remove/update affected entries) but probably
// not worth it since these entries expire after 30 seconds
// anyway.
- cache.clear();
- javaHomePrefixCache.clear();
+ if (useCanonCaches) {
+ cache.clear();
+ }
+ if (useCanonPrefixCache) {
+ javaHomePrefixCache.clear();
+ }
return delete0(f);
}
private native boolean delete0(File f);
@@ -279,8 +285,12 @@
// (i.e., only remove/update affected entries) but probably
// not worth it since these entries expire after 30 seconds
// anyway.
- cache.clear();
- javaHomePrefixCache.clear();
+ if (useCanonCaches) {
+ cache.clear();
+ }
+ if (useCanonPrefixCache) {
+ javaHomePrefixCache.clear();
+ }
return rename0(f1, f2);
}
private native boolean rename0(File f1, File f2);
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.base/windows/classes/java/io/WinNTFileSystem.java
--- a/src/java.base/windows/classes/java/io/WinNTFileSystem.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.base/windows/classes/java/io/WinNTFileSystem.java Mon Aug 27 16:02:55 2018 -0400
@@ -51,6 +51,8 @@
semicolon = props.getProperty("path.separator").charAt(0);
altSlash = (this.slash == '\\') ? '/' : '\\';
userDir = normalize(props.getProperty("user.dir"));
+ cache = useCanonCaches ? new ExpiringCache() : null;
+ prefixCache = useCanonPrefixCache ? new ExpiringCache() : null;
}
private boolean isSlash(char c) {
@@ -387,8 +389,8 @@
// same directory, and must not create results differing from the true
// canonicalization algorithm in canonicalize_md.c. For this reason the
// prefix cache is conservative and is not used for complex path names.
- private ExpiringCache cache = new ExpiringCache();
- private ExpiringCache prefixCache = new ExpiringCache();
+ private final ExpiringCache cache;
+ private final ExpiringCache prefixCache;
@Override
public String canonicalize(String path) throws IOException {
@@ -568,8 +570,12 @@
// (i.e., only remove/update affected entries) but probably
// not worth it since these entries expire after 30 seconds
// anyway.
- cache.clear();
- prefixCache.clear();
+ if (useCanonCaches) {
+ cache.clear();
+ }
+ if (useCanonPrefixCache) {
+ prefixCache.clear();
+ }
return delete0(f);
}
@@ -582,8 +588,12 @@
// (i.e., only remove/update affected entries) but probably
// not worth it since these entries expire after 30 seconds
// anyway.
- cache.clear();
- prefixCache.clear();
+ if (useCanonCaches) {
+ cache.clear();
+ }
+ if (useCanonPrefixCache) {
+ prefixCache.clear();
+ }
return rename0(f1, f2);
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.logging/share/classes/java/util/logging/Level.java
--- a/src/java.logging/share/classes/java/util/logging/Level.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.logging/share/classes/java/util/logging/Level.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -610,10 +610,7 @@
}
private static void registerWithClassLoader(Level customLevel) {
- PrivilegedAction pa =
- () -> customLevel.getClass().getClassLoader();
- PrivilegedAction pn = customLevel.getClass()::getName;
- final String name = AccessController.doPrivileged(pn);
+ PrivilegedAction pa = customLevel.getClass()::getClassLoader;
final ClassLoader cl = AccessController.doPrivileged(pa);
CUSTOM_LEVEL_CLV.computeIfAbsent(cl, (c, v) -> new ArrayList<>())
.add(customLevel);
@@ -624,19 +621,10 @@
// the mirroredLevel object is always added to the list
// before the custom Level instance
KnownLevel o = new KnownLevel(l);
- List list = nameToLevels.get(l.name);
- if (list == null) {
- list = new ArrayList<>();
- nameToLevels.put(l.name, list);
- }
- list.add(o);
-
- list = intToLevels.get(l.value);
- if (list == null) {
- list = new ArrayList<>();
- intToLevels.put(l.value, list);
- }
- list.add(o);
+ nameToLevels.computeIfAbsent(l.name, (k) -> new ArrayList<>())
+ .add(o);
+ intToLevels.computeIfAbsent(l.value, (k) -> new ArrayList<>())
+ .add(o);
// keep the custom level reachable from its class loader
// This will ensure that custom level values are not GC'ed
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.smartcardio/share/classes/sun/security/smartcardio/ChannelImpl.java
--- a/src/java.smartcardio/share/classes/sun/security/smartcardio/ChannelImpl.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.smartcardio/share/classes/sun/security/smartcardio/ChannelImpl.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -188,7 +188,7 @@
byte[] response = SCardTransmit
(card.cardId, card.protocol, command, 0, n);
int rn = response.length;
- if (getresponse && (rn >= 2)) {
+ if (getresponse && (rn >= 2) && (n >= 1)) {
// see ISO 7816/2005, 5.1.3
if ((rn == 2) && (response[0] == 0x6c)) {
// Resend command using SW2 as short Le field
@@ -201,6 +201,11 @@
if (rn > 2) {
result = concat(result, response, rn - 2);
}
+ if (command.length < 5) {
+ byte cla = command[0];
+ command = new byte[5];
+ command[0] = cla;
+ }
command[1] = (byte)0xC0;
command[2] = 0;
command[3] = 0;
@@ -208,7 +213,6 @@
n = 5;
continue;
}
-
}
result = concat(result, response, rn);
break;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/java.xml/share/classes/javax/xml/validation/Validator.java
--- a/src/java.xml/share/classes/javax/xml/validation/Validator.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/java.xml/share/classes/javax/xml/validation/Validator.java Mon Aug 27 16:02:55 2018 -0400
@@ -214,7 +214,7 @@
*
* @throws IllegalArgumentException
* If the {@code Result} type doesn't match the
- * {@code Source} type of if the {@code Source}
+ * {@code Source} type or if the {@code Source}
* is an XML artifact that the implementation cannot
* validate (for example, a processing instruction).
* @throws SAXException
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -539,7 +539,13 @@
}
nameSimplifier.addUsage(t.tsym);
visit(t.getTypeArguments());
- if (t.getEnclosingType() != Type.noType)
+ Type enclosingType;
+ try {
+ enclosingType = t.getEnclosingType();
+ } catch (CompletionFailure cf) {
+ return null;
+ }
+ if (enclosingType != Type.noType)
visit(t.getEnclosingType());
return null;
}
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/x86/LinuxX86CFrame.java Mon Aug 27 16:02:55 2018 -0400
@@ -55,7 +55,15 @@
public CFrame sender(ThreadProxy thread) {
X86ThreadContext context = (X86ThreadContext) thread.getContext();
- Address esp = context.getRegisterAsAddress(X86ThreadContext.ESP);
+ /*
+ * Native code fills in the stack pointer register value using index
+ * X86ThreadContext.SP.
+ * See file LinuxDebuggerLocal.c macro REG_INDEX(reg).
+ *
+ * Be sure to use SP, or UESP which is aliased to SP in Java code,
+ * for the frame pointer validity check.
+ */
+ Address esp = context.getRegisterAsAddress(X86ThreadContext.SP);
if ( (ebp == null) || ebp.lessThan(esp) ) {
return null;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windows/x86/WindowsX86CFrame.java
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windows/x86/WindowsX86CFrame.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windows/x86/WindowsX86CFrame.java Mon Aug 27 16:02:55 2018 -0400
@@ -46,7 +46,15 @@
public CFrame sender(ThreadProxy thread) {
X86ThreadContext context = (X86ThreadContext) thread.getContext();
- Address esp = context.getRegisterAsAddress(X86ThreadContext.ESP);
+ /*
+ * Native code fills in the stack pointer register value using index
+ * X86ThreadContext.SP.
+ * See file sawindbg.cpp macro REG_INDEX(x).
+ *
+ * Be sure to use SP, or UESP which is aliased to SP in Java code,
+ * for the frame pointer validity check.
+ */
+ Address esp = context.getRegisterAsAddress(X86ThreadContext.SP);
if ( (ebp == null) || ebp.lessThan(esp) ) {
return null;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Symbol.java
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Symbol.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Symbol.java Mon Aug 27 16:02:55 2018 -0400
@@ -80,15 +80,16 @@
// _identity_hash is a short
private static CIntegerField idHash;
- public int identityHash() {
+ public long identityHash() {
long addr_value = getAddress().asLongValue();
- int addr_bits = (int)(addr_value >> (VM.getVM().getLogMinObjAlignmentInBytes() + 3));
+ long addr_bits =
+ (addr_value >> (VM.getVM().getLogMinObjAlignmentInBytes() + 3)) & 0xffffffffL;
int length = (int)getLength();
int byte0 = getByteAt(0);
int byte1 = getByteAt(1);
- int id_hash = (int)(0xffff & idHash.getValue(this.addr));
- return id_hash |
- ((addr_bits ^ (length << 8) ^ ((byte0 << 8) | byte1)) << 16);
+ long id_hash = 0xffffL & (long)idHash.getValue(this.addr);
+ return (id_hash |
+ ((addr_bits ^ (length << 8) ^ ((byte0 << 8) | byte1)) << 16)) & 0xffffffffL;
}
public boolean equals(byte[] modUTF8Chars) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,8 +49,8 @@
return HashtableEntry.class;
}
- public int computeHash(Symbol name) {
- return (int) name.identityHash();
+ public long computeHash(Symbol name) {
+ return name.identityHash();
}
public int hashToIndex(long fullHash) {
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
package jdk.vm.ci.hotspot;
import jdk.vm.ci.meta.JavaMethodProfile;
diff -r 41e17fe9fbeb -r 6668bbc41155 src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java Mon Aug 27 16:01:38 2018 -0400
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,3 +1,28 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
package jdk.jfr.internal;
import java.util.HashMap;
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/gtest/utilities/test_singleWriterSynchronizer.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/utilities/test_singleWriterSynchronizer.cpp Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/orderAccess.hpp"
+#include "runtime/os.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalCounter.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
+#include "utilities/singleWriterSynchronizer.hpp"
+#include "threadHelper.inline.hpp"
+#include "unittest.hpp"
+
+class SingleWriterSynchronizerTestReader : public JavaTestThread {
+ SingleWriterSynchronizer* _synchronizer;
+ volatile uintx* _synchronized_value;
+ volatile int* _continue_running;
+
+ static const uint reader_iterations = 10;
+
+public:
+ SingleWriterSynchronizerTestReader(Semaphore* post,
+ SingleWriterSynchronizer* synchronizer,
+ volatile uintx* synchronized_value,
+ volatile int* continue_running) :
+ JavaTestThread(post),
+ _synchronizer(synchronizer),
+ _synchronized_value(synchronized_value),
+ _continue_running(continue_running)
+ {}
+
+ virtual void main_run() {
+ uintx iterations = 0;
+ while (OrderAccess::load_acquire(_continue_running) != 0) {
+ ++iterations;
+ SingleWriterSynchronizer::CriticalSection cs(_synchronizer);
+ uintx value = OrderAccess::load_acquire(_synchronized_value);
+ for (uint i = 0; i < reader_iterations; ++i) {
+ uintx new_value = OrderAccess::load_acquire(_synchronized_value);
+ // A reader can see either the value it first read after
+ // entering the critical section, or that value + 1. No other
+ // values are possible.
+ if (value != new_value) {
+ ASSERT_EQ((value + 1), new_value);
+ }
+ }
+ }
+ tty->print_cr("reader iterations: " UINTX_FORMAT, iterations);
+ }
+};
+
+class SingleWriterSynchronizerTestWriter : public JavaTestThread {
+ SingleWriterSynchronizer* _synchronizer;
+ volatile uintx* _synchronized_value;
+ volatile int* _continue_running;
+
+public:
+ SingleWriterSynchronizerTestWriter(Semaphore* post,
+ SingleWriterSynchronizer* synchronizer,
+ volatile uintx* synchronized_value,
+ volatile int* continue_running) :
+ JavaTestThread(post),
+ _synchronizer(synchronizer),
+ _synchronized_value(synchronized_value),
+ _continue_running(continue_running)
+ {}
+
+ virtual void main_run() {
+ while (OrderAccess::load_acquire(_continue_running) != 0) {
+ ++*_synchronized_value;
+ _synchronizer->synchronize();
+ }
+ tty->print_cr("writer iterations: " UINTX_FORMAT, *_synchronized_value);
+ }
+};
+
+const uint nreaders = 5;
+const uint milliseconds_to_run = 3000;
+
+TEST_VM(TestSingleWriterSynchronizer, stress) {
+ Semaphore post;
+ SingleWriterSynchronizer synchronizer;
+ volatile uintx synchronized_value = 0;
+ volatile int continue_running = 1;
+
+ JavaTestThread* readers[nreaders] = {};
+ for (uint i = 0; i < nreaders; ++i) {
+ readers[i] = new SingleWriterSynchronizerTestReader(&post,
+ &synchronizer,
+ &synchronized_value,
+ &continue_running);
+ readers[i]->doit();
+ }
+
+ JavaTestThread* writer =
+ new SingleWriterSynchronizerTestWriter(&post,
+ &synchronizer,
+ &synchronized_value,
+ &continue_running);
+
+ writer->doit();
+
+ tty->print_cr("Stressing synchronizer for %u ms", milliseconds_to_run);
+ {
+ ThreadInVMfromNative invm(JavaThread::current());
+ os::sleep(Thread::current(), milliseconds_to_run, true);
+ }
+ continue_running = 0;
+ for (uint i = 0; i < nreaders + 1; ++i) {
+ post.wait();
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/ProblemList-cds-mode.txt
--- a/test/hotspot/jtreg/ProblemList-cds-mode.txt Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/ProblemList-cds-mode.txt Mon Aug 27 16:02:55 2018 -0400
@@ -27,5 +27,3 @@
#
#############################################################################
-serviceability/sa/TestInstanceKlassSize.java 8204308 generic-all
-serviceability/sa/TestInstanceKlassSizeForInterface.java 8204308 generic-all
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/ProblemList.txt
--- a/test/hotspot/jtreg/ProblemList.txt Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/ProblemList.txt Mon Aug 27 16:02:55 2018 -0400
@@ -83,6 +83,7 @@
runtime/CompressedOops/UseCompressedOops.java 8079353 generic-all
runtime/RedefineTests/RedefineRunningMethods.java 8208778 macosx-x64
runtime/SharedArchiveFile/SASymbolTableTest.java 8193639 solaris-all
+runtime/MemberName/MemberNameLeak.java 8209844 generic-all
#############################################################################
@@ -91,6 +92,7 @@
serviceability/sa/ClhsdbAttach.java 8193639 solaris-all
serviceability/sa/ClhsdbCDSCore.java 8193639 solaris-all
serviceability/sa/ClhsdbCDSJstackPrintAll.java 8193639 solaris-all
+serviceability/sa/CDSJMapClstats.java 8193639 solaris-all
serviceability/sa/ClhsdbField.java 8193639 solaris-all
serviceability/sa/ClhsdbFindPC.java 8193639 solaris-all
serviceability/sa/ClhsdbFlags.java 8193639 solaris-all
@@ -179,7 +181,6 @@
vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java 6606767 generic-all
vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java 7013634,6606767 generic-all
vmTestbase/nsk/jvmti/ThreadStart/threadstart001/TestDescription.java 8016181 generic-all
-vmTestbase/nsk/jvmti/ThreadStart/threadstart003/TestDescription.java 8034084 generic-all
vmTestbase/nsk/jvmti/scenarios/extension/EX03/ex03t001/TestDescription.java 8173658 generic-all
vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t002/TestDescription.java 8204506,8203350 generic-all
vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t001/hs204t001.java 6813266 generic-all
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/compiler/c2/SubsumingLoadsCauseFlagSpill.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/c2/SubsumingLoadsCauseFlagSpill.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8209639
+ * @summary assert failure in coalesce.cpp: attempted to spill a non-spillable item
+ *
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,SubsumingLoadsCauseFlagSpill::not_inlined -Xmx1024m SubsumingLoadsCauseFlagSpill
+ *
+ */
+
+public class SubsumingLoadsCauseFlagSpill {
+ private static Object field;
+ private static boolean do_throw;
+ private static volatile boolean barrier;
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 20_000; i++) {
+ do_throw = true;
+ field = null;
+ test(0);
+ do_throw = false;
+ field = new Object();
+ test(0);
+ }
+ }
+
+ private static float test(float f) {
+ Object v = null;
+ try {
+ not_inlined();
+ v = field;
+ } catch (MyException me) {
+ v = field;
+ barrier = true;
+ }
+ if (v == null) {
+ return f * f;
+ }
+ return f;
+ }
+
+ private static void not_inlined() throws MyException{
+ if (do_throw) {
+ throw new MyException();
+ }
+ }
+
+ private static class MyException extends Throwable {
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/compiler/interpreter/TestVerifyStackAfterDeopt.java
--- a/test/hotspot/jtreg/compiler/interpreter/TestVerifyStackAfterDeopt.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/compiler/interpreter/TestVerifyStackAfterDeopt.java Mon Aug 27 16:02:55 2018 -0400
@@ -25,8 +25,10 @@
/*
* @test TestVerifyStackAfterDeopt
* @bug 8148871
+ * @bug 8209825
* @summary Checks VerifyStack after deoptimization of array allocation slow call
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TieredStopAtLevel=1
+ * -XX:MinTLABSize=1k -XX:TLABSize=1k
* -XX:+DeoptimizeALot -XX:+VerifyStack
* compiler.interpreter.TestVerifyStackAfterDeopt
*/
@@ -35,9 +37,11 @@
public class TestVerifyStackAfterDeopt {
- private void method(Object[] a) {
+ private long method(long l1, long l2, Object[] a) {
+ return l1 + l2;
+ }
- }
+ private long result[] = new long[1];
private void test() {
// For the array allocation, C1 emits a slow call into the runtime
@@ -45,7 +49,7 @@
// The VerifyStack code then gets confused because the following
// bytecode instruction is an invoke and the interpreter oop map
// generator reports the oop map after execution of that invoke.
- method(new Object[0]);
+ this.result[0] = method(1L, 2L, new Object[0]);
}
public static void main(String[] args) {
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java
--- a/test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* @library /test/lib
*
* @run main/othervm -XX:-TieredCompilation -Xbatch
- * -XX:CompileCommand=compileonly,compiler.intrinsics.object.TestClone::f
+ * -XX:CompileCommand=compileonly,compiler.intrinsics.object.TestClone::test*
* compiler.intrinsics.object.TestClone
*/
@@ -37,6 +37,43 @@
import jdk.test.lib.Asserts;
+abstract class MyAbstract {
+
+ public Object myClone1() throws CloneNotSupportedException {
+ return this.clone();
+ }
+
+ public Object myClone2() throws CloneNotSupportedException {
+ return this.clone();
+ }
+
+ public Object myClone3() throws CloneNotSupportedException {
+ return this.clone();
+ }
+}
+
+class MyClass1 extends MyAbstract {
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+}
+
+class MyClass2 extends MyAbstract {
+
+}
+
+class MyClass3 extends MyAbstract implements Cloneable {
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+}
+
+class MyClass4 extends MyAbstract implements Cloneable {
+
+}
+
public class TestClone implements Cloneable {
static class A extends TestClone {}
static class B extends TestClone {
@@ -56,29 +93,70 @@
}
static TestClone a = new A(), b = new B(), c = new C(), d = new D();
- public static Object f(TestClone o) throws CloneNotSupportedException {
+ public static Object test1(TestClone o) throws CloneNotSupportedException {
// Polymorphic call site: >90% Object::clone / <10% other methods
return o.clone();
}
+ public static void test2(MyAbstract obj, boolean shouldThrow) throws Exception {
+ try {
+ obj.myClone1();
+ } catch (Exception e) {
+ return; // Expected
+ }
+ Asserts.assertFalse(shouldThrow, "No exception thrown");
+ }
+
+ public static void test3(MyAbstract obj, boolean shouldThrow) throws Exception {
+ try {
+ obj.myClone2();
+ } catch (Exception e) {
+ return; // Expected
+ }
+ Asserts.assertFalse(shouldThrow, "No exception thrown");
+ }
+
+ public static void test4(MyAbstract obj, boolean shouldThrow) throws Exception {
+ try {
+ obj.myClone3();
+ } catch (Exception e) {
+ return; // Expected
+ }
+ Asserts.assertFalse(shouldThrow, "No exception thrown");
+ }
+
public static void main(String[] args) throws Exception {
TestClone[] params1 = {a, a, a, a, a, a, a, a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a,
b, c, d};
+ MyClass1 obj1 = new MyClass1();
+ MyClass2 obj2 = new MyClass2();
+ MyClass3 obj3 = new MyClass3();
+ MyClass4 obj4 = new MyClass4();
+
for (int i = 0; i < 15000; i++) {
- f(params1[i % params1.length]);
+ test1(params1[i % params1.length]);
+
+ test2(obj1, true);
+ test2(obj2, true);
+
+ test3(obj3, false);
+ test3(obj2, true);
+
+ test4(obj3, false);
+ test4(obj4, false);
}
- Asserts.assertTrue(f(a) != a);
- Asserts.assertTrue(f(b) == b);
- Asserts.assertTrue(f(c) == c);
- Asserts.assertTrue(f(d) == d);
+ Asserts.assertTrue(test1(a) != a);
+ Asserts.assertTrue(test1(b) == b);
+ Asserts.assertTrue(test1(c) == c);
+ Asserts.assertTrue(test1(d) == d);
try {
- f(null);
- throw new AssertionError("");
+ test1(null);
+ throw new AssertionError("No exception thrown");
} catch (NullPointerException e) { /* expected */ }
System.out.println("TEST PASSED");
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/HelloExtTest.java
--- a/test/hotspot/jtreg/runtime/appcds/HelloExtTest.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/HelloExtTest.java Mon Aug 27 16:02:55 2018 -0400
@@ -52,7 +52,7 @@
TestCommon.dump(appJar,
TestCommon.list("javax/annotation/processing/FilerException", "[Ljava/lang/Comparable;"),
- bootClassPath, "-verbose:class");
+ bootClassPath);
String prefix = ".class.load. ";
String class_pattern = ".*LambdaForm[$]MH[/][0123456789].*";
@@ -60,12 +60,12 @@
String pattern = prefix + class_pattern + suffix;
TestCommon.run("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "-cp", appJar, bootClassPath, "-verbose:class", "HelloExt")
+ "-cp", appJar, bootClassPath, "-Xlog:class+load", "HelloExt")
.assertNormalExit(output -> output.shouldNotMatch(pattern));
TestCommon.run("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "-cp", appJar, bootClassPath, "-verbose:class",
+ "-cp", appJar, bootClassPath, "-Xlog:class+load",
"-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary",
"HelloExt")
.assertNormalExit(output -> output.shouldNotMatch(class_pattern));
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/OldClassTest.java
--- a/test/hotspot/jtreg/runtime/appcds/OldClassTest.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/OldClassTest.java Mon Aug 27 16:02:55 2018 -0400
@@ -67,7 +67,6 @@
TestCommon.run(
"-cp", jar,
- "-verbose:class",
"Hello")
.assertNormalExit("Hello Unicode world (Old)");
@@ -79,7 +78,6 @@
TestCommon.run(
"-cp", classpath,
- "-verbose:class",
"Hello")
.assertNormalExit("Hello Unicode world (Old)");
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java
--- a/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java Mon Aug 27 16:02:55 2018 -0400
@@ -79,20 +79,20 @@
// -Xshare:on
TestCommon.run(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper")
+ "-cp", appJar, "ProhibitedHelper")
.assertNormalExit("Prohibited package name: java.lang");
// -Xshare:auto
output = TestCommon.execAuto(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper");
+ "-cp", appJar, "ProhibitedHelper");
CDSOptions opts = (new CDSOptions()).setXShareMode("auto");
TestCommon.checkExec(output, opts, "Prohibited package name: java.lang");
// -Xshare:off
output = TestCommon.execOff(
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "-cp", appJar, "-Xlog:class+load=info", "ProhibitedHelper");
+ "-cp", appJar, "ProhibitedHelper");
output.shouldContain("Prohibited package name: java.lang");
}
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java
--- a/test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/ProtectionDomain.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,16 +57,16 @@
OutputAnalyzer output;
// First class is loaded from CDS, second class is loaded from JAR
- output = TestCommon.exec(appJar, "-verbose:class", "ProtDomain");
+ output = TestCommon.exec(appJar, "ProtDomain");
TestCommon.checkExec(output, "Protection Domains match");
// First class is loaded from JAR, second class is loaded from CDS
- output = TestCommon.exec(appJar, "-verbose:class", "ProtDomainB");
+ output = TestCommon.exec(appJar, "ProtDomainB");
TestCommon.checkExec(output, "Protection Domains match");
// Test ProtectionDomain for application and extension module classes from the
// "modules" jimage
- output = TestCommon.exec(appJar, "-verbose:class", "JimageClassProtDomain");
+ output = TestCommon.exec(appJar, "JimageClassProtDomain");
output.shouldNotContain("Failed: Protection Domains do not match");
}
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassTest.java
--- a/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassTest.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/RedefineClassTest.java Mon Aug 27 16:02:55 2018 -0400
@@ -34,7 +34,7 @@
* RedefineClassApp
* InstrumentationClassFileTransformer
* InstrumentationRegisterClassFileTransformer
- * @run main/othervm RedefineClassTest
+ * @run main RedefineClassTest
*/
import com.sun.tools.attach.VirtualMachine;
@@ -89,7 +89,7 @@
bootCP,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
- "-Xlog:gc+region=trace,cds=info",
+ "-Xlog:cds=info",
agentCmdArg,
"RedefineClassApp", bootJar, appJar);
out.reportDiagnosticSummary();
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/javaldr/ArrayTest.java
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/ArrayTest.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/javaldr/ArrayTest.java Mon Aug 27 16:02:55 2018 -0400
@@ -57,7 +57,7 @@
String bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar;
// create an archive containing array classes
- OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list(arrayClasses), bootClassPath, "-verbose:class");
+ OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list(arrayClasses), bootClassPath);
// we currently don't support array classes during CDS dump
output.shouldContain("Preload Warning: Cannot find [Ljava/lang/Comparable;")
.shouldContain("Preload Warning: Cannot find [I")
@@ -70,7 +70,6 @@
argsList.add("-cp");
argsList.add(appJar);
argsList.add(bootClassPath);
- argsList.add("-verbose:class");
argsList.add("ArrayTestHelper");
// the following are input args to the ArrayTestHelper.
// skip checking array classes during run time
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDump.java
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDump.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDump.java Mon Aug 27 16:02:55 2018 -0400
@@ -56,7 +56,8 @@
String appJar =
ClassFileInstaller.writeJar("GCDuringDumpApp.jar", appClasses);
- String gcLog = "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug";
+ String gcLog = Boolean.getBoolean("test.cds.verbose.gc") ?
+ "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug" : "-showversion";
for (int i=0; i<2; i++) {
// i = 0 -- run without agent = no extra GCs
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.java
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCDuringDumpTransformer.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,13 +28,8 @@
import java.security.ProtectionDomain;
public class GCDuringDumpTransformer implements ClassFileTransformer {
- static int n = 0;
public byte[] transform(ClassLoader loader, String name, Class> classBeingRedefined,
ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException {
- n++;
-
- System.out.println("dump time loading: " + name + " in loader: " + loader);
- System.out.println("making garbage: " + n);
try {
makeGarbage();
} catch (Throwable t) {
@@ -43,7 +38,6 @@
Thread.sleep(200); // let GC to have a chance to run
} catch (Throwable t2) {}
}
- System.out.println("making garbage: done");
return null;
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDump.java
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDump.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/javaldr/GCSharedStringsDuringDump.java Mon Aug 27 16:02:55 2018 -0400
@@ -62,7 +62,8 @@
String appJar =
ClassFileInstaller.writeJar("GCSharedStringsDuringDumpApp.jar", appClasses);
- String gcLog = "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug";
+ String gcLog = Boolean.getBoolean("test.cds.verbose.gc") ?
+ "-Xlog:gc*=info,gc+region=trace,gc+alloc+region=debug" : "-showversion";
String sharedArchiveCfgFile =
System.getProperty("user.dir") + File.separator + "GCSharedStringDuringDump_gen.txt";
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java Mon Aug 27 16:02:55 2018 -0400
@@ -87,7 +87,6 @@
// the class in the modular jar in the -cp won't be archived.
OutputAnalyzer output = TestCommon.createArchive(
destJar.toString(), appClasses,
- "-Xlog:class+load=trace",
"--module-path", moduleDir.toString(),
"-m", TEST_MODULE1);
TestCommon.checkDump(output);
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java Mon Aug 27 16:02:55 2018 -0400
@@ -118,7 +118,6 @@
// the module in the --module-path
OutputAnalyzer output = TestCommon.createArchive(
appJar.toString(), appClasses,
- "-Xlog:class+load=trace",
"--module-path", moduleDir.toString(),
"--add-modules", TEST_MODULE2, MAIN_CLASS);
TestCommon.checkDump(output);
@@ -142,7 +141,6 @@
// unnmaed.
output = TestCommon.createArchive(
appJar2.toString(), appClasses2,
- "-Xlog:class+load=trace",
"--module-path", moduleDir.toString(),
"--add-modules", TEST_MODULE2,
"--add-exports", "org.astro/org.astro=ALL-UNNAMED",
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java Mon Aug 27 16:02:55 2018 -0400
@@ -113,7 +113,6 @@
appJar,
TestCommon.list("JvmtiApp", "ExtraClass", MAIN_CLASS),
use_whitebox_jar,
- "-Xlog:class+load=trace",
modulePath);
TestCommon.checkDump(output);
@@ -143,7 +142,6 @@
output = TestCommon.createArchive(
appJar, TestCommon.list("JvmtiApp", "ExtraClass"),
use_whitebox_jar,
- "-Xlog:class+load=trace",
modulePath);
TestCommon.checkDump(output);
run(twoAppJars, modulePath,
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java Mon Aug 27 16:02:55 2018 -0400
@@ -90,7 +90,6 @@
// the class in the modular jar in the -cp won't be archived.
OutputAnalyzer output = TestCommon.createArchive(
destJar.toString(), appClasses,
- "-Xlog:class+load=trace",
"--module-path", moduleDir.toString(),
"-m", TEST_MODULE1);
TestCommon.checkDump(output);
@@ -169,8 +168,7 @@
// run with the archive and the jar with modified timestamp.
// It should fail due to timestamp of the jar doesn't match the one
// used during dump time.
- TestCommon.run("-Xlog:class+load=trace",
- "-cp", destJar.toString(),
+ TestCommon.run("-cp", destJar.toString(),
"--module-path", moduleDir.toString(),
"-m", TEST_MODULE1)
.assertAbnormalExit(
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java Mon Aug 27 16:02:55 2018 -0400
@@ -188,7 +188,6 @@
TestCommon.run("-Xlog:class+load=info",
"-cp", appJar,
- "--add-opens=java.base/java.security=ALL-UNNAMED",
agentParam,
"CustomLoaderApp",
customJar, loaderType, child)
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java
--- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java Mon Aug 27 16:02:55 2018 -0400
@@ -29,15 +29,11 @@
* @requires vm.cds.archived.java.heap
* @requires (vm.gc=="null")
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
- * @modules java.base/jdk.internal.misc
- * @modules java.management
- * jdk.jartool/sun.tools.jar
+ * @modules jdk.jartool/sun.tools.jar
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @build HelloString
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. IncompatibleOptions
- * @run main/othervm -XX:+UseStringDeduplication -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. IncompatibleOptions
- * @run main/othervm -XX:-CompactStrings -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. IncompatibleOptions
*/
import jdk.test.lib.Asserts;
@@ -59,8 +55,10 @@
"The shared archive file's CompactStrings setting .* does not equal the current CompactStrings setting";
static String appJar;
+ static String[] globalVmOptions;
public static void main(String[] args) throws Exception {
+ globalVmOptions = args; // specified by "@run main" in IncompatibleOptions_*.java
appJar = JarBuilder.build("IncompatibleOptions", "HelloString");
// Uncompressed OOPs
@@ -116,14 +114,16 @@
System.out.println("Testcase: " + testCaseNr);
OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello"),
- "-XX:+UseCompressedOops",
- collectorOption,
- "-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("SharedStringsBasic.txt"),
- "-Xlog:cds,cds+hashtables",
- extraOption);
+ TestCommon.concat(globalVmOptions,
+ "-XX:+UseCompressedOops",
+ collectorOption,
+ "-XX:SharedArchiveConfigFile=" + TestCommon.getSourceFile("SharedStringsBasic.txt"),
+ "-Xlog:cds,cds+hashtables",
+ extraOption));
- if (expectedWarning != null)
+ if (expectedWarning != null) {
output.shouldContain(expectedWarning);
+ }
if (expectedToFail) {
Asserts.assertNE(output.getExitValue(), 0,
@@ -140,19 +140,25 @@
// needed, otherwise system considers empty extra option as a
// main class param, and fails with "Could not find or load main class"
if (!extraOption.isEmpty()) {
- output = TestCommon.exec(appJar, "-XX:+UseCompressedOops",
- collectorOption, "-Xlog:cds", extraOption, "HelloString");
+ output = TestCommon.exec(appJar,
+ TestCommon.concat(globalVmOptions,
+ "-XX:+UseCompressedOops",
+ collectorOption, "-Xlog:cds", extraOption, "HelloString"));
} else {
- output = TestCommon.exec(appJar, "-XX:+UseCompressedOops",
- collectorOption, "-Xlog:cds", "HelloString");
+ output = TestCommon.exec(appJar,
+ TestCommon.concat(globalVmOptions,
+ "-XX:+UseCompressedOops",
+ collectorOption, "-Xlog:cds", "HelloString"));
}
- if (expectedWarning != null)
+ if (expectedWarning != null) {
output.shouldMatch(expectedWarning);
+ }
- if (expectedToFail)
+ if (expectedToFail) {
Asserts.assertNE(output.getExitValue(), 0);
- else
+ } else {
SharedStringsUtils.checkExec(output);
+ }
}
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions_noCompactStrings.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions_noCompactStrings.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test options that are incompatible with use of shared strings
+ * Also test mismatch in oops encoding between dump time and run time
+ * @requires vm.cds.archived.java.heap
+ * @requires (vm.gc=="null")
+ * @library /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.jartool/sun.tools.jar
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @build HelloString
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. IncompatibleOptions -XX:-CompactStrings
+ */
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions_stringDedup.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions_stringDedup.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test options that are incompatible with use of shared strings
+ * Also test mismatch in oops encoding between dump time and run time
+ * @requires vm.cds.archived.java.heap
+ * @requires (vm.gc=="null")
+ * @library /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.jartool/sun.tools.jar
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @build HelloString
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. IncompatibleOptions -XX:+UseStringDeduplication
+ */
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/runtime/logging/RedefineClasses.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8197901 8209758
+ * @summary Redefine classes with enabling logging to verify Klass:external_name() during GC.
+ * @comment This test is simplified version of runtime/RedefineTests/RedefineRunningMethods.java.
+ * @library /test/lib
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -Xlog:all=trace:file=all.log RedefineClasses
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineClasses_B {
+ public static void test() {
+ }
+}
+
+public class RedefineClasses {
+ static Object[] obj = new Object[20];
+ public static String newB =
+ "class RedefineClasses_B {" +
+ " public static void test() { " +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ RedefineClassHelper.redefineClass(RedefineClasses_B.class, newB);
+ RedefineClasses_B.test();
+ for (int i = 0; i < 20 ; i++) {
+ obj[i] = new byte[1024 * 1024];
+ System.gc();
+ }
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8204308
+ * @summary Test the jhsdb jmap -clstats command with CDS enabled
+ * @requires vm.hasSAandCanAttach & vm.cds
+ * @library /test/lib
+ * @run main/othervm/timeout=2400 CDSJMapClstats
+ */
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.JDKToolLauncher;
+
+public class CDSJMapClstats {
+
+ private static void runClstats(long lingeredAppPid) throws Exception {
+
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+ launcher.addToolArg("jmap");
+ launcher.addToolArg("--clstats");
+ launcher.addToolArg("--pid");
+ launcher.addToolArg(Long.toString(lingeredAppPid));
+
+ ProcessBuilder processBuilder = new ProcessBuilder();
+ processBuilder.command(launcher.getCommand());
+ System.out.println(
+ processBuilder.command().stream().collect(Collectors.joining(" ")));
+
+ OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
+ System.out.println(SAOutput.getOutput());
+ SAOutput.shouldHaveExitValue(0);
+ SAOutput.shouldContain("BootClassLoader");
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Starting CDSJMapClstats test");
+ String sharedArchiveName = "ArchiveForCDSJMapClstats.jsa";
+ LingeredApp theApp = null;
+
+ try {
+ CDSOptions opts = (new CDSOptions()).setArchiveName(sharedArchiveName);
+ CDSTestUtils.createArchiveAndCheck(opts);
+
+ List vmArgs = Arrays.asList(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + sharedArchiveName,
+ "-Xshare:auto");
+ theApp = LingeredApp.startApp(vmArgs);
+ System.out.println("Started LingeredApp with pid " + theApp.getPid());
+ runClstats(theApp.getPid());
+ } catch (Exception ex) {
+ throw new RuntimeException("Test ERROR " + ex, ex);
+ } finally {
+ LingeredApp.stopApp(theApp);
+ }
+ System.out.println("Test PASSED");
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/serviceability/sa/LingeredAppWithNativeMethod.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithNativeMethod.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,74 @@
+
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.apps.LingeredApp;
+
+public class LingeredAppWithNativeMethod extends LingeredApp {
+
+ public static final String THREAD_NAME = "NoFramePointerJNIFib";
+ private static final int UPPER_BOUND = 55;
+ private static final int LOWER_BOUND = 40;
+
+ static {
+ // JNI library compiled with no frame pointer info
+ System.loadLibrary("NoFramePointer");
+ }
+
+ public void callNative() {
+ // Call JNI code which does something compute
+ // intensive: fibonacci
+ // That is to ensure that the native bits run when
+ // jstack --mixed info is to be gathered.
+ // Results of fibonacci calculation from JNI are
+ // reported via callback(). That's where the process
+ // of calculating fibonacci restarts.
+ int num = (int) (Math.random() * UPPER_BOUND);
+ while (num < LOWER_BOUND) {
+ num = (int) (Math.random() * UPPER_BOUND);
+ }
+ System.out.print("fib(" + num + ") = ");
+ callJNI(this, num);
+ }
+
+ // Called from JNI library libNoFramePointer
+ private void callback(long val) {
+ System.out.println(val);
+ // Call native again so as to increase chances of
+ // being currently in JNI code when jstack --mixed
+ // runs.
+ callNative();
+ }
+
+ public static native void callJNI(Object target, int num);
+
+ public static void main(String[] args) {
+ LingeredAppWithNativeMethod app = new LingeredAppWithNativeMethod();
+ Thread fibonacci = new Thread(() -> {
+ app.callNative();
+ });
+ fibonacci.setName(THREAD_NAME);
+ fibonacci.start();
+ LingeredApp.main(args);
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Utils;
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/**
+ * @test
+ * @bug 8208091
+ * @requires (os.family == "linux") & (vm.hasSAandCanAttach)
+ * @library /test/lib
+ * @run main/othervm TestJhsdbJstackMixed
+ */
+public class TestJhsdbJstackMixed {
+
+ private static final int MAX_ITERATIONS = 20;
+ private static final String NATIVE_FUNCTION_NAME = "fib";
+ private static final String LINE_MATCHER_STR = ".*" + NATIVE_FUNCTION_NAME
+ + ".*";
+ private static final Pattern LINE_PATTERN = Pattern
+ .compile(LINE_MATCHER_STR);
+ private static final String HEX_STR_PATTERN = "0x([a-fA-F0-9]+)";
+ private static final String FIB_SPLIT_PATTERN = NATIVE_FUNCTION_NAME
+ + "\\s+\\+";
+ private static final Pattern HEX_PATTERN = Pattern.compile(HEX_STR_PATTERN);
+ private static final int ADDRESS_ALIGNMENT_X86 = 4;
+
+ /*
+ * UnmappedAddressException will be thrown iff:
+ * - The JNI code is being compiled with -fomit-frame-pointer AND
+ * - The JNI code is currently executing at address A = pc() + offset
+ * where A % ADDRESS_SIZE == 0.
+ *
+ * In the below example we have: pc() == f6401546, offset == 56,
+ * ADDRESS_SIZE == 4. Thus, A == F640159C which satisfies this condition.
+ *
+ * "NoFramePointerJNIFib" #11 prio=5 tid=0xa357bc00 nid=0x6de9 runnable [0xa365b000]
+ * java.lang.Thread.State: RUNNABLE
+ * JavaThread state: _thread_in_native
+ * 0xf6401546 fib + 0x56
+ */
+ private static boolean isFibAndAlignedAddress(List lines) {
+ List fibLines = findFibLines(lines);
+ System.out.println("DEBUG: " + fibLines);
+ // we're only interested in the first matched line.
+ if (fibLines.size() >= 1) {
+ String line = fibLines.get(0);
+ return isMatchLine(line);
+ }
+ return false;
+ }
+
+ private static boolean isMatchLine(String line) {
+ String[] tokens = line.split(FIB_SPLIT_PATTERN);
+ if (tokens.length != 2) {
+ return false; // NOT exactly two tokens, ignore.
+ }
+ String pcRaw = tokens[0].trim();
+ String offsetRaw = tokens[1].trim();
+ Matcher matcher = HEX_PATTERN.matcher(pcRaw);
+ long pcVal = 3;
+ boolean pcMatched = matcher.matches();
+ if (pcMatched) {
+ String pc = matcher.group(1);
+ pcVal = Long.parseUnsignedLong(pc, 16);
+ }
+ matcher = HEX_PATTERN.matcher(offsetRaw);
+ long offsetVal = 0;
+ boolean offsetMatched = matcher.matches();
+ if (offsetMatched) {
+ String offset = matcher.group(1);
+ offsetVal = Long.parseUnsignedLong(offset, 16);
+ }
+ if (offsetMatched && pcMatched
+ && (pcVal + offsetVal) % ADDRESS_ALIGNMENT_X86 == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ private static List findFibLines(List lines) {
+ boolean startReached = false;
+ boolean endReached = false;
+ List interestingLines = new ArrayList<>();
+ for (String line : lines) {
+ if (line.contains(LingeredAppWithNativeMethod.THREAD_NAME)) {
+ startReached = true;
+ }
+ if (startReached && line.contains("-------")) {
+ endReached = true;
+ }
+ if (startReached && !endReached) {
+ Matcher matcher = LINE_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ interestingLines.add(line);
+ }
+ }
+ }
+ return interestingLines;
+ }
+
+ private static void runJstackMixedInLoop(LingeredApp app) throws Exception {
+ for (int i = 0; i < MAX_ITERATIONS; i++) {
+ JDKToolLauncher launcher = JDKToolLauncher
+ .createUsingTestJDK("jhsdb");
+ launcher.addToolArg("jstack");
+ launcher.addToolArg("--mixed");
+ launcher.addToolArg("--pid");
+ launcher.addToolArg(Long.toString(app.getPid()));
+
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(launcher.getCommand());
+ Process jhsdb = pb.start();
+ OutputAnalyzer out = new OutputAnalyzer(jhsdb);
+
+ jhsdb.waitFor();
+
+ System.out.println(out.getStdout());
+ System.err.println(out.getStderr());
+
+ out.shouldContain(LingeredAppWithNativeMethod.THREAD_NAME);
+ if (isFibAndAlignedAddress(out.asLines())) {
+ System.out.println("DEBUG: Test triggered interesting condition.");
+ out.shouldNotContain("sun.jvm.hotspot.debugger.UnmappedAddressException:");
+ System.out.println("DEBUG: Test PASSED.");
+ return; // If we've reached here, all is well.
+ }
+ System.out.println("DEBUG: Iteration: " + (i + 1)
+ + " - Test didn't trigger interesting condition.");
+ out.shouldNotContain("sun.jvm.hotspot.debugger.UnmappedAddressException:");
+ }
+ System.out.println("DEBUG: Test didn't trigger interesting condition " +
+ "but no UnmappedAddressException was thrown. PASS!");
+ }
+
+ public static void main(String... args) throws Exception {
+
+ LingeredApp app = null;
+
+ try {
+ List vmArgs = new ArrayList(Utils.getVmOptions());
+ // Needed for LingeredApp to be able to resolve native library.
+ String libPath = System.getProperty("java.library.path");
+ if (libPath != null) {
+ vmArgs.add("-Djava.library.path=" + libPath);
+ }
+
+ app = new LingeredAppWithNativeMethod();
+ LingeredApp.startApp(vmArgs, app);
+ System.out.println("Started LingeredApp with pid " + app.getPid());
+ runJstackMixedInLoop(app);
+ System.out.println("Test Completed");
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ LingeredApp.stopApp(app);
+ }
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/serviceability/sa/libNoFramePointer.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/libNoFramePointer.c Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+static jlong fib(jint num) {
+ if (num == 0) {
+ return 0;
+ }
+ if (num <= 2) {
+ return 1;
+ }
+ return fib(num - 2) + fib(num -1);
+}
+
+static void callCallback(JNIEnv *env, jclass cls, jobject target, jlong result) {
+ jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(J)V");
+ if (mid == NULL) {
+ jclass nsme = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env, "java/lang/NoSuchMethodException"));
+ if (nsme != NULL) {
+ (*env)->ThrowNew(env, nsme, "Can't find method callback()");
+ }
+ return;
+ }
+ (*env)->CallVoidMethod(env, target, mid, result);
+}
+
+static void calculateAndCallCallback(JNIEnv *env, jclass cls, jobject target, jint num) {
+ jlong result = -1;
+ result = fib(num);
+ callCallback(env, cls, target, result);
+}
+
+JNIEXPORT void JNICALL
+Java_LingeredAppWithNativeMethod_callJNI(JNIEnv *env, jclass cls, jobject target, jint num) {
+ calculateAndCallCallback(env, cls, target, num);
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/hotspot/jtreg/vmTestbase/nsk/jvmti/ThreadStart/threadstart003/threadstart003.c
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ThreadStart/threadstart003/threadstart003.c Mon Aug 27 16:01:38 2018 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ThreadStart/threadstart003/threadstart003.c Mon Aug 27 16:02:55 2018 -0400
@@ -216,7 +216,7 @@
TranslateError(err), err);
result = STATUS_FAILED;
}
- err = (*jvmti)->RawMonitorWait(jvmti, wait_lock, (jlong)WAIT_TIME);
+ err = (*jvmti)->RawMonitorWait(jvmti, wait_lock, 0);
if (err != JVMTI_ERROR_NONE) {
printf("(RawMonitorWait) unexpected error: %s (%d)\n",
TranslateError(err), err);
@@ -235,7 +235,16 @@
TranslateError(err), err);
result = STATUS_FAILED;
}
- err = (*jvmti)->RawMonitorWait(jvmti, wait_lock, (jlong)WAIT_TIME);
+ // Wait for up to 3 seconds for the thread end event
+ {
+ int i;
+ for (i = 0; i < 3 ; i++) {
+ err = (*jvmti)->RawMonitorWait(jvmti, wait_lock, (jlong)WAIT_TIME);
+ if (endsCount == endsExpected || err != JVMTI_ERROR_NONE) {
+ break;
+ }
+ }
+ }
if (err != JVMTI_ERROR_NONE) {
printf("(RawMonitorWait) unexpected error: %s (%d)\n",
TranslateError(err), err);
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,8 +59,6 @@
import java.util.Hashtable;
import java.util.Locale;
-import static java.lang.Math.abs;
-
import org.netbeans.jemmy.CharBindingMap;
import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.ComponentSearcher;
@@ -1222,6 +1220,48 @@
}
/**
+ * Wait till the component reaches exact location on screen.
+ *
+ * @param exactLocation exact expected screen location.
+ */
+ public void waitComponentLocationOnScreen(Point exactlocation) {
+ waitComponentLocationOnScreen(exactlocation, exactlocation);
+ }
+
+ /**
+ * Wait till the component location on screen reaches between minLocation
+ * and maxLocation
+ *
+ * @param minLocation minimum expected location on screen.
+ * @param maxLocation maximum expected location on screen.
+ */
+ public void waitComponentLocationOnScreen(
+ final Point minLocation, final Point maxLocation) {
+ waitState(new ComponentChooser() {
+ @Override
+ public boolean checkComponent(Component comp) {
+ Point location = comp.getLocationOnScreen();
+ return location.x >= minLocation.x
+ && location.x <= maxLocation.x
+ && location.y >= minLocation.y
+ && location.y <= maxLocation.y;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Component location on screen reaches between :"
+ + minLocation + "and " + maxLocation;
+ }
+
+ @Override
+ public String toString() {
+ return "ComponentOperator.waitComponentLocationOnScreen"
+ + ".Waitable{description = " + getDescription() + '}';
+ }
+ });
+ }
+
+ /**
* Returns information about component.
*/
@Override
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComponentOperator.java
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComponentOperator.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JComponentOperator.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,6 @@
import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.ComponentSearcher;
-import org.netbeans.jemmy.JemmyProperties;
import org.netbeans.jemmy.Outputable;
import org.netbeans.jemmy.TestOut;
import org.netbeans.jemmy.TimeoutExpiredException;
@@ -307,15 +306,7 @@
}
public JToolTip waitToolTip() {
- return ((JToolTip) waitComponent(WindowOperator.
- waitWindow(new JToolTipWindowFinder(),
- 0,
- getTimeouts(),
- getOutput()),
- new JToolTipFinder(),
- 0,
- getTimeouts(),
- getOutput()));
+ return JToolTipOperator.waitJToolTip(this);
}
/**
@@ -1228,61 +1219,4 @@
}
}
- static class JToolTipWindowFinder implements ComponentChooser {
-
- ComponentChooser ppFinder;
-
- public JToolTipWindowFinder() {
- ppFinder = new ComponentChooser() {
- @Override
- public boolean checkComponent(Component comp) {
- return (comp.isShowing()
- && comp.isVisible()
- && comp instanceof JToolTip);
- }
-
- @Override
- public String getDescription() {
- return "A tool tip";
- }
-
- @Override
- public String toString() {
- return "JComponentOperator.JToolTipWindowFinder.ComponentChooser{description = " + getDescription() + '}';
- }
- };
- }
-
- @Override
- public boolean checkComponent(Component comp) {
- if (comp.isShowing() && comp instanceof Window) {
- ComponentSearcher cs = new ComponentSearcher((Container) comp);
- cs.setOutput(JemmyProperties.getCurrentOutput().createErrorOutput());
- return (cs.findComponent(ppFinder)
- != null);
- }
- return false;
- }
-
- @Override
- public String getDescription() {
- return "A tool tip window";
- }
-
- @Override
- public String toString() {
- return "JToolTipWindowFinder{" + "ppFinder=" + ppFinder + '}';
- }
- }
-
- class JToolTipFinder extends Finder {
-
- public JToolTipFinder(ComponentChooser sf) {
- super(JToolTip.class, sf);
- }
-
- public JToolTipFinder() {
- super(JToolTip.class);
- }
- }
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JToolTipOperator.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JToolTipOperator.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.netbeans.jemmy.operators;
+
+import java.awt.Component;
+import java.awt.Window;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.swing.JComponent;
+import javax.swing.JToolTip;
+import javax.swing.plaf.ToolTipUI;
+
+import org.netbeans.jemmy.ComponentChooser;
+import org.netbeans.jemmy.ComponentSearcher;
+import org.netbeans.jemmy.TimeoutExpiredException;
+import org.netbeans.jemmy.Waitable;
+
+/**
+ *
+ *
+ * Timeouts used:
+ * {@code ComponentOperator.WaitComponentTimeout} - time to wait component
+ * displayed.
+ * {@code ComponentOperator.WaitStateTimeout} - time to wait for tip text.
+ *
+ * @see org.netbeans.jemmy.Timeouts
+ */
+public class JToolTipOperator extends JComponentOperator {
+
+ /**
+ * Identifier for a "tip text" property.
+ *
+ * @see #getDump()
+ */
+ public static final String TIP_TEXT_DPROP = "TipText";
+
+ /**
+ * Constructs a JToolTipOperator object, waiting for a shown
+ * JToolTip.
+ */
+ public JToolTipOperator() {
+ this(TRUE_CHOOSER);
+ }
+
+ /**
+ * Constructs a JToolTipOperator object for a given JToolTip component.
+ *
+ * @param toolTip
+ * a component
+ */
+ public JToolTipOperator(JToolTip toolTip) {
+ super(toolTip);
+ }
+
+ /**
+ * Constructs a JToolTipOperator object waiting for the JToolTip having a
+ * given tip text (compared using default string comparator).
+ *
+ * @param tipText
+ * tip text.
+ * @see #getDefaultStringComparator()
+ */
+ public JToolTipOperator(String tipText) {
+ this(waitJToolTip(new JToolTipByTipTextFinder(tipText,
+ getDefaultStringComparator())));
+ }
+
+ /**
+ * Constructs a JToolTipOperator object waiting for the JToolTip
+ * associated with the given component. Uses {@code comp}'s timeout and
+ * output for waiting. Copies environment from {@code comp}.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @see #copyEnvironment(org.netbeans.jemmy.operators.Operator)
+ */
+ public JToolTipOperator(ComponentOperator comp) {
+ this(comp, TRUE_CHOOSER);
+ }
+
+ /**
+ * Constructs a JToolTipOperator object waiting for the JToolTip
+ * conforming to the given component chooser.
+ *
+ * @param chooser
+ * a component chooser specifying searching criteria.
+ */
+ public JToolTipOperator(ComponentChooser chooser) {
+ this(null, chooser);
+ }
+
+ /**
+ * Constructs a JToolTipOperator object waiting for the JToolTip
+ * associated with the given component and conforming to the given
+ * component chooser. Uses {@code comp}'s timeout and output for waiting.
+ * Copies environment from {@code comp}.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @param chooser
+ * a component chooser specifying searching criteria.
+ * @see #copyEnvironment(org.netbeans.jemmy.operators.Operator)
+ */
+ public JToolTipOperator(ComponentOperator comp, ComponentChooser chooser) {
+ this(waitJToolTip(comp, chooser));
+ if(comp != null) {
+ copyEnvironment(comp);
+ }
+ }
+
+ /**
+ * Constructs a JToolTipOperator object waiting for the JToolTip
+ * associated with the given component and having the given tip text.
+ * Uses {@code comp}'s string comparator for tip text comparison, timeout
+ * and output for waiting. Copies environment from {@code comp}.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @param tipText
+ * tip text
+ * @see #getComparator()
+ * @see #copyEnvironment(org.netbeans.jemmy.operators.Operator)
+ */
+ public JToolTipOperator(ComponentOperator comp, String tipText) {
+ this(waitJToolTip(comp,
+ new JToolTipByTipTextFinder(tipText, comp.getComparator())));
+ copyEnvironment(comp);
+ }
+
+ /**
+ * Searches for the JToolTip associated with the given component and
+ * conforming to the given component chooser. Uses {@code comp}'s timeout
+ * and output for waiting.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @param chooser
+ * a component chooser specifying searching criteria.
+ * @return JToolTip instance or null if component was not found.
+ */
+ public static JToolTip findJToolTip(ComponentOperator comp,
+ ComponentChooser chooser) {
+ List windowList;
+ if(comp != null && comp.getWindow() != null) {
+ windowList = new ArrayList<>(
+ Arrays.asList(comp.getWindow().getOwnedWindows()));
+ windowList.add(comp.getWindow());
+ } else {
+ windowList = new ArrayList<>(
+ Arrays.asList(WindowOperator.getWindows()));
+ }
+ ComponentChooser toolTipChooser = new JToolTipFinder(chooser);
+ for (Window w : windowList) {
+ ComponentSearcher searcher = new ComponentSearcher(w);
+ Component[] components = searcher.findComponents(toolTipChooser);
+ if (components.length > 0) {
+ if(comp!= null && comp.getSource() != null) {
+ if(comp.getSource().equals(
+ ((JToolTip) components[0]).getComponent())) {
+ return (JToolTip) components[0];
+ }
+ } else {
+ return (JToolTip) components[0];
+ }
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Searches for a JToolTip.
+ *
+ * @return JToolTip instance or null if component was not found.
+ */
+ public static JToolTip findJToolTip() {
+ return findJToolTip(null);
+ }
+
+ /**
+ * Searches for the JToolTip associated with the given component. Uses
+ * {@code comp}'s timeout and output for waiting.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @return JToolTip instance or null if component was not found.
+ */
+ public static JToolTip findJToolTip(ComponentOperator comp) {
+ return findJToolTip(comp, TRUE_CHOOSER);
+ }
+
+ /**
+ * Searches for the JToolTip associated with the given component and
+ * looking for given tip text using specified string comparator options.
+ * Uses {@code comp}'s timeout and output for waiting.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @param tipText
+ * Tip text.
+ * @param ce
+ * Compare text exactly.
+ * @param ccs
+ * Compare text case sensitively.
+ * @return JToolTip instance or null if component was not found.
+ * @see DefaultStringComparator
+ * @see JToolTipByTipTextFinder
+ */
+ public static JToolTip findJToolTip(ComponentOperator comp, String tipText,
+ boolean ce, boolean ccs) {
+ return findJToolTip(comp, new JToolTipByTipTextFinder(tipText,
+ new DefaultStringComparator(ce, ccs)));
+ }
+
+ /**
+ * Waits for a JToolTip.
+ *
+ * @return JToolTip instance.
+ * @see TimeoutExpiredException
+ */
+ public static JToolTip waitJToolTip() {
+ return waitJToolTip(TRUE_CHOOSER);
+ }
+
+
+ /**
+ * Waits for the first JToolTip associated with the given component.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @return JToolTip instance.
+ * @see TimeoutExpiredException
+ */
+ public static JToolTip waitJToolTip(ComponentOperator comp) {
+ return waitJToolTip(comp, TRUE_CHOOSER);
+ }
+
+ /**
+ * Waits for the JToolTip conforming to the given component
+ * chooser.
+ *
+ * @param chooser
+ * a component chooser specifying searching criteria.
+ * @return JToolTip instance.
+ * @see TimeoutExpiredException
+ */
+ public static JToolTip waitJToolTip(ComponentChooser chooser) {
+ return waitJToolTip(null, chooser);
+ }
+
+ /**
+ * Waits for the JToolTip associated with the given component and
+ * conforming to the specified component chooser.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @param chooser
+ * a component chooser specifying searching criteria.
+ * @return JToolTip instance.
+ * @see TimeoutExpiredException
+ */
+ public static JToolTip waitJToolTip(ComponentOperator comp,
+ ComponentChooser chooser) {
+ return Operator.getEnvironmentOperator().
+ waitState(new Waitable() {
+ @Override
+ public JToolTip actionProduced(Void obj) {
+ return findJToolTip(comp, chooser);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Wait for JTooltip to be displayed for Component = "
+ + comp + ", " + "chooser = " + chooser;
+ }
+
+ @Override
+ public String toString() {
+ return "JToolTipOperator.waitJToolTip.Waitable{description = "
+ + getDescription() + '}';
+ }
+ });
+ }
+
+ /**
+ * Waits for the JToolTip associated with the given component and having
+ * the given tip text compared using given string comparator options.
+ *
+ * @param comp
+ * component on which tool tip associated
+ * @param tipText
+ * Tip text.
+ * @param ce
+ * Compare text exactly.
+ * @param ccs
+ * Compare text case sensitively.
+ * @return JToolTip instance.
+ * @see TimeoutExpiredException
+ */
+ public static JToolTip waitJToolTip(ComponentOperator comp, String tipText,
+ boolean ce, boolean ccs) {
+ return waitJToolTip(comp, new JToolTipByTipTextFinder(tipText,
+ new DefaultStringComparator(ce, ccs)));
+ }
+
+ /**
+ * Waits for the given tip text. Uses {@linkplain #getComparator()}
+ * comparator.
+ *
+ * @param tipText
+ * Tip text to wait for.
+ * @see TimeoutExpiredException
+ */
+ public void waitTipText(String tipText) {
+ getOutput().printLine("Wait \"" + tipText
+ + "\" tip text in JToolTip \n : " + toStringSource());
+ getOutput().printGolden("Wait \"" + tipText + "\" tip text");
+ waitState(new JToolTipByTipTextFinder(tipText, getComparator()));
+ }
+
+ /**
+ * Returns information about the component.
+ *
+ * @return Map of component properties.
+ */
+ @Override
+ public Hashtable getDump() {
+ Hashtable result = super.getDump();
+ String tipText = getTipText();
+ if (tipText != null) {
+ result.put(TIP_TEXT_DPROP, tipText);
+ } else {
+ result.put(TIP_TEXT_DPROP, "null");
+ }
+ return result;
+ }
+
+ ////////////////////////////////////////////////////////
+ // Mapping //
+
+ /**
+ * Maps {@linkplain JToolTip#getTipText()} through queue
+ *
+ * @return
+ */
+ public String getTipText() {
+ return runMapping(new MapAction("getTipText") {
+ @Override
+ public String map() {
+ return ((JToolTip) getSource()).getTipText();
+ }
+ });
+ }
+
+ /**
+ * Maps {@linkplain JToolTip#getComponent()} through queue
+ *
+ * @return
+ */
+ public JComponent getComponent() {
+ return runMapping(new MapAction("getComponent") {
+ @Override
+ public JComponent map() {
+ return ((JToolTip) getSource()).getComponent();
+ }
+ });
+ }
+
+ /**
+ * Maps {@linkplain JToolTip#getUI()} through queue
+ *
+ * @return
+ */
+ public ToolTipUI getUI() {
+ return runMapping(new MapAction("getUI") {
+ @Override
+ public ToolTipUI map() {
+ return ((JToolTip) getSource()).getUI();
+ }
+ });
+ }
+
+ /**
+ * Maps {@linkplain JToolTip#setTipText(String)} through queue
+ *
+ * @param tipText
+ */
+ public void setTipText(final String tipText) {
+ runMapping(new MapVoidAction("setTipText") {
+ @Override
+ public void map() {
+ ((JToolTip) getSource()).setTipText(tipText);
+ }
+ });
+ }
+
+ /**
+ * Maps {@linkplain JToolTip#setComponent(JComponent)} through queue
+ *
+ * @param component
+ */
+ public void setComponent(final JComponent component) {
+ runMapping(new MapVoidAction("setComponent") {
+ @Override
+ public void map() {
+ ((JToolTip) getSource()).setComponent(component);
+ }
+ });
+ }
+ // End of mapping //
+ ////////////////////////////////////////////////////////
+
+
+ /**
+ * Allows to find JToolTip by tip text.
+ */
+ public static class JToolTipByTipTextFinder implements ComponentChooser {
+
+ String tipText;
+ StringComparator comparator;
+
+ /**
+ * Constructs JToolTipByTipTextFinder.
+ *
+ * @param tipText
+ * a tip text pattern
+ * @param comparator
+ * specifies string comparison algorithm.
+ */
+ public JToolTipByTipTextFinder(String tipText,
+ StringComparator comparator) {
+ this.tipText = tipText;
+ this.comparator = comparator;
+ }
+
+ /**
+ * Constructs JToolTipByTipTextFinder.
+ *
+ * @param tipText
+ * a tip text pattern
+ */
+ public JToolTipByTipTextFinder(String tipText) {
+ this(tipText, Operator.getDefaultStringComparator());
+ }
+
+ @Override
+ public boolean checkComponent(Component comp) {
+ if (comp instanceof JToolTip) {
+ if (((JToolTip) comp).getTipText() != null) {
+ return (comparator.equals(((JToolTip) comp).getTipText(),
+ tipText));
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getDescription() {
+ return "JToolTip with tip text \"" + tipText + "\"";
+ }
+
+ @Override
+ public String toString() {
+ return "JToolTipByTipTextFinder{" + "tipText=" + tipText
+ + ", comparator=" + comparator + '}';
+ }
+ }
+
+ /**
+ * Allows to find JToolTips among components.
+ */
+ public static class JToolTipFinder extends Finder {
+
+ /**
+ * Constructs JToolTipFinder chaining another component chooser.
+ *
+ * @param sf
+ * other searching criteria.
+ */
+ public JToolTipFinder(ComponentChooser sf) {
+ super(JToolTip.class, sf);
+ }
+
+ /**
+ * Constructs JToolTipFinder.
+ */
+ public JToolTipFinder() {
+ super(JToolTip.class);
+ }
+ }
+
+ private static final ComponentChooser TRUE_CHOOSER = ComponentSearcher
+ .getTrueChooser("Any JToolTip");
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java Mon Aug 27 16:02:55 2018 -0400
@@ -693,7 +693,7 @@
* defined by {@code "ComponentOperator.WaitStateTimeout"}
*/
public void waitState(final ComponentChooser state) {
- Waiter stateWaiter = new Waiter<>(new Waitable() {
+ waitState(new Waitable() {
@Override
public String actionProduced(Void obj) {
return state.checkComponent(getSource()) ? "" : null;
@@ -710,13 +710,20 @@
return "Operator.waitState.Waitable{description = " + getDescription() + '}';
}
});
- stateWaiter.setTimeoutsToCloneOf(getTimeouts(), "ComponentOperator.WaitStateTimeout");
+ }
+
+ public R waitState(Waitable waitable) {
+ Waiter stateWaiter = new Waiter<>(waitable);
+ stateWaiter.setTimeoutsToCloneOf(getTimeouts(),
+ "ComponentOperator.WaitStateTimeout");
stateWaiter.setOutput(getOutput().createErrorOutput());
try {
- stateWaiter.waitAction(null);
+ return stateWaiter.waitAction(null);
} catch (InterruptedException e) {
- throw (new JemmyException("Waiting of \"" + state.getDescription()
- + "\" state has been interrupted!"));
+ Thread.currentThread().interrupt();
+ throw (new JemmyException(
+ "Waiting of \"" + waitable.getDescription()
+ + "\" state has been interrupted!"));
}
}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/WindowOperator.java
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/WindowOperator.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/WindowOperator.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
import org.netbeans.jemmy.JemmyException;
import org.netbeans.jemmy.JemmyProperties;
import org.netbeans.jemmy.Outputable;
+import org.netbeans.jemmy.QueueTool;
import org.netbeans.jemmy.TestOut;
import org.netbeans.jemmy.TimeoutExpiredException;
import org.netbeans.jemmy.Timeouts;
@@ -585,6 +586,21 @@
});
}
+ /**
+ * Maps {@code Window.getWindows()} through queue
+ *
+ * @return result of {@code Window.getWindows()}
+ */
+ public static Window[] getWindows() {
+ return new QueueTool().invokeSmoothly(
+ new QueueTool.QueueAction("getWindows") {
+ @Override
+ public Window[] launch() throws Exception {
+ return Window.getWindows();
+ }
+ });
+ }
+
//End of mapping //
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info Mon Aug 27 16:01:38 2018 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info Mon Aug 27 16:02:55 2018 -0400
@@ -1,6 +1,6 @@
Manifest-version: 1.0
Main-Class: org.netbeans.jemmy.JemmyProperties
Jemmy-MajorVersion: 3.0
-Jemmy-MinorVersion: 3.0
+Jemmy-MinorVersion: 4.0
Jemmy-Build: @BUILD_NUMBER@
diff -r 41e17fe9fbeb -r 6668bbc41155 test/jdk/sun/security/smartcardio/TestTransmit.java
--- a/test/jdk/sun/security/smartcardio/TestTransmit.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/jdk/sun/security/smartcardio/TestTransmit.java Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6293769 6294527
+ * @bug 6293769 6294527 6474858
* @summary test transmit() works
* @author Andreas Sterbenz
* @modules java.smartcardio/javax.smartcardio
@@ -90,6 +90,13 @@
} // else ignore
}
+ // JDK-6474858 : CardChannel.transmit(CommandAPDU) throws
+ // unexpected ArrayIndexOutOfBoundsException
+ {
+ CommandAPDU capdu2 = new CommandAPDU(0x00, 0xA4, 0x00, 0x00);
+ channel.transmit(capdu2);
+ }
+
// disconnect
card.disconnect(true);
diff -r 41e17fe9fbeb -r 6668bbc41155 test/langtools/tools/javac/T8209173/CodeCompletionExceptTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8209173/CodeCompletionExceptTest.java Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8209173
+ * @summary javac fails with completion exception while reporting an error
+ * @library /tools/lib
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.util
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @run main CodeCompletionExceptTest
+ */
+
+import java.io.File;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class CodeCompletionExceptTest {
+ private static final String MyListSource =
+ "import java.util.List;\n" +
+ "public interface MyList extends List {}";
+
+ private static final String C1Source =
+ "public class C1 {\n" +
+ " int m(MyList list) {\n" +
+ " return 0;\n" +
+ " }\n" +
+ "}";
+
+ private static final String C2Source =
+ "class C2 {\n" +
+ " void m() {\n" +
+ " (new C1()).m(1, 2, 3);\n" +
+ " }\n" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ new CodeCompletionExceptTest().run();
+ }
+
+ ToolBox tb = new ToolBox();
+
+ void run() throws Exception {
+ // first we compile MyList
+ new JavacTask(tb)
+ .sources(MyListSource)
+ .run();
+
+ // then with MyList.class in the cp we compile C1
+ new JavacTask(tb)
+ .sources(C1Source)
+ .classpath(System.getProperty("user.dir"))
+ .run();
+ // now we delete MyList.class
+ tb.deleteFiles(System.getProperty("user.dir") + File.separatorChar + "MyList.class");
+ /** and try to compile C2 which uses C1 which uses MyList but, MyList won't be in the
+ * classpath so its symbol can't be completed while javac is generating the diagnostic error
+ * the compiler should capture the completion exception and still be able to produce an error
+ * message without crashing
+ */
+ String javacOut = new JavacTask(tb)
+ .sources(C2Source)
+ .classpath(System.getProperty("user.dir"))
+ .options("-XDrawDiagnostics")
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+ String expectedOuput =
+ "C2.java:3:19: compiler.err.cant.apply.symbol: kindname.method, m, MyList, int,int,int, kindname.class, C1, (compiler.misc.arg.length.mismatch)";
+ if (!javacOut.contains(expectedOuput)) {
+ throw new Exception("test failed, unexpected output");
+ }
+ }
+}
diff -r 41e17fe9fbeb -r 6668bbc41155 test/lib/jdk/test/lib/cds/CDSTestUtils.java
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java Mon Aug 27 16:01:38 2018 -0400
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java Mon Aug 27 16:02:55 2018 -0400
@@ -200,11 +200,19 @@
}
}
- // Specify this property to copy sdandard output of the child test process to
- // the parent/main stdout of the test.
- // By default such output is logged into a file, and is copied into the main stdout.
- public static final boolean CopyChildStdoutToMainStdout =
- Boolean.valueOf(System.getProperty("test.cds.copy.child.stdout", "true"));
+ // A number to be included in the filename of the stdout and the stderr output file.
+ static int logCounter = 0;
+
+ private static int getNextLogCounter() {
+ return logCounter++;
+ }
+
+ // By default, stdout of child processes are logged in files such as
+ // -0000-exec.stdout. If you want to also include the stdout
+ // inside jtr files, you can override this in the jtreg command line like
+ // "jtreg -Dtest.cds.copy.child.stdout=true ...."
+ public static final boolean copyChildStdoutToMainStdout =
+ Boolean.getBoolean("test.cds.copy.child.stdout");
// This property is passed to child test processes
public static final String TestTimeoutFactor = System.getProperty("test.timeout.factor", "1.0");
@@ -549,13 +557,17 @@
public static OutputAnalyzer executeAndLog(ProcessBuilder pb, String logName) throws Exception {
long started = System.currentTimeMillis();
OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ String outputFileNamePrefix =
+ getTestName() + "-" + String.format("%04d", getNextLogCounter()) + "-" + logName;
- writeFile(getOutputFile(logName + ".stdout"), output.getStdout());
- writeFile(getOutputFile(logName + ".stderr"), output.getStderr());
+ writeFile(getOutputFile(outputFileNamePrefix + ".stdout"), output.getStdout());
+ writeFile(getOutputFile(outputFileNamePrefix + ".stderr"), output.getStderr());
System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]");
+ System.out.println("[logging stdout to " + outputFileNamePrefix + ".stdout]");
+ System.out.println("[logging stderr to " + outputFileNamePrefix + ".stderr]");
System.out.println("[STDERR]\n" + output.getStderr());
- if (CopyChildStdoutToMainStdout)
+ if (copyChildStdoutToMainStdout)
System.out.println("[STDOUT]\n" + output.getStdout());
return output;