This commit is contained in:
Jesper Wilhelmsson 2020-12-15 03:40:30 +00:00
commit 381021aebf
42 changed files with 720 additions and 230 deletions

@ -539,6 +539,20 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
}
#endif
// debugging support
// tracing
if (log_is_enabled(Info, exceptions)) {
ResourceMark rm;
stringStream tempst;
assert(nm->method() != NULL, "Unexpected NULL method()");
tempst.print("C1 compiled method <%s>\n"
" at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,
nm->method()->print_value_string(), p2i(pc), p2i(thread));
Exceptions::log_exception(exception, tempst.as_string());
}
// for AbortVMOnException flag
Exceptions::debug_check_abort(exception);
// Check the stack guard pages and reenable them if necessary and there is
// enough space on the stack to do so. Use fast exceptions only if the guard
// pages are enabled.
@ -585,20 +599,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// New exception handling mechanism can support inlined methods
// with exception handlers since the mappings are from PC to PC
// debugging support
// tracing
if (log_is_enabled(Info, exceptions)) {
ResourceMark rm;
stringStream tempst;
assert(nm->method() != NULL, "Unexpected NULL method()");
tempst.print("compiled method <%s>\n"
" at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,
nm->method()->print_value_string(), p2i(pc), p2i(thread));
Exceptions::log_exception(exception, tempst.as_string());
}
// for AbortVMOnException flag
Exceptions::debug_check_abort(exception);
// Clear out the exception oop and pc since looking up an
// exception handler can cause class loading, which might throw an
// exception and those fields are expected to be clear during

@ -47,6 +47,7 @@ ciMethodData::ciMethodData(MethodData* md)
_saw_free_extra_data(false),
// Initialize the escape information (to "don't know.");
_eflags(0), _arg_local(0), _arg_stack(0), _arg_returned(0),
_creation_mileage(0),
_current_mileage(0),
_invocation_counter(0),
_backedge_counter(0),
@ -242,6 +243,7 @@ void ciMethodData::load_data() {
load_remaining_extra_data();
// Note: Extra data are all BitData, and do not need translation.
_creation_mileage = mdo->creation_mileage();
_current_mileage = MethodData::mileage_of(mdo->method());
_invocation_counter = mdo->invocation_count();
_backedge_counter = mdo->backedge_count();

@ -395,6 +395,8 @@ private:
intx _arg_stack; // bit set of stack-allocatable arguments
intx _arg_returned; // bit set of returned arguments
int _creation_mileage; // method mileage at MDO creation
// Maturity of the oop when the snapshot is taken.
int _current_mileage;
@ -475,7 +477,7 @@ public:
bool is_empty() { return _state == empty_state; }
bool is_mature() { return _state == mature_state; }
int creation_mileage() { return _orig.creation_mileage(); }
int creation_mileage() { return _creation_mileage; }
int current_mileage() { return _current_mileage; }
int invocation_count() { return _invocation_counter; }

@ -472,6 +472,7 @@ bool G1HeapVerifier::should_verify(G1VerifyType type) {
void G1HeapVerifier::verify(VerifyOption vo) {
assert_at_safepoint_on_vm_thread();
assert(Heap_lock->is_locked(), "heap must be locked");
log_debug(gc, verify)("Roots");
VerifyRootsClosure rootsCl(vo);

@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "gc/shared/allocTracer.hpp"
#include "gc/shared/threadLocalAllocBuffer.inline.hpp"
#include "jfr/jfrEvents.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
@ -32,91 +31,18 @@
#include "jfr/support/jfrAllocationTracer.hpp"
#endif
static THREAD_LOCAL int64_t _last_allocated_bytes = 0;
inline void send_allocation_sample(const Klass* klass, int64_t allocated_bytes) {
assert(allocated_bytes > 0, "invariant");
EventObjectAllocationSample event;
if (event.should_commit()) {
const size_t weight = allocated_bytes - _last_allocated_bytes;
assert(weight > 0, "invariant");
event.set_objectClass(klass);
event.set_weight(weight);
event.commit();
_last_allocated_bytes = allocated_bytes;
}
}
inline bool send_allocation_sample_with_result(const Klass* klass, int64_t allocated_bytes) {
assert(allocated_bytes > 0, "invariant");
EventObjectAllocationSample event;
if (event.should_commit()) {
const size_t weight = allocated_bytes - _last_allocated_bytes;
assert(weight > 0, "invariant");
event.set_objectClass(klass);
event.set_weight(weight);
event.commit();
_last_allocated_bytes = allocated_bytes;
return true;
}
return false;
}
inline intptr_t estimate_tlab_size_bytes(Thread* thread) {
assert(thread != NULL, "invariant");
const size_t desired_tlab_size_bytes = thread->tlab().desired_size() * HeapWordSize;
const size_t alignment_reserve_bytes = thread->tlab().alignment_reserve_in_bytes();
assert(desired_tlab_size_bytes > alignment_reserve_bytes, "invariant");
return static_cast<intptr_t>(desired_tlab_size_bytes - alignment_reserve_bytes);
}
inline int64_t load_allocated_bytes(Thread* thread) {
const int64_t allocated_bytes = thread->allocated_bytes();
if (allocated_bytes < _last_allocated_bytes) {
// A hw thread can detach and reattach to the VM, and when it does,
// it gets a new JavaThread representation. The thread local variable
// tracking _last_allocated_bytes is mapped to the existing hw thread,
// so it needs to be reset.
_last_allocated_bytes = 0;
}
return allocated_bytes == _last_allocated_bytes ? 0 : allocated_bytes;
}
// To avoid large objects from being undersampled compared to the regular TLAB samples,
// the data amount is normalized as if it was a TLAB, giving a number of TLAB sampling attempts to the large object.
static void normalize_as_tlab_and_send_allocation_samples(Klass* klass, intptr_t obj_alloc_size_bytes, Thread* thread) {
const int64_t allocated_bytes = load_allocated_bytes(thread);
assert(allocated_bytes > 0, "invariant"); // obj_alloc_size_bytes is already attributed to allocated_bytes at this point.
if (!UseTLAB) {
send_allocation_sample(klass, allocated_bytes);
return;
}
const intptr_t tlab_size_bytes = estimate_tlab_size_bytes(thread);
if (allocated_bytes - _last_allocated_bytes < tlab_size_bytes) {
return;
}
assert(obj_alloc_size_bytes > 0, "invariant");
do {
if (send_allocation_sample_with_result(klass, allocated_bytes)) {
return;
}
obj_alloc_size_bytes -= tlab_size_bytes;
} while (obj_alloc_size_bytes > 0);
}
void AllocTracer::send_allocation_outside_tlab(Klass* klass, HeapWord* obj, size_t alloc_size, Thread* thread) {
JFR_ONLY(JfrAllocationTracer tracer(obj, alloc_size, thread);)
JFR_ONLY(JfrAllocationTracer tracer(klass, obj, alloc_size, true, thread);)
EventObjectAllocationOutsideTLAB event;
if (event.should_commit()) {
event.set_objectClass(klass);
event.set_allocationSize(alloc_size);
event.commit();
}
normalize_as_tlab_and_send_allocation_samples(klass, static_cast<intptr_t>(alloc_size), thread);
}
void AllocTracer::send_allocation_in_new_tlab(Klass* klass, HeapWord* obj, size_t tlab_size, size_t alloc_size, Thread* thread) {
JFR_ONLY(JfrAllocationTracer tracer(obj, alloc_size, thread);)
JFR_ONLY(JfrAllocationTracer tracer(klass, obj, alloc_size, false, thread);)
EventObjectAllocationInNewTLAB event;
if (event.should_commit()) {
event.set_objectClass(klass);
@ -124,11 +50,6 @@ void AllocTracer::send_allocation_in_new_tlab(Klass* klass, HeapWord* obj, size_
event.set_tlabSize(tlab_size);
event.commit();
}
const int64_t allocated_bytes = load_allocated_bytes(thread);
if (allocated_bytes == 0) {
return;
}
send_allocation_sample(klass, allocated_bytes);
}
void AllocTracer::send_allocation_requiring_gc_event(size_t size, uint gcId) {

@ -46,6 +46,20 @@
#include "gc/g1/g1Policy.hpp"
#endif // INCLUDE_G1GC
bool VM_GC_Sync_Operation::doit_prologue() {
Heap_lock->lock();
return true;
}
void VM_GC_Sync_Operation::doit_epilogue() {
Heap_lock->unlock();
}
void VM_Verify::doit() {
Universe::heap()->prepare_for_verify();
Universe::verify();
}
VM_GC_Operation::~VM_GC_Operation() {
CollectedHeap* ch = Universe::heap();
ch->soft_ref_policy()->set_all_soft_refs_clear(false);
@ -94,8 +108,7 @@ bool VM_GC_Operation::doit_prologue() {
proper_unit_for_byte_size(NewSize)));
}
// If the GC count has changed someone beat us to the collection
Heap_lock->lock();
VM_GC_Sync_Operation::doit_prologue();
// Check invocations
if (skip_operation()) {
@ -116,7 +129,7 @@ void VM_GC_Operation::doit_epilogue() {
if (Universe::has_reference_pending_list()) {
Heap_lock->notify_all();
}
Heap_lock->unlock();
VM_GC_Sync_Operation::doit_epilogue();
}
bool VM_GC_HeapInspection::skip_operation() const {

@ -39,17 +39,27 @@
// a set of operations (VM_Operation) related to GC.
//
// VM_Operation
// VM_GC_Sync_Operation
// VM_GC_Operation
// VM_GC_HeapInspection
// VM_GenCollectFull
// VM_GenCollectFullConcurrent
// VM_ParallelGCSystemGC
// VM_CollectForAllocation
// VM_GenCollectForAllocation
// VM_ParallelGCFailedAllocation
// VM_GC_HeapInspection
// VM_PopulateDynamicDumpSharedSpace
// VM_GenCollectFull
// VM_GenCollectFullConcurrent
// VM_ParallelGCSystemGC
// VM_CollectForAllocation
// VM_GenCollectForAllocation
// VM_ParallelGCFailedAllocation
// VM_Verify
// VM_PopulateDumpSharedSpace
//
// VM_GC_Sync_Operation
// - implements only synchronization with other VM operations of the
// same kind using the Heap_lock, not actually doing a GC.
//
// VM_GC_Operation
// - implements methods common to all classes in the hierarchy:
// prevents multiple gc requests and manages lock on heap;
// - implements methods common to all operations that perform garbage collections,
// checking that the VM is in a state to do GC and preventing multiple GC
// requests.
//
// VM_GC_HeapInspection
// - prints class histogram on SIGBREAK if PrintClassHistogram
@ -68,11 +78,37 @@
// - these operations preform full collection of heaps of
// different kind
//
// VM_Verify
// - verifies the heap
//
// VM_PopulateDynamicDumpSharedSpace
// - populates the CDS archive area with the information from the archive file.
//
// VM_PopulateDumpSharedSpace
// - creates the CDS archive
//
class VM_GC_Operation: public VM_Operation {
class VM_GC_Sync_Operation : public VM_Operation {
public:
VM_GC_Sync_Operation() : VM_Operation() { }
// Acquires the Heap_lock.
virtual bool doit_prologue();
// Releases the Heap_lock.
virtual void doit_epilogue();
};
class VM_Verify : public VM_GC_Sync_Operation {
public:
VMOp_Type type() const { return VMOp_Verify; }
void doit();
};
class VM_GC_Operation: public VM_GC_Sync_Operation {
protected:
uint _gc_count_before; // gc count before acquiring PLL
uint _full_gc_count_before; // full gc count before acquiring PLL
uint _gc_count_before; // gc count before acquiring the Heap_lock
uint _full_gc_count_before; // full gc count before acquiring the Heap_lock
bool _full; // whether a "full" collection
bool _prologue_succeeded; // whether doit_prologue succeeded
GCCause::Cause _gc_cause; // the putative cause for this gc op
@ -84,7 +120,7 @@ class VM_GC_Operation: public VM_Operation {
VM_GC_Operation(uint gc_count_before,
GCCause::Cause _cause,
uint full_gc_count_before = 0,
bool full = false) {
bool full = false) : VM_GC_Sync_Operation() {
_full = full;
_prologue_succeeded = false;
_gc_count_before = gc_count_before;
@ -106,9 +142,10 @@ class VM_GC_Operation: public VM_Operation {
}
~VM_GC_Operation();
// Acquire the reference synchronization lock
// Acquire the Heap_lock and determine if this VM operation should be executed
// (i.e. not skipped). Return this result, and also store it in _prologue_succeeded.
virtual bool doit_prologue();
// Do notifyAll (if needed) and release held lock
// Notify the Heap_lock if needed and release it.
virtual void doit_epilogue();
virtual bool allow_nested_vm_operations() const { return true; }

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "gc/shared/isGCActiveMark.hpp"
#include "gc/z/zBreakpoint.hpp"
#include "gc/z/zCollectedHeap.hpp"

@ -25,10 +25,12 @@
#include "precompiled.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/support/jfrAllocationTracer.hpp"
#include "jfr/support/jfrObjectAllocationSample.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/thread.hpp"
JfrAllocationTracer::JfrAllocationTracer(HeapWord* obj, size_t alloc_size, Thread* thread) : _tl(NULL) {
JfrAllocationTracer::JfrAllocationTracer(const Klass* klass, HeapWord* obj, size_t alloc_size, bool outside_tlab, Thread* thread) : _tl(NULL) {
JfrObjectAllocationSample::send_event(klass, alloc_size, outside_tlab, thread);
if (LeakProfiler::is_running()) {
_tl = thread->jfr_thread_local();
LeakProfiler::sample(obj, alloc_size, thread->as_Java_thread());

@ -27,13 +27,15 @@
#include "memory/allocation.hpp"
class Klass;
class JfrThreadLocal;
class Thread;
class JfrAllocationTracer : public StackObj {
private:
JfrThreadLocal* _tl;
public:
JfrAllocationTracer(HeapWord* obj, size_t alloc_size, Thread* thread);
JfrAllocationTracer(const Klass* klass, HeapWord* obj, size_t alloc_size, bool outside_tlab, Thread* thread);
~JfrAllocationTracer();
};

@ -0,0 +1,113 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc/shared/threadLocalAllocBuffer.inline.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/support/jfrObjectAllocationSample.hpp"
#include "utilities/globalDefinitions.hpp"
static THREAD_LOCAL int64_t _last_allocated_bytes = 0;
inline void send_allocation_sample(const Klass* klass, int64_t allocated_bytes) {
assert(allocated_bytes > 0, "invariant");
EventObjectAllocationSample event;
if (event.should_commit()) {
const size_t weight = allocated_bytes - _last_allocated_bytes;
assert(weight > 0, "invariant");
event.set_objectClass(klass);
event.set_weight(weight);
event.commit();
_last_allocated_bytes = allocated_bytes;
}
}
inline bool send_allocation_sample_with_result(const Klass* klass, int64_t allocated_bytes) {
assert(allocated_bytes > 0, "invariant");
EventObjectAllocationSample event;
if (event.should_commit()) {
const size_t weight = allocated_bytes - _last_allocated_bytes;
assert(weight > 0, "invariant");
event.set_objectClass(klass);
event.set_weight(weight);
event.commit();
_last_allocated_bytes = allocated_bytes;
return true;
}
return false;
}
inline intptr_t estimate_tlab_size_bytes(Thread* thread) {
const size_t desired_tlab_size_bytes = thread->tlab().desired_size() * HeapWordSize;
const size_t alignment_reserve_bytes = thread->tlab().alignment_reserve_in_bytes();
assert(desired_tlab_size_bytes > alignment_reserve_bytes, "invariant");
return static_cast<intptr_t>(desired_tlab_size_bytes - alignment_reserve_bytes);
}
inline int64_t load_allocated_bytes(Thread* thread) {
assert(thread != NULL, "invariant");
const int64_t allocated_bytes = thread->allocated_bytes();
if (allocated_bytes < _last_allocated_bytes) {
// A hw thread can detach and reattach to the VM, and when it does,
// it gets a new JavaThread representation. The thread local variable
// tracking _last_allocated_bytes is mapped to the existing hw thread,
// so it needs to be reset.
_last_allocated_bytes = 0;
}
return allocated_bytes == _last_allocated_bytes ? 0 : allocated_bytes;
}
// To avoid large objects from being undersampled compared to the regular TLAB samples,
// the data amount is normalized as if it was a TLAB, giving a number of TLAB sampling attempts to the large object.
static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, intptr_t obj_alloc_size_bytes, Thread* thread) {
const int64_t allocated_bytes = load_allocated_bytes(thread);
assert(allocated_bytes > 0, "invariant"); // obj_alloc_size_bytes is already attributed to allocated_bytes at this point.
if (!UseTLAB) {
send_allocation_sample(klass, allocated_bytes);
return;
}
const intptr_t tlab_size_bytes = estimate_tlab_size_bytes(thread);
if (allocated_bytes - _last_allocated_bytes < tlab_size_bytes) {
return;
}
assert(obj_alloc_size_bytes > 0, "invariant");
do {
if (send_allocation_sample_with_result(klass, allocated_bytes)) {
return;
}
obj_alloc_size_bytes -= tlab_size_bytes;
} while (obj_alloc_size_bytes > 0);
}
void JfrObjectAllocationSample::send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, Thread* thread) {
if (outside_tlab) {
normalize_as_tlab_and_send_allocation_samples(klass, static_cast<intptr_t>(alloc_size), thread);
return;
}
const int64_t allocated_bytes = load_allocated_bytes(thread);
if (allocated_bytes == 0) {
return;
}
send_allocation_sample(klass, allocated_bytes);
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* 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_JFR_SUPPORT_JFROBJECTALLOCATIONSAMPLE_HPP
#define SHARE_JFR_SUPPORT_JFROBJECTALLOCATIONSAMPLE_HPP
#include "memory/allocation.hpp"
class Klass;
class Thread;
class JfrObjectAllocationSample : AllStatic {
friend class JfrAllocationTracer;
static void send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, Thread* thread);
};
#endif // SHARE_JFR_SUPPORT_JFROBJECTALLOCATIONSAMPLE_HPP

@ -267,6 +267,20 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
}
#endif
// debugging support
// tracing
if (log_is_enabled(Info, exceptions)) {
ResourceMark rm;
stringStream tempst;
assert(cm->method() != NULL, "Unexpected null method()");
tempst.print("JVMCI compiled method <%s>\n"
" at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,
cm->method()->print_value_string(), p2i(pc), p2i(thread));
Exceptions::log_exception(exception, tempst.as_string());
}
// for AbortVMOnException flag
Exceptions::debug_check_abort(exception);
// Check the stack guard pages and reenable them if necessary and there is
// enough space on the stack to do so. Use fast exceptions only if the guard
// pages are enabled.
@ -313,20 +327,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// New exception handling mechanism can support inlined methods
// with exception handlers since the mappings are from PC to PC
// debugging support
// tracing
if (log_is_enabled(Info, exceptions)) {
ResourceMark rm;
stringStream tempst;
assert(cm->method() != NULL, "Unexpected null method()");
tempst.print("compiled method <%s>\n"
" at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,
cm->method()->print_value_string(), p2i(pc), p2i(thread));
Exceptions::log_exception(exception, tempst.as_string());
}
// for AbortVMOnException flag
NOT_PRODUCT(Exceptions::debug_check_abort(exception));
// Clear out the exception oop and pc since looking up an
// exception handler can cause class loading, which might throw an
// exception and those fields are expected to be clear during

@ -27,6 +27,7 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "logging/log.hpp"
#include "memory/archiveBuilder.hpp"
#include "memory/archiveUtils.inline.hpp"
@ -541,10 +542,10 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data) {
log_info(cds, dynamic)("%d klasses; %d symbols", num_klasses, num_symbols);
}
class VM_PopulateDynamicDumpSharedSpace: public VM_Operation {
class VM_PopulateDynamicDumpSharedSpace: public VM_GC_Sync_Operation {
DynamicArchiveBuilder* _builder;
public:
VM_PopulateDynamicDumpSharedSpace(DynamicArchiveBuilder* builder) : _builder(builder) {}
VM_PopulateDynamicDumpSharedSpace(DynamicArchiveBuilder* builder) : VM_GC_Sync_Operation(), _builder(builder) {}
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
void doit() {
ResourceMark rm;

@ -33,6 +33,7 @@
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
#include "logging/logStream.hpp"
@ -655,8 +656,10 @@ static void verify_the_heap(Klass* k, const char* which) {
ResourceMark rm;
log_info(cds, heap)("Verify heap %s initializing static field(s) in %s",
which, k->external_name());
VM_Verify verify_op;
VMThread::execute(&verify_op);
if (!FLAG_IS_DEFAULT(VerifyArchivedFields)) {
// If VerifyArchivedFields has a non-default value (e.g., specified on the command-line), do
// more expensive checks.

@ -37,6 +37,7 @@
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "interpreter/abstractInterpreter.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/bytecodes.hpp"
@ -577,7 +578,7 @@ void MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread
}
}
class VM_PopulateDumpSharedSpace: public VM_Operation {
class VM_PopulateDumpSharedSpace : public VM_GC_Operation {
private:
GrowableArray<MemRegion> *_closed_archive_heap_regions;
GrowableArray<MemRegion> *_open_archive_heap_regions;
@ -602,6 +603,12 @@ private:
public:
VM_PopulateDumpSharedSpace() : VM_GC_Operation(0, /* total collections, ignored */
GCCause::_archive_time_gc)
{ }
bool skip_operation() const { return false; }
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
void doit(); // outline because gdb sucks
bool allow_nested_vm_operations() const { return true; }
@ -1085,8 +1092,6 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
#endif
VM_PopulateDumpSharedSpace op;
MutexLocker ml(THREAD, HeapShared::is_heap_object_archiving_allowed() ?
Heap_lock : NULL); // needed by HeapShared::run_gc()
VMThread::execute(&op);
}
}

@ -739,6 +739,12 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
}
bool InstanceKlass::is_record() const {
return _record_components != NULL &&
is_final() &&
java_super() == SystemDictionary::Record_klass();
}
bool InstanceKlass::is_sealed() const {
return _permitted_subclasses != NULL &&
_permitted_subclasses != Universe::the_empty_short_array();

@ -473,7 +473,7 @@ class InstanceKlass: public Klass {
void set_record_components(Array<RecordComponent*>* record_components) {
_record_components = record_components;
}
bool is_record() const { return _record_components != NULL; }
bool is_record() const;
// permitted subclasses
Array<u2>* permitted_subclasses() const { return _permitted_subclasses; }

@ -1207,7 +1207,7 @@ void MethodData::post_initialize(BytecodeStream* stream) {
MethodData::MethodData(const methodHandle& method)
: _method(method()),
_extra_data_lock(Mutex::leaf, "MDO extra data lock"),
_compiler_counters(method()),
_compiler_counters(),
_parameters_type_data_di(parameters_uninitialized) {
initialize();
}
@ -1218,6 +1218,7 @@ void MethodData::initialize() {
ResourceMark rm(thread);
init();
set_creation_mileage(mileage_of(method()));
// Go through the bytecodes and allocate and initialize the
// corresponding data cells.
@ -1282,6 +1283,7 @@ void MethodData::initialize() {
}
void MethodData::init() {
_compiler_counters = CompilerCounters(); // reset compiler counters
_invocation_counter.init();
_backedge_counter.init();
_invocation_counter_start = 0;

@ -1974,7 +1974,6 @@ public:
friend class VMStructs;
friend class JVMCIVMStructs;
int _creation_mileage; // method mileage at MDO creation
uint _nof_decompiles; // count of all nmethod removals
uint _nof_overflow_recompiles; // recompile count, excluding recomp. bits
uint _nof_overflow_traps; // trap count, excluding _trap_hist
@ -1983,16 +1982,12 @@ public:
u1 _array[JVMCI_ONLY(2 *) MethodData::_trap_hist_limit];
} _trap_hist;
CompilerCounters(int current_mileage) : _creation_mileage(current_mileage), _nof_decompiles(0), _nof_overflow_recompiles(0), _nof_overflow_traps(0) {
public:
CompilerCounters() : _nof_decompiles(0), _nof_overflow_recompiles(0), _nof_overflow_traps(0) {
static_assert(sizeof(_trap_hist) % HeapWordSize == 0, "align");
uint size_in_words = sizeof(_trap_hist) / HeapWordSize;
Copy::zero_to_words((HeapWord*) &_trap_hist, size_in_words);
}
public:
CompilerCounters(Method* m) : CompilerCounters(MethodData::mileage_of(m)) {}
CompilerCounters() : CompilerCounters(0) {} // for ciMethodData
int creation_mileage() const { return _creation_mileage; }
// Return (uint)-1 for overflow.
uint trap_count(int reason) const {
@ -2044,6 +2039,8 @@ private:
intx _arg_stack; // bit set of stack-allocatable arguments
intx _arg_returned; // bit set of returned arguments
int _creation_mileage; // method mileage at MDO creation
// How many invocations has this MDO seen?
// These counters are used to determine the exact age of MDO.
// We need those because in tiered a method can be concurrently
@ -2188,7 +2185,8 @@ public:
int size_in_bytes() const { return _size; }
int size() const { return align_metadata_size(align_up(_size, BytesPerWord)/BytesPerWord); }
int creation_mileage() const { return _compiler_counters.creation_mileage(); }
int creation_mileage() const { return _creation_mileage; }
void set_creation_mileage(int x) { _creation_mileage = x; }
int invocation_count() {
if (invocation_counter()->carry()) {

@ -1851,6 +1851,9 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
}
JVM_END
// A class is a record if and only if it is final and a direct subclass of
// java.lang.Record and has a Record attribute; otherwise, it is not a record.
JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls))
{
JVMWrapper("JVM_IsRecord");
@ -1864,6 +1867,11 @@ JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls))
}
JVM_END
// Returns an array containing the components of the Record attribute,
// or NULL if the attribute is not present.
//
// Note that this function returns the components of the Record attribute
// even if the class is not a record.
JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
{
JVMWrapper("JVM_GetRecordComponents");
@ -1871,31 +1879,26 @@ JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
assert(c->is_instance_klass(), "must be");
InstanceKlass* ik = InstanceKlass::cast(c);
if (ik->is_record()) {
Array<RecordComponent*>* components = ik->record_components();
assert(components != NULL, "components should not be NULL");
{
JvmtiVMObjectAllocEventCollector oam;
constantPoolHandle cp(THREAD, ik->constants());
int length = components->length();
assert(length >= 0, "unexpected record_components length");
objArrayOop record_components =
oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), length, CHECK_NULL);
objArrayHandle components_h (THREAD, record_components);
Array<RecordComponent*>* components = ik->record_components();
if (components != NULL) {
JvmtiVMObjectAllocEventCollector oam;
constantPoolHandle cp(THREAD, ik->constants());
int length = components->length();
assert(length >= 0, "unexpected record_components length");
objArrayOop record_components =
oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), length, CHECK_NULL);
objArrayHandle components_h (THREAD, record_components);
for (int x = 0; x < length; x++) {
RecordComponent* component = components->at(x);
assert(component != NULL, "unexpected NULL record component");
oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL);
components_h->obj_at_put(x, component_oop);
}
return (jobjectArray)JNIHandles::make_local(THREAD, components_h());
for (int x = 0; x < length; x++) {
RecordComponent* component = components->at(x);
assert(component != NULL, "unexpected NULL record component");
oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL);
components_h->obj_at_put(x, component_oop);
}
return (jobjectArray)JNIHandles::make_local(THREAD, components_h());
}
// Return empty array if ofClass is not a record.
objArrayOop result = oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), 0, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(THREAD, result);
return NULL;
}
JVM_END

@ -1731,6 +1731,18 @@ address Deoptimization::deoptimize_for_missing_exception_handler(CompiledMethod*
frame runtime_frame = thread->last_frame();
frame caller_frame = runtime_frame.sender(&reg_map);
assert(caller_frame.cb()->as_compiled_method_or_null() == cm, "expect top frame compiled method");
vframe* vf = vframe::new_vframe(&caller_frame, &reg_map, thread);
compiledVFrame* cvf = compiledVFrame::cast(vf);
ScopeDesc* imm_scope = cvf->scope();
MethodData* imm_mdo = get_method_data(thread, methodHandle(thread, imm_scope->method()), true);
if (imm_mdo != NULL) {
ProfileData* pdata = imm_mdo->allocate_bci_to_data(imm_scope->bci(), NULL);
if (pdata != NULL && pdata->is_BitData()) {
BitData* bit_data = (BitData*) pdata;
bit_data->set_exception_seen();
}
}
Deoptimization::deoptimize(thread, caller_frame, Deoptimization::Reason_not_compiled_exception_handler);
MethodData* trap_mdo = get_method_data(thread, methodHandle(thread, cm->method()), true);

@ -599,6 +599,28 @@ void SharedRuntime::throw_and_post_jvmti_exception(JavaThread *thread, Handle h_
address bcp = method()->bcp_from(vfst.bci());
JvmtiExport::post_exception_throw(thread, method(), bcp, h_exception());
}
#if INCLUDE_JVMCI
if (EnableJVMCI && UseJVMCICompiler) {
vframeStream vfst(thread, true);
methodHandle method = methodHandle(thread, vfst.method());
int bci = vfst.bci();
MethodData* trap_mdo = method->method_data();
if (trap_mdo != NULL) {
// Set exception_seen if the exceptional bytecode is an invoke
Bytecode_invoke call = Bytecode_invoke_check(method, bci);
if (call.is_valid()) {
ResourceMark rm(thread);
ProfileData* pdata = trap_mdo->allocate_bci_to_data(bci, NULL);
if (pdata != NULL && pdata->is_BitData()) {
BitData* bit_data = (BitData*) pdata;
bit_data->set_exception_seen();
}
}
}
}
#endif
Exceptions::_throw(thread, __FILE__, __LINE__, h_exception);
}

@ -39,6 +39,7 @@
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/gcLocker.inline.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "gc/shared/oopStorage.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/workgroup.hpp"

@ -156,11 +156,6 @@ void VM_ZombieAll::doit() {
#endif // !PRODUCT
void VM_Verify::doit() {
Universe::heap()->prepare_for_verify();
Universe::verify();
}
bool VM_PrintThreads::doit_prologue() {
// Get Heap_lock if concurrent locks will be dumped
if (_print_concurrent_locks) {

@ -277,13 +277,6 @@ class VM_ZombieAll: public VM_Operation {
};
#endif // PRODUCT
class VM_Verify: public VM_Operation {
public:
VMOp_Type type() const { return VMOp_Verify; }
void doit();
};
class VM_PrintThreads: public VM_Operation {
private:
outputStream* _out;

@ -2383,11 +2383,7 @@ public final class Class<T> implements java.io.Serializable,
if (!isRecord()) {
return null;
}
RecordComponent[] recordComponents = getRecordComponents0();
if (recordComponents == null) {
return new RecordComponent[0];
}
return recordComponents;
return getRecordComponents0();
}
/**
@ -3577,9 +3573,17 @@ public final class Class<T> implements java.io.Serializable,
private native Field[] getDeclaredFields0(boolean publicOnly);
private native Method[] getDeclaredMethods0(boolean publicOnly);
private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
private native Class<?>[] getDeclaredClasses0();
private native Class<?>[] getDeclaredClasses0();
/*
* Returns an array containing the components of the Record attribute,
* or null if the attribute is not present.
*
* Note that this method returns non-null array on a class with
* the Record attribute even if this class is not a record.
*/
private native RecordComponent[] getRecordComponents0();
private native boolean isRecord0();
private native boolean isRecord0();
/**
* Helper method to get the method name from arguments.
@ -3706,6 +3710,8 @@ public final class Class<T> implements java.io.Serializable,
* @since 16
*/
public boolean isRecord() {
// this superclass and final modifier check is not strictly necessary
// they are intrinsified and serve as a fast-path check
return getSuperclass() == java.lang.Record.class &&
(this.getModifiers() & Modifier.FINAL) != 0 &&
isRecord0();

@ -111,15 +111,14 @@ public abstract class Record {
* <li> If the component is of a reference type, the component is
* considered equal if and only if {@link
* java.util.Objects#equals(Object,Object)
* Objects.equals(this.c(), r.c()} would return {@code true}.
* Objects.equals(this.c, r.c} would return {@code true}.
*
* <li> If the component is of a primitive type, using the
* corresponding primitive wrapper class {@code PW} (the
* corresponding wrapper class for {@code int} is {@code
* java.lang.Integer}, and so on), the component is considered
* equal if and only if {@code
* PW.valueOf(this.c()).equals(PW.valueOf(r.c()))} would return
* {@code true}.
* PW.compare(this.c, r.c)} would return {@code 0}.
*
* </ul>
*

@ -1871,6 +1871,8 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
* interrupted.
*/
private Object waitingGet(boolean interruptible) {
if (interruptible && Thread.interrupted())
return null;
Signaller q = null;
boolean queued = false;
Object r;
@ -1882,25 +1884,25 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
}
else if (!queued)
queued = tryPushStack(q);
else if (interruptible && q.interrupted) {
q.thread = null;
cleanStack();
return null;
}
else {
try {
ForkJoinPool.managedBlock(q);
} catch (InterruptedException ie) { // currently cannot happen
q.interrupted = true;
}
if (q.interrupted && interruptible)
break;
}
}
if (q != null && queued) {
if (q != null) {
q.thread = null;
if (!interruptible && q.interrupted)
if (q.interrupted)
Thread.currentThread().interrupt();
if (r == null)
cleanStack();
}
if (r != null || (r = result) != null)
postComplete();
postComplete();
return r;
}

@ -109,7 +109,7 @@ public interface RoundEnvironment {
* annotation types, or an empty set if there are none
* @throws IllegalArgumentException if the any elements of the
* argument set do not represent an annotation type
* @jls 9.6.3 Repeatable Annotation Types
* @jls 9.6.3 Repeatable Annotation Interfaces
* @since 9
*/
default Set<? extends Element> getElementsAnnotatedWithAny(TypeElement... annotations){
@ -191,7 +191,7 @@ public interface RoundEnvironment {
* annotation types, or an empty set if there are none
* @throws IllegalArgumentException if the any elements of the
* argument set do not represent an annotation type
* @jls 9.6.3 Repeatable Annotation Types
* @jls 9.6.3 Repeatable Annotation Interfaces
*
* @see javax.lang.model.AnnotatedConstruct#getAnnotation(Class)
* @see javax.lang.model.AnnotatedConstruct#getAnnotationsByType(Class)

@ -129,10 +129,10 @@ import javax.lang.model.type.*;
* </ul>
*
* @since 1.8
* @jls 9.6 Annotation Types
* @jls 9.6 Annotation Interfaces
* @jls 9.6.4.3 {@code @Inherited}
* @jls 9.7.4 Where Annotations May Appear
* @jls 9.7.5 Multiple Annotations of the Same Type
* @jls 9.7.5 Multiple Annotations of the Same Interface
*/
public interface AnnotatedConstruct {
/**
@ -184,7 +184,7 @@ public interface AnnotatedConstruct {
* @see IncompleteAnnotationException
* @see MirroredTypeException
* @see MirroredTypesException
* @jls 9.6.1 Annotation Type Elements
* @jls 9.6.1 Annotation Interface Elements
*/
<A extends Annotation> A getAnnotation(Class<A> annotationType);
@ -244,8 +244,8 @@ public interface AnnotatedConstruct {
* @see IncompleteAnnotationException
* @see MirroredTypeException
* @see MirroredTypesException
* @jls 9.6 Annotation Types
* @jls 9.6.1 Annotation Type Elements
* @jls 9.6 Annotation Interfaces
* @jls 9.6.1 Annotation Interface Elements
*/
<A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType);
}

@ -229,7 +229,7 @@ public interface Element extends javax.lang.model.AnnotatedConstruct {
* @see ModuleElement#getEnclosedElements
* @see Elements#getAllMembers
* @jls 8.8.9 Default Constructor
* @jls 8.9 Enum Types
* @jls 8.9 Enum Classes
* @revised 9
*/
List<? extends Element> getEnclosedElements();

@ -91,7 +91,7 @@ public enum NestingKind {
/**
* A class or interface that is a named member of another class or
* interface.
* @jls 8.5 Member Type Declarations
* @jls 8.5 Member Class and Interface Declarations
*/
MEMBER,

@ -116,7 +116,7 @@
* @jls 8.1 Class Declarations
* @jls 8.3 Field Declarations
* @jls 8.4 Method Declarations
* @jls 8.5 Member Type Declarations
* @jls 8.5 Member Class and Interface Declarations
* @jls 8.8 Constructor Declarations
* @jls 9.1 Interface Declarations
* @since 1.6

@ -354,7 +354,7 @@ public interface Elements {
* @param c the construct the annotation mirror modifies
* @param a the annotation mirror being examined
* @jls 9.6.3 Repeatable Annotation Types
* @jls 9.7.5 Multiple Annotations of the Same Type
* @jls 9.7.5 Multiple Annotations of the Same Interface
* @since 9
*/
default Origin getOrigin(AnnotatedConstruct c,
@ -428,7 +428,7 @@ public interface Elements {
* @jls 8.8.9 Default Constructor
* @jls 8.9.3 Enum Members
* @jls 9.6.3 Repeatable Annotation Types
* @jls 9.7.5 Multiple Annotations of the Same Type
* @jls 9.7.5 Multiple Annotations of the Same Interface
*/
MANDATED,

@ -233,15 +233,15 @@ void JfrGTestAdaptiveSampling::test(JfrGTestAdaptiveSampling::incoming inc, size
assertDistributionProperties(100, population, sample, population_size, sample_size, output);
}
TEST_VM_F(JfrGTestAdaptiveSampling, uniform_rate) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_uniform_rate) {
test(&JfrGTestAdaptiveSampling::incoming_uniform, expected_sample_points_per_window, 0.05, "random uniform, all samples");
}
TEST_VM_F(JfrGTestAdaptiveSampling, low_rate) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_low_rate) {
test(&JfrGTestAdaptiveSampling::incoming_low_rate, min_population_per_window, 0.05, "low rate");
}
TEST_VM_F(JfrGTestAdaptiveSampling, high_rate) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_high_rate) {
test(&JfrGTestAdaptiveSampling::incoming_high_rate, expected_sample_points_per_window, 0.02, "high rate");
}
@ -259,23 +259,23 @@ TEST_VM_F(JfrGTestAdaptiveSampling, high_rate) {
// - late end of the second -> each second will have sampled the window set point + accumulated debt for the first 9 windows (i.e. it will have sampled all)
//
TEST_VM_F(JfrGTestAdaptiveSampling, early_burst) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_early_burst) {
test(&JfrGTestAdaptiveSampling::incoming_early_burst, expected_sample_points_per_window, 0.9, "early burst");
}
TEST_VM_F(JfrGTestAdaptiveSampling, mid_burst) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_mid_burst) {
test(&JfrGTestAdaptiveSampling::incoming_mid_burst, expected_sample_points_per_window, 0.5, "mid burst");
}
TEST_VM_F(JfrGTestAdaptiveSampling, late_burst) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_late_burst) {
test(&JfrGTestAdaptiveSampling::incoming_late_burst, expected_sample_points_per_window, 0.0, "late burst");
}
// These are randomized burst tests
TEST_VM_F(JfrGTestAdaptiveSampling, bursty_rate_10_percent) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_bursty_rate_10_percent) {
test(&JfrGTestAdaptiveSampling::incoming_bursty_10_percent, expected_sample_points_per_window, 0.96, "bursty 10%");
}
TEST_VM_F(JfrGTestAdaptiveSampling, bursty_rate_90_percent) {
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_bursty_rate_90_percent) {
test(&JfrGTestAdaptiveSampling::incoming_bursty_10_percent, expected_sample_points_per_window, 0.96, "bursty 90%");
}

@ -28,3 +28,26 @@
#############################################################################
vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java 8205957 generic-all
compiler/blackhole/BlackholeDiagnosticUnlockTest.java 8258101 generic-all
compiler/blackhole/BlackholeInstanceReturnTest.java#c1 8258101 generic-all
compiler/blackhole/BlackholeInstanceReturnTest.java#c1-no-coops 8258101 generic-all
compiler/blackhole/BlackholeInstanceReturnTest.java#c2 8258101 generic-all
compiler/blackhole/BlackholeInstanceReturnTest.java#c2-no-coops 8258101 generic-all
compiler/blackhole/BlackholeInstanceTest.java#c1 8258101 generic-all
compiler/blackhole/BlackholeInstanceTest.java#c1-no-coops 8258101 generic-all
compiler/blackhole/BlackholeInstanceTest.java#c2 8258101 generic-all
compiler/blackhole/BlackholeInstanceTest.java#c2-no-coops 8258101 generic-all
compiler/blackhole/BlackholeNonVoidWarningTest.java 8258101 generic-all
compiler/blackhole/BlackholeNullCheckTest.java#c1 8258101 generic-all
compiler/blackhole/BlackholeNullCheckTest.java#c1-no-coops 8258101 generic-all
compiler/blackhole/BlackholeNullCheckTest.java#c2 8258101 generic-all
compiler/blackhole/BlackholeNullCheckTest.java#c2-no-coops 8258101 generic-all
compiler/blackhole/BlackholeStaticReturnTest.java#c1 8258101 generic-all
compiler/blackhole/BlackholeStaticReturnTest.java#c1-no-coops 8258101 generic-all
compiler/blackhole/BlackholeStaticReturnTest.java#c2 8258101 generic-all
compiler/blackhole/BlackholeStaticReturnTest.java#c2-no-coops 8258101 generic-all
compiler/blackhole/BlackholeStaticTest.java#c1 8258101 generic-all
compiler/blackhole/BlackholeStaticTest.java#c1-no-coops 8258101 generic-all
compiler/blackhole/BlackholeStaticTest.java#c2 8258101 generic-all
compiler/blackhole/BlackholeStaticTest.java#c2-no-coops 8258101 generic-all

@ -44,8 +44,6 @@ compiler/ciReplay/TestSAServer.java 8029528 generic-all
compiler/codecache/jmx/PoolsIndependenceTest.java 8167015 generic-all
compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8225370 generic-all
compiler/jvmci/compilerToVM/GetFlagValueTest.java 8204459 generic-all
compiler/jvmci/compilerToVM/IsMatureVsReprofileTest.java 8257919 generic-all
compiler/jvmci/compilerToVM/ReprofileTest.java 8257919 generic-all
compiler/tiered/LevelTransitionTest.java 8067651 generic-all
compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all

@ -0,0 +1,132 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* 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 8257598
* @summary check that Record::equals uses the fields and not the accessors for the comparison
* @run testng CheckEqualityIsBasedOnFields
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class CheckEqualityIsBasedOnFields {
public record R01(boolean x) {
public boolean x() {
return x ? x : !x;
}
}
public record R02(byte x) {
public byte x() {
return (x >= 50) ? (byte)(x - 50) : x;
}
}
public record R03(short x) {
public short x() {
return (x >= 50) ? (short)(x - 50) : x;
}
}
public record R04(char x) {
public char x() {
return (x >= 50) ? (char)(x - 50) : x;
}
}
public record R05(int x) {
public int x() {
return (x >= 50) ? (x - 50) : x;
}
}
public record R06(long x) {
public long x() {
return (x >= 50) ? (long)(x - 50) : x;
}
}
public record R07(float x) {
public float x() {
return (x >= 50) ? (float)(x - 50) : x;
}
}
public record R08(double x) {
public double x() {
return (x >= 50) ? (double)(x - 50) : x;
}
}
public record R09(String x) {
public String x() {
return (x.length() > 1) ? x.substring(0, 1) : x;
}
}
@DataProvider(name = "recordData")
public Object[][] recordTypeAndExpectedValue() {
return new Object[][] {
new Object[] { R01.class, boolean.class, new Object[]{true, false} },
new Object[] { R02.class, byte.class, new Object[]{(byte)0, (byte)1, (byte)2, (byte)3, (byte)4, (byte)5,
(byte)50, (byte)51, (byte)52, (byte)53, (byte)54, (byte)55} },
new Object[] { R03.class, short.class, new Object[]{(short)0, (short)1, (short)2, (short)3, (short)4, (short)5,
(short)50, (short)51, (short)52, (short)53, (short)54, (short)55} },
new Object[] { R04.class, char.class, new Object[]{(char)0, (char)1, (char)2, (char)3, (char)4, (char)5,
(char)50, (char)51, (char)52, (char)53, (char)54, (char)55} },
new Object[] { R05.class, int.class, new Object[]{0, 1, 2, 3, 4, 5, 50, 51, 52, 53, 54, 55} },
new Object[] { R06.class, long.class, new Object[]{0L, 1L, 2L, 3L, 4L, 5L, 50L, 51L, 52L, 53L, 54L, 55L} },
new Object[] { R07.class, float.class, new Object[]{(float)0, (float)1, (float)2, (float)3, (float)4, (float)5,
(float)50, (float)51, (float)52, (float)53, (float)54, (float)55} },
new Object[] { R08.class, double.class, new Object[]{(double)0, (double)1, (double)2, (double)3, (double)4, (double)5,
(double)50, (double)51, (double)52, (double)53, (double)54, (double)55} },
new Object[] { R09.class, String.class, new Object[]{"1", "2", "3", "4", "5",
"1_", "2_", "3_", "4_", "5_"} },
};
}
@Test(dataProvider = "recordData")
public void testEqualsDoesntUseAccessors(Class<?> clazz, Class<?> componentClass, Object[] expectedXValues) throws Exception {
Constructor<?> ctor;
Method getter, equalsMethod;
ctor = clazz.getConstructor(componentClass);
equalsMethod = clazz.getMethod("equals", Object.class);
getter = clazz.getMethod("x");
for (int i = 0; i < expectedXValues.length / 2; i++) {
Object rec1 = ctor.newInstance(expectedXValues[i]);
Object rec2 = ctor.newInstance(expectedXValues[i + expectedXValues.length / 2]);
System.out.println(rec1.toString());
System.out.println(rec2.toString());
assertFalse((boolean) equalsMethod.invoke(rec1, rec2));
assertNotEquals(expectedXValues[i], expectedXValues[i + expectedXValues.length / 2]);
assertEquals(getter.invoke(rec1), getter.invoke(rec2));
}
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* 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.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ThreadLocalRandom;
import static java.util.concurrent.TimeUnit.DAYS;
/*
* @test
* @bug 8254350
* @run main LostInterrupt
* @summary CompletableFuture.get may swallow interrupt status
* @key randomness
*/
// TODO: Rewrite as a CompletableFuture tck test ?
/**
* Submits a task that completes immediately, then invokes CompletableFuture.get
* with the interrupt status set. CompletableFuture.get should either complete
* immediately with the interrupt status set, or else throw InterruptedException
* with the interrupt status cleared.
*/
public class LostInterrupt {
static final int ITERATIONS = 10_000;
public static void main(String[] args) throws Exception {
ThreadLocalRandom rnd = ThreadLocalRandom.current();
ForkJoinPool executor = new ForkJoinPool(1);
try {
for (int i = 0; i < ITERATIONS; i++) {
CompletableFuture<String> future = new CompletableFuture<>();
boolean timed = rnd.nextBoolean();
executor.execute(() -> future.complete("foo"));
Thread.currentThread().interrupt();
try {
String result = timed ? future.get(1, DAYS) : future.get();
if (!Thread.interrupted())
throw new AssertionError("lost interrupt, run=" + i);
} catch (InterruptedException expected) {
if (Thread.interrupted())
throw new AssertionError(
"interrupt status not cleared, run=" + i);
}
}
} finally {
executor.shutdown();
}
}
}

@ -0,0 +1,90 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* 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.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicReference;
/*
* @test
* @bug 8254350
* @run main SwallowedInterruptedException
* @key randomness
*/
public class SwallowedInterruptedException {
static final int ITERATIONS = 100;
public static void main(String[] args) throws Throwable {
for (int i = 1; i <= ITERATIONS; i++) {
System.out.format("Iteration %d%n", i);
CompletableFuture<Void> future = new CompletableFuture<>();
CountDownLatch running = new CountDownLatch(1);
AtomicReference<String> failed = new AtomicReference<>();
Thread thread = new Thread(() -> {
// signal main thread that child is running
running.countDown();
// invoke Future.get, it complete with the interrupt status set or
// else throw InterruptedException with the interrupt status not set.
try {
future.get();
// interrupt status should be set
if (!Thread.currentThread().isInterrupted()) {
failed.set("Future.get completed with interrupt status not set");
}
} catch (InterruptedException ex) {
// interrupt status should be cleared
if (Thread.currentThread().isInterrupted()) {
failed.set("InterruptedException with interrupt status set");
}
} catch (Throwable ex) {
failed.set("Unexpected exception " + ex);
}
});
thread.setDaemon(true);
thread.start();
// wait for thread to run
running.await();
// interrupt thread and set result after an optional (random) delay
thread.interrupt();
long sleepMillis = ThreadLocalRandom.current().nextLong(10);
if (sleepMillis > 0)
Thread.sleep(sleepMillis);
future.complete(null);
// wait for thread to terminate and check for failure
thread.join();
String failedReason = failed.get();
if (failedReason != null) {
throw new RuntimeException("Test failed: " + failedReason);
}
}
}
}

@ -51,6 +51,7 @@ public class TestHtmlTableTags extends JavadocTester {
javadoc("-d", "out",
"-sourcepath", testSrc,
"-use",
"--no-platform-links",
"pkg1", "pkg2");
checkExit(Exit.OK);
@ -66,6 +67,7 @@ public class TestHtmlTableTags extends JavadocTester {
"-nocomment",
"-sourcepath", testSrc,
"-use",
"--no-platform-links",
"pkg1", "pkg2");
checkExit(Exit.OK);
@ -683,12 +685,8 @@ public class TestHtmlTableTags extends JavadocTester {
// Constant values
checkOutput("constant-values.html", true,
"""
<div class="col-first even-row-color"><code id="pkg1.C1.CONSTANT1">public&nbsp;s\
tatic&nbsp;final&nbsp;<a href="https://download.java.net/java/early_access/jdk17\
/docs/api/java.base/java/lang/String.html" title="class or interface in java.lan\
g" class="external-link">String</a></code></div>
<div class="col-second even-row-color"><code><a href="pkg1/C1.html#CONSTANT1">CO\
NSTANT1</a></code></div>
<div class="col-first even-row-color"><code id="pkg1.C1.CONSTANT1">public&nbsp;static&nbsp;final&nbsp;java.lang.String</code></div>
<div class="col-second even-row-color"><code><a href="pkg1/C1.html#CONSTANT1">CONSTANT1</a></code></div>
<div class="col-last even-row-color"><code>"C1"</code></div>
</div>""");
@ -814,12 +812,8 @@ public class TestHtmlTableTags extends JavadocTester {
// Constant values
checkOutput("constant-values.html", true,
"""
<div class="col-first even-row-color"><code id="pkg1.C1.CONSTANT1">public&nbsp;s\
tatic&nbsp;final&nbsp;<a href="https://download.java.net/java/early_access/jdk17\
/docs/api/java.base/java/lang/String.html" title="class or interface in java.lan\
g" class="external-link">String</a></code></div>
<div class="col-second even-row-color"><code><a href="pkg1/C1.html#CONSTANT1">CO\
NSTANT1</a></code></div>
<div class="col-first even-row-color"><code id="pkg1.C1.CONSTANT1">public&nbsp;static&nbsp;final&nbsp;java.lang.String</code></div>
<div class="col-second even-row-color"><code><a href="pkg1/C1.html#CONSTANT1">CONSTANT1</a></code></div>
<div class="col-last even-row-color"><code>"C1"</code></div>
</div>""");