bool JfrStorage::initialize() {
assert(_control == NULL, "invariant");
assert(_global_mspace == NULL, "invariant");
assert(_thread_local_mspace == NULL, "invariant");
assert(_transient_mspace == NULL, "invariant");
assert(_age_mspace == NULL, "invariant");
const size_t num_global_buffers = (size_t)JfrOptionSet::num_global_buffers();
assert(num_global_buffers >= in_memory_discard_threshold_delta, "invariant");
const size_t memory_size = (size_t)JfrOptionSet::memory_size();
const size_t global_buffer_size = (size_t)JfrOptionSet::global_buffer_size();
const size_t thread_buffer_size = (size_t)JfrOptionSet::thread_buffer_size();
_control = new JfrStorageControl(num_global_buffers, num_global_buffers - in_memory_discard_threshold_delta);
if (_control == NULL) {
return false;
}
_global_mspace = create_mspace<JfrStorageMspace>(global_buffer_size, memory_size, num_global_buffers, this);
if (_global_mspace == NULL) {
return false;
}
_thread_local_mspace = create_mspace<JfrThreadLocalMspace>(thread_buffer_size, unlimited_mspace_size, thread_local_cache_count, this);
if (_thread_local_mspace == NULL) {
return false;
}
_transient_mspace = create_mspace<JfrStorageMspace>(thread_buffer_size * transient_buffer_size_multiplier, unlimited_mspace_size, 0, this);
if (_transient_mspace == NULL) {
return false;
}
_age_mspace = create_mspace<JfrStorageAgeMspace>(0 /* no extra size except header */, unlimited_mspace_size, num_global_buffers, this);
if (_age_mspace == NULL) {
return false;
}
control().set_scavenge_threshold(thread_local_scavenge_threshold);
return true;
}
JfrStorageControl& JfrStorage::control() {
return *instance()._control;
}
static void log_allocation_failure(const char* msg, size_t size) {
if (LogJFR) tty->print_cr("Unable to allocate " SIZE_FORMAT " bytes of %s.", size, msg);
}
BufferPtr JfrStorage::acquire_thread_local(Thread* thread, size_t size /* 0 */) {
BufferPtr buffer = mspace_get_to_full(size, instance()._thread_local_mspace, thread);
if (buffer == NULL) {
log_allocation_failure("thread local_memory", size);
return NULL;
}
assert(buffer->acquired_by_self(), "invariant");
return buffer;
}
BufferPtr JfrStorage::acquire_transient(size_t size, Thread* thread) {
BufferPtr buffer = mspace_allocate_transient_lease_to_full(size, instance()._transient_mspace, thread);
if (buffer == NULL) {
log_allocation_failure("transient memory", size);
return NULL;
}
assert(buffer->acquired_by_self(), "invariant");
assert(buffer->transient(), "invariant");
assert(buffer->lease(), "invariant");
return buffer;
}
static BufferPtr get_lease(size_t size, JfrStorageMspace* mspace, JfrStorage& storage_instance, size_t retry_count, Thread* thread) {
assert(size <= mspace->min_elem_size(), "invariant");
while (true) {
BufferPtr t = mspace_get_free_lease_with_retry(size, mspace, retry_count, thread);
if (t == NULL && storage_instance.control().should_discard()) {
storage_instance.discard_oldest(thread);
continue;
}
return t;
}
}
static BufferPtr get_promotion_buffer(size_t size, JfrStorageMspace* mspace, JfrStorage& storage_instance, size_t retry_count, Thread* thread) {
assert(size <= mspace->min_elem_size(), "invariant");
while (true) {
BufferPtr t = mspace_get_free_with_retry(size, mspace, retry_count, thread);
if (t == NULL && storage_instance.control().should_discard()) {
storage_instance.discard_oldest(thread);
continue;
}
return t;
}
}
static const size_t lease_retry = 10;
BufferPtr JfrStorage::acquire_large(size_t size, Thread* thread) {
JfrStorage& storage_instance = instance();
const size_t max_elem_size = storage_instance._global_mspace->min_elem_size(); // min is also max
if (size < max_elem_size && storage_instance.control().is_global_lease_allowed()) {
BufferPtr const buffer = get_lease(size, storage_instance._global_mspace, storage_instance, lease_retry, thread);
if (buffer != NULL) {
assert(buffer->acquired_by_self(), "invariant");
assert(!buffer->transient(), "invariant");
assert(buffer->lease(), "invariant");
storage_instance.control().increment_leased();
return buffer;
}
}
return acquire_transient(size, thread);
}
static void write_data_loss_event(JfrBuffer* buffer, u8 unflushed_size, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(buffer->empty(), "invariant");
const u8 total_data_loss = thread->jfr_thread_local()->add_data_lost(unflushed_size);
if (EventDataLoss::is_enabled()) {
JfrNativeEventWriter writer(buffer, thread);
writer.write<u8>(EventDataLoss::eventId);
writer.write(JfrTicks::now());
writer.write(unflushed_size);
writer.write(total_data_loss);
}
}
static void write_data_loss(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
const size_t unflushed_size = buffer->unflushed_size();
buffer->concurrent_reinitialization();
if (unflushed_size == 0) {
return;
}
write_data_loss_event(buffer, unflushed_size, thread);
}
static const size_t promotion_retry = 100;
bool JfrStorage::flush_regular_buffer(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(!buffer->lease(), "invariant");
assert(!buffer->transient(), "invariant");
const size_t unflushed_size = buffer->unflushed_size();
if (unflushed_size == 0) {
buffer->concurrent_reinitialization();
assert(buffer->empty(), "invariant");
return true;
}
BufferPtr const promotion_buffer = get_promotion_buffer(unflushed_size, _global_mspace, *this, promotion_retry, thread);
if (promotion_buffer == NULL) {
write_data_loss(buffer, thread);
return false;
}
if (!JfrRecorder::is_shutting_down()) {
assert(promotion_buffer->acquired_by_self(), "invariant");
}
assert(promotion_buffer->free_size() >= unflushed_size, "invariant");
buffer->concurrent_move_and_reinitialize(promotion_buffer, unflushed_size);
assert(buffer->empty(), "invariant");
return true;
}
void JfrStorage::release_large(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(buffer->lease(), "invariant");
assert(buffer->acquired_by_self(), "invariant");
buffer->clear_lease();
if (buffer->transient()) {
buffer->set_retired();
register_full(buffer, thread);
} else {
buffer->release();
control().decrement_leased();
}
}
static JfrAgeNode* new_age_node(BufferPtr buffer, JfrStorageAgeMspace* age_mspace, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(age_mspace != NULL, "invariant");
return mspace_allocate_transient(0, age_mspace, thread);
}
static void log_registration_failure(size_t unflushed_size) {
if (LogJFR) tty->print_cr("Unable to register a full buffer of " SIZE_FORMAT " bytes.", unflushed_size);
if (LogJFR) tty->print_cr("Cleared 1 full buffer of " SIZE_FORMAT " bytes.", unflushed_size);
}
static void handle_registration_failure(BufferPtr buffer) {
assert(buffer != NULL, "invariant");
assert(buffer->retired(), "invariant");
const size_t unflushed_size = buffer->unflushed_size();
buffer->reinitialize();
log_registration_failure(unflushed_size);
}
static JfrAgeNode* get_free_age_node(JfrStorageAgeMspace* age_mspace, Thread* thread) {
assert(JfrBuffer_lock->owned_by_self(), "invariant");
return mspace_get_free_with_detach(0, age_mspace, thread);
}
static bool insert_full_age_node(JfrAgeNode* age_node, JfrStorageAgeMspace* age_mspace, Thread* thread) {
assert(JfrBuffer_lock->owned_by_self(), "invariant");
assert(age_node->retired_buffer()->retired(), "invariant");
age_mspace->insert_full_head(age_node);
return true;
}
static bool full_buffer_registration(BufferPtr buffer, JfrStorageAgeMspace* age_mspace, JfrStorageControl& control, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(buffer->retired(), "invariant");
assert(age_mspace != NULL, "invariant");
MutexLockerEx lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
JfrAgeNode* age_node = get_free_age_node(age_mspace, thread);
if (age_node == NULL) {
age_node = new_age_node(buffer, age_mspace, thread);
if (age_node == NULL) {
return false;
}
}
assert(age_node->acquired_by_self(), "invariant");
assert(age_node != NULL, "invariant");
age_node->set_retired_buffer(buffer);
control.increment_full();
return insert_full_age_node(age_node, age_mspace, thread);
}
void JfrStorage::register_full(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(buffer->retired(), "invariant");
assert(buffer->acquired_by(thread), "invariant");
if (!full_buffer_registration(buffer, _age_mspace, control(), thread)) {
handle_registration_failure(buffer);
}
if (control().should_post_buffer_full_message()) {
_post_box.post(MSG_FULLBUFFER);
}
}
void JfrStorage::lock() {
assert(!JfrBuffer_lock->owned_by_self(), "invariant");
JfrBuffer_lock->lock_without_safepoint_check();
}
void JfrStorage::unlock() {
assert(JfrBuffer_lock->owned_by_self(), "invariant");
JfrBuffer_lock->unlock();
}
#ifdef ASSERT
bool JfrStorage::is_locked() const {
return JfrBuffer_lock->owned_by_self();
}
#endif
void JfrStorage::release(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(!buffer->lease(), "invariant");
assert(!buffer->transient(), "invariant");
assert(!buffer->retired(), "invariant");
if (!buffer->empty()) {
if (!flush_regular_buffer(buffer, thread)) {
buffer->concurrent_reinitialization();
}
}
assert(buffer->empty(), "invariant");
assert(buffer->identity() != NULL, "invariant");
control().increment_dead();
buffer->set_retired();
}
void JfrStorage::release_thread_local(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
JfrStorage& storage_instance = instance();
storage_instance.release(buffer, thread);
if (storage_instance.control().should_scavenge()) {
storage_instance._post_box.post(MSG_DEADBUFFER);
}
}
static void log_discard(size_t count, size_t amount, size_t current) {
assert(count > 0, "invariant");
if (LogJFR) tty->print_cr("Cleared " SIZE_FORMAT " full buffer(s) of " SIZE_FORMAT" bytes.", count, amount);
if (LogJFR) tty->print_cr("Current number of full buffers " SIZE_FORMAT "", current);
}
void JfrStorage::discard_oldest(Thread* thread) {
if (JfrBuffer_lock->try_lock()) {
if (!control().should_discard()) {
return;
}
const size_t num_full_pre_discard = control().full_count();
size_t num_full_post_discard = 0;
size_t discarded_size = 0;
while (true) {
JfrAgeNode* const oldest_age_node = _age_mspace->full_tail();
if (oldest_age_node == NULL) {
break;
}
BufferPtr const buffer = oldest_age_node->retired_buffer();
assert(buffer->retired(), "invariant");
discarded_size += buffer->unflushed_size();
num_full_post_discard = control().decrement_full();
if (buffer->transient()) {
mspace_release_full(buffer, _transient_mspace);
mspace_release_full(oldest_age_node, _age_mspace);
continue;
} else {
mspace_release_full(oldest_age_node, _age_mspace);
buffer->reinitialize();
buffer->release(); // pusb
break;
}
}
JfrBuffer_lock->unlock();
const size_t number_of_discards = num_full_pre_discard - num_full_post_discard;
if (number_of_discards > 0) {
log_discard(number_of_discards, discarded_size, num_full_post_discard);
}
}
}
#ifdef ASSERT
typedef const BufferPtr ConstBufferPtr;
static void assert_flush_precondition(ConstBufferPtr cur, size_t used, bool native, const Thread* t) {
assert(t != NULL, "invariant");
assert(cur != NULL, "invariant");
assert(cur->pos() + used <= cur->end(), "invariant");
assert(native ? t->jfr_thread_local()->native_buffer() == cur : t->jfr_thread_local()->java_buffer() == cur, "invariant");
}
static void assert_flush_regular_precondition(ConstBufferPtr cur, const u1* const cur_pos, size_t used, size_t req, const Thread* t) {
assert(t != NULL, "invariant");
assert(t->jfr_thread_local()->shelved_buffer() == NULL, "invariant");
assert(cur != NULL, "invariant");
assert(!cur->lease(), "invariant");
assert(cur_pos != NULL, "invariant");
assert(req >= used, "invariant");
}
static void assert_provision_large_precondition(ConstBufferPtr cur, size_t used, size_t req, const Thread* t) {
assert(cur != NULL, "invariant");
assert(t != NULL, "invariant");
assert(t->jfr_thread_local()->shelved_buffer() != NULL, "invariant");
assert(req >= used, "invariant");
}
static void assert_flush_large_precondition(ConstBufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
assert(t != NULL, "invariant");
assert(cur != NULL, "invariant");
assert(cur->lease(), "invariant");
assert(cur_pos != NULL, "invariant");
assert(native ? t->jfr_thread_local()->native_buffer() == cur : t->jfr_thread_local()->java_buffer() == cur, "invariant");
assert(t->jfr_thread_local()->shelved_buffer() != NULL, "invariant");
assert(req >= used, "invariant");
assert(cur != t->jfr_thread_local()->shelved_buffer(), "invariant");
}
#endif // ASSERT
BufferPtr JfrStorage::flush(BufferPtr cur, size_t used, size_t req, bool native, Thread* t) {
debug_only(assert_flush_precondition(cur, used, native, t);)
const u1* const cur_pos = cur->pos();
req += used;
return cur->lease() ? instance().flush_large(cur, cur_pos, used, req, native, t) :
instance().flush_regular(cur, cur_pos, used, req, native, t);
}
BufferPtr JfrStorage::flush_regular(BufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
debug_only(assert_flush_regular_precondition(cur, cur_pos, used, req, t);)
if (!cur->empty()) {
flush_regular_buffer(cur, t);
}
assert(t->jfr_thread_local()->shelved_buffer() == NULL, "invariant");
if (cur->free_size() >= req) {
if (used > 0) {
memmove(cur->pos(), (void*)cur_pos, used);
}
assert(native ? t->jfr_thread_local()->native_buffer() == cur : t->jfr_thread_local()->java_buffer() == cur, "invariant");
return cur;
}
t->jfr_thread_local()->shelve_buffer(cur);
return provision_large(cur, cur_pos, used, req, native, t);
}
static BufferPtr store_buffer_to_thread_local(BufferPtr buffer, JfrThreadLocal* jfr_thread_local, bool native) {
assert(buffer != NULL, "invariant");
if (native) {
jfr_thread_local->set_native_buffer(buffer);
} else {
jfr_thread_local->set_java_buffer(buffer);
}
return buffer;
}
static BufferPtr restore_shelved_buffer(bool native, Thread* t) {
JfrThreadLocal* const tl = t->jfr_thread_local();
BufferPtr shelved = tl->shelved_buffer();
assert(shelved != NULL, "invariant");
tl->shelve_buffer(NULL);
return store_buffer_to_thread_local(shelved, tl, native);
}
BufferPtr JfrStorage::flush_large(BufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
debug_only(assert_flush_large_precondition(cur, cur_pos, used, req, native, t);)
BufferPtr shelved = t->jfr_thread_local()->shelved_buffer();
assert(shelved != NULL, "invariant");
if (shelved->free_size() >= req) {
if (req > 0) {
memcpy(shelved->pos(), (void*)cur_pos, (size_t)used);
}
release_large(cur, t);
return restore_shelved_buffer(native, t);
}
return provision_large(cur, cur_pos, used, req, native, t);
}
static BufferPtr large_fail(BufferPtr cur, bool native, JfrStorage& storage_instance, Thread* t) {
assert(cur != NULL, "invariant");
assert(t != NULL, "invariant");
if (cur->lease()) {
storage_instance.release_large(cur, t);
}
return restore_shelved_buffer(native, t);
}
BufferPtr JfrStorage::provision_large(BufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
debug_only(assert_provision_large_precondition(cur, used, req, t);)
assert(t->jfr_thread_local()->shelved_buffer() != NULL, "invariant");
BufferPtr const buffer = acquire_large(req, t);
if (buffer == NULL) {
return large_fail(cur, native, *this, t);
}
assert(buffer->free_size() >= req, "invariant");
assert(buffer->lease(), "invariant");
memcpy(buffer->pos(), (void*)cur_pos, used);
if (cur->lease()) {
release_large(cur, t);
}
return store_buffer_to_thread_local(buffer, t->jfr_thread_local(), native);
}
typedef UnBufferedWriteToChunk<JfrBuffer> WriteOperation;
typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
typedef ConcurrentWriteOp<WriteOperation> ConcurrentWriteOperation;
typedef ConcurrentWriteOpExcludeRetired<WriteOperation> ThreadLocalConcurrentWriteOperation;
size_t JfrStorage::write() {
const size_t full_size_processed = write_full();
WriteOperation wo(_chunkwriter);
ThreadLocalConcurrentWriteOperation tlwo(wo);
process_full_list(tlwo, _thread_local_mspace);
ConcurrentWriteOperation cwo(wo);
process_free_list(cwo, _global_mspace);
return full_size_processed + wo.processed();
}
size_t JfrStorage::write_at_safepoint() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
WriteOperation wo(_chunkwriter);
MutexedWriteOperation writer(wo); // mutexed write mode
process_full_list(writer, _thread_local_mspace);
assert(_transient_mspace->is_free_empty(), "invariant");
process_full_list(writer, _transient_mspace);
assert(_global_mspace->is_full_empty(), "invariant");
process_free_list(writer, _global_mspace);
return wo.processed();
}
typedef DiscardOp<DefaultDiscarder<JfrStorage::Buffer> > DiscardOperation;
typedef ReleaseOp<JfrStorageMspace> ReleaseOperation;
typedef CompositeOperation<MutexedWriteOperation, ReleaseOperation> FullOperation;
size_t JfrStorage::clear() {
const size_t full_size_processed = clear_full();
DiscardOperation discarder(concurrent); // concurrent discard mode
process_full_list(discarder, _thread_local_mspace);
assert(_transient_mspace->is_free_empty(), "invariant");
process_full_list(discarder, _transient_mspace);
assert(_global_mspace->is_full_empty(), "invariant");
process_free_list(discarder, _global_mspace);
return full_size_processed + discarder.processed();
}
static void insert_free_age_nodes(JfrStorageAgeMspace* age_mspace, JfrAgeNode* head, JfrAgeNode* tail, size_t count) {
if (tail != NULL) {
assert(tail->next() == NULL, "invariant");
assert(head != NULL, "invariant");
assert(head->prev() == NULL, "invariant");
MutexLockerEx buffer_lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
age_mspace->insert_free_tail(head, tail, count);
}
}
template <typename Processor>
static void process_age_list(Processor& processor, JfrStorageAgeMspace* age_mspace, JfrAgeNode* head, size_t count) {
assert(age_mspace != NULL, "invariant");
assert(head != NULL, "invariant");
assert(count > 0, "invariant");
JfrAgeNode* node = head;
JfrAgeNode* last = NULL;
while (node != NULL) {
last = node;
BufferPtr const buffer = node->retired_buffer();
assert(buffer != NULL, "invariant");
assert(buffer->retired(), "invariant");
processor.process(buffer);
node->clear_identity();
JfrAgeNode* const next = (JfrAgeNode*)node->next();
if (node->transient()) {
last = (JfrAgeNode*)last->prev();
if (last != NULL) {
last->set_next(next);
} else {
head = next;
}
if (next != NULL) {
next->set_prev(last);
}
--count;
age_mspace->deallocate(node);
}
node = next;
}
insert_free_age_nodes(age_mspace, head, last, count);
}
template <typename Processor>
static size_t process_full(Processor& processor, JfrStorageControl& control, JfrStorageAgeMspace* age_mspace) {
assert(age_mspace != NULL, "invariant");
if (age_mspace->is_full_empty()) {
return 0;
}
size_t count;
JfrAgeNode* head;
{
MutexLockerEx buffer_lock(JfrBuffer_lock, Mutex::_no_safepoint_check_flag);
count = age_mspace->full_count();
head = age_mspace->clear_full();
control.reset_full();
}
assert(head != NULL, "invariant");
assert(count > 0, "invariant");
process_age_list(processor, age_mspace, head, count);
return count;
}
static void log(size_t count, size_t amount, bool clear = false) {
if (count > 0) {
if (LogJFR) tty->print_cr("%s " SIZE_FORMAT " full buffer(s) of " SIZE_FORMAT" B of data%s",
clear ? "Discarded" : "Wrote", count, amount, clear ? "." : " to chunk.");
}
}
size_t JfrStorage::write_full() {
assert(_chunkwriter.is_valid(), "invariant");
Thread* const thread = Thread::current();
WriteOperation wo(_chunkwriter);
MutexedWriteOperation writer(wo); // a retired buffer implies mutexed access
ReleaseOperation ro(_transient_mspace, thread);
FullOperation cmd(&writer, &ro);
const size_t count = process_full(cmd, control(), _age_mspace);
log(count, writer.processed());
return writer.processed();
}
size_t JfrStorage::clear_full() {
DiscardOperation discarder(mutexed); // a retired buffer implies mutexed access
const size_t count = process_full(discarder, control(), _age_mspace);
log(count, discarder.processed(), true);
return discarder.processed();
}
static void scavenge_log(size_t count, size_t amount, size_t current) {
if (count > 0) {
if (LogJFR) tty->print_cr("Released " SIZE_FORMAT " dead buffer(s) of " SIZE_FORMAT" B of data.", count, amount);
if (LogJFR) tty->print_cr("Current number of dead buffers " SIZE_FORMAT "", current);
}
}
template <typename Mspace>
class Scavenger {
private:
JfrStorageControl& _control;
Mspace* _mspace;
size_t _count;
size_t _amount;
public:
typedef typename Mspace::Type Type;
Scavenger(JfrStorageControl& control, Mspace* mspace) : _control(control), _mspace(mspace), _count(0), _amount(0) {}
bool process(Type* t) {
if (t->retired()) {
assert(t->identity() != NULL, "invariant");
assert(t->empty(), "invariant");
assert(!t->transient(), "invariant");
assert(!t->lease(), "invariant");
++_count;
_amount += t->total_size();
t->clear_retired();
t->release();
_control.decrement_dead();
mspace_release_full_critical(t, _mspace);
}
return true;
}
size_t processed() const { return _count; }
size_t amount() const { return _amount; }
};
size_t JfrStorage::scavenge() {
JfrStorageControl& ctrl = control();
if (ctrl.dead_count() == 0) {
return 0;
}
Scavenger<JfrThreadLocalMspace> scavenger(ctrl, _thread_local_mspace);
process_full_list(scavenger, _thread_local_mspace);
scavenge_log(scavenger.processed(), scavenger.amount(), ctrl.dead_count());
return scavenger.processed();
}
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrStorage.hpp
#ifndef SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGE_HPP
#define SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGE_HPP
#include "jfr/recorder/storage/jfrBuffer.hpp"
#include "jfr/recorder/storage/jfrMemorySpace.hpp"
#include "jfr/recorder/storage/jfrMemorySpaceRetrieval.hpp"
class JfrChunkWriter;
class JfrPostBox;
class JfrStorage;
class JfrStorageControl;
typedef JfrMemorySpace<JfrBuffer, JfrMspaceAlternatingRetrieval, JfrStorage> JfrStorageMspace;
typedef JfrMemorySpace<JfrBuffer, JfrThreadLocalRetrieval, JfrStorage> JfrThreadLocalMspace;
typedef JfrMemorySpace<JfrAgeNode, JfrMspaceSequentialRetrieval, JfrStorage> JfrStorageAgeMspace;
class JfrStorage : public JfrCHeapObj {
public:
typedef JfrStorageMspace::Type Buffer;
private:
JfrStorageControl* _control;
JfrStorageMspace* _global_mspace;
JfrThreadLocalMspace* _thread_local_mspace;
JfrStorageMspace* _transient_mspace;
JfrStorageAgeMspace* _age_mspace;
JfrChunkWriter& _chunkwriter;
JfrPostBox& _post_box;
void register_full(Buffer* t, Thread* thread);
void lock();
void unlock();
DEBUG_ONLY(bool is_locked() const;)
Buffer* acquire_large(size_t size, Thread* t);
Buffer* acquire_transient(size_t size, Thread* thread);
bool flush_regular_buffer(Buffer* const buffer, Thread* t);
Buffer* flush_regular(Buffer* cur, const u1* cur_pos, size_t used, size_t req, bool native, Thread* t);
Buffer* flush_large(Buffer* cur, const u1* cur_pos, size_t used, size_t req, bool native, Thread* t);
Buffer* provision_large(Buffer* cur, const u1* cur_pos, size_t used, size_t req, bool native, Thread* t);
void release(Buffer* buffer, Thread* t);
size_t clear();
size_t clear_full();
size_t write();
size_t write_full();
size_t write_at_safepoint();
size_t scavenge();
JfrStorage(JfrChunkWriter& cw, JfrPostBox& post_box);
~JfrStorage();
static JfrStorage& instance();
static JfrStorage* create(JfrChunkWriter& chunkwriter, JfrPostBox& post_box);
bool initialize();
static void destroy();
public:
static Buffer* acquire_thread_local(Thread* t, size_t size = 0);
static void release_thread_local(Buffer* buffer, Thread* t);
void release_large(Buffer* const buffer, Thread* t);
static Buffer* flush(Buffer* cur, size_t used, size_t req, bool native, Thread* t);
void discard_oldest(Thread* t);
static JfrStorageControl& control();
friend class JfrRecorder;
friend class JfrRecorderService;
template <typename, template <typename> class, typename>
friend class JfrMemorySpace;
};
#endif // SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrStorageControl.cpp
#include "precompiled.hpp"
#include "jfr/recorder/storage/jfrStorageControl.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.inline.hpp"
static jlong atomic_add(size_t value, size_t volatile* const dest) {
size_t compare_value;
size_t exchange_value;
do {
compare_value = OrderAccess::load_ptr_acquire((intptr_t*)dest);
exchange_value = compare_value + value;
} while ((unsigned long)Atomic::cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value) != compare_value);
return exchange_value;
}
static jlong atomic_dec(size_t volatile* const dest) {
size_t compare_value;
size_t exchange_value;
do {
compare_value = OrderAccess::load_ptr_acquire((intptr_t*)dest);
assert(compare_value >= 1, "invariant");
exchange_value = compare_value - 1;
} while ((unsigned long)Atomic::cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value) != compare_value);
return exchange_value;
}
const size_t max_lease_factor = 2;
JfrStorageControl::JfrStorageControl(size_t global_count_total, size_t in_memory_discard_threshold) :
_global_count_total(global_count_total),
_full_count(0),
_global_lease_count(0),
_dead_count(0),
_to_disk_threshold(0),
_in_memory_discard_threshold(in_memory_discard_threshold),
_global_lease_threshold(global_count_total / max_lease_factor),
_scavenge_threshold(0),
_to_disk(false) {}
bool JfrStorageControl::to_disk() const {
return _to_disk;
}
void JfrStorageControl::set_to_disk(bool enable) {
_to_disk = enable;
}
size_t JfrStorageControl::full_count() const {
return _full_count;
}
size_t JfrStorageControl::increment_full() {
assert(JfrBuffer_lock->owned_by_self(), "invariant");
return ++_full_count;
}
size_t JfrStorageControl::decrement_full() {
assert(JfrBuffer_lock->owned_by_self(), "invariant");
assert(_full_count > 0, "invariant");
return --_full_count;
}
void JfrStorageControl::reset_full() {
assert(JfrBuffer_lock->owned_by_self(), "invariant");
_full_count = 0;
}
bool JfrStorageControl::should_post_buffer_full_message() const {
return to_disk() && (full_count() > _to_disk_threshold);
}
bool JfrStorageControl::should_discard() const {
return !to_disk() && full_count() >= _in_memory_discard_threshold;
}
size_t JfrStorageControl::global_lease_count() const {
return (size_t)OrderAccess::load_ptr_acquire((intptr_t*)&_global_lease_count);
}
size_t JfrStorageControl::increment_leased() {
return atomic_add(1, &_global_lease_count);
}
size_t JfrStorageControl::decrement_leased() {
return atomic_dec(&_global_lease_count);
}
bool JfrStorageControl::is_global_lease_allowed() const {
return global_lease_count() <= _global_lease_threshold;
}
size_t JfrStorageControl::dead_count() const {
return _dead_count;
}
size_t JfrStorageControl::increment_dead() {
return atomic_add(1, &_dead_count);
}
size_t JfrStorageControl::decrement_dead() {
return atomic_dec(&_dead_count);
}
bool JfrStorageControl::should_scavenge() const {
return dead_count() >= _scavenge_threshold;
}
void JfrStorageControl::set_scavenge_threshold(size_t number_of_dead_buffers) {
_scavenge_threshold = number_of_dead_buffers;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrStorageControl.hpp
#ifndef SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGECONTROL_HPP
#define SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGECONTROL_HPP
#include "jfr/utilities/jfrAllocation.hpp"
class JfrStorageControl : public JfrCHeapObj {
private:
size_t _global_count_total;
size_t _full_count;
volatile size_t _global_lease_count;
volatile size_t _dead_count;
size_t _to_disk_threshold;
size_t _in_memory_discard_threshold;
size_t _global_lease_threshold;
size_t _scavenge_threshold;
bool _to_disk;
public:
JfrStorageControl(size_t global_count_total, size_t in_memory_discard_threshold);
void set_to_disk(bool enable);
bool to_disk() const;
size_t full_count() const;
size_t increment_full();
size_t decrement_full();
void reset_full();
bool should_post_buffer_full_message() const;
bool should_discard() const;
size_t global_lease_count() const;
size_t increment_leased();
size_t decrement_leased();
bool is_global_lease_allowed() const;
size_t dead_count() const;
size_t increment_dead();
size_t decrement_dead();
void set_scavenge_threshold(size_t number_of_dead_buffers);
bool should_scavenge() const;
};
#endif // SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGECONTROL_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrStorageUtils.hpp
#ifndef SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_HPP
#define SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_HPP
#include "jfr/recorder/storage/jfrBuffer.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/utilities/jfrAllocation.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "runtime/thread.hpp"
template <typename Operation, typename NextOperation>
class CompositeOperation {
private:
Operation* _op;
NextOperation* _next;
public:
CompositeOperation(Operation* op, NextOperation* next) : _op(op), _next(next) {
assert(_op != NULL, "invariant");
}
typedef typename Operation::Type Type;
bool process(Type* t = NULL) {
return _next == NULL ? _op->process(t) : _op->process(t) && _next->process(t);
}
size_t processed() const {
return _next == NULL ? _op->processed() : _op->processed() + _next->processed();
}
};
template <typename T>
class UnBufferedWriteToChunk {
private:
JfrChunkWriter& _writer;
size_t _processed;
public:
typedef T Type;
UnBufferedWriteToChunk(JfrChunkWriter& writer) : _writer(writer), _processed(0) {}
bool write(Type* t, const u1* data, size_t size);
size_t processed() { return _processed; }
};
template <typename T>
class DefaultDiscarder {
private:
size_t _processed;
public:
typedef T Type;
DefaultDiscarder() : _processed() {}
bool discard(Type* t, const u1* data, size_t size);
size_t processed() const { return _processed; }
};
template <typename Operation>
class ConcurrentWriteOp {
private:
Operation& _operation;
public:
typedef typename Operation::Type Type;
ConcurrentWriteOp(Operation& operation) : _operation(operation) {}
bool process(Type* t);
size_t processed() const { return _operation.processed(); }
};
template <typename Operation>
class ConcurrentWriteOpExcludeRetired : private ConcurrentWriteOp<Operation> {
public:
typedef typename Operation::Type Type;
ConcurrentWriteOpExcludeRetired(Operation& operation) : ConcurrentWriteOp<Operation>(operation) {}
bool process(Type* t);
size_t processed() const { return ConcurrentWriteOp<Operation>::processed(); }
};
template <typename Operation>
class MutexedWriteOp {
private:
Operation& _operation;
public:
typedef typename Operation::Type Type;
MutexedWriteOp(Operation& operation) : _operation(operation) {}
bool process(Type* t);
size_t processed() const { return _operation.processed(); }
};
template <typename Operation>
class ExclusiveOp : private MutexedWriteOp<Operation> {
public:
typedef typename Operation::Type Type;
ExclusiveOp(Operation& operation) : MutexedWriteOp<Operation>(operation) {}
bool process(Type* t);
size_t processed() const { return MutexedWriteOp<Operation>::processed(); }
};
enum jfr_operation_mode {
mutexed = 1,
concurrent
};
template <typename Operation>
class DiscardOp {
private:
Operation _operation;
jfr_operation_mode _mode;
public:
typedef typename Operation::Type Type;
DiscardOp(jfr_operation_mode mode = concurrent) : _operation(), _mode(mode) {}
bool process(Type* t);
size_t processed() const { return _operation.processed(); }
};
#endif // SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp
#ifndef SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP
#define SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP
#include "jfr/recorder/storage/jfrStorageUtils.hpp"
#include "runtime/thread.inline.hpp"
template <typename T>
inline bool UnBufferedWriteToChunk<T>::write(T* t, const u1* data, size_t size) {
_writer.write_unbuffered(data, size);
_processed += size;
return true;
}
template <typename T>
inline bool DefaultDiscarder<T>::discard(T* t, const u1* data, size_t size) {
_processed += size;
return true;
}
template <typename Operation>
inline bool ConcurrentWriteOp<Operation>::process(typename Operation::Type* t) {
const u1* const current_top = t->concurrent_top();
const size_t unflushed_size = t->pos() - current_top;
if (unflushed_size == 0) {
t->set_concurrent_top(current_top);
return true;
}
const bool result = _operation.write(t, current_top, unflushed_size);
t->set_concurrent_top(current_top + unflushed_size);
return result;
}
template <typename Operation>
inline bool ConcurrentWriteOpExcludeRetired<Operation>::process(typename Operation::Type* t) {
if (t->retired()) {
assert(t->empty(), "invariant");
return true;
}
return ConcurrentWriteOp<Operation>::process(t);
}
template <typename Operation>
inline bool MutexedWriteOp<Operation>::process(typename Operation::Type* t) {
assert(t != NULL, "invariant");
const u1* const current_top = t->top();
const size_t unflushed_size = t->pos() - current_top;
if (unflushed_size == 0) {
return true;
}
const bool result = _operation.write(t, current_top, unflushed_size);
t->set_top(current_top + unflushed_size);
return result;
}
template <typename Type>
static void retired_sensitive_acquire(Type* t) {
assert(t != NULL, "invariant");
if (t->retired()) {
return;
}
Thread* const thread = Thread::current();
while (!t->try_acquire(thread)) {
if (t->retired()) {
return;
}
}
}
template <typename Operation>
inline bool ExclusiveOp<Operation>::process(typename Operation::Type* t) {
retired_sensitive_acquire(t);
assert(t->acquired_by_self() || t->retired(), "invariant");
return MutexedWriteOp<Operation>::process(t);
}
template <typename Operation>
inline bool DiscardOp<Operation>::process(typename Operation::Type* t) {
assert(t != NULL, "invariant");
const u1* const current_top = _mode == concurrent ? t->concurrent_top() : t->top();
const size_t unflushed_size = t->pos() - current_top;
if (unflushed_size == 0) {
if (_mode == concurrent) {
t->set_concurrent_top(current_top);
}
return true;
}
const bool result = _operation.discard(t, current_top, unflushed_size);
if (_mode == concurrent) {
t->set_concurrent_top(current_top + unflushed_size);
} else {
t->set_top(current_top + unflushed_size);
}
return result;
}
#endif // SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrVirtualMemory.cpp
#include "precompiled.hpp"
#include "jfr/recorder/storage/jfrVirtualMemory.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/virtualspace.hpp"
#include "runtime/os.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
class JfrVirtualMemorySegment : public JfrCHeapObj {
friend class JfrVirtualMemoryManager;
private:
JfrVirtualMemorySegment* _next;
char* _top;
ReservedSpace _rs;
VirtualSpace _virtual_memory;
const u1* committed_low() const { return (const u1*)_virtual_memory.low(); }
const u1* committed_high() const { return (const u1*)_virtual_memory.high(); }
const u1* reserved_low() const { return (const u1*)_virtual_memory.low_boundary(); }
const u1* reserved_high() const { return (const u1*)_virtual_memory.high_boundary(); }
size_t reserved_words() const { return _virtual_memory.reserved_size() / BytesPerWord; }
size_t committed_words() const { return _virtual_memory.actual_committed_size() / BytesPerWord; }
bool is_pre_committed() const { return _virtual_memory.special(); }
VirtualSpace& virtual_space() { return _virtual_memory; }
JfrVirtualMemorySegment();
~JfrVirtualMemorySegment();
JfrVirtualMemorySegment* next() const { return _next; }
void set_next(JfrVirtualMemorySegment* v) { _next = v; }
bool is_available(size_t block_size_request_words) {
return block_size_request_words <= pointer_delta(committed_high(), _top, sizeof(char*));
}
char* top() const { return _top; }
void inc_top(size_t size_in_words) {
assert(is_available(size_in_words), "invariant");
_top += size_in_words * BytesPerWord;
assert(_top <= _virtual_memory.high(), "invariant");
}
bool initialize(size_t reservation_size_request_bytes);
void* take_from_committed(size_t block_size_request_words);
void* commit(size_t block_size_request_words) {
return take_from_committed(block_size_request_words);
}
bool expand_by(size_t block_size_request_words);
void decommit();
};
JfrVirtualMemorySegment::JfrVirtualMemorySegment() :
_next(NULL),
_top(NULL),
_rs(),
_virtual_memory() {}
JfrVirtualMemorySegment::~JfrVirtualMemorySegment() {
decommit();
_rs.release();
}
bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes) {
assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant");
_rs = ReservedSpace(reservation_size_request_bytes,
os::vm_allocation_granularity(),
UseLargePages && os::can_commit_large_page_memory(),
false);
if (!_rs.is_reserved()) {
return false;
}
assert(_rs.base() != NULL, "invariant");
assert(_rs.size() != 0, "invariant");
assert(is_aligned(_rs.base(), os::vm_allocation_granularity()), "invariant");
assert(is_aligned(_rs.size(), os::vm_allocation_granularity()), "invariant");
os::trace_page_sizes("Jfr", reservation_size_request_bytes,
reservation_size_request_bytes,
os::vm_page_size(),
_rs.base(),
_rs.size());
MemTracker::record_virtual_memory_type((address)_rs.base(), mtTracing);
assert(is_aligned(_rs.base(), os::vm_page_size()), "invariant");
assert(is_aligned(_rs.size(), os::vm_page_size()), "invariant");
const size_t pre_committed_size = _rs.special() ? _rs.size() : 0;
const bool result = virtual_space().initialize_with_granularity(_rs, pre_committed_size, os::vm_page_size());
if (result) {
assert(virtual_space().committed_size() == virtual_space().actual_committed_size(),
"Checking that the pre-committed memory was registered by the VirtualSpace");
_top = virtual_space().low();
}
return result;
}
bool JfrVirtualMemorySegment::expand_by(size_t block_size_request_words) {
size_t block_size_request_bytes = block_size_request_words * BytesPerWord;
const size_t uncommitted = virtual_space().reserved_size() - virtual_space().actual_committed_size();
if (uncommitted < block_size_request_bytes) {
block_size_request_bytes = uncommitted;
}
assert(is_aligned(block_size_request_bytes, os::vm_allocation_granularity()), "invariant");
bool result = virtual_space().expand_by(block_size_request_bytes, false);
assert(result, "Failed to commit memory");
return result;
}
void JfrVirtualMemorySegment::decommit() {
assert(_virtual_memory.committed_size() == _virtual_memory.actual_committed_size(),
"The committed memory doesn't match the expanded memory.");
const size_t committed_size = virtual_space().actual_committed_size();
if (committed_size > 0) {
virtual_space().shrink_by(committed_size);
}
assert(_virtual_memory.actual_committed_size() == 0, "invariant");
}
void* JfrVirtualMemorySegment::take_from_committed(size_t block_size_request_words) {
assert(_virtual_memory.committed_size() == _virtual_memory.actual_committed_size(),
"The committed memory doesn't match the expanded memory.");
if (!is_available(block_size_request_words)) {
return NULL;
}
void* const block = top();
assert(block != NULL, "invariant");
inc_top(block_size_request_words);
return block;
}
class JfrVirtualMemoryManager : public JfrCHeapObj {
typedef JfrVirtualMemorySegment Segment;
private:
Segment* _segments;
Segment* _current_segment;
size_t _reservation_size_request_words;
size_t _reservation_size_request_limit_words; // total reservation limit
size_t _current_reserved_words;
size_t _current_committed_words;
void link(Segment* segment);
Segment* current();
void inc_reserved_words(size_t words);
void inc_committed_words(size_t words);
bool new_segment(size_t reservation_size_request_words);
bool expand_segment_by(Segment* segment, size_t block_size_request_words);
bool expand_by(size_t block_size_request_words, size_t reservation_size_request_words);
bool can_reserve() const;
public:
JfrVirtualMemoryManager();
~JfrVirtualMemoryManager();
bool initialize(size_t reservation_size_request_words, size_t segment_count = 1);
void* commit(size_t requested_block_size_words);
bool is_full() const {
return reserved_high() == committed_high();
}
const u1* committed_low() const { return _current_segment->committed_low(); }
const u1* committed_high() const { return _current_segment->committed_high(); }
const u1* reserved_low() const { return _current_segment->reserved_low(); }
const u1* reserved_high() const { return _current_segment->reserved_high(); }
};
JfrVirtualMemoryManager::JfrVirtualMemoryManager() :
_segments(NULL),
_current_segment(NULL),
_reservation_size_request_words(0),
_reservation_size_request_limit_words(0),
_current_reserved_words(0),
_current_committed_words(0) {}
JfrVirtualMemoryManager::~JfrVirtualMemoryManager() {
JfrVirtualMemorySegment* segment = _segments;
while (segment != NULL) {
JfrVirtualMemorySegment* next_segment = segment->next();
delete segment;
segment = next_segment;
}
}
bool JfrVirtualMemoryManager::initialize(size_t reservation_size_request_words, size_t segment_count /* 1 */) {
assert(is_aligned(reservation_size_request_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
_reservation_size_request_words = reservation_size_request_words;
assert(segment_count > 0, "invariant");
_reservation_size_request_limit_words = reservation_size_request_words * segment_count;
assert(is_aligned(_reservation_size_request_limit_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
return new_segment(_reservation_size_request_words);
}
bool JfrVirtualMemoryManager::can_reserve() const {
return _reservation_size_request_limit_words == 0 ? true : _current_reserved_words < _reservation_size_request_limit_words;
}
bool JfrVirtualMemoryManager::new_segment(size_t reservation_size_request_words) {
assert(reservation_size_request_words > 0, "invariant");
assert(is_aligned(reservation_size_request_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
Segment* segment = new Segment();
if (NULL == segment) {
return false;
}
if (!segment->initialize(reservation_size_request_words * BytesPerWord)) {
delete segment;
return false;
}
assert(segment->reserved_words() == reservation_size_request_words,
"Actual reserved memory size differs from requested reservation memory size");
link(segment);
return true;
}
bool JfrVirtualMemoryManager::expand_segment_by(JfrVirtualMemorySegment* segment, size_t block_size_request_words) {
assert(segment != NULL, "invariant");
const size_t before = segment->committed_words();
const bool result = segment->expand_by(block_size_request_words);
const size_t after = segment->committed_words();
assert(after >= before, "Inconsistency");
inc_committed_words(after - before);
return result;
}
void JfrVirtualMemoryManager::inc_reserved_words(size_t words) {
_current_reserved_words += words;
}
JfrVirtualMemorySegment* JfrVirtualMemoryManager::current() {
return _current_segment;
}
void JfrVirtualMemoryManager::inc_committed_words(size_t words) {
_current_committed_words += words;
}
bool JfrVirtualMemoryManager::expand_by(size_t block_size_request_words, size_t reservation_size_request_words) {
assert(is_aligned(block_size_request_words * BytesPerWord, os::vm_page_size()), "invariant");
assert(is_aligned(block_size_request_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
assert(is_aligned(reservation_size_request_words * BytesPerWord, os::vm_page_size()), "invariant");
assert(is_aligned(reservation_size_request_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
assert(block_size_request_words <= reservation_size_request_words, "invariant");
if (expand_segment_by(current(), block_size_request_words)) {
return true;
}
if (!can_reserve()) {
return false;
}
if (!new_segment(reservation_size_request_words)) {
return false;
}
if (current()->is_pre_committed()) {
assert(block_size_request_words <= current()->committed_words(),
"The new VirtualSpace was pre-committed, so it"
"should be large enough to fit the alloc request.");
return true;
}
return expand_segment_by(current(), block_size_request_words);
}
void JfrVirtualMemoryManager::link(JfrVirtualMemorySegment* segment) {
assert(segment != NULL, "invariant");
if (_segments == NULL) {
_segments = segment;
} else {
assert(_current_segment != NULL, "invariant");
assert(_segments == _current_segment, "invariant");
_current_segment->set_next(segment);
}
_current_segment = segment;
inc_reserved_words(segment->reserved_words());
inc_committed_words(segment->committed_words());
}
void* JfrVirtualMemoryManager::commit(size_t block_size_request_words) {
assert(is_aligned(block_size_request_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
void* block = current()->commit(block_size_request_words);
if (block != NULL) {
return block;
}
assert(block == NULL, "invariant");
if (is_full()) {
return NULL;
}
assert(block_size_request_words <= _reservation_size_request_words, "invariant");
if (expand_by(block_size_request_words, _reservation_size_request_words)) {
block = current()->commit(block_size_request_words);
assert(block != NULL, "The allocation was expected to succeed after the expansion");
}
return block;
}
JfrVirtualMemory::JfrVirtualMemory() :
_vmm(NULL),
_reserved_low(),
_reserved_high(),
_top(NULL),
_commit_point(NULL),
_physical_commit_size_request_words(0),
_aligned_datum_size_bytes(0) {}
JfrVirtualMemory::~JfrVirtualMemory() {
assert(_vmm != NULL, "invariant");
delete _vmm;
}
size_t JfrVirtualMemory::aligned_datum_size_bytes() const {
return _aligned_datum_size_bytes;
}
static void adjust_allocation_ratio(size_t* const reservation_size_bytes, size_t* const commit_size_bytes) {
assert(reservation_size_bytes != NULL, "invariant");
assert(*reservation_size_bytes > 0, "invariant");
assert(commit_size_bytes != NULL, "invariant");
assert(*commit_size_bytes > 0, "invariant");
assert(*reservation_size_bytes >= *commit_size_bytes, "invariant");
assert(is_aligned(*reservation_size_bytes, os::vm_allocation_granularity()), "invariant");
assert(is_aligned(*commit_size_bytes, os::vm_allocation_granularity()), "invariant");
size_t reservation_size_units = *reservation_size_bytes / os::vm_allocation_granularity();
size_t commit_size_units = *commit_size_bytes / os::vm_allocation_granularity();
assert(reservation_size_units > 0, "invariant");
assert(commit_size_units > 0, "invariant");
size_t original_ratio_units = reservation_size_units / commit_size_units;
size_t rem = reservation_size_units % commit_size_units;
assert(original_ratio_units > 0, "invariant");
if (rem > 0) {
reservation_size_units -= rem % original_ratio_units;
commit_size_units += rem / original_ratio_units;
}
assert(commit_size_units > 0, "invariant");
assert(reservation_size_units % original_ratio_units == 0, "invariant");
assert(original_ratio_units * commit_size_units == reservation_size_units , "invariant");
assert(original_ratio_units == reservation_size_units / commit_size_units, "invariant");
assert((*reservation_size_bytes % *commit_size_bytes) == 0, "invariant");
}
void* JfrVirtualMemory::initialize(size_t reservation_size_request_bytes,
size_t block_size_request_bytes,
size_t datum_size_bytes /* 1 */) {
assert(_vmm == NULL, "invariant");
_vmm = new JfrVirtualMemoryManager();
if (_vmm == NULL) {
return NULL;
}
assert(reservation_size_request_bytes > 0, "invariant");
_aligned_datum_size_bytes = align_up(datum_size_bytes, BytesPerWord);
assert(is_aligned(_aligned_datum_size_bytes, BytesPerWord), "invariant");
reservation_size_request_bytes = ReservedSpace::allocation_align_size_up(reservation_size_request_bytes);
assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant");
assert(is_aligned(reservation_size_request_bytes, _aligned_datum_size_bytes), "invariant");
block_size_request_bytes = MAX2(block_size_request_bytes, (size_t)os::vm_allocation_granularity());
block_size_request_bytes = ReservedSpace::allocation_align_size_up(block_size_request_bytes);
assert(is_aligned(block_size_request_bytes, os::vm_allocation_granularity()), "invariant");
assert(is_aligned(block_size_request_bytes, _aligned_datum_size_bytes), "invariant");
adjust_allocation_ratio(&reservation_size_request_bytes, &block_size_request_bytes);
assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant");
assert(is_aligned(reservation_size_request_bytes, _aligned_datum_size_bytes), "invariant");
assert(is_aligned(block_size_request_bytes, os::vm_allocation_granularity()), "invariant");
assert(is_aligned(block_size_request_bytes, _aligned_datum_size_bytes), "invariant");
assert((reservation_size_request_bytes % block_size_request_bytes) == 0, "invariant");
const size_t reservation_size_request_words = reservation_size_request_bytes / BytesPerWord;
_physical_commit_size_request_words = block_size_request_bytes / BytesPerWord;
if (!_vmm->initialize(reservation_size_request_words)) {
assert(is_full(), "invariant");
return NULL;
}
_reserved_low = (const u1*)_vmm->reserved_low();
_reserved_high = (const u1*)_vmm->reserved_high();
_top = (u1*)_vmm->committed_high();
_commit_point = _top;
assert(_reserved_low == _top, "invariant"); // initial empty state
assert((size_t)(_reserved_high - _reserved_low) == reservation_size_request_bytes, "invariant");
commit_memory_block();
return _top;
}
void* JfrVirtualMemory::commit(size_t block_size_request_words) {
assert(_vmm != NULL, "invariant");
assert(is_aligned(block_size_request_words * BytesPerWord, os::vm_allocation_granularity()), "invariant");
return _vmm->commit(block_size_request_words);
}
bool JfrVirtualMemory::is_full() const {
return _top == _reserved_high;
}
bool JfrVirtualMemory::is_empty() const {
return _top == _reserved_low;
}
bool JfrVirtualMemory::commit_memory_block() {
assert(_vmm != NULL, "invariant");
assert(!is_full(), "invariant");
assert(_top == _commit_point, "invariant");
void* const block = _vmm->commit(_physical_commit_size_request_words);
if (block != NULL) {
_commit_point = _vmm->committed_high();
return true;
}
assert(block == NULL, "invariant");
assert(_vmm->reserved_high() == _vmm->committed_high(), "invariant");
return false;
}
void* JfrVirtualMemory::new_datum() {
assert(_vmm != NULL, "invariant");
assert(!is_full(), "invariant");
if (_top == _commit_point) {
if (!commit_memory_block()) {
assert(is_full(), "invariant");
return NULL;
}
}
assert(_top + _aligned_datum_size_bytes <= _commit_point, "invariant");
u1* allocation = _top;
_top += _aligned_datum_size_bytes;
assert(is_aligned(allocation, _aligned_datum_size_bytes), "invariant");
return allocation;
}
void* JfrVirtualMemory::index_ptr(size_t index) {
assert((index * _aligned_datum_size_bytes) + _reserved_low < _commit_point, "invariant");
return (void*)((index * _aligned_datum_size_bytes) + _reserved_low);
}
void* JfrVirtualMemory::get(size_t index) {
return index_ptr(index);
}
size_t JfrVirtualMemory::count() const {
return (_top - _reserved_low) / _aligned_datum_size_bytes;
}
size_t JfrVirtualMemory::live_set() const {
return _top - _reserved_low;
}
size_t JfrVirtualMemory::reserved_size() const {
return _reserved_high - _reserved_low;
}
bool JfrVirtualMemory::compact(size_t index) {
assert(index > 0, "invariant");
assert(index <= reserved_size(), "invariant");
const u1* low = static_cast<u1*>(index_ptr(index));
const size_t block_size = _top - low;
memcpy(const_cast<u1*>(_reserved_low), low, block_size);
_top = const_cast<u1*>(_reserved_low) + block_size;
assert(live_set() == block_size, "invariant");
return true;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/storage/jfrVirtualMemory.hpp
#ifndef SHARE_VM_JFR_RECORDER_STORAGE_JFRVIRTUALMEMORY_HPP
#define SHARE_VM_JFR_RECORDER_STORAGE_JFRVIRTUALMEMORY_HPP
#include "jfr/utilities/jfrAllocation.hpp"
class JfrVirtualMemoryManager;
class JfrVirtualMemory : public JfrCHeapObj {
private:
JfrVirtualMemoryManager* _vmm;
const u1* _reserved_low; // lowest address of reservation
const u1* _reserved_high; // highest address of reservation
u1* _top; // current allocation address
const u1* _commit_point; // synch points for committing new memory
size_t _physical_commit_size_request_words; // aligned to os::vm_allocation_granularity()
size_t _aligned_datum_size_bytes; // datum alignment
bool commit_memory_block();
void* commit(size_t block_size_request_words);
void* index_ptr(size_t index); // index to address map
public:
JfrVirtualMemory();
~JfrVirtualMemory();
void* initialize(size_t reservation_size_request_bytes, size_t block_size_request_bytes, size_t datum_size_bytes = 1);
void* new_datum(); // datum oriented allocation
void* get(size_t index); // direct access retrieval
size_t aligned_datum_size_bytes() const;
bool is_full() const; // limit of reservation committed and in use
bool is_empty() const;
size_t count() const; // how many
size_t live_set() const; // how much resident memory (actually in use)
size_t reserved_size() const; // size of reservation
bool compact(size_t index);
};
#endif // SHARE_VM_JFR_RECORDER_STORAGE_JFRVIRTUALMEMORY_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/stringpool/jfrStringPool.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
#include "jfr/recorder/stringpool/jfrStringPool.hpp"
#include "jfr/recorder/stringpool/jfrStringPoolWriter.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
typedef JfrStringPool::Buffer* BufferPtr;
static JfrStringPool* _instance = NULL;
JfrStringPool& JfrStringPool::instance() {
return *_instance;
}
JfrStringPool* JfrStringPool::create(JfrChunkWriter& cw) {
assert(_instance == NULL, "invariant");
_instance = new JfrStringPool(cw);
return _instance;
}
void JfrStringPool::destroy() {
assert(_instance != NULL, "invariant");
delete _instance;
_instance = NULL;
}
JfrStringPool::JfrStringPool(JfrChunkWriter& cw) : _free_list_mspace(NULL), _lock(NULL), _chunkwriter(cw) {}
JfrStringPool::~JfrStringPool() {
if (_free_list_mspace != NULL) {
delete _free_list_mspace;
}
if (_lock != NULL) {
delete _lock;
}
}
static const size_t unlimited_mspace_size = 0;
static const size_t string_pool_cache_count = 2;
static const size_t string_pool_buffer_size = 512 * K;
bool JfrStringPool::initialize() {
assert(_free_list_mspace == NULL, "invariant");
_free_list_mspace = new JfrStringPoolMspace(string_pool_buffer_size, unlimited_mspace_size, string_pool_cache_count, this);
if (_free_list_mspace == NULL || !_free_list_mspace->initialize()) {
return false;
}
assert(_lock == NULL, "invariant");
_lock = new Mutex(Monitor::leaf - 1, "Checkpoint mutex", Mutex::_allow_vm_block_flag);
return _lock != NULL;
}
static void release(BufferPtr buffer, Thread* thread) {
assert(buffer != NULL, "invariant");
assert(buffer->lease(), "invariant");
assert(buffer->acquired_by_self(), "invariant");
buffer->clear_lease();
buffer->release();
}
BufferPtr JfrStringPool::flush(BufferPtr old, size_t used, size_t requested, Thread* thread) {
assert(old != NULL, "invariant");
assert(old->lease(), "invariant");
if (0 == requested) {
release(old, thread);
return NULL;
}
BufferPtr const new_buffer = lease_buffer(thread, used + requested);
if (new_buffer != NULL) {
migrate_outstanding_writes(old, new_buffer, used, requested);
}
release(old, thread);
return new_buffer; // might be NULL
}
static const size_t lease_retry = 10;
BufferPtr JfrStringPool::lease_buffer(Thread* thread, size_t size /* 0 */) {
BufferPtr buffer = mspace_get_free_lease_with_retry(size, instance()._free_list_mspace, lease_retry, thread);
if (buffer == NULL) {
buffer = mspace_allocate_transient_lease_to_free(size, instance()._free_list_mspace, thread);
}
assert(buffer->acquired_by_self(), "invariant");
assert(buffer->lease(), "invariant");
return buffer;
}
bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) {
assert(jt != NULL, "invariant");
const bool current_epoch = (JfrTraceIdEpoch::epoch() != 0);
if (current_epoch == epoch) {
JfrStringPoolWriter writer(jt);
writer.write(id);
writer.write(string);
writer.inc_nof_strings();
}
return current_epoch;
}
template <template <typename> class Operation>
class StringPoolOp {
public:
typedef JfrStringPoolBuffer Type;
private:
Operation<Type> _op;
Thread* _thread;
size_t _strings_processed;
public:
StringPoolOp() : _op(), _thread(Thread::current()), _strings_processed(0) {}
StringPoolOp(JfrChunkWriter& writer, Thread* thread) : _op(writer), _thread(thread), _strings_processed(0) {}
bool write(Type* buffer, const u1* data, size_t size) {
assert(buffer->acquired_by(_thread) || buffer->retired(), "invariant");
const uint64_t nof_strings_used = buffer->string_count();
assert(nof_strings_used > 0, "invariant");
buffer->set_string_top(buffer->string_top() + nof_strings_used);
_strings_processed += nof_strings_used;
return _op.write(buffer, data, size);
}
size_t processed() { return _strings_processed; }
};
template <typename Type>
class StringPoolDiscarderStub {
public:
bool write(Type* buffer, const u1* data, size_t size) {
return true;
}
};
typedef StringPoolOp<UnBufferedWriteToChunk> WriteOperation;
typedef StringPoolOp<StringPoolDiscarderStub> DiscardOperation;
typedef ExclusiveOp<WriteOperation> ExclusiveWriteOperation;
typedef ExclusiveOp<DiscardOperation> ExclusiveDiscardOperation;
typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation;
typedef CompositeOperation<ExclusiveWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation;
typedef CompositeOperation<ExclusiveDiscardOperation, StringPoolReleaseOperation> StringPoolDiscardOperation;
size_t JfrStringPool::write() {
Thread* const thread = Thread::current();
WriteOperation wo(_chunkwriter, thread);
ExclusiveWriteOperation ewo(wo);
StringPoolReleaseOperation spro(_free_list_mspace, thread, false);
StringPoolWriteOperation spwo(&ewo, &spro);
assert(_free_list_mspace->is_full_empty(), "invariant");
process_free_list(spwo, _free_list_mspace);
return wo.processed();
}
size_t JfrStringPool::write_at_safepoint() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
return write();
}
size_t JfrStringPool::clear() {
DiscardOperation discard_operation;
ExclusiveDiscardOperation edo(discard_operation);
StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false);
StringPoolDiscardOperation spdo(&edo, &spro);
assert(_free_list_mspace->is_full_empty(), "invariant");
process_free_list(spdo, _free_list_mspace);
return discard_operation.processed();
}
void JfrStringPool::register_full(BufferPtr t, Thread* thread) {
assert(t != NULL, "invariant");
assert(t->acquired_by(thread), "invariant");
assert(t->retired(), "invariant");
}
void JfrStringPool::lock() {
assert(!_lock->owned_by_self(), "invariant");
_lock->lock_without_safepoint_check();
}
void JfrStringPool::unlock() {
_lock->unlock();
}
#ifdef ASSERT
bool JfrStringPool::is_locked() const {
return _lock->owned_by_self();
}
#endif
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/stringpool/jfrStringPool.hpp
#ifndef SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOL_HPP
#define SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOL_HPP
#include "jni.h"
#include "jfr/recorder/storage/jfrMemorySpace.hpp"
#include "jfr/recorder/storage/jfrMemorySpaceRetrieval.hpp"
#include "jfr/recorder/stringpool/jfrStringPoolBuffer.hpp"
class JfrChunkWriter;
class JfrStringPool;
class Mutex;
typedef JfrMemorySpace<JfrStringPoolBuffer, JfrMspaceSequentialRetrieval, JfrStringPool> JfrStringPoolMspace;
class JfrStringPool : public JfrCHeapObj {
public:
static bool add(bool epoch, jlong id, jstring string, JavaThread* jt);
size_t write();
size_t write_at_safepoint();
size_t clear();
typedef JfrStringPoolMspace::Type Buffer;
private:
JfrStringPoolMspace* _free_list_mspace;
Mutex* _lock;
JfrChunkWriter& _chunkwriter;
void register_full(Buffer* t, Thread* thread);
void lock();
void unlock();
DEBUG_ONLY(bool is_locked() const;)
static Buffer* lease_buffer(Thread* thread, size_t size = 0);
static Buffer* flush(Buffer* old, size_t used, size_t requested, Thread* t);
JfrStringPool(JfrChunkWriter& cw);
~JfrStringPool();
static JfrStringPool& instance();
static JfrStringPool* create(JfrChunkWriter& cw);
bool initialize();
static void destroy();
friend class JfrRecorder;
friend class JfrRecorderService;
friend class JfrStringPoolFlush;
friend class JfrStringPoolWriter;
template <typename, template <typename> class, typename>
friend class JfrMemorySpace;
};
#endif // SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOL_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/stringpool/jfrStringPoolBuffer.cpp
#include "precompiled.hpp"
#include "jfr/recorder/stringpool/jfrStringPoolBuffer.hpp"
JfrStringPoolBuffer::JfrStringPoolBuffer() : JfrBuffer(), _string_count_pos(0), _string_count_top(0) {}
void JfrStringPoolBuffer::reinitialize() {
assert(acquired_by_self() || retired(), "invariant");
set_string_pos(0);
set_string_top(0);
JfrBuffer::reinitialize();
}
uint64_t JfrStringPoolBuffer::string_pos() const {
assert(acquired_by_self() || retired(), "invariant");
return _string_count_pos;
}
uint64_t JfrStringPoolBuffer::string_top() const {
assert(acquired_by_self() || retired(), "invariant");
return _string_count_top;
}
uint64_t JfrStringPoolBuffer::string_count() const {
assert(acquired_by_self() || retired(), "invariant");
return string_pos() - string_top();
}
void JfrStringPoolBuffer::set_string_pos(uint64_t value) {
assert(acquired_by_self() || retired(), "invariant");
_string_count_pos = value;
}
void JfrStringPoolBuffer::increment(uint64_t value) {
assert(acquired_by_self(), "invariant");
++_string_count_pos;
}
void JfrStringPoolBuffer::set_string_top(uint64_t value) {
assert(acquired_by_self() || retired(), "invariant");
_string_count_top = value;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/stringpool/jfrStringPoolBuffer.hpp
#ifndef SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOLBUFFER_HPP
#define SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOLBUFFER_HPP
#include "jfr/recorder/storage/jfrBuffer.hpp"
class JfrStringPoolBuffer : public JfrBuffer {
private:
uint64_t _string_count_pos;
uint64_t _string_count_top;
public:
JfrStringPoolBuffer();
void reinitialize();
uint64_t string_pos() const;
uint64_t string_top() const;
uint64_t string_count() const;
void increment(uint64_t value);
void set_string_pos(uint64_t value);
void set_string_top(uint64_t value);
};
#endif // SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOLBUFFER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/stringpool/jfrStringPoolWriter.cpp
#include "precompiled.hpp"
#include "jfr/recorder/stringpool/jfrStringPool.hpp"
#include "jfr/recorder/stringpool/jfrStringPoolWriter.hpp"
#include "jfr/writers/jfrEventWriterHost.inline.hpp"
#include "jfr/writers/jfrMemoryWriterHost.inline.hpp"
JfrStringPoolFlush::JfrStringPoolFlush(Type* old, size_t used, size_t requested, Thread* t) :
_result(JfrStringPool::flush(old, used, requested, t)) {}
JfrStringPoolWriter::JfrStringPoolWriter(Thread* thread) :
JfrStringPoolWriterBase(JfrStringPool::lease_buffer(thread), thread), _nof_strings(0) {}
JfrStringPoolWriter::~JfrStringPoolWriter() {
assert(this->is_acquired(), "invariant");
if (!this->is_valid() || this->used_size() == 0) {
return;
}
assert(this->used_size() > 0, "invariant");
this->storage()->increment(_nof_strings);
this->commit();
assert(0 == this->current_offset(), "invariant");
}
void JfrStringPoolWriter::inc_nof_strings() {
++_nof_strings;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/recorder/stringpool/jfrStringPoolWriter.hpp
#ifndef SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOLWRITER_HPP
#define SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOLWRITER_HPP
#include "memory/allocation.hpp"
#include "jfr/recorder/stringpool/jfrStringPoolBuffer.hpp"
#include "jfr/writers/jfrEventWriterHost.hpp"
#include "jfr/writers/jfrMemoryWriterHost.hpp"
#include "jfr/writers/jfrStorageAdapter.hpp"
class Thread;
class JfrStringPoolFlush : public StackObj {
public:
typedef JfrStringPoolBuffer Type;
JfrStringPoolFlush(Type* old, size_t used, size_t requested, Thread* t);
Type* result() { return _result; }
private:
Type* _result;
};
typedef Adapter<JfrStringPoolFlush> JfrStringPoolAdapter;
typedef AcquireReleaseMemoryWriterHost<JfrStringPoolAdapter, StackObj> JfrTransactionalStringPoolWriter;
typedef EventWriterHost<BigEndianEncoder, CompressedIntegerEncoder, JfrTransactionalStringPoolWriter> JfrStringPoolWriterBase;
class JfrStringPoolWriter : public JfrStringPoolWriterBase {
private:
size_t _nof_strings;
public:
JfrStringPoolWriter(Thread* thread);
~JfrStringPoolWriter();
void inc_nof_strings();
};
#endif // SHARE_VM_JFR_RECORDER_STRINGPOOL_JFRSTRINGPOOLWRITER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrAllocationTracer.cpp
#include "precompiled.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/support/jfrAllocationTracer.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/thread.hpp"
JfrAllocationTracer::JfrAllocationTracer(HeapWord* obj, size_t alloc_size, Thread* thread) : _tl(NULL) {
if (LeakProfiler::is_running()) {
assert(thread->is_Java_thread(), "invariant");
_tl = thread->jfr_thread_local();
LeakProfiler::sample(obj, alloc_size, (JavaThread*)thread);
}
}
JfrAllocationTracer::~JfrAllocationTracer() {
if (_tl != NULL) {
_tl->clear_cached_stack_trace();
}
}
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrAllocationTracer.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRALLOCATIONTRACER_HPP
#define SHARE_VM_JFR_SUPPORT_JFRALLOCATIONTRACER_HPP
#include "memory/allocation.hpp"
class JfrThreadLocal;
class JfrAllocationTracer : public StackObj {
private:
JfrThreadLocal* _tl;
public:
JfrAllocationTracer(HeapWord* obj, size_t alloc_size, Thread* thread);
~JfrAllocationTracer();
};
#endif // SHARE_VM_JFR_SUPPORT_JFRALLOCATIONTRACER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrEventClass.cpp
#include "precompiled.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/support/jfrEventClass.hpp"
bool JdkJfrEvent::is(const Klass* k) {
return JfrTraceId::is_jdk_jfr_event(k);
}
bool JdkJfrEvent::is(const jclass jc) {
return JfrTraceId::is_jdk_jfr_event(jc);
}
void JdkJfrEvent::tag_as(const Klass* k) {
JfrTraceId::tag_as_jdk_jfr_event(k);
}
bool JdkJfrEvent::is_subklass(const Klass* k) {
return JfrTraceId::is_jdk_jfr_event_sub(k);
}
bool JdkJfrEvent::is_subklass(const jclass jc) {
return JfrTraceId::is_jdk_jfr_event_sub(jc);
}
void JdkJfrEvent::tag_as_subklass(const Klass* k) {
JfrTraceId::tag_as_jdk_jfr_event_sub(k);
}
void JdkJfrEvent::tag_as_subklass(const jclass jc) {
JfrTraceId::tag_as_jdk_jfr_event_sub(jc);
}
bool JdkJfrEvent::is_a(const Klass* k) {
return JfrTraceId::in_jdk_jfr_event_hierarchy(k);
}
bool JdkJfrEvent::is_a(const jclass jc) {
return JfrTraceId::in_jdk_jfr_event_hierarchy(jc);
}
bool JdkJfrEvent::is_host(const Klass* k) {
return JfrTraceId::is_event_host(k);
}
bool JdkJfrEvent::is_host(const jclass jc) {
return JfrTraceId::is_event_host(jc);
}
void JdkJfrEvent::tag_as_host(const Klass* k) {
JfrTraceId::tag_as_event_host(k);
}
void JdkJfrEvent::tag_as_host(const jclass jc) {
JfrTraceId::tag_as_event_host(jc);
}
bool JdkJfrEvent::is_visible(const Klass* k) {
return JfrTraceId::in_visible_set(k);
}
bool JdkJfrEvent::is_visible(const jclass jc) {
return JfrTraceId::in_visible_set(jc);
}
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrEventClass.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFREVENTCLASS_HPP
#define SHARE_VM_JFR_SUPPORT_JFREVENTCLASS_HPP
#include "jni.h"
#include "memory/allocation.hpp"
class Klass;
class JdkJfrEvent : AllStatic {
public:
static bool is(const Klass* k);
static bool is(const jclass jc);
static void tag_as(const Klass* k);
static bool is_subklass(const Klass* k);
static bool is_subklass(const jclass jc);
static void tag_as_subklass(const Klass* k);
static void tag_as_subklass(const jclass jc);
static bool is_a(const Klass* k);
static bool is_a(const jclass jc);
static bool is_host(const Klass* k);
static bool is_host(const jclass jc);
static void tag_as_host(const Klass* k);
static void tag_as_host(const jclass jc);
static bool is_visible(const Klass* k);
static bool is_visible(const jclass jc);
};
#endif // SHARE_VM_JFR_SUPPORT_JFREVENTCLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrFlush.cpp
#include "precompiled.hpp"
#include "jfr/recorder/jfrEventSetting.inline.hpp"
#include "jfr/recorder/storage/jfrStorage.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
#include "jfr/support/jfrFlush.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/debug.hpp"
JfrFlush::JfrFlush(JfrStorage::Buffer* old, size_t used, size_t requested, Thread* t) :
_result(JfrStorage::flush(old, used, requested, true, t)) {
}
template <typename T>
class LessThanHalfBufferSize : AllStatic {
public:
static bool evaluate(T* t) {
assert(t != NULL, "invariant");
return t->free_size() < t->size() / 2;
}
};
template <typename T>
class LessThanSize : AllStatic {
public:
static bool evaluate(T* t, size_t size) {
assert(t != NULL, "invariant");
return t->free_size() < size;
}
};
bool jfr_is_event_enabled(JfrEventId id) {
return JfrEventSetting::is_enabled(id);
}
bool jfr_has_stacktrace_enabled(JfrEventId id) {
return JfrEventSetting::has_stacktrace(id);
}
void jfr_conditional_flush(JfrEventId id, size_t size, Thread* t) {
if (t->jfr_thread_local()->has_native_buffer()) {
JfrStorage::Buffer* const buffer = t->jfr_thread_local()->native_buffer();
if (LessThanSize<JfrStorage::Buffer>::evaluate(buffer, size)) {
JfrFlush f(buffer, 0, 0, t);
}
}
}
bool jfr_save_stacktrace(Thread* t) {
JfrThreadLocal* const tl = t->jfr_thread_local();
if (tl->has_cached_stack_trace()) {
return false; // no ownership
}
tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(t));
return true;
}
void jfr_clear_stacktrace(Thread* t) {
t->jfr_thread_local()->clear_cached_stack_trace();
}
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrFlush.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRFLUSH_HPP
#define SHARE_VM_JFR_SUPPORT_JFRFLUSH_HPP
#include "jfr/recorder/storage/jfrBuffer.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "memory/allocation.hpp"
class Thread;
class JfrFlush : public StackObj {
public:
typedef JfrBuffer Type;
JfrFlush(Type* old, size_t used, size_t requested, Thread* t);
Type* result() const { return _result; }
private:
Type* _result;
};
void jfr_conditional_flush(JfrEventId id, size_t size, Thread* t);
bool jfr_is_event_enabled(JfrEventId id);
bool jfr_has_stacktrace_enabled(JfrEventId id);
bool jfr_save_stacktrace(Thread* t);
void jfr_clear_stacktrace(Thread* t);
template <typename Event>
class JfrConditionalFlush {
protected:
bool _enabled;
public:
typedef JfrBuffer Type;
JfrConditionalFlush(Thread* t) : _enabled(jfr_is_event_enabled(Event::eventId)) {
if (_enabled) {
jfr_conditional_flush(Event::eventId, sizeof(Event), t);
}
}
};
template <typename Event>
class JfrConditionalFlushWithStacktrace : public JfrConditionalFlush<Event> {
Thread* _t;
bool _owner;
public:
JfrConditionalFlushWithStacktrace(Thread* t) : JfrConditionalFlush<Event>(t), _t(t), _owner(false) {
if (this->_enabled && Event::has_stacktrace() && jfr_has_stacktrace_enabled(Event::eventId)) {
_owner = jfr_save_stacktrace(t);
}
}
~JfrConditionalFlushWithStacktrace() {
if (_owner) {
jfr_clear_stacktrace(_t);
}
}
};
#endif // SHARE_VM_JFR_SUPPORT_JFRFLUSH_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrIntrinsics.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRINTRINSICS_HPP
#define SHARE_VM_JFR_SUPPORT_JFRINTRINSICS_HPP
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrKlassExtension.hpp"
#include "jfr/support/jfrThreadExtension.hpp"
#include "jfr/utilities/jfrTime.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp"
#define JFR_TEMPLATES(template) \
template(jdk_jfr_internal_JVM, "jdk/jfr/internal/JVM")
#define JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \
do_intrinsic(_counterTime, jdk_jfr_internal_JVM, counterTime_name, void_long_signature, F_SN) \
do_name( counterTime_name, "counterTime") \
do_intrinsic(_getClassId, jdk_jfr_internal_JVM, getClassId_name, class_long_signature, F_SN) \
do_name( getClassId_name, "getClassId") \
do_intrinsic(_getEventWriter, jdk_jfr_internal_JVM, getEventWriter_name, void_object_signature, F_SN) \
do_name( getEventWriter_name, "getEventWriter") \
#define JFR_HAVE_INTRINSICS
#define JFR_TIME_FUNCTION JfrTime::time_function()
#else // !INCLUDE_JFR
#define JFR_TEMPLATES(template)
#define JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)
#endif // INCLUDE_JFR
#endif // SHARE_VM_JFR_SUPPORT_JFRINTRINSICS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrKlassExtension.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRKLASSEXTENSION_HPP
#define SHARE_VM_JFR_SUPPORT_JFRKLASSEXTENSION_HPP
#include "jfr/instrumentation/jfrEventClassTransformer.hpp"
#include "jfr/support/jfrTraceIdExtension.hpp"
#define DEFINE_KLASS_TRACE_ID_OFFSET \
static ByteSize trace_id_offset() { return in_ByteSize(offset_of(InstanceKlass, _trace_id)); }
#define KLASS_TRACE_ID_OFFSET InstanceKlass::trace_id_offset()
#define JDK_JFR_EVENT_SUBKLASS 16
#define JDK_JFR_EVENT_KLASS 32
#define EVENT_HOST_KLASS 64
#define IS_EVENT_KLASS(ptr) (((ptr)->trace_id() & (JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS)) != 0)
#define ON_KLASS_CREATION(k, p, t) if (IS_EVENT_KLASS(k)) JfrEventClassTransformer::on_klass_creation(k, p, t)
#endif // SHARE_VM_JFR_SUPPORT_JFRKLASSEXTENSION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrStackTraceMark.cpp
#include "precompiled.hpp"
#include "jfr/recorder/jfrEventSetting.inline.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
#include "jfr/support/jfrStackTraceMark.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/thread.inline.hpp"
JfrStackTraceMark::JfrStackTraceMark() : _t(Thread::current()), _previous_id(0), _previous_hash(0) {
JfrThreadLocal* const tl = _t->jfr_thread_local();
if (tl->has_cached_stack_trace()) {
_previous_id = tl->cached_stack_trace_id();
_previous_hash = tl->cached_stack_trace_hash();
}
tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(Thread::current()));
}
JfrStackTraceMark::JfrStackTraceMark(Thread* t) : _t(t), _previous_id(0), _previous_hash(0) {
JfrThreadLocal* const tl = _t->jfr_thread_local();
if (tl->has_cached_stack_trace()) {
_previous_id = tl->cached_stack_trace_id();
_previous_hash = tl->cached_stack_trace_hash();
}
tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(t));
}
JfrStackTraceMark::JfrStackTraceMark(JfrEventId eventId) : _t(NULL), _previous_id(0), _previous_hash(0) {
if (JfrEventSetting::has_stacktrace(eventId)) {
_t = Thread::current();
JfrThreadLocal* const tl = _t->jfr_thread_local();
if (tl->has_cached_stack_trace()) {
_previous_id = tl->cached_stack_trace_id();
_previous_hash = tl->cached_stack_trace_hash();
}
tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(_t));
}
}
JfrStackTraceMark::JfrStackTraceMark(JfrEventId eventId, Thread* t) : _t(NULL), _previous_id(0), _previous_hash(0) {
if (JfrEventSetting::has_stacktrace(eventId)) {
_t = t;
JfrThreadLocal* const tl = _t->jfr_thread_local();
if (tl->has_cached_stack_trace()) {
_previous_id = tl->cached_stack_trace_id();
_previous_hash = tl->cached_stack_trace_hash();
}
tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(_t));
}
}
JfrStackTraceMark::~JfrStackTraceMark() {
if (_previous_id != 0) {
_t->jfr_thread_local()->set_cached_stack_trace_id(_previous_id, _previous_hash);
} else {
if (_t != NULL) {
_t->jfr_thread_local()->clear_cached_stack_trace();
}
}
}
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrStackTraceMark.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRSTACKTRACEMARK_HPP
#define SHARE_VM_JFR_SUPPORT_JFRSTACKTRACEMARK_HPP
#include "memory/allocation.hpp"
#include "jfrfiles/jfrEventIds.hpp"
#include "jfr/utilities/jfrTypes.hpp"
class Thread;
class JfrStackTraceMark {
private:
Thread* _t;
traceid _previous_id;
unsigned int _previous_hash;
public:
JfrStackTraceMark();
JfrStackTraceMark(Thread* t);
JfrStackTraceMark(JfrEventId eventId);
JfrStackTraceMark(JfrEventId eventId, Thread* t);
~JfrStackTraceMark();
};
#endif // SHARE_VM_JFR_SUPPORT_JFRSTACKTRACEMARK_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrThreadExtension.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRTHREADEXTENSION_HPP
#define SHARE_VM_JFR_SUPPORT_JFRTHREADEXTENSION_HPP
#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#define DEFINE_THREAD_LOCAL_FIELD_JFR mutable JfrThreadLocal _jfr_thread_local
#define DEFINE_THREAD_LOCAL_OFFSET_JFR \
static ByteSize jfr_thread_local_offset() { return in_ByteSize(offset_of(Thread, _jfr_thread_local)); }
#define THREAD_LOCAL_OFFSET_JFR Thread::jfr_thread_local_offset()
#define DEFINE_THREAD_LOCAL_TRACE_ID_OFFSET_JFR \
static ByteSize trace_id_offset() { return in_ByteSize(offset_of(JfrThreadLocal, _trace_id)); }
#define DEFINE_THREAD_LOCAL_ACCESSOR_JFR \
JfrThreadLocal* jfr_thread_local() const { return &_jfr_thread_local; }
#define THREAD_ID_OFFSET_JFR JfrThreadLocal::trace_id_offset()
#define THREAD_LOCAL_WRITER_OFFSET_JFR \
JfrThreadLocal::java_event_writer_offset() + THREAD_LOCAL_OFFSET_JFR
#define DEFINE_TRACE_SUSPEND_FLAG_METHODS \
void set_trace_flag() { set_suspend_flag(_trace_flag); } \
void clear_trace_flag() { clear_suspend_flag(_trace_flag); } \
bool is_trace_suspend() { return (_suspend_flags & _trace_flag) != 0; }
#define SUSPEND_THREAD_CONDITIONAL(thread) if ((thread)->is_trace_suspend()) JfrThreadSampling::on_javathread_suspend(thread)
#endif // SHARE_VM_JFR_SUPPORT_JFRTHREADEXTENSION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrThreadId.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRTHREADID_HPP
#define SHARE_VM_JFR_SUPPORT_JFRTHREADID_HPP
#include "utilities/macros.hpp"
#include "utilities/globalDefinitions.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrThreadLocal.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#define JFR_THREAD_ID(thread) ((thread)->jfr_thread_local()->thread_id())
#else
typedef u8 traceid;
#define JFR_THREAD_ID(thread) ((traceid)(thread)->osthread()->thread_id())
#endif
#endif // SHARE_VM_JFR_SUPPORT_JFRTHREADID_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrThreadLocal.cpp
#include "precompiled.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/periodic/jfrThreadCPULoadEvent.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/recorder/storage/jfrStorage.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/sizes.hpp"
JfrThreadLocal::JfrThreadLocal() :
_java_event_writer(NULL),
_java_buffer(NULL),
_native_buffer(NULL),
_shelved_buffer(NULL),
_stackframes(NULL),
_trace_id(JfrTraceId::assign_thread_id()),
_thread_cp(),
_data_lost(0),
_stack_trace_id(max_julong),
_user_time(0),
_cpu_time(0),
_wallclock_time(os::javaTimeNanos()),
_stack_trace_hash(0),
_stackdepth(0),
_entering_suspend_flag(0),
_dead(false) {
Thread* thread = Thread::current_or_null();
_parent_trace_id = thread != NULL ? thread->jfr_thread_local()->trace_id() : (traceid)0;
}
u8 JfrThreadLocal::add_data_lost(u8 value) {
_data_lost += value;
return _data_lost;
}
bool JfrThreadLocal::has_thread_checkpoint() const {
return _thread_cp.valid();
}
void JfrThreadLocal::set_thread_checkpoint(const JfrCheckpointBlobHandle& ref) {
assert(!_thread_cp.valid(), "invariant");
_thread_cp = ref;
}
const JfrCheckpointBlobHandle& JfrThreadLocal::thread_checkpoint() const {
return _thread_cp;
}
static void send_java_thread_start_event(JavaThread* jt) {
EventThreadStart event;
event.set_thread(jt->jfr_thread_local()->thread_id());
event.set_parentThread(jt->jfr_thread_local()->parent_thread_id());
event.commit();
}
void JfrThreadLocal::on_start(Thread* t) {
assert(t != NULL, "invariant");
assert(Thread::current() == t, "invariant");
if (JfrRecorder::is_recording()) {
if (t->is_Java_thread()) {
send_java_thread_start_event((JavaThread*)t);
}
}
if (t->jfr_thread_local()->has_cached_stack_trace()) {
t->jfr_thread_local()->clear_cached_stack_trace();
}
}
static void send_java_thread_end_events(traceid id, JavaThread* jt) {
assert(jt != NULL, "invariant");
assert(Thread::current() == jt, "invariant");
assert(jt->jfr_thread_local()->trace_id() == id, "invariant");
EventThreadEnd event;
event.set_thread(id);
event.commit();
JfrThreadCPULoadEvent::send_event_for_thread(jt);
}
void JfrThreadLocal::release(JfrThreadLocal* tl, Thread* t) {
assert(tl != NULL, "invariant");
assert(t != NULL, "invariant");
assert(Thread::current() == t, "invariant");
assert(!tl->is_dead(), "invariant");
assert(tl->shelved_buffer() == NULL, "invariant");
if (tl->has_native_buffer()) {
JfrStorage::release_thread_local(tl->native_buffer(), t);
}
if (tl->has_java_buffer()) {
JfrStorage::release_thread_local(tl->java_buffer(), t);
}
if (tl->has_java_event_writer()) {
assert(t->is_Java_thread(), "invariant");
JfrJavaSupport::destroy_global_jni_handle(tl->java_event_writer());
}
if (tl->_stackframes != NULL) {
FREE_C_HEAP_ARRAY(JfrStackFrame, tl->_stackframes, mtTracing);
}
tl->_dead = true;
}
void JfrThreadLocal::on_exit(Thread* t) {
assert(t != NULL, "invariant");
JfrThreadLocal * const tl = t->jfr_thread_local();
assert(!tl->is_dead(), "invariant");
if (JfrRecorder::is_recording()) {
if (t->is_Java_thread()) {
send_java_thread_end_events(tl->thread_id(), (JavaThread*)t);
}
}
release(tl, Thread::current()); // because it could be that Thread::current() != t
}
JfrBuffer* JfrThreadLocal::install_native_buffer() const {
assert(!has_native_buffer(), "invariant");
_native_buffer = JfrStorage::acquire_thread_local(Thread::current());
return _native_buffer;
}
JfrBuffer* JfrThreadLocal::install_java_buffer() const {
assert(!has_java_buffer(), "invariant");
assert(!has_java_event_writer(), "invariant");
_java_buffer = JfrStorage::acquire_thread_local(Thread::current());
return _java_buffer;
}
JfrStackFrame* JfrThreadLocal::install_stackframes() const {
assert(_stackframes == NULL, "invariant");
_stackframes = NEW_C_HEAP_ARRAY(JfrStackFrame, stackdepth(), mtTracing);
return _stackframes;
}
ByteSize JfrThreadLocal::trace_id_offset() {
return in_ByteSize(offset_of(JfrThreadLocal, _trace_id));
}
ByteSize JfrThreadLocal::java_event_writer_offset() {
return in_ByteSize(offset_of(JfrThreadLocal, _java_event_writer));
}
u4 JfrThreadLocal::stackdepth() const {
return _stackdepth != 0 ? _stackdepth : (u4)JfrOptionSet::stackdepth();
}
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrThreadLocal.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRTHREADLOCAL_HPP
#define SHARE_VM_JFR_SUPPORT_JFRTHREADLOCAL_HPP
#include "jfr/recorder/checkpoint/jfrCheckpointBlob.hpp"
#include "jfr/utilities/jfrTypes.hpp"
class JavaThread;
class JfrBuffer;
class JfrStackFrame;
class Thread;
class JfrThreadLocal {
private:
jobject _java_event_writer;
mutable JfrBuffer* _java_buffer;
mutable JfrBuffer* _native_buffer;
JfrBuffer* _shelved_buffer;
mutable JfrStackFrame* _stackframes;
mutable traceid _trace_id;
JfrCheckpointBlobHandle _thread_cp;
u8 _data_lost;
traceid _stack_trace_id;
jlong _user_time;
jlong _cpu_time;
jlong _wallclock_time;
unsigned int _stack_trace_hash;
mutable u4 _stackdepth;
volatile jint _entering_suspend_flag;
bool _dead;
traceid _parent_trace_id;
JfrBuffer* install_native_buffer() const;
JfrBuffer* install_java_buffer() const;
JfrStackFrame* install_stackframes() const;
static void release(JfrThreadLocal* tl, Thread* t);
public:
JfrThreadLocal();
JfrBuffer* native_buffer() const {
return _native_buffer != NULL ? _native_buffer : install_native_buffer();
}
bool has_native_buffer() const {
return _native_buffer != NULL;
}
void set_native_buffer(JfrBuffer* buffer) {
_native_buffer = buffer;
}
JfrBuffer* java_buffer() const {
return _java_buffer != NULL ? _java_buffer : install_java_buffer();
}
bool has_java_buffer() const {
return _java_buffer != NULL;
}
void set_java_buffer(JfrBuffer* buffer) {
_java_buffer = buffer;
}
JfrBuffer* shelved_buffer() const {
return _shelved_buffer;
}
void shelve_buffer(JfrBuffer* buffer) {
_shelved_buffer = buffer;
}
bool has_java_event_writer() const {
return _java_event_writer != NULL;
}
jobject java_event_writer() {
return _java_event_writer;
}
void set_java_event_writer(jobject java_event_writer) {
_java_event_writer = java_event_writer;
}
JfrStackFrame* stackframes() const {
return _stackframes != NULL ? _stackframes : install_stackframes();
}
void set_stackframes(JfrStackFrame* frames) {
_stackframes = frames;
}
u4 stackdepth() const;
void set_stackdepth(u4 depth) {
_stackdepth = depth;
}
traceid thread_id() const {
return _trace_id;
}
void set_thread_id(traceid thread_id) {
_trace_id = thread_id;
}
traceid parent_thread_id() const {
return _parent_trace_id;
}
void set_cached_stack_trace_id(traceid id, unsigned int hash = 0) {
_stack_trace_id = id;
_stack_trace_hash = hash;
}
bool has_cached_stack_trace() const {
return _stack_trace_id != max_julong;
}
void clear_cached_stack_trace() {
_stack_trace_id = max_julong;
_stack_trace_hash = 0;
}
traceid cached_stack_trace_id() const {
return _stack_trace_id;
}
unsigned int cached_stack_trace_hash() const {
return _stack_trace_hash;
}
void set_trace_block() {
_entering_suspend_flag = 1;
}
void clear_trace_block() {
_entering_suspend_flag = 0;
}
bool is_trace_block() const {
return _entering_suspend_flag != 0;
}
u8 data_lost() const {
return _data_lost;
}
u8 add_data_lost(u8 value);
jlong get_user_time() const {
return _user_time;
}
void set_user_time(jlong user_time) {
_user_time = user_time;
}
jlong get_cpu_time() const {
return _cpu_time;
}
void set_cpu_time(jlong cpu_time) {
_cpu_time = cpu_time;
}
jlong get_wallclock_time() const {
return _wallclock_time;
}
void set_wallclock_time(jlong wallclock_time) {
_wallclock_time = wallclock_time;
}
traceid trace_id() const {
return _trace_id;
}
traceid* const trace_id_addr() const {
return &_trace_id;
}
void set_trace_id(traceid id) const {
_trace_id = id;
}
bool is_dead() const {
return _dead;
}
bool has_thread_checkpoint() const;
void set_thread_checkpoint(const JfrCheckpointBlobHandle& handle);
const JfrCheckpointBlobHandle& thread_checkpoint() const;
static void on_start(Thread* t);
static void on_exit(Thread* t);
static ByteSize trace_id_offset();
static ByteSize java_event_writer_offset();
};
#endif // SHARE_VM_JFR_SUPPORT_JFRTHREADLOCAL_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/support/jfrTraceIdExtension.hpp
#ifndef SHARE_VM_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
#define SHARE_VM_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp"
#define DEFINE_TRACE_ID_FIELD mutable traceid _trace_id
#define DEFINE_TRACE_ID_METHODS \
traceid trace_id() const { return _trace_id; } \
traceid* const trace_id_addr() const { return &_trace_id; } \
void set_trace_id(traceid id) const { _trace_id = id; }
#define DEFINE_TRACE_ID_SIZE \
static size_t trace_id_size() { return sizeof(traceid); }
#define INIT_ID(data) JfrTraceId::assign(data)
#define REMOVE_ID(k) JfrTraceId::remove(k);
#define RESTORE_ID(k) JfrTraceId::restore(k);
class JfrTraceFlag {
private:
mutable jbyte _flags;
public:
JfrTraceFlag() : _flags(0) {}
explicit JfrTraceFlag(jbyte flags) : _flags(flags) {}
void set_flag(jbyte flag) const {
_flags |= flag;
}
void clear_flag(jbyte flag) const {
_flags &= (~flag);
}
jbyte flags() const { return _flags; }
bool is_set(jbyte flag) const {
return (_flags & flag) != 0;
}
jbyte* const flags_addr() const {
return &_flags;
}
};
#define DEFINE_TRACE_FLAG mutable JfrTraceFlag _trace_flags
#define DEFINE_TRACE_FLAG_ACCESSOR \
void set_trace_flag(jbyte flag) const { \
_trace_flags.set_flag(flag); \
} \
jbyte trace_flags() const { \
return _trace_flags.flags(); \
} \
bool is_trace_flag_set(jbyte flag) const { \
return _trace_flags.is_set(flag); \
} \
jbyte* const trace_flags_addr() const { \
return _trace_flags.flags_addr(); \
}
#endif // SHARE_VM_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrAllocation.cpp
#include "precompiled.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/utilities/jfrAllocation.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/vm_version.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/debug.hpp"
#include "utilities/macros.hpp"
#include "utilities/nativeCallStack.hpp"
jlong atomic_add_jlong(jlong value, jlong volatile* const dest) {
jlong compare_value;
jlong exchange_value;
#ifndef SUPPORTS_NATIVE_CX8
if (!VM_Version::supports_cx8()) {
MutexLockerEx mu(JfrCounters_lock, Mutex::_no_safepoint_check_flag);
return *dest += value;
}
#endif
do {
compare_value = OrderAccess::load_acquire(dest);
exchange_value = compare_value + value;
} while (Atomic::cmpxchg(exchange_value, dest, compare_value) != compare_value);
return exchange_value;
}
#ifdef ASSERT
static volatile jlong _allocated_bytes = 0;
static volatile jlong _deallocated_bytes = 0;
static volatile jlong _live_set_bytes = 0;
static void add(size_t alloc_size) {
if (!JfrRecorder::is_created()) {
const jlong total_allocated = atomic_add_jlong((jlong)alloc_size, &_allocated_bytes);
const jlong current_live_set = atomic_add_jlong((jlong)alloc_size, &_live_set_bytes);
if (LogJFR && Verbose) tty->print_cr("Allocation: [" SIZE_FORMAT "] bytes", alloc_size);
if (LogJFR && Verbose) tty->print_cr("Total alloc [" JLONG_FORMAT "] bytes", total_allocated);
if (LogJFR && Verbose) tty->print_cr("Liveset: [" JLONG_FORMAT "] bytes", current_live_set);
}
}
static void subtract(size_t dealloc_size) {
if (!JfrRecorder::is_created()) {
const jlong total_deallocated = atomic_add_jlong((jlong)dealloc_size, &_deallocated_bytes);
const jlong current_live_set = atomic_add_jlong(((jlong)dealloc_size * -1), &_live_set_bytes);
if (LogJFR && Verbose) tty->print_cr("Deallocation: [" SIZE_FORMAT "] bytes", dealloc_size);
if (LogJFR && Verbose) tty->print_cr("Total dealloc [" JLONG_FORMAT "] bytes", total_deallocated);
if (LogJFR && Verbose) tty->print_cr("Liveset: [" JLONG_FORMAT "] bytes", current_live_set);
}
}
static void hook_memory_deallocation(size_t dealloc_size) {
subtract(dealloc_size);
}
#endif // ASSERT
static void hook_memory_allocation(const char* allocation, size_t alloc_size) {
if (NULL == allocation) {
if (!JfrRecorder::is_created()) {
if (LogJFR) tty->print_cr("Memory allocation failed for size [" SIZE_FORMAT "] bytes", alloc_size);
return;
} else {
vm_exit_out_of_memory(alloc_size, OOM_MALLOC_ERROR, "AllocateHeap");
}
}
debug_only(add(alloc_size));
}
void JfrCHeapObj::on_memory_allocation(const void* allocation, size_t size) {
hook_memory_allocation((const char*)allocation, size);
}
void* JfrCHeapObj::operator new(size_t size) throw() {
return operator new(size, std::nothrow);
}
void* JfrCHeapObj::operator new (size_t size, const std::nothrow_t& nothrow_constant) throw() {
void* const memory = CHeapObj<mtTracing>::operator new(size, nothrow_constant, CALLER_PC);
hook_memory_allocation((const char*)memory, size);
return memory;
}
void* JfrCHeapObj::operator new [](size_t size) throw() {
return operator new[](size, std::nothrow);
}
void* JfrCHeapObj::operator new [](size_t size, const std::nothrow_t& nothrow_constant) throw() {
void* const memory = CHeapObj<mtTracing>::operator new[](size, nothrow_constant, CALLER_PC);
hook_memory_allocation((const char*)memory, size);
return memory;
}
void JfrCHeapObj::operator delete(void* p, size_t size) {
debug_only(hook_memory_deallocation(size);)
CHeapObj<mtTracing>::operator delete(p);
}
void JfrCHeapObj::operator delete[](void* p, size_t size) {
debug_only(hook_memory_deallocation(size);)
CHeapObj<mtTracing>::operator delete[](p);
}
char* JfrCHeapObj::realloc_array(char* old, size_t size) {
char* const memory = ReallocateHeap(old, size, mtTracing, AllocFailStrategy::RETURN_NULL);
hook_memory_allocation(memory, size);
return memory;
}
void JfrCHeapObj::free(void* p, size_t size) {
debug_only(hook_memory_deallocation(size);)
FreeHeap(p);
}
char* JfrCHeapObj::allocate_array_noinline(size_t elements, size_t element_size) {
return AllocateHeap(elements * element_size, mtTracing, CALLER_PC, AllocFailStrategy::RETURN_NULL);
}
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrAllocation.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRALLOCATION_HPP
#define SHARE_VM_JFR_UTILITIES_JFRALLOCATION_HPP
#include "memory/allocation.hpp"
#include "services/memTracker.hpp"
#include "utilities/exceptions.hpp"
class JfrCHeapObj : public CHeapObj<mtTracing> {
private:
static void on_memory_allocation(const void* allocation, size_t size);
static char* allocate_array_noinline(size_t elements, size_t element_size);
public:
NOINLINE void* operator new(size_t size) throw();
NOINLINE void* operator new (size_t size, const std::nothrow_t& nothrow_constant) throw();
NOINLINE void* operator new [](size_t size) throw();
NOINLINE void* operator new [](size_t size, const std::nothrow_t& nothrow_constant) throw();
void operator delete(void* p, size_t size);
void operator delete [] (void* p, size_t size);
static char* realloc_array(char* old, size_t size);
static void free(void* p, size_t size = 0);
template <class T>
static T* new_array(size_t size) {
T* const memory = (T*)allocate_array_noinline(size, sizeof(T));
on_memory_allocation(memory, sizeof(T) * size);
return memory;
}
};
#endif // SHARE_VM_JFR_UTILITIES_JFRALLOCATION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrBigEndian.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP
#define SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP
#include "memory/allocation.hpp"
#include "utilities/macros.hpp"
#ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "bytes_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "bytes_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "bytes_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "bytes_ppc.hpp"
#endif
#ifndef VM_LITTLE_ENDIAN
# define bigendian_16(x) (x)
# define bigendian_32(x) (x)
# define bigendian_64(x) (x)
#else
# define bigendian_16(x) Bytes::swap_u2(x)
# define bigendian_32(x) Bytes::swap_u4(x)
# define bigendian_64(x) Bytes::swap_u8(x)
#endif
class JfrBigEndian : AllStatic {
private:
template <typename T>
static T read_bytes(const address location);
template <typename T>
static T read_unaligned(const address location);
public:
static bool platform_supports_unaligned_reads(void);
static bool is_aligned(const void* location, size_t size);
template <typename T>
static T read(const void* location);
};
inline bool JfrBigEndian::is_aligned(const void* location, size_t size) {
assert(size <= sizeof(u8), "just checking");
if (size == sizeof(u1)) {
return true;
}
return (((uintptr_t)location & (size -1)) == 0);
}
template <>
inline u1 JfrBigEndian::read_bytes(const address location) {
return (*location & 0xFF);
}
template <>
inline u2 JfrBigEndian::read_bytes(const address location) {
return Bytes::get_Java_u2(location);
}
template <>
inline u4 JfrBigEndian::read_bytes(const address location) {
return Bytes::get_Java_u4(location);
}
template <>
inline u8 JfrBigEndian::read_bytes(const address location) {
return Bytes::get_Java_u8(location);
}
template <typename T>
inline T JfrBigEndian::read_unaligned(const address location) {
assert(location != NULL, "just checking");
switch (sizeof(T)) {
case sizeof(u1) :
return read_bytes<u1>(location);
case sizeof(u2):
return read_bytes<u2>(location);
case sizeof(u4):
return read_bytes<u4>(location);
case sizeof(u8):
return read_bytes<u8>(location);
default:
assert(false, "not reach");
}
return 0;
}
inline bool JfrBigEndian::platform_supports_unaligned_reads(void) {
#if defined(IA32) || defined(AMD64) || defined(PPC) || defined(S390)
return true;
#elif defined(SPARC) || defined(ARM) || defined(AARCH64)
return false;
#else
#warning "Unconfigured platform"
return false;
#endif
}
template<typename T>
inline T JfrBigEndian::read(const void* location) {
assert(location != NULL, "just checking");
assert(sizeof(T) <= sizeof(u8), "no support for arbitrary sizes");
if (sizeof(T) == sizeof(u1)) {
return *(T*)location;
}
if (is_aligned(location, sizeof(T)) || platform_supports_unaligned_reads()) {
switch (sizeof(T)) {
case sizeof(u1):
return *(T*)location;
case sizeof(u2):
return bigendian_16(*(T*)(location));
case sizeof(u4):
return bigendian_32(*(T*)(location));
case sizeof(u8):
return bigendian_64(*(T*)(location));
}
}
return read_unaligned<T>((const address)location);
}
#endif // SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrDoublyLinkedList.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP
#define SHARE_VM_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP
#include "memory/allocation.hpp"
template <typename T>
class JfrDoublyLinkedList {
private:
T* _head;
T* _tail;
size_t _count;
T** list_head() { return &_head; }
T** list_tail() { return &_tail; }
public:
typedef T Node;
JfrDoublyLinkedList() : _head(NULL), _tail(NULL), _count(0) {}
T* head() const { return _head; }
T* tail() const { return _tail; }
size_t count() const { return _count; }
T* clear(bool return_tail = false);
T* remove(T* const node);
void prepend(T* const node);
void append(T* const node);
void append_list(T* const head_node, T* const tail_node, size_t count);
debug_only(bool in_list(const T* const target_node) const;)
debug_only(bool locate(const T* start_node, const T* const target_node) const;)
};
template <typename T>
inline void JfrDoublyLinkedList<T>::prepend(T* const node) {
assert(node != NULL, "invariant");
node->set_prev(NULL);
assert(!in_list(node), "already in list error");
T** lh = list_head();
if (*lh != NULL) {
(*lh)->set_prev(node);
node->set_next(*lh);
} else {
T** lt = list_tail();
assert(*lt == NULL, "invariant");
node->set_next(NULL);
assert(tail() == node, "invariant");
assert(node->next() == NULL, "invariant");
}
++_count;
assert(head() == node, "head error");
assert(in_list(node), "not in list error");
assert(node->prev() == NULL, "invariant");
}
template <typename T>
void JfrDoublyLinkedList<T>::append(T* const node) {
assert(node != NULL, "invariant");
node->set_next(NULL);
assert(!in_list(node), "already in list error");
T** lt = list_tail();
if (*lt != NULL) {
node->set_prev(*lt);
(*lt)->set_next(node);
} else {
assert(*lt == NULL, "invariant");
T** lh = list_head();
assert(*lh == NULL, "invariant");
node->set_prev(NULL);
assert(head() == node, "invariant");
}
++_count;
assert(tail() == node, "invariant");
assert(in_list(node), "not in list error");
assert(node->next() == NULL, "invariant");
}
template <typename T>
T* JfrDoublyLinkedList<T>::remove(T* const node) {
assert(node != NULL, "invariant");
assert(in_list(node), "invariant");
T* const prev = (T*)node->prev();
T* const next = (T*)node->next();
if (prev == NULL) {
assert(head() == node, "head error");
if (next != NULL) {
next->set_prev(NULL);
} else {
assert(next == NULL, "invariant");
assert(tail() == node, "tail error");
T** lt = list_tail();
assert(tail() == NULL, "invariant");
}
T** lh = list_head();
assert(head() == next, "invariant");
} else {
assert(prev != NULL, "invariant");
if (next == NULL) {
assert(tail() == node, "tail error");
T** lt = list_tail();
assert(tail() == prev, "invariant");
} else {
next->set_prev(prev);
}
prev->set_next(next);
}
--_count;
assert(_count >= 0, "invariant");
assert(!in_list(node), "still in list error");
return node;
}
template <typename T>
T* JfrDoublyLinkedList<T>::clear(bool return_tail /* false */) {
T* const node = return_tail ? tail() : head();
T** l = list_head();
l = list_tail();
_count = 0;
assert(head() == NULL, "invariant");
assert(tail() == NULL, "invariant");
return node;
}
#ifdef ASSERT
template <typename T>
bool JfrDoublyLinkedList<T>::locate(const T* node, const T* const target) const {
assert(target != NULL, "invariant");
while (node != NULL) {
if (node == target) {
return true;
}
node = (T*)node->next();
}
return false;
}
template <typename T>
bool JfrDoublyLinkedList<T>::in_list(const T* const target) const {
assert(target != NULL, "invariant");
return locate(head(), target);
}
template <typename T>
inline void validate_count_param(T* node, size_t count_param) {
assert(node != NULL, "invariant");
size_t count = 0;
while (node) {
++count;
node = (T*)node->next();
}
assert(count_param == count, "invariant");
}
#endif // ASSERT
template <typename T>
void JfrDoublyLinkedList<T>::append_list(T* const head_node, T* const tail_node, size_t count) {
assert(head_node != NULL, "invariant");
assert(!in_list(head_node), "already in list error");
assert(tail_node != NULL, "invariant");
assert(!in_list(tail_node), "already in list error");
assert(tail_node->next() == NULL, "invariant");
assert(locate(head_node, tail_node), "invariant");
T** lt = list_tail();
if (*lt != NULL) {
head_node->set_prev(*lt);
(*lt)->set_next(head_node);
} else {
assert(*lt == NULL, "invariant");
T** lh = list_head();
assert(*lh == NULL, "invariant");
head_node->set_prev(NULL);
assert(head() == head_node, "invariant");
}
const T* node = head_node;
debug_only(validate_count_param(node, count);)
_count += count;
assert(tail() == tail_node, "invariant");
assert(in_list(tail_node), "not in list error");
assert(in_list(head_node), "not in list error");
}
#endif // SHARE_VM_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrHashtable.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRHASHTABLE_HPP
#define SHARE_VM_JFR_UTILITIES_JFRHASHTABLE_HPP
#include "memory/allocation.inline.hpp"
#include "runtime/orderAccess.hpp"
#include "utilities/debug.hpp"
#include "utilities/macros.hpp"
template <typename T>
class JfrBasicHashtableEntry {
private:
typedef JfrBasicHashtableEntry<T> Entry;
Entry* _next;
T _literal; // ref to item in table.
uintptr_t _hash;
public:
uintptr_t hash() const { return _hash; }
void set_hash(uintptr_t hash) { _hash = hash; }
T literal() const { return _literal; }
T* literal_addr() { return &_literal; }
void set_literal(T s) { _literal = s; }
void set_next(Entry* next) { _next = next; }
Entry* next() const { return _next; }
Entry** next_addr() { return &_next; }
};
template <typename T>
class JfrHashtableBucket : public CHeapObj<mtTracing> {
template <typename>
friend class JfrBasicHashtable;
private:
typedef JfrBasicHashtableEntry<T> TableEntry;
TableEntry* _entry;
TableEntry* get_entry() const {
return (TableEntry*)OrderAccess::load_ptr_acquire(&_entry);
}
void set_entry(TableEntry* entry) { OrderAccess::release_store_ptr(&_entry, entry);}
TableEntry** entry_addr() { return &_entry; }
};
template <typename T>
class JfrBasicHashtable : public CHeapObj<mtTracing> {
private:
typedef JfrHashtableBucket<T> Bucket;
typedef JfrBasicHashtableEntry<T> TableEntry;
Bucket* _buckets;
uintptr_t _table_size;
const size_t _entry_size;
size_t _number_of_entries;
protected:
JfrBasicHashtable(uintptr_t table_size, size_t entry_size) :
_buckets(NULL), _table_size(table_size), _entry_size(entry_size), _number_of_entries(0) {
_buckets = NEW_C_HEAP_ARRAY2(Bucket, table_size, mtTracing, CURRENT_PC);
memset((void*)_buckets, 0, table_size * sizeof(Bucket));
}
size_t hash_to_index(uintptr_t full_hash) const {
const uintptr_t h = full_hash % _table_size;
assert(h >= 0 && h < _table_size, "Illegal hash value");
return (size_t)h;
}
size_t entry_size() const { return _entry_size; }
void unlink_entry(TableEntry* entry) {
entry->set_next(NULL);
--_number_of_entries;
}
void free_buckets() {
if (NULL != _buckets) {
FREE_C_HEAP_ARRAY(Bucket, _buckets, mtTracing);
_buckets = NULL;
}
}
TableEntry* bucket(size_t i) { return _buckets[i].get_entry();}
TableEntry** bucket_addr(size_t i) { return _buckets[i].entry_addr(); }
uintptr_t table_size() const { return _table_size; }
size_t number_of_entries() const { return _number_of_entries; }
void add_entry(size_t index, TableEntry* entry) {
assert(entry != NULL, "invariant");
entry->set_next(bucket(index));
_buckets[index].set_entry(entry);
++_number_of_entries;
}
};
template <typename IdType, typename Entry, typename T>
class AscendingId : public CHeapObj<mtTracing> {
private:
IdType _id;
public:
AscendingId() : _id(0) {}
void assign_id(Entry* entry) {
assert(entry != NULL, "invariant");
assert(entry->id() == 0, "invariant");
entry->set_id(++_id);
}
bool equals(const T& data, uintptr_t hash, const Entry* entry) {
assert(entry->hash() == hash, "invariant");
return true;
}
};
template <typename T, typename IdType>
class Entry : public JfrBasicHashtableEntry<T> {
public:
typedef IdType ID;
void init() { _id = 0; }
ID id() const { return _id; }
void set_id(ID id) { _id = id; }
void set_value(const T& value) { this->set_literal(value); }
T& value() const { return *const_cast<Entry*>(this)->literal_addr();}
const T* value_addr() const { return const_cast<Entry*>(this)->literal_addr(); }
private:
ID _id;
};
template <typename T, typename IdType, template <typename, typename> class Entry,
typename Callback = AscendingId<IdType, Entry<T, IdType>, T> ,
size_t TABLE_SIZE = 1009>
class HashTableHost : public JfrBasicHashtable<T> {
public:
typedef Entry<T, IdType> HashEntry;
HashTableHost() : _callback(new Callback()) {}
HashTableHost(Callback* cb) : JfrBasicHashtable<T>(TABLE_SIZE, sizeof(HashEntry)), _callback(cb) {}
~HashTableHost() {
this->clear_entries();
this->free_buckets();
}
HashEntry& put(const T& data, uintptr_t hash);
HashEntry& lookup_put(const T& data, uintptr_t hash) {
HashEntry* entry = lookup_only(data, hash);
return entry == NULL ? put(data, hash) : *entry;
}
HashEntry* lookup_only(const T& query, uintptr_t hash);
IdType id(const T& data, uintptr_t hash) {
assert(data != NULL, "invariant");
const HashEntry& entry = lookup_put(data, hash);
assert(entry.id() > 0, "invariant");
return entry.id();
}
template <typename Functor>
void iterate_value(Functor& f);
template <typename Functor>
void iterate_entry(Functor& f);
size_t cardinality() const { return this->number_of_entries(); }
bool has_entries() const { return this->cardinality() > 0; }
void clear_entries();
void free_entry(HashEntry* entry) {
assert(entry != NULL, "invariant");
JfrBasicHashtable<T>::unlink_entry(entry);
FREE_C_HEAP_ARRAY(char, entry, mtTracing);
}
private:
Callback* _callback;
size_t index_for(uintptr_t hash) { return this->hash_to_index(hash); }
HashEntry* new_entry(const T& data, uintptr_t hash);
void add_entry(size_t index, HashEntry* new_entry) {
assert(new_entry != NULL, "invariant");
_callback->assign_id(new_entry);
assert(new_entry->id() > 0, "invariant");
JfrBasicHashtable<T>::add_entry(index, new_entry);
}
};
template <typename T, typename IdType, template <typename, typename> class Entry, typename Callback, size_t TABLE_SIZE>
Entry<T, IdType>& HashTableHost<T, IdType, Entry, Callback, TABLE_SIZE>::put(const T& data, uintptr_t hash) {
assert(lookup_only(data, hash) == NULL, "use lookup_put()");
HashEntry* const entry = new_entry(data, hash);
add_entry(index_for(hash), entry);
return *entry;
}
template <typename T, typename IdType, template <typename, typename> class Entry, typename Callback, size_t TABLE_SIZE>
Entry<T, IdType>* HashTableHost<T, IdType, Entry, Callback, TABLE_SIZE>::lookup_only(const T& query, uintptr_t hash) {
HashEntry* entry = (HashEntry*)this->bucket(index_for(hash));
while (entry != NULL) {
if (entry->hash() == hash && _callback->equals(query, hash, entry)) {
return entry;
}
entry = (HashEntry*)entry->next();
}
return NULL;
}
template <typename T, typename IdType, template <typename, typename> class Entry, typename Callback, size_t TABLE_SIZE>
template <typename Functor>
void HashTableHost<T, IdType, Entry, Callback, TABLE_SIZE>::iterate_value(Functor& f) {
for (size_t i = 0; i < this->table_size(); ++i) {
const HashEntry* entry = (const HashEntry*)this->bucket(i);
while (entry != NULL) {
if (!f(entry->value())) {
break;
}
entry = (HashEntry*)entry->next();
}
}
}
template <typename T, typename IdType, template <typename, typename> class Entry, typename Callback, size_t TABLE_SIZE>
template <typename Functor>
void HashTableHost<T, IdType, Entry, Callback, TABLE_SIZE>::iterate_entry(Functor& f) {
for (size_t i = 0; i < this->table_size(); ++i) {
const HashEntry* entry = (const HashEntry*)this->bucket(i);
while (entry != NULL) {
if (!f(entry)) {
break;
}
entry = (const HashEntry*)entry->next();
}
}
}
template <typename T, typename IdType, template <typename, typename> class Entry, typename Callback, size_t TABLE_SIZE>
void HashTableHost<T, IdType, Entry, Callback, TABLE_SIZE>::clear_entries() {
for (size_t i = 0; i < this->table_size(); ++i) {
HashEntry** bucket = (HashEntry**)this->bucket_addr(i);
HashEntry* entry = *bucket;
while (entry != NULL) {
HashEntry* entry_to_remove = entry;
entry = (HashEntry*)entry->next();
this->free_entry(entry_to_remove);
}
}
assert(this->number_of_entries() == 0, "should have removed all entries");
}
template <typename T, typename IdType, template <typename, typename> class Entry, typename Callback, size_t TABLE_SIZE>
Entry<T, IdType>* HashTableHost<T, IdType, Entry, Callback, TABLE_SIZE>::new_entry(const T& data, uintptr_t hash) {
assert(sizeof(HashEntry) == this->entry_size(), "invariant");
HashEntry* const entry = (HashEntry*) NEW_C_HEAP_ARRAY2(char, this->entry_size(), mtTracing, CURRENT_PC);
entry->init();
entry->set_hash(hash);
entry->set_value(data);
entry->set_next(NULL);
assert(0 == entry->id(), "invariant");
return entry;
}
#endif // SHARE_VM_JFR_UTILITIES_JFRHASHTABLE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrIterator.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRLISTITERATOR_HPP
#define SHARE_VM_JFR_UTILITIES_JFRLISTITERATOR_HPP
#include "memory/allocation.hpp"
enum jfr_iter_direction {
forward = 1,
backward
};
template <typename Node>
class StopOnNullCondition : public AllStatic {
public:
static bool has_next(const Node* node) {
return node != NULL;
}
};
template <typename List, template <typename> class ContinuationPredicate>
class Navigator {
public:
typedef typename List::Node Node;
typedef jfr_iter_direction Direction;
Navigator(List& list, Direction direction) :
_list(list), _node(direction == forward ? list.head() : list.tail()), _direction(direction) {}
bool has_next() const {
return ContinuationPredicate<Node>::has_next(_node);
}
bool direction_forward() const {
return _direction == forward;
}
Node* next() const {
assert(_node != NULL, "invariant");
Node* temp = _node;
_node = direction_forward() ? (Node*)_node->next() : (Node*)_node->prev();
return temp;
}
void set_direction(Direction direction) {
_direction = direction;
}
void reset(Direction direction) {
set_direction(direction);
_node = direction_forward() ? _list.head() : _list.tail();
}
private:
List& _list;
mutable Node* _node;
Direction _direction;
};
template <typename List>
class NavigatorStopOnNull : public Navigator<List, StopOnNullCondition> {
public:
NavigatorStopOnNull(List& list, jfr_iter_direction direction = forward) : Navigator<List, StopOnNullCondition>(list, direction) {}
};
template<typename List, template <typename> class Navigator, typename AP = StackObj>
class IteratorHost : public AP {
private:
Navigator<List> _navigator;
public:
typedef typename List::Node Node;
typedef jfr_iter_direction Direction;
IteratorHost(List& list, Direction direction = forward) : AP(), _navigator(list, direction) {}
void reset(Direction direction = forward) { _navigator.reset(direction); }
bool has_next() const { return _navigator.has_next(); }
Node* next() const { return _navigator.next(); }
void set_direction(Direction direction) { _navigator.set_direction(direction); }
};
template<typename List, typename AP = StackObj>
class StopOnNullIterator : public IteratorHost<List, NavigatorStopOnNull, AP> {
public:
StopOnNullIterator(List& list, jfr_iter_direction direction = forward) : IteratorHost<List, NavigatorStopOnNull, AP>(list, direction) {}
};
#endif // SHARE_VM_JFR_UTILITIES_JFRLISTITERATOR_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrJavaLog.cpp
#include "precompiled.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/utilities/jfrJavaLog.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/thread.inline.hpp"
void JfrJavaLog::subscribe_log_level(jobject log_tag, jint id, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
}
void JfrJavaLog::log(jint tag_set, jint level, jstring message, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
if (!LogJFR) {
return;
}
if (message == NULL) {
return;
}
ResourceMark rm(THREAD);
const char* const s = JfrJavaSupport::c_str(message, CHECK);
assert(s != NULL, "invariant");
tty->print_cr("JFR: %s", s);
}
bool JfrJavaLog::should_log(jint level, TRAPS) {
return LogJFR;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrJavaLog.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRJAVALOG_HPP
#define SHARE_VM_JFR_UTILITIES_JFRJAVALOG_HPP
#include "memory/allocation.hpp"
#include "utilities/exceptions.hpp"
class JfrJavaLog : public AllStatic {
public:
static void subscribe_log_level(jobject log_tag, jint id, TRAPS);
static void log(jint tag_set, jint level, jstring message, TRAPS);
static bool should_log(jint level, TRAPS);
};
#endif // SHARE_VM_JFR_UTILITIES_JFRJAVALOG_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrRefCountPointer.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP
#define SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP
#include "jfr/utilities/jfrAllocation.hpp"
#include "runtime/atomic.hpp"
template <typename T>
class RefCountHandle {
template <typename, typename>
friend class RefCountPointer;
private:
const T* _ptr;
RefCountHandle(const T* ptr) : _ptr(ptr) {
assert(_ptr != NULL, "invariant");
_ptr->add_ref();
}
public:
RefCountHandle() : _ptr(NULL) {}
RefCountHandle(const RefCountHandle<T>& rhs) : _ptr(rhs._ptr) {
if (_ptr != NULL) {
_ptr->add_ref();
}
}
~RefCountHandle() {
if (_ptr != NULL) {
const T* temp = _ptr;
_ptr = NULL;
temp->remove_ref();
}
}
void operator=(RefCountHandle<T> rhs) {
const T* temp = rhs._ptr;
rhs._ptr = _ptr;
_ptr = temp;
}
bool operator==(const RefCountHandle<T>& rhs) const {
return _ptr == rhs._ptr;
}
bool operator!=(const RefCountHandle<T>& rhs) const {
return !operator==(rhs);
}
bool valid() const {
return _ptr != NULL;
}
const T & operator->() const {
return *_ptr;
}
T& operator->() {
return *const_cast<T*>(_ptr);
}
};
class MultiThreadedRefCounter {
private:
mutable volatile int _refs;
public:
MultiThreadedRefCounter() : _refs(0) {}
void inc() const {
Atomic::add(1, &_refs);
}
bool dec() const {
return 0 == Atomic::add((-1), &_refs);
}
int current() const {
return _refs;
}
};
template <typename T, typename RefCountImpl = MultiThreadedRefCounter>
class RefCountPointer : public JfrCHeapObj {
template <typename>
friend class RefCountHandle;
typedef RefCountHandle<RefCountPointer<T, RefCountImpl> > RefHandle;
private:
const T* _ptr;
mutable RefCountImpl _refs;
RefCountPointer(const RefCountPointer<T, RefCountImpl>& rhs);
void operator=(const RefCountPointer<T, RefCountImpl>& rhs);
~RefCountPointer() {
assert(_refs.current() == 0, "invariant");
delete const_cast<T*>(_ptr);
}
void add_ref() const {
_refs.inc();
}
void remove_ref() const {
if (_refs.dec()) {
delete this;
}
}
RefCountPointer(const T* ptr) : _ptr(ptr), _refs() {
assert(_ptr != NULL, "invariant");
}
public:
const T* operator->() const {
return _ptr;
}
T* operator->() {
return const_cast<T*>(_ptr);
}
static RefHandle make(const T* ptr) {
assert(ptr != NULL, "invariant");
return RefHandle(new RefCountPointer<T, RefCountImpl>(ptr));
}
};
#endif // SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrResourceManager.hpp
#ifndef SHARE_VM_JFR_UTILITIES_RESOURCEMANAGER_HPP
#define SHARE_VM_JFR_UTILITIES_RESOURCEMANAGER_HPP
#include "memory/allocation.hpp"
template <class T>
class ResourceManager : public StackObj {
private:
T* const _resource;
public:
ResourceManager(T* resource) : _resource(resource) {}
~ResourceManager() {
if (_resource != NULL) {
delete _resource;
}
}
operator T*() { return _resource; }
T* operator->() { return _resource; }
};
template <class T>
class ResourceArrayManager : public StackObj {
private:
T* const _resource_array;
public:
ResourceArrayManager(T* resource_array) : _resource_array(resource_array) {}
~ResourceArrayManager() {
if (_resource_array != NULL) {
delete [] _resource_array;
}
}
operator T*() { return _resource_array; }
T* operator->() const { return _resource_array; }
};
#endif // SHARE_VM_JFR_UTILITIES_RESOURCEMANAGER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrSpinlockHelper.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP
#define SHARE_VM_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP
#include "runtime/thread.hpp"
class JfrSpinlockHelper {
private:
volatile int* const _lock;
public:
JfrSpinlockHelper(volatile int* lock) : _lock(lock) {
Thread::SpinAcquire(_lock, NULL);
}
JfrSpinlockHelper(volatile int* const lock, const char* name) : _lock(lock) {
Thread::SpinAcquire(_lock, name);
}
~JfrSpinlockHelper() {
Thread::SpinRelease(_lock);
}
};
#endif // SHARE_VM_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrTime.cpp
#include "precompiled.hpp"
#include "jfr/utilities/jfrTime.hpp"
#include "runtime/os.hpp"
#if defined(X86) && !defined(ZERO)
#include "rdtsc_x86.hpp"
#endif
bool JfrTime::_ft_enabled = false;
bool JfrTime::initialize() {
static bool initialized = false;
if (!initialized) {
#if defined(X86) && !defined(ZERO)
_ft_enabled = Rdtsc::initialize();
#else
_ft_enabled = false;
#endif
initialized = true;
}
return initialized;
}
bool JfrTime::is_ft_supported() {
#if defined(X86) && !defined(ZERO)
return Rdtsc::is_supported();
#else
return false;
#endif
}
const void* JfrTime::time_function() {
#if defined(X86) && !defined(ZERO)
return _ft_enabled ? (const void*)Rdtsc::elapsed_counter : (const void*)os::elapsed_counter;
#else
return (const void*)os::elapsed_counter;
#endif
}
jlong JfrTime::frequency() {
#if defined(X86) && !defined(ZERO)
return _ft_enabled ? Rdtsc::frequency() : os::elapsed_frequency();
#else
return os::elapsed_frequency();
#endif
}
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrTime.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRTIME_HPP
#define SHARE_VM_JFR_UTILITIES_JFRTIME_HPP
#include "utilities/ticks.hpp"
typedef TimeInstant<CounterRepresentation, FastUnorderedElapsedCounterSource> JfrTicks;
typedef TimeInterval<CounterRepresentation, FastUnorderedElapsedCounterSource> JfrTickspan;
class JfrTime {
private:
static bool _ft_enabled;
public:
static bool initialize();
static bool is_ft_enabled() { return _ft_enabled; }
static bool is_ft_supported();
static jlong frequency();
static const void* time_function();
};
#endif // SHARE_VM_JFR_UTILITIES_JFRTIME_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrTimeConverter.cpp
#include "precompiled.hpp"
#include "jfr/utilities/jfrTimeConverter.hpp"
#include "jfr/utilities/jfrTime.hpp"
#include "runtime/os.hpp"
static double ft_counter_to_nanos_factor = .0;
static double nanos_to_ft_counter_factor = .0;
static double os_counter_to_nanos_factor = .0;
static double nanos_to_os_counter_factor = .0;
const double JfrTimeConverter::NANOS_PER_SEC = 1000000000.0;
const double JfrTimeConverter::NANOS_PER_MILLISEC = 1000000.0;
const double JfrTimeConverter::NANOS_PER_MICROSEC = 1000.0;
static bool initialized = false;
void JfrTimeConverter::initialize() {
if (!initialized) {
nanos_to_os_counter_factor = (double)os::elapsed_frequency() / NANOS_PER_SEC;
assert(nanos_to_os_counter_factor != .0, "error in conversion!");
os_counter_to_nanos_factor = (double)1.0 / nanos_to_os_counter_factor;
assert(os_counter_to_nanos_factor != .0, "error in conversion!");
if (JfrTime::is_ft_enabled()) {
nanos_to_ft_counter_factor = (double)JfrTime::frequency() / NANOS_PER_SEC;
assert(nanos_to_ft_counter_factor != .0, "error in conversion!");
ft_counter_to_nanos_factor = (double)1.0 / nanos_to_ft_counter_factor;
assert(ft_counter_to_nanos_factor != .0, "error in conversion!");
}
initialized = true;
}
}
double JfrTimeConverter::counter_to_nano_multiplier(bool is_os_time) {
if (!initialized) {
initialize();
}
return JfrTime::is_ft_enabled() && !is_os_time ? ft_counter_to_nanos_factor : os_counter_to_nanos_factor;
}
double JfrTimeConverter::nano_to_counter_multiplier(bool is_os_time) {
if (!initialized) {
initialize();
}
return JfrTime::is_ft_enabled() && !is_os_time ? nanos_to_ft_counter_factor : nanos_to_os_counter_factor;
}
double JfrTimeConverter::counter_to_nanos_internal(jlong c, bool is_os_time) {
return (double)c * counter_to_nano_multiplier(is_os_time);
}
double JfrTimeConverter::counter_to_millis_internal(jlong c, bool is_os_time) {
return (counter_to_nanos_internal(c, is_os_time) / NANOS_PER_MILLISEC);
}
jlong JfrTimeConverter::counter_to_nanos(jlong c, bool is_os_time) {
return (jlong)counter_to_nanos_internal(c, is_os_time);
}
jlong JfrTimeConverter::counter_to_millis(jlong c, bool is_os_time) {
return (jlong)counter_to_millis_internal(c, is_os_time);
}
jlong JfrTimeConverter::nanos_to_countertime(jlong nanos, bool as_os_time) {
return nanos <= 0 ? 0 : (jlong)((double)nanos * nano_to_counter_multiplier(as_os_time));
}
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrTimeConverter.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRTIMECONVERTER_HPP
#define SHARE_VM_JFR_UTILITIES_JFRTIMECONVERTER_HPP
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
class JfrTimeConverter : AllStatic {
private:
static double counter_to_nano_multiplier(bool is_os_time = false);
static double counter_to_nanos_internal(jlong c, bool is_os_time = false);
static double counter_to_millis_internal(jlong c, bool is_os_time = false);
static void initialize();
public:
static const double NANOS_PER_SEC;
static const double NANOS_PER_MILLISEC;
static const double NANOS_PER_MICROSEC;
static double nano_to_counter_multiplier(bool is_os_time = false);
static jlong counter_to_nanos(jlong c, bool is_os_time = false);
static jlong counter_to_millis(jlong c, bool is_os_time = false);
static jlong nanos_to_countertime(jlong c, bool as_os_time = false);
};
#endif // SHARE_VM_JFR_UTILITIES_JFRTIMECONVERTER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrTryLock.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRTRYLOCK_HPP
#define SHARE_VM_JFR_UTILITIES_JFRTRYLOCK_HPP
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/debug.hpp"
class JfrTryLock {
private:
volatile int* const _lock;
bool _has_lock;
public:
JfrTryLock(volatile int* lock) : _lock(lock), _has_lock(Atomic::cmpxchg(1, lock, 0) == 0) {}
~JfrTryLock() {
if (_has_lock) {
OrderAccess::fence();
}
}
bool has_lock() const {
return _has_lock;
}
};
class JfrMonitorTryLock : public StackObj {
private:
Monitor* _lock;
bool _acquired;
public:
JfrMonitorTryLock(Monitor* lock) : _lock(lock), _acquired(lock->try_lock()) {}
~JfrMonitorTryLock() {
if (_acquired) {
assert(_lock->owned_by_self(), "invariant");
_lock->unlock();
}
}
bool acquired() const {
return _acquired;
}
};
#endif // SHARE_VM_JFR_UTILITIES_JFRTRYLOCK_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/utilities/jfrTypes.hpp
#ifndef SHARE_VM_JFR_UTILITIES_JFRTYPES_HPP
#define SHARE_VM_JFR_UTILITIES_JFRTYPES_HPP
#include "jfrfiles/jfrEventIds.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
typedef u8 traceid;
typedef int fio_fd;
const int invalid_fd = -1;
const jlong invalid_offset = -1;
const u4 STACK_DEPTH_DEFAULT = 64;
const u4 MIN_STACK_DEPTH = 1;
const u4 MAX_STACK_DEPTH = 2048;
enum EventStartTime {
UNTIMED,
TIMED
};
jlong atomic_add_jlong(jlong value, jlong volatile* const dest);
#endif // SHARE_VM_JFR_UTILITIES_JFRTYPES_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrBigEndianWriter.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRBIGENDIANWRITER_HPP
#define SHARE_VM_JFR_WRITERS_JFRBIGENDIANWRITER_HPP
#include "jfr/writers/jfrEncoding.hpp"
#include "jfr/writers/jfrMemoryWriterHost.inline.hpp"
#include "jfr/writers/jfrStorageAdapter.hpp"
#include "jfr/writers/jfrWriterHost.inline.hpp"
typedef MemoryWriterHost<NoOwnershipAdapter, StackObj > MemoryWriter;
typedef WriterHost<BigEndianEncoder, BigEndianEncoder, MemoryWriter> BigEndianWriterBase;
class JfrBigEndianWriter : public BigEndianWriterBase {
public:
template <typename StorageType>
JfrBigEndianWriter(StorageType* storage, size_t size) : BigEndianWriterBase(storage, size + size_safety_cushion) {}
};
#endif // SHARE_VM_JFR_WRITERS_JFRBIGENDIANWRITER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrEncoders.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRENCODERS_HPP
#define SHARE_VM_JFR_WRITERS_JFRENCODERS_HPP
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "bytes_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "bytes_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "bytes_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "bytes_ppc.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "bytes_aarch64.hpp"
#endif
class BigEndianEncoderImpl {
public:
template <typename T>
static size_t encode(T value, u1* dest);
template <typename T>
static size_t encode(const T* src, size_t len, u1* dest);
template <typename T>
static size_t encode_padded(T value, u1* dest);
template <typename T>
static size_t encode_padded(const T* src, size_t len, u1* dest);
};
template <typename T>
inline size_t BigEndianEncoderImpl::encode(T value, u1* dest) {
assert(dest != NULL, "invariant");
switch (sizeof(T)) {
case 1: {
ShouldNotReachHere();
return 0;
}
case 2: {
Bytes::put_Java_u2(dest, value);
return 2;
}
case 4: {
Bytes::put_Java_u4(dest, value);
return 4;
}
case 8: {
Bytes::put_Java_u8(dest, value);
return 8;
}
}
ShouldNotReachHere();
return 0;
}
template <typename T>
inline size_t BigEndianEncoderImpl::encode(const T* src, size_t len, u1* dest) {
assert(dest != NULL, "invariant");
assert(len >= 1, "invariant");
if (1 == sizeof(T)) {
memcpy(dest, src, len);
return len;
}
size_t size = encode(*src, dest);
if (len > 1) {
for (size_t i = 1; i < len; ++i) {
size += encode(*(src + i), dest + size);
}
}
return size;
}
template <typename T>
inline size_t BigEndianEncoderImpl::encode_padded(T value, u1* dest) {
return encode(value, dest);
}
template <typename T>
inline size_t BigEndianEncoderImpl::encode_padded(const T* src, size_t len, u1* dest) {
assert(dest != NULL, "invariant");
assert(len >= 1, "invariant");
if (1 == sizeof(T)) {
memcpy(dest, src, len);
return len;
}
size_t size = encode_padded(*src, dest);
if (len > 1) {
for (size_t i = 1; i < len; ++i) {
size += encode_padded(*(src + i), dest + size);
}
}
return size;
}
class Varint128EncoderImpl {
private:
template <typename T>
static u8 to_u8(T value);
public:
template <typename T>
static size_t encode(T value, u1* dest);
template <typename T>
static size_t encode(const T* src, size_t len, u1* dest);
template <typename T>
static size_t encode_padded(T value, u1* dest);
template <typename T>
static size_t encode_padded(const T* src, size_t len, u1* dest);
};
template <typename T>
inline u8 Varint128EncoderImpl::to_u8(T value) {
switch(sizeof(T)) {
case 1:
return static_cast<u8>(static_cast<u1>(value) & static_cast<u1>(0xff));
case 2:
return static_cast<u8>(static_cast<u2>(value) & static_cast<u2>(0xffff));
case 4:
return static_cast<u8>(static_cast<u4>(value) & static_cast<u4>(0xffffffff));
case 8:
return static_cast<u8>(value);
default:
fatal("unsupported type");
}
return 0;
}
static const u1 ext_bit = 0x80;
#define GREATER_THAN_OR_EQUAL_TO_128(v) (((u8)(~(ext_bit - 1)) & (v)))
#define LESS_THAN_128(v) !GREATER_THAN_OR_EQUAL_TO_128(v)
template <typename T>
inline size_t Varint128EncoderImpl::encode(T value, u1* dest) {
assert(dest != NULL, "invariant");
const u8 v = to_u8(value);
if (LESS_THAN_128(v)) {
return 1;
}
if (LESS_THAN_128(v >> 7)) {
return 2;
}
if (LESS_THAN_128(v >> 14)) {
return 3;
}
if (LESS_THAN_128(v >> 21)) {
return 4;
}
if (LESS_THAN_128(v >> 28)) {
return 5;
}
if (LESS_THAN_128(v >> 35)) {
return 6;
}
if (LESS_THAN_128(v >> 42)) {
return 7;
}
if (LESS_THAN_128(v >> 49)) {
return 8;
}
return 9;
}
template <typename T>
inline size_t Varint128EncoderImpl::encode(const T* src, size_t len, u1* dest) {
assert(dest != NULL, "invariant");
assert(len >= 1, "invariant");
size_t size = encode(*src, dest);
if (len > 1) {
for (size_t i = 1; i < len; ++i) {
size += encode(*(src + i), dest + size);
}
}
return size;
}
template <typename T>
inline size_t Varint128EncoderImpl::encode_padded(T value, u1* dest) {
assert(dest != NULL, "invariant");
const u8 v = to_u8(value);
switch (sizeof(T)) {
case 1:
dest[0] = static_cast<u1>(v);
return 1;
case 2:
dest[0] = static_cast<u1>(v | 0x80);
dest[1] = static_cast<u1>(v >> 7);
return 2;
case 4:
dest[0] = static_cast<u1>(v | 0x80);
dest[1] = static_cast<u1>(v >> 7 | 0x80);
dest[2] = static_cast<u1>(v >> 14 | 0x80);
dest[3] = static_cast<u1>(v >> 21);
return 4;
case 8:
dest[0] = static_cast<u1>(v | 0x80);
dest[1] = static_cast<u1>(v >> 7 | 0x80);
dest[2] = static_cast<u1>(v >> 14 | 0x80);
dest[3] = static_cast<u1>(v >> 21 | 0x80);
dest[4] = static_cast<u1>(v >> 28 | 0x80);
dest[5] = static_cast<u1>(v >> 35 | 0x80);
dest[6] = static_cast<u1>(v >> 42 | 0x80);
dest[7] = static_cast<u1>(v >> 49);
return 8;
default:
ShouldNotReachHere();
}
return 0;
}
template <typename T>
inline size_t Varint128EncoderImpl::encode_padded(const T* src, size_t len, u1* dest) {
assert(dest != NULL, "invariant");
assert(len >= 1, "invariant");
size_t size = encode_padded(*src, dest);
if (len > 1) {
for (size_t i = 1; i < len; ++i) {
size += encode_padded(*(src + i), dest + size);
}
}
return size;
}
#endif // SHARE_VM_JFR_WRITERS_JFRENCODERS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrEncoding.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRENCODING_HPP
#define SHARE_VM_JFR_WRITERS_JFRENCODING_HPP
#include "jfr/writers/jfrEncoders.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
enum JfrStringEncoding {
NULL_STRING = 0,
EMPTY_STRING,
STRING_CONSTANT,
UTF8,
UTF16,
LATIN1,
NOF_STRING_ENCODINGS
};
template <typename IntegerEncoder, typename BaseEncoder>
class EncoderHost : public AllStatic {
public:
template <typename T>
static u1* be_write(T value, u1* pos) {
return be_write(&value, 1, pos);
}
template <typename T>
static u1* be_write(const T* value, size_t len, u1* pos) {
assert(value != NULL, "invariant");
assert(pos != NULL, "invariant");
assert(len > 0, "invariant");
return pos + BaseEncoder::encode(value, len, pos);
}
template <typename T>
static u1* write_padded(T value, u1* pos) {
assert(pos != NULL, "invariant");
return write_padded(&value, 1, pos);
}
template <typename T>
static u1* write_padded(const T* value, size_t len, u1* pos) {
assert(value != NULL, "invariant");
assert(pos != NULL, "invariant");
assert(len > 0, "invariant");
return pos + IntegerEncoder::encode_padded(value, len, pos);
}
template <typename T>
static u1* write(T value, u1* pos) {
return write(&value, 1, pos);
}
template <typename T>
static u1* write(const T* value, size_t len, u1* pos) {
assert(value != NULL, "invariant");
assert(pos != NULL, "invariant");
assert(len > 0, "invariant");
return pos + IntegerEncoder::encode(value, len, pos);
}
static u1* write(bool value, u1* pos) {
return be_write((u1)value, pos);
}
static u1* write(float value, u1* pos) {
return be_write(*(u4*)&(value), pos);
}
static u1* write(double value, u1* pos) {
return be_write(*(u8*)&(value), pos);
}
static u1* write(const char* value, u1* pos) {
u2 len = 0;
if (value != NULL) {
len = MIN2<u2>(max_jushort, (jushort)strlen(value));
}
pos = write(len, pos);
if (len > 0) {
pos = be_write(value, len, pos);
}
return pos;
}
static u1* write(char* value, u1* pos) {
return write(const_cast<const char*>(value), pos);
}
};
typedef EncoderHost<BigEndianEncoderImpl, BigEndianEncoderImpl> BigEndianEncoder;
typedef EncoderHost<Varint128EncoderImpl, BigEndianEncoderImpl> CompressedIntegerEncoder;
#endif // SHARE_VM_JFR_WRITERS_JFRENCODING_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrEventWriterHost.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFREVENTWRITERHOST_HPP
#define SHARE_VM_JFR_WRITERS_JFREVENTWRITERHOST_HPP
#include "jfr/writers/jfrWriterHost.inline.hpp"
template <typename BE, typename IE, typename WriterPolicyImpl>
class EventWriterHost : public WriterHost<BE, IE, WriterPolicyImpl> {
public:
template <typename StorageType>
EventWriterHost(StorageType* storage, Thread* thread);
EventWriterHost(Thread* thread);
void begin_write();
intptr_t end_write();
void begin_event_write();
intptr_t end_event_write();
};
template <typename BE, typename IE, typename WriterPolicyImpl >
class StackEventWriterHost : public EventWriterHost<BE, IE, WriterPolicyImpl> {
public:
template <typename StorageType>
StackEventWriterHost(StorageType* storage, Thread* thread);
StackEventWriterHost(Thread* thread);
~StackEventWriterHost();
};
#endif // SHARE_VM_JFR_WRITERS_JFREVENTWRITERHOST_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrEventWriterHost.inline.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFREVENTWRITERHOST_INLINE_HPP
#define SHARE_VM_JFR_WRITERS_JFREVENTWRITERHOST_INLINE_HPP
#include "jfr/writers/jfrEventWriterHost.hpp"
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename StorageType>
inline EventWriterHost<BE, IE, WriterPolicyImpl>::
EventWriterHost(StorageType* storage, Thread* thread) : WriterHost<BE, IE, WriterPolicyImpl>(storage, thread) {}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline EventWriterHost<BE, IE, WriterPolicyImpl>::EventWriterHost(Thread* thread) : WriterHost<BE, IE, WriterPolicyImpl>(thread) {
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void EventWriterHost<BE, IE, WriterPolicyImpl>::begin_write() {
assert(this->is_valid(), "invariant");
assert(!this->is_acquired(), "calling begin with writer already in acquired state!");
this->acquire();
assert(this->used_offset() == 0, "invariant");
assert(this->is_acquired(), "invariant");
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline intptr_t EventWriterHost<BE, IE, WriterPolicyImpl>::end_write(void) {
assert(this->is_acquired(),
"state corruption, calling end with writer with non-acquired state!");
return this->is_valid() ? (intptr_t)this->used_offset() : 0;
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void EventWriterHost<BE, IE, WriterPolicyImpl>::begin_event_write() {
assert(this->is_valid(), "invariant");
assert(!this->is_acquired(), "calling begin with writer already in acquired state!");
this->begin_write();
this->reserve(sizeof(u4)); // reserve the event size slot
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline intptr_t EventWriterHost<BE, IE, WriterPolicyImpl>::end_event_write() {
assert(this->is_acquired(), "invariant");
if (!this->is_valid()) {
this->release();
return 0;
}
const u4 written = (u4)end_write();
if (written > sizeof(u4)) { // larger than header reserve
this->write_padded_at_offset(written, 0);
this->commit();
}
this->release();
assert(!this->is_acquired(), "invariant");
return written;
}
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename StorageType>
inline StackEventWriterHost<BE, IE, WriterPolicyImpl>::
StackEventWriterHost(StorageType* storage, Thread* thread) : EventWriterHost<BE, IE, WriterPolicyImpl>(storage, thread) {
this->begin_event_write();
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline StackEventWriterHost<BE, IE, WriterPolicyImpl>::StackEventWriterHost(Thread* thread) : EventWriterHost<BE, IE, WriterPolicyImpl>(thread) {
this->begin_event_write();
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline StackEventWriterHost<BE, IE, WriterPolicyImpl>::~StackEventWriterHost() {
this->end_event_write();
}
#endif // SHARE_VM_JFR_WRITERS_JFREVENTWRITERHOST_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrJavaEventWriter.cpp
#include "precompiled.hpp"
#include "jni.h"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/recorder/storage/jfrStorage.hpp"
#include "jfr/support/jfrThreadId.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "jfr/writers/jfrJavaEventWriter.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/handles.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/thread.inline.hpp"
static int start_pos_offset = invalid_offset;
static int start_pos_address_offset = invalid_offset;
static int current_pos_offset = invalid_offset;
static int max_pos_offset = invalid_offset;
static int max_event_size_offset = invalid_offset;
static int notified_offset = invalid_offset;
static int thread_id_offset = invalid_offset;
static int valid_offset = invalid_offset;
static bool find_field(InstanceKlass* ik,
Symbol* name_symbol,
Symbol* signature_symbol,
fieldDescriptor* fd,
bool is_static = false,
bool allow_super = false) {
if (allow_super || is_static) {
return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL;
} else {
return ik->find_local_field(name_symbol, signature_symbol, fd);
}
}
static void compute_offset(int &dest_offset,
Klass* klass,
Symbol* name_symbol,
Symbol* signature_symbol,
bool is_static = false, bool allow_super = false) {
fieldDescriptor fd;
InstanceKlass* ik = InstanceKlass::cast(klass);
if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) {
assert(false, "invariant");
}
dest_offset = fd.offset();
}
static bool setup_event_writer_offsets(TRAPS) {
const char class_name[] = "jdk/jfr/internal/EventWriter";
Symbol* const k_sym = SymbolTable::lookup(class_name, sizeof class_name - 1, CHECK_false);
assert(k_sym != NULL, "invariant");
Klass* klass = SystemDictionary::resolve_or_fail(k_sym, true, CHECK_false);
assert(klass != NULL, "invariant");
const char start_pos_name[] = "startPosition";
Symbol* const start_pos_sym = SymbolTable::lookup(start_pos_name, sizeof start_pos_name - 1, CHECK_false);
assert(start_pos_sym != NULL, "invariant");
assert(invalid_offset == start_pos_offset, "invariant");
compute_offset(start_pos_offset, klass, start_pos_sym, vmSymbols::long_signature());
assert(start_pos_offset != invalid_offset, "invariant");
const char start_pos_address_name[] = "startPositionAddress";
Symbol* const start_pos_address_sym = SymbolTable::lookup(start_pos_address_name, sizeof start_pos_address_name - 1, CHECK_false);
assert(start_pos_address_sym != NULL, "invariant");
assert(invalid_offset == start_pos_address_offset, "invariant");
compute_offset(start_pos_address_offset, klass, start_pos_address_sym, vmSymbols::long_signature());
assert(start_pos_address_offset != invalid_offset, "invariant");
const char event_pos_name[] = "currentPosition";
Symbol* const event_pos_sym = SymbolTable::lookup(event_pos_name, sizeof event_pos_name - 1, CHECK_false);
assert(event_pos_sym != NULL, "invariant");
assert(invalid_offset == current_pos_offset, "invariant");
compute_offset(current_pos_offset, klass, event_pos_sym,vmSymbols::long_signature());
assert(current_pos_offset != invalid_offset, "invariant");
const char max_pos_name[] = "maxPosition";
Symbol* const max_pos_sym = SymbolTable::lookup(max_pos_name, sizeof max_pos_name - 1, CHECK_false);
assert(max_pos_sym != NULL, "invariant");
assert(invalid_offset == max_pos_offset, "invariant");
compute_offset(max_pos_offset, klass, max_pos_sym, vmSymbols::long_signature());
assert(max_pos_offset != invalid_offset, "invariant");
const char max_event_size_name[] = "maxEventSize";
Symbol* const max_event_size_sym = SymbolTable::lookup(max_event_size_name, sizeof max_event_size_name - 1, CHECK_false);
assert (max_event_size_sym != NULL, "invariant");
assert(invalid_offset == max_event_size_offset, "invariant");
compute_offset(max_event_size_offset, klass, max_event_size_sym, vmSymbols::int_signature());
assert(max_event_size_offset != invalid_offset, "invariant");
const char notified_name[] = "notified";
Symbol* const notified_sym = SymbolTable::lookup(notified_name, sizeof notified_name - 1, CHECK_false);
assert (notified_sym != NULL, "invariant");
assert(invalid_offset == notified_offset, "invariant");
compute_offset(notified_offset, klass, notified_sym, vmSymbols::bool_signature());
assert(notified_offset != invalid_offset, "invariant");
const char valid_name[] = "valid";
Symbol* const valid_sym = SymbolTable::lookup(valid_name, sizeof valid_name - 1, CHECK_false);
assert (valid_sym != NULL, "invariant");
assert(invalid_offset == valid_offset, "invariant");
compute_offset(valid_offset, klass, valid_sym, vmSymbols::bool_signature());
assert(valid_offset != invalid_offset, "invariant");
return true;
}
bool JfrJavaEventWriter::has_required_classes(TRAPS) {
const char class_name[] = "jdk/jfr/internal/EventWriter";
Symbol* const k_sym = SymbolTable::lookup(class_name, sizeof class_name - 1, CHECK_false);
Klass* klass = SystemDictionary::resolve_or_null(k_sym, CHECK_false);
return (klass != NULL);
}
bool JfrJavaEventWriter::initialize() {
static bool initialized = false;
if (!initialized) {
initialized = setup_event_writer_offsets(Thread::current());
}
return initialized;
}
jboolean JfrJavaEventWriter::flush(jobject writer, jint used, jint requested, JavaThread* jt) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
assert(writer != NULL, "invariant");
oop const w = JNIHandles::resolve_non_null(writer);
assert(w != NULL, "invariant");
JfrBuffer* const current = jt->jfr_thread_local()->java_buffer();
assert(current != NULL, "invariant");
JfrBuffer* const buffer = JfrStorage::flush(current, used, requested, false, jt);
assert(buffer != NULL, "invariant");
const bool is_valid = buffer->free_size() >= (size_t)(used + requested);
u1* const new_current_position = is_valid ? buffer->pos() + used : buffer->pos();
assert(start_pos_offset != invalid_offset, "invariant");
w->long_field_put(start_pos_offset, (jlong)buffer->pos());
w->long_field_put(current_pos_offset, (jlong)new_current_position);
if (buffer != current) {
w->long_field_put(start_pos_address_offset, (jlong)buffer->pos_address());
w->long_field_put(max_pos_offset, (jlong)buffer->end());
}
if (!is_valid) {
w->release_bool_field_put(valid_offset, JNI_FALSE);
return JNI_FALSE;
}
return buffer->lease() ? JNI_TRUE : JNI_FALSE;
}
class JfrJavaEventWriterNotificationClosure : public ThreadClosure {
public:
void do_thread(Thread* t) {
if (t->is_Java_thread()) {
JfrJavaEventWriter::notify((JavaThread*)t);
}
}
};
void JfrJavaEventWriter::notify() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
JfrJavaEventWriterNotificationClosure closure;
Threads::threads_do(&closure);
}
void JfrJavaEventWriter::notify(JavaThread* jt) {
assert(jt != NULL, "invariant");
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
if (jt->jfr_thread_local()->has_java_event_writer()) {
oop buffer_writer = JNIHandles::resolve_non_null(jt->jfr_thread_local()->java_event_writer());
assert(buffer_writer != NULL, "invariant");
buffer_writer->release_bool_field_put(notified_offset, JNI_TRUE);
}
}
static jobject create_new_event_writer(JfrBuffer* buffer, TRAPS) {
assert(buffer != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
HandleMark hm(THREAD);
static const char klass[] = "jdk/jfr/internal/EventWriter";
static const char method[] = "<init>";
static const char signature[] = "(JJJJZ)V";
JavaValue result(T_OBJECT);
JfrJavaArguments args(&result, klass, method, signature, CHECK_NULL);
args.push_long((jlong)buffer->pos());
args.push_long((jlong)buffer->end());
args.push_long((jlong)buffer->pos_address());
args.push_long((jlong)JFR_THREAD_ID(THREAD));
args.push_int((int)JNI_TRUE);
JfrJavaSupport::new_object_global_ref(&args, CHECK_NULL);
return result.get_jobject();
}
jobject JfrJavaEventWriter::event_writer(Thread* t) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t));
JfrThreadLocal* const tl = t->jfr_thread_local();
assert(tl->shelved_buffer() == NULL, "invariant");
return tl->java_event_writer();
}
jobject JfrJavaEventWriter::new_event_writer(TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
assert(event_writer(THREAD) == NULL, "invariant");
JfrThreadLocal* const tl = THREAD->jfr_thread_local();
assert(!tl->has_java_buffer(), "invariant");
JfrBuffer* const buffer = tl->java_buffer();
if (buffer == NULL) {
JfrJavaSupport::throw_out_of_memory_error("OOME for thread local buffer", THREAD);
return NULL;
}
jobject java_event_writer = create_new_event_writer(buffer, CHECK_NULL);
tl->set_java_event_writer(java_event_writer);
assert(tl->has_java_event_writer(), "invariant");
return java_event_writer;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrJavaEventWriter.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRJAVAEVENTWRITER_HPP
#define SHARE_VM_JFR_WRITERS_JFRJAVAEVENTWRITER_HPP
#include "jni.h"
#include "memory/allocation.hpp"
class JavaThread;
class Thread;
class JfrJavaEventWriter : AllStatic {
friend class JfrCheckpointThreadClosure;
friend class JfrJavaEventWriterNotificationClosure;
friend class JfrJavaEventWriterNotifyOperation;
friend class JfrRecorder;
private:
static bool initialize();
static void notify(JavaThread* jt);
public:
static bool has_required_classes(TRAPS);
static void notify();
static jobject event_writer(Thread* t);
static jobject new_event_writer(TRAPS);
static jboolean flush(jobject writer, jint used, jint requested, JavaThread* jt);
};
#endif // SHARE_VM_JFR_WRITERS_JFRJAVAEVENTWRITER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrMemoryWriterHost.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRMEMORYWRITERHOST_HPP
#define SHARE_VM_JFR_WRITERS_JFRMEMORYWRITERHOST_HPP
#include "jfr/writers/jfrStorageHost.inline.hpp"
#ifdef ASSERT
class ExclusiveAccessAssert {
private:
bool _acquired;
public:
ExclusiveAccessAssert() : _acquired(false) {}
void acquire() { assert_non_acquired(); _acquired = true; }
void release() { assert_acquired(); _acquired = false; }
bool is_acquired() const { return _acquired; }
void assert_acquired() const { assert(_acquired, "Not acquired!"); }
void assert_non_acquired() const { assert(!_acquired, "Already acquired!"); }
};
#else
class ExclusiveAccessAssert {};
#endif
template <typename Adapter, typename AP, typename AccessAssert = ExclusiveAccessAssert>
class MemoryWriterHost : public StorageHost<Adapter, AP> {
debug_only(AccessAssert _access;)
public:
typedef typename Adapter::StorageType StorageType;
protected:
void bytes(void* dest, const void* buf, size_t len);
MemoryWriterHost(StorageType* storage, Thread* thread);
MemoryWriterHost(StorageType* storage, size_t size);
MemoryWriterHost(Thread* thread);
debug_only(bool is_acquired() const;)
public:
void acquire();
void release();
};
template <typename Adapter, typename AP>
class AcquireReleaseMemoryWriterHost : public MemoryWriterHost<Adapter, AP> {
public:
typedef typename Adapter::StorageType StorageType;
AcquireReleaseMemoryWriterHost(StorageType* storage, Thread* thread);
AcquireReleaseMemoryWriterHost(StorageType* storage, size_t size);
AcquireReleaseMemoryWriterHost(Thread* thread);
~AcquireReleaseMemoryWriterHost();
};
#endif // SHARE_VM_JFR_WRITERS_JFRMEMORYWRITERHOST_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrMemoryWriterHost.inline.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRMEMORYWRITERHOST_INLINE_HPP
#define SHARE_VM_JFR_WRITERS_JFRMEMORYWRITERHOST_INLINE_HPP
#include "jfr/writers/jfrMemoryWriterHost.hpp"
template <typename Adapter, typename AP, typename AccessAssert>
inline void MemoryWriterHost<Adapter, AP, AccessAssert>::bytes(void* dest, const void* buf, size_t len) {
assert(dest != NULL, "invariant");
memcpy(dest, buf, len); // no encoding
this->set_current_pos(len);
}
template <typename Adapter, typename AP, typename AccessAssert>
inline MemoryWriterHost<Adapter, AP, AccessAssert>::MemoryWriterHost(typename Adapter::StorageType* storage, Thread* thread) :
StorageHost<Adapter, AP>(storage, thread) {
}
template <typename Adapter, typename AP, typename AccessAssert>
inline MemoryWriterHost<Adapter, AP, AccessAssert>::MemoryWriterHost(typename Adapter::StorageType* storage, size_t size) :
StorageHost<Adapter, AP>(storage, size) {
}
template <typename Adapter, typename AP, typename AccessAssert>
inline MemoryWriterHost<Adapter, AP, AccessAssert>::MemoryWriterHost(Thread* thread) :
StorageHost<Adapter, AP>(thread) {
}
template <typename Adapter, typename AP, typename AccessAssert>
inline void MemoryWriterHost<Adapter, AP, AccessAssert>::acquire() {
debug_only(_access.acquire();)
if (!this->is_valid()) {
this->flush();
}
debug_only(is_acquired();)
}
template <typename Adapter, typename AP, typename AccessAssert>
inline void MemoryWriterHost<Adapter, AP, AccessAssert>::release() {
debug_only(is_acquired();)
StorageHost<Adapter, AP>::release();
debug_only(_access.release();)
}
#ifdef ASSERT
template <typename Adapter, typename AP, typename AccessAssert>
inline bool MemoryWriterHost<Adapter, AP, AccessAssert>::is_acquired() const {
return _access.is_acquired();
}
#endif
template <typename Adapter, typename AP>
inline AcquireReleaseMemoryWriterHost<Adapter, AP>::AcquireReleaseMemoryWriterHost(typename Adapter::StorageType* storage, Thread* thread) :
MemoryWriterHost<Adapter, AP>(storage, thread) {
this->acquire();
}
template <typename Adapter, typename AP>
inline AcquireReleaseMemoryWriterHost<Adapter, AP>::AcquireReleaseMemoryWriterHost(typename Adapter::StorageType* storage, size_t size) :
MemoryWriterHost<Adapter, AP>(storage, size) {
this->acquire();
}
template <typename Adapter, typename AP>
inline AcquireReleaseMemoryWriterHost<Adapter, AP>::AcquireReleaseMemoryWriterHost(Thread* thread) :
MemoryWriterHost<Adapter, AP>(thread) {
this->acquire();
}
template <typename Adapter, typename AP>
inline AcquireReleaseMemoryWriterHost<Adapter, AP>::~AcquireReleaseMemoryWriterHost() {
assert(this->is_acquired(), "invariant");
this->release();
}
#endif // SHARE_VM_JFR_WRITERS_JFRMEMORYWRITERHOST_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrNativeEventWriter.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRNATIVEEVENTWRITER_HPP
#define SHARE_VM_JFR_WRITERS_JFRNATIVEEVENTWRITER_HPP
#include "jfr/support/jfrFlush.hpp"
#include "jfr/writers/jfrEncoding.hpp"
#include "jfr/writers/jfrEventWriterHost.inline.hpp"
#include "jfr/writers/jfrMemoryWriterHost.inline.hpp"
#include "jfr/writers/jfrStorageAdapter.hpp"
typedef Adapter<JfrFlush> JfrNativeEventAdapter;
typedef MemoryWriterHost<JfrNativeEventAdapter, StackObj> JfrNativeEventWriterImpl;
typedef StackEventWriterHost<BigEndianEncoder, CompressedIntegerEncoder, JfrNativeEventWriterImpl> JfrNativeEventWriter;
#endif // SHARE_VM_JFR_WRITERS_JFRNATIVEEVENTWRITER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrPosition.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRPOSITION_HPP
#define SHARE_VM_JFR_WRITERS_JFRPOSITION_HPP
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
template <typename AP> // AllocationPolicy
class Position : public AP {
private:
const u1* _start_pos; // logical start
u1* _current_pos;
const u1* _end_pos;
protected:
const u1* start_pos() const;
void set_start_pos(const u1* position);
u1* current_pos();
void set_current_pos(const u1* new_position);
void set_current_pos(size_t size);
const u1* end_pos() const;
void set_end_pos(const u1* position);
Position(const u1* start_pos, size_t size);
Position();
public:
size_t available_size() const;
int64_t used_offset() const;
int64_t current_offset() const;
size_t used_size() const;
void reset();
};
#endif // SHARE_VM_JFR_WRITERS_JFRPOSITION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrPosition.inline.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRPOSITION_INLINE_HPP
#define SHARE_VM_JFR_WRITERS_JFRPOSITION_INLINE_HPP
#include "jfr/writers/jfrPosition.hpp"
template <typename AP>
inline const u1* Position<AP>::start_pos() const {
return _start_pos;
}
template <typename AP>
inline void Position<AP>::set_start_pos(const u1* position) {
_start_pos = position;
}
template <typename AP>
inline u1* Position<AP>::current_pos() {
return _current_pos;
}
template <typename AP>
inline void Position<AP>::set_current_pos(const u1* new_position) {
_current_pos = const_cast<u1*>(new_position);
}
template <typename AP>
inline void Position<AP>::set_current_pos(size_t size) {
_current_pos += size;
}
template <typename AP>
inline const u1* Position<AP>::end_pos() const {
return _end_pos;
}
template <typename AP>
inline void Position<AP>::set_end_pos(const u1* position) {
_end_pos = position;
}
template <typename AP>
inline Position<AP>::Position(const u1* start_pos, size_t size) :
AP(),
_start_pos(start_pos),
_current_pos(const_cast<u1*>(start_pos)),
_end_pos(start_pos + size) {
}
template <typename AP>
inline Position<AP>::Position() : _start_pos(NULL), _current_pos(NULL), _end_pos(NULL) {
}
template <typename AP>
inline size_t Position<AP>::available_size() const {
return _end_pos - _current_pos;
}
template <typename AP>
inline int64_t Position<AP>::used_offset() const {
return _current_pos - _start_pos;
}
template <typename AP>
inline int64_t Position<AP>::current_offset() const {
return this->used_offset();
}
template <typename AP>
inline size_t Position<AP>::used_size() const {
return (size_t)used_offset();
}
template <typename AP>
inline void Position<AP>::reset() {
set_current_pos(_start_pos);
}
#endif // SHARE_VM_JFR_WRITERS_JFRPOSITION_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrStorageAdapter.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRSTORAGEADAPTER_HPP
#define SHARE_VM_JFR_WRITERS_JFRSTORAGEADAPTER_HPP
#include "jfr/utilities/jfrAllocation.hpp"
class Thread;
template <typename Flush>
class Adapter {
public:
typedef typename Flush::Type StorageType;
Adapter(StorageType* storage, Thread* thread) : _storage(storage), _thread(thread) {}
Adapter(Thread* thread) : _storage(NULL), _thread(thread) {}
void set_storage(StorageType* storage) {
_storage = storage;
}
StorageType* storage() {
return _storage;
}
const u1* start() const {
assert(_storage != NULL, "invariant");
return _storage->start();
}
u1* pos() {
assert(_storage != NULL, "invariant");
return _storage->pos();
}
const u1* end() const {
assert(_storage != NULL, "invariant");
return _storage->end();
}
void commit(u1* position) {
assert(_storage != NULL, "invariant");
_storage->set_pos(position);
}
bool flush(size_t used, size_t requested) {
assert(_thread != NULL, "invariant");
Flush f(_storage, used, requested, _thread);
_storage = f.result();
return _storage != NULL;
}
void release() {
if (_storage != NULL && _storage->lease()) {
flush(0, 0);
}
}
private:
StorageType* _storage;
Thread* _thread;
};
template <size_t DEFAULT_SIZE = K>
class MallocAdapter {
private:
u1* _start;
u1* _pos;
u1* _end;
size_t _initial_size;
bool _has_ownership;
bool allocate(size_t size);
void deallocate();
public:
typedef u1 StorageType;
MallocAdapter(u1* storage, Thread* thread);
MallocAdapter(u1* storage, size_t size);
MallocAdapter(Thread* thread);
~MallocAdapter();
StorageType* storage() { return _start; }
const u1* start() const { return _start; }
u1* pos() { return _pos; }
void commit(u1* position) { _pos = position; }
const u1* end() const { return _end; }
void release() {}
bool flush(size_t used, size_t requested);
};
template <size_t DEFAULT_SIZE>
MallocAdapter<DEFAULT_SIZE>::MallocAdapter(u1* storage, size_t size) :
_start(storage),
_pos(storage),
_end(storage + size),
_initial_size(size),
_has_ownership(false) {
}
template <size_t DEFAULT_SIZE>
MallocAdapter<DEFAULT_SIZE> ::MallocAdapter(u1* storage, Thread* thread) :
_start(storage),
_pos(storage),
_end(storage),
_initial_size(0),
_has_ownership(false) {
}
template <size_t DEFAULT_SIZE>
MallocAdapter<DEFAULT_SIZE>::MallocAdapter(Thread* thread) :
_start(NULL),
_pos(NULL),
_end(NULL),
_initial_size(DEFAULT_SIZE),
_has_ownership(true) {
allocate(DEFAULT_SIZE);
}
template <size_t DEFAULT_SIZE>
MallocAdapter<DEFAULT_SIZE>::~MallocAdapter() {
if (_has_ownership) {
deallocate();
}
}
template <size_t DEFAULT_SIZE>
bool MallocAdapter<DEFAULT_SIZE>::allocate(size_t size) {
if (NULL == _start) {
_start = JfrCHeapObj::new_array<u1>(size);
if (_start) {
_pos = _start;
_end = _start + size;
_initial_size = size;
}
}
return _start != NULL;
}
template <size_t DEFAULT_SIZE>
void MallocAdapter<DEFAULT_SIZE>::deallocate() {
if (_start != NULL) {
JfrCHeapObj::free(_start, (size_t)(_end - _start));
}
}
template <size_t DEFAULT_SIZE>
bool MallocAdapter<DEFAULT_SIZE>::flush(size_t used, size_t requested) {
if (!_has_ownership) {
return false;
}
assert(_start != NULL, "invariant");
assert(used <= (size_t)(_end - _pos), "invariant");
assert(_pos + used <= _end, "invariant");
const size_t previous_storage_size = _end - _start;
const size_t new_storage_size = used + requested + (previous_storage_size * 2);
u1* const new_storage = JfrCHeapObj::new_array<u1>(new_storage_size);
if (!new_storage) {
return false;
}
const size_t previous_pos_offset = _pos - _start;
memcpy(new_storage, _start, previous_pos_offset + used);
JfrCHeapObj::free(_start, previous_storage_size);
_start = new_storage;
_pos = _start + previous_pos_offset;
_end = _start + new_storage_size;
return true;
}
class NoOwnershipAdapter {
private:
u1* _start;
u1* _pos;
u1* _end;
size_t _size;
public:
typedef u1 StorageType;
NoOwnershipAdapter(u1* storage, size_t size) : _start(storage), _pos(storage), _end(storage + size), _size(size) {}
NoOwnershipAdapter(u1* storage, Thread* thread) : _start(storage), _pos(storage), _end(storage), _size(0) {
ShouldNotCallThis();
}
NoOwnershipAdapter(Thread* thread) : _start(NULL), _pos(NULL), _end(NULL), _size(0) {
ShouldNotCallThis();
}
StorageType* storage() { return _start; }
const u1* start() const { return _start; }
u1* pos() { return _pos; }
void commit(u1* position) { _pos = position; }
const u1* end() const { return _end; }
void release() {}
bool flush(size_t used, size_t requested) {
return false;
}
};
#endif // SHARE_VM_JFR_WRITERS_JFRSTORAGEADAPTER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrStorageHost.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRSTORAGEHOST_HPP
#define SHARE_VM_JFR_WRITERS_JFRSTORAGEHOST_HPP
#include "jfr/writers/jfrPosition.inline.hpp"
template <typename Adapter, typename AP> // Adapter and AllocationPolicy
class StorageHost : public Position<AP> {
public:
typedef typename Adapter::StorageType StorageType;
private:
Adapter _adapter;
protected:
void bind();
void soft_reset();
void hard_reset();
void cancel();
bool is_backed();
bool accommodate(size_t used, size_t requested);
void commit();
void release();
StorageHost(StorageType* storage, Thread* thread);
StorageHost(StorageType* storage, size_t size);
StorageHost(Thread* thread);
public:
StorageType* storage();
bool is_valid() const;
void set_storage(StorageType* storage);
void flush();
void seek(intptr_t offset);
};
#endif // SHARE_VM_JFR_WRITERS_JFRSTORAGEHOST_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrStorageHost.inline.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRSTORAGEHOST_INLINE_HPP
#define SHARE_VM_JFR_WRITERS_JFRSTORAGEHOST_INLINE_HPP
#include "jfr/writers/jfrStorageHost.hpp"
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::bind() {
if (is_backed()) {
this->hard_reset();
assert(is_valid(), "invariant");
return;
}
this->set_start_pos(NULL);
this->set_current_pos((const u1*)NULL);
this->set_end_pos(NULL);
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::soft_reset() {
this->set_start_pos(this->current_pos());
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::hard_reset() {
this->set_start_pos(_adapter.pos());
this->set_current_pos(_adapter.pos());
this->set_end_pos(_adapter.end());
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::cancel() {
this->set_end_pos(NULL);
}
template <typename Adapter, typename AP>
inline bool StorageHost<Adapter, AP>::is_backed() {
return _adapter.storage() != NULL;
}
template <typename Adapter, typename AP>
inline bool StorageHost<Adapter, AP>::accommodate(size_t used, size_t requested) {
if (!_adapter.flush(used, requested)) {
this->cancel();
return false;
}
assert(is_backed(), "invariant");
this->hard_reset();
this->set_current_pos(used);
return true;
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::commit() {
if (this->is_valid()) {
assert(_adapter.pos() == this->start_pos(), "invariant");
assert(_adapter.end() == this->end_pos(), "invariant");
u1* new_position = this->current_pos();
_adapter.commit(new_position);
this->set_start_pos(new_position);
}
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::release() {
_adapter.release();
}
template <typename Adapter, typename AP>
inline StorageHost<Adapter, AP>::StorageHost(typename Adapter::StorageType* storage, Thread* thread) : Position<AP>(), _adapter(storage, thread) {
bind();
}
template <typename Adapter, typename AP>
inline StorageHost<Adapter, AP>::StorageHost(typename Adapter::StorageType* storage, size_t size) : Position<AP>(), _adapter(storage, size) {
bind();
}
template <typename Adapter, typename AP>
inline StorageHost<Adapter, AP>::StorageHost(Thread* thread) : Position<AP>(), _adapter(thread) {
bind();
}
template <typename Adapter, typename AP>
inline bool StorageHost<Adapter, AP>::is_valid() const {
return this->end_pos() != NULL;
}
template <typename Adapter, typename AP>
inline typename Adapter::StorageType* StorageHost<Adapter, AP>::storage() {
return _adapter.storage();
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::set_storage(typename Adapter::StorageType* storage) {
_adapter.set_storage(storage);
bind();
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::flush() {
this->accommodate(this->is_valid() ? this->used_size() : 0, 0);
}
template <typename Adapter, typename AP>
inline void StorageHost<Adapter, AP>::seek(intptr_t offset) {
if (this->is_valid()) {
assert(offset >= 0, "negative offsets not supported");
assert(this->start_pos() + offset <= this->end_pos(), "invariant");
assert(this->start_pos() + offset >= this->start_pos(), "invariant");
this->set_current_pos(this->start_pos() + offset);
}
}
#endif // SHARE_VM_JFR_WRITERS_JFRSTORAGEHOST_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrStreamWriterHost.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRSTREAMWRITERHOST_HPP
#define SHARE_VM_JFR_WRITERS_JFRSTREAMWRITERHOST_HPP
#include "jfr/utilities/jfrTypes.hpp"
#include "jfr/writers/jfrMemoryWriterHost.inline.hpp"
template <typename Adapter, typename AP> // Adapter and AllocationPolicy
class StreamWriterHost : public MemoryWriterHost<Adapter, AP> {
public:
typedef typename Adapter::StorageType StorageType;
private:
int64_t _stream_pos;
fio_fd _fd;
int64_t current_stream_position() const;
protected:
StreamWriterHost(StorageType* storage, Thread* thread);
StreamWriterHost(StorageType* storage, size_t size);
StreamWriterHost(Thread* thread);
bool accommodate(size_t used, size_t requested);
void bytes(void* dest, const void* src, size_t len);
void flush(size_t size);
bool has_valid_fd() const;
public:
int64_t current_offset() const;
void seek(int64_t offset);
void flush();
void write_unbuffered(const void* src, size_t len);
bool is_valid() const;
void close_fd();
void reset(fio_fd fd);
};
#endif // SHARE_VM_JFR_WRITERS_JFRSTREAMWRITERHOST_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrStreamWriterHost.inline.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP
#define SHARE_VM_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP
#include "jfr/writers/jfrStreamWriterHost.hpp"
#include "runtime/os.hpp"
template <typename Adapter, typename AP>
StreamWriterHost<Adapter, AP>::StreamWriterHost(typename Adapter::StorageType* storage, Thread* thread) :
MemoryWriterHost<Adapter, AP>(storage, thread), _stream_pos(0), _fd(invalid_fd) {
}
template <typename Adapter, typename AP>
StreamWriterHost<Adapter, AP>::StreamWriterHost(typename Adapter::StorageType* storage, size_t size) :
MemoryWriterHost<Adapter, AP>(storage, size), _stream_pos(0), _fd(invalid_fd) {
}
template <typename Adapter, typename AP>
StreamWriterHost<Adapter, AP>::StreamWriterHost(Thread* thread) :
MemoryWriterHost<Adapter, AP>(thread), _stream_pos(0), _fd(invalid_fd) {
}
template <typename Adapter, typename AP>
inline int64_t StreamWriterHost<Adapter, AP>::current_stream_position() const {
return this->used_offset() + _stream_pos;
}
template <typename Adapter, typename AP>
inline bool StreamWriterHost<Adapter, AP>::accommodate(size_t used, size_t requested) {
if (used > 0) {
this->flush(used);
}
assert(this->used_size() == 0, "invariant");
if (this->available_size() >= requested) {
return true;
}
return StorageHost<Adapter, AP>::accommodate(0, requested);
}
template <typename Adapter, typename AP>
inline void StreamWriterHost<Adapter, AP>::bytes(void* dest, const void* buf, size_t len) {
if (len > this->available_size()) {
this->write_unbuffered(buf, len);
return;
}
MemoryWriterHost<Adapter, AP>::bytes(dest, buf, len);
}
template <typename Adapter, typename AP>
inline void StreamWriterHost<Adapter, AP>::flush(size_t size) {
assert(size > 0, "invariant");
assert(this->is_valid(), "invariant");
_stream_pos += os::write(_fd, this->start_pos(), (unsigned int)size);
StorageHost<Adapter, AP>::reset();
assert(0 == this->used_offset(), "invariant");
}
template <typename Adapter, typename AP>
inline bool StreamWriterHost<Adapter, AP>::has_valid_fd() const {
return invalid_fd != _fd;
}
template <typename Adapter, typename AP>
inline int64_t StreamWriterHost<Adapter, AP>::current_offset() const {
return current_stream_position();
}
template <typename Adapter, typename AP>
void StreamWriterHost<Adapter, AP>::seek(int64_t offset) {
this->flush();
assert(0 == this->used_offset(), "can only seek from beginning");
_stream_pos = os::seek_to_file_offset(_fd, offset);
}
template <typename Adapter, typename AP>
void StreamWriterHost<Adapter, AP>::flush() {
if (this->is_valid()) {
const size_t used = this->used_size();
if (used > 0) {
this->flush(used);
}
}
}
template <typename Adapter, typename AP>
void StreamWriterHost<Adapter, AP>::write_unbuffered(const void* buf, size_t len) {
this->flush();
assert(0 == this->used_offset(), "can only seek from beginning");
while (len > 0) {
const unsigned int n = MIN2((unsigned int)len, (unsigned int)INT_MAX);
_stream_pos += os::write(_fd, buf, n);
len -= n;
}
}
template <typename Adapter, typename AP>
inline bool StreamWriterHost<Adapter, AP>::is_valid() const {
return has_valid_fd();
}
template <typename Adapter, typename AP>
inline void StreamWriterHost<Adapter, AP>::close_fd() {
assert(this->has_valid_fd(), "closing invalid fd!");
os::close(_fd);
_fd = invalid_fd;
}
template <typename Adapter, typename AP>
inline void StreamWriterHost<Adapter, AP>::reset(fio_fd fd) {
assert(!this->has_valid_fd(), "invariant");
_fd = fd;
_stream_pos = 0;
this->hard_reset();
}
#endif // SHARE_VM_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrWriterHost.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRWRITERHOST_HPP
#define SHARE_VM_JFR_WRITERS_JFRWRITERHOST_HPP
#include "jni.h"
#include "utilities/globalDefinitions.hpp"
#include "jfr/utilities/jfrTime.hpp"
class ClassLoaderData;
class Klass;
class Method;
class Symbol;
class Thread;
template <typename BE, typename IE, typename WriterPolicyImpl >
class WriterHost : public WriterPolicyImpl {
private:
const bool _compressed_integers;
template <typename T>
void write_padded(T value);
template <typename T>
void write_padded(const T* value, size_t len);
template <typename T>
u1* write_padded(const T* value, size_t len, u1* pos);
template <typename T>
void write(const T* value, size_t len);
template <typename T>
u1* write(const T* value, size_t len, u1* pos);
void write_utf8(const char* value);
void write_utf16(const jchar* value, jint len);
protected:
template <typename T>
void be_write(T value);
template <typename T>
void be_write(const T* value, size_t len);
template <typename StorageType>
WriterHost(StorageType* storage, Thread* thread);
template <typename StorageType>
WriterHost(StorageType* storage, size_t size);
WriterHost(Thread* thread);
u1* ensure_size(size_t requested_size);
public:
template <typename T>
void write(T value);
void write(bool value);
void write(float value);
void write(double value);
void write(const char* value);
void write(char* value);
void write(jstring value);
void write(const ClassLoaderData* cld);
void write(const Klass* klass);
void write(const Method* method);
void write(const Symbol* symbol);
void write(const Ticks& time);
void write(const Tickspan& time);
void write(const JfrTicks& time);
void write(const JfrTickspan& time);
void bytes(const void* buf, size_t len);
void write_utf8_u2_len(const char* value);
template <typename T>
void write_padded_at_offset(T value, int64_t offset);
template <typename T>
void write_at_offset(T value, int64_t offset);
template <typename T>
void write_be_at_offset(T value, int64_t offset);
int64_t reserve(size_t size);
};
#endif // SHARE_VM_JFR_WRITERS_JFRWRITERHOST_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/writers/jfrWriterHost.inline.hpp
#ifndef SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP
#define SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP
#include "classfile/javaClasses.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/writers/jfrEncoding.hpp"
#include "jfr/writers/jfrWriterHost.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.hpp"
#include "oops/symbol.hpp"
inline bool compressed_integers() {
static const bool comp_integers = JfrOptionSet::compressed_integers();
return comp_integers;
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded(T value) {
write_padded(&value, 1);
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded(const T* value, size_t len) {
assert(value != NULL, "invariant");
assert(len > 0, "invariant");
u1* const pos = ensure_size(sizeof(T) * len);
if (pos) {
this->set_current_pos(write_padded(value, len, pos));
}
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline u1* WriterHost<BE, IE, WriterPolicyImpl>::write_padded(const T* value, size_t len, u1* pos) {
assert(value != NULL, "invariant");
assert(len > 0, "invariant");
assert(pos != NULL, "invariant");
return _compressed_integers ? IE::write_padded(value, len, pos) : BE::write_padded(value, len, pos);
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(const T* value, size_t len) {
assert(value != NULL, "invariant");
assert(len > 0, "invariant");
u1* const pos = ensure_size(sizeof(T) * len + len);
if (pos) {
this->set_current_pos(write(value, len, pos));
}
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline u1* WriterHost<BE, IE, WriterPolicyImpl>::write(const T* value, size_t len, u1* pos) {
assert(value != NULL, "invariant");
assert(len > 0, "invariant");
assert(pos != NULL, "invariant");
return _compressed_integers ? IE::write(value, len, pos) : BE::write(value, len, pos);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8(const char* value) {
if (NULL == value) {
write<u1>(NULL_STRING);
return;
}
write<u1>(UTF8); // designate encoding
const jint len = MIN2<jint>(max_jint, (jint)strlen(value));
write(len);
if (len > 0) {
be_write(value, len);
}
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write_utf16(const jchar* value, jint len) {
assert(value != NULL, "invariant");
write((u1)UTF16); // designate encoding
write(len);
if (len > 0) {
write(value, len);
}
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::be_write(T value) {
u1* const pos = ensure_size(sizeof(T));
if (pos) {
this->set_current_pos(BE::be_write(&value, 1, pos));
}
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::be_write(const T* value, size_t len) {
assert(value != NULL, "invariant");
assert(len > 0, "invariant");
u1* const pos = ensure_size(sizeof(T) * len + len);
if (pos) {
this->set_current_pos(BE::be_write(value, len, pos));
}
}
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename StorageType>
inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(StorageType* storage, Thread* thread) :
WriterPolicyImpl(storage, thread),
_compressed_integers(compressed_integers()) {
}
static const size_t size_safety_cushion = 1;
template <typename BE, typename IE, typename WriterPolicyImpl >
template <typename StorageType>
inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(StorageType* storage, size_t size) :
WriterPolicyImpl(storage, size + size_safety_cushion),
_compressed_integers(compressed_integers()) {
}
template <typename BE, typename IE, typename WriterPolicyImpl >
inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(Thread* thread) :
WriterPolicyImpl(thread),
_compressed_integers(compressed_integers()) {
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline u1* WriterHost<BE, IE, WriterPolicyImpl>::ensure_size(size_t requested_size) {
if (!this->is_valid()) {
return NULL;
}
if (this->available_size() < requested_size) {
if (!this->accommodate(this->used_size(), requested_size)) {
this->cancel();
return NULL;
}
}
assert(requested_size <= this->available_size(), "invariant");
return this->current_pos();
}
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(T value) {
write(&value, 1);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(bool value) {
be_write((u1)value);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(float value) {
be_write(*(u4*)&(value));
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(double value) {
be_write(*(u8*)&(value));
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(const char* value) {
write_utf8(value);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(char* value) {
write(const_cast<const char*>(value));
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write(jstring string) {
if (string == NULL) {
write<u1>(NULL_STRING);
return;
}
const oop string_oop = JNIHandles::resolve_external_guard(string);
assert(string_oop != NULL, "invariant");
const size_t length = (size_t)java_lang_String::length(string_oop);
if (0 == length) {
write<u1>(EMPTY_STRING);
return;
}
const bool is_latin1_encoded = false;
const typeArrayOop value = java_lang_String::value(string_oop);
assert(value != NULL, "invariant");
if (is_latin1_encoded) {
write<u1>(LATIN1);
write<u4>((u4)length);
be_write(value->byte_at_addr(0), length);
} else {
write<u1>(UTF16);
write<u4>((u4)length);
write(value->char_at_addr(0), length);
}
}
template <typename Writer, typename T>
inline void tag_write(Writer* w, const T* t) {
assert(w != NULL, "invariant");
const traceid id = t == NULL ? 0 : JfrTraceId::use(t);
w->write(id);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const ClassLoaderData* cld) {
tag_write(this, cld);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const Klass* klass) {
tag_write(this, klass);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const Method* method) {
tag_write(this, method);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const Symbol* symbol) {
ResourceMark rm;
write_utf8(symbol != NULL ? symbol->as_C_string() : NULL);
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const Ticks& time) {
write((u8)JfrTime::is_ft_enabled() ? time.ft_value() : time.value());
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const Tickspan& time) {
write((u8)JfrTime::is_ft_enabled() ? time.ft_value() : time.value());
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const JfrTicks& time) {
write((u8)time.value());
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::write(const JfrTickspan& time) {
write((u8)time.value());
}
template <typename BE, typename IE, typename WriterPolicyImpl>
void WriterHost<BE, IE, WriterPolicyImpl>::bytes(const void* buf, size_t len) {
u1* const pos = this->ensure_size(len);
if (pos != NULL) {
WriterPolicyImpl::bytes(pos, buf, len); // WriterPolicyImpl responsible for position update
}
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8_u2_len(const char* value) {
u2 len = 0;
if (value != NULL) {
len = MIN2<u2>(max_jushort, (u2)strlen(value));
}
write(len);
if (len > 0) {
be_write(value, len);
}
}
template <typename BE, typename IE, typename WriterPolicyImpl>
inline int64_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) {
if (ensure_size(size) != NULL) {
const int64_t reserved_offset = this->current_offset();
this->set_current_pos(size);
return reserved_offset;
}
this->cancel();
return 0;
}
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
const int64_t current = this->current_offset();
this->seek(offset);
write_padded(value);
this->seek(current); // restore
}
}
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
const int64_t current = this->current_offset();
this->seek(offset);
write(value);
this->seek(current); // restore
}
}
template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline void WriterHost<BE, IE, WriterPolicyImpl>::write_be_at_offset(T value, int64_t offset) {
if (this->is_valid()) {
const int64_t current = this->current_offset();
this->seek(offset);
be_write(value);
this->seek(current); // restore
}
}
#endif // SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/libadt/dict.cpp
#include "precompiled.hpp"
#include "libadt/dict.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/thread.hpp"
#include <assert.h>
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#define MAXID 20
static byte initflag = 0; // True after 1st initialization
static const char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6};
static short xsum[MAXID];
class bucket : public ResourceObj {
public:
uint _cnt, _max; // Size of bucket
void **_keyvals; // Array of keys and values
};
Dict::Dict(CmpKey initcmp, Hash inithash) : _hash(inithash), _cmp(initcmp),
_arena(Thread::current()->resource_area()) {
int i;
if( !initflag ) { // Not initializated yet?
xsum[0] = (1<<shft[0])+1; // Initialize
for(i=1; i<MAXID; i++) {
xsum[i] = (1<<shft[i])+1+xsum[i-1];
}
initflag = 1; // Never again
}
_size = 16; // Size is a power of 2
_cnt = 0; // Dictionary is empty
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket)*_size);
memset(_bin,0,sizeof(bucket)*_size);
}
Dict::Dict(CmpKey initcmp, Hash inithash, Arena *arena, int size)
: _hash(inithash), _cmp(initcmp), _arena(arena) {
int i;
if( !initflag ) { // Not initializated yet?
xsum[0] = (1<<shft[0])+1; // Initialize
for(i=1; i<MAXID; i++) {
xsum[i] = (1<<shft[i])+1+xsum[i-1];
}
initflag = 1; // Never again
}
i=16;
while( i < size ) i <<= 1;
_size = i; // Size is a power of 2
_cnt = 0; // Dictionary is empty
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket)*_size);
memset(_bin,0,sizeof(bucket)*_size);
}
Dict::~Dict() {
tty->print("~Dict %d/%d: ",_cnt,_size);
for( uint i=0; i < _size; i++) // For complete new table do
tty->print("%d ",_bin[i]._cnt);
tty->print("\n");*/
FREE_FAST( _bin[i]._keyvals );
} */
}
void Dict::Clear() {
_cnt = 0; // Empty contents
for( uint i=0; i<_size; i++ )
_bin[i]._cnt = 0; // Empty buckets, but leave allocated
}
void Dict::doubhash(void) {
uint oldsize = _size;
_size <<= 1; // Double in size
_bin = (bucket*)_arena->Arealloc( _bin, sizeof(bucket)*oldsize, sizeof(bucket)*_size );
memset( &_bin[oldsize], 0, oldsize*sizeof(bucket) );
for( uint i=0; i < oldsize; i++) { // For complete OLD table do
bucket *b = &_bin[i]; // Handy shortcut for _bin[i]
if( !b->_keyvals ) continue; // Skip empties fast
bucket *nb = &_bin[i+oldsize]; // New bucket shortcut
uint j = b->_max; // Trim new bucket to nearest power of 2
while( j > b->_cnt ) j >>= 1; // above old bucket _cnt
if( !j ) j = 1; // Handle zero-sized buckets
nb->_max = j<<1;
nb->_keyvals = (void**)_arena->Amalloc_4( sizeof(void *)*nb->_max*2 );
uint nbcnt = 0;
for( j=0; j<b->_cnt; j++ ) { // Rehash all keys in this bucket
void *key = b->_keyvals[j+j];
if( (_hash( key ) & (_size-1)) != i ) { // Moving to hi bucket?
nb->_keyvals[nbcnt+nbcnt] = key;
nb->_keyvals[nbcnt+nbcnt+1] = b->_keyvals[j+j+1];
nb->_cnt = nbcnt = nbcnt+1;
b->_cnt--; // Remove key/value from lo bucket
b->_keyvals[j+j ] = b->_keyvals[b->_cnt+b->_cnt ];
b->_keyvals[j+j+1] = b->_keyvals[b->_cnt+b->_cnt+1];
j--; // Hash compacted element also
}
} // End of for all key-value pairs in bucket
} // End of for all buckets
}
Dict::Dict( const Dict &d ) : _size(d._size), _cnt(d._cnt), _hash(d._hash),_cmp(d._cmp), _arena(d._arena) {
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket)*_size);
memcpy( _bin, d._bin, sizeof(bucket)*_size );
for( uint i=0; i<_size; i++ ) {
if( !_bin[i]._keyvals ) continue;
_bin[i]._keyvals=(void**)_arena->Amalloc_4( sizeof(void *)*_bin[i]._max*2);
memcpy( _bin[i]._keyvals, d._bin[i]._keyvals,_bin[i]._cnt*2*sizeof(void*));
}
}
Dict &Dict::operator =( const Dict &d ) {
if( _size < d._size ) { // If must have more buckets
_arena = d._arena;
_bin = (bucket*)_arena->Arealloc( _bin, sizeof(bucket)*_size, sizeof(bucket)*d._size );
memset( &_bin[_size], 0, (d._size-_size)*sizeof(bucket) );
_size = d._size;
}
uint i;
for( i=0; i<_size; i++ ) // All buckets are empty
_bin[i]._cnt = 0; // But leave bucket allocations alone
_cnt = d._cnt;
for( i=0; i<_size; i++ ) {
bucket *b = &d._bin[i]; // Shortcut to source bucket
for( uint j=0; j<b->_cnt; j++ )
Insert( b->_keyvals[j+j], b->_keyvals[j+j+1] );
}
return *this;
}
void *Dict::Insert(void *key, void *val, bool replace) {
uint hash = _hash( key ); // Get hash key
uint i = hash & (_size-1); // Get hash key, corrected for size
bucket *b = &_bin[i]; // Handy shortcut
for( uint j=0; j<b->_cnt; j++ ) {
if( !_cmp(key,b->_keyvals[j+j]) ) {
if (!replace) {
return b->_keyvals[j+j+1];
} else {
void *prior = b->_keyvals[j+j+1];
b->_keyvals[j+j ] = key; // Insert current key-value
b->_keyvals[j+j+1] = val;
return prior; // Return prior
}
}
}
if( ++_cnt > _size ) { // Hash table is full
doubhash(); // Grow whole table if too full
i = hash & (_size-1); // Rehash
b = &_bin[i]; // Handy shortcut
}
if( b->_cnt == b->_max ) { // Must grow bucket?
if( !b->_keyvals ) {
b->_max = 2; // Initial bucket size
b->_keyvals = (void**)_arena->Amalloc_4(sizeof(void*) * b->_max * 2);
} else {
b->_keyvals = (void**)_arena->Arealloc(b->_keyvals, sizeof(void*) * b->_max * 2, sizeof(void*) * b->_max * 4);
b->_max <<= 1; // Double bucket
}
}
b->_keyvals[b->_cnt+b->_cnt ] = key;
b->_keyvals[b->_cnt+b->_cnt+1] = val;
b->_cnt++;
return NULL; // Nothing found prior
}
void *Dict::Delete(void *key) {
uint i = _hash( key ) & (_size-1); // Get hash key, corrected for size
bucket *b = &_bin[i]; // Handy shortcut
for( uint j=0; j<b->_cnt; j++ )
if( !_cmp(key,b->_keyvals[j+j]) ) {
void *prior = b->_keyvals[j+j+1];
b->_cnt--; // Remove key/value from lo bucket
b->_keyvals[j+j ] = b->_keyvals[b->_cnt+b->_cnt ];
b->_keyvals[j+j+1] = b->_keyvals[b->_cnt+b->_cnt+1];
_cnt--; // One less thing in table
return prior;
}
return NULL;
}
void *Dict::operator [](const void *key) const {
uint i = _hash( key ) & (_size-1); // Get hash key, corrected for size
bucket *b = &_bin[i]; // Handy shortcut
for( uint j=0; j<b->_cnt; j++ )
if( !_cmp(key,b->_keyvals[j+j]) )
return b->_keyvals[j+j+1];
return NULL;
}
int32 Dict::operator ==(const Dict &d2) const {
if( _cnt != d2._cnt ) return 0;
if( _hash != d2._hash ) return 0;
if( _cmp != d2._cmp ) return 0;
for( uint i=0; i < _size; i++) { // For complete hash table do
bucket *b = &_bin[i]; // Handy shortcut
if( b->_cnt != d2._bin[i]._cnt ) return 0;
if( memcmp(b->_keyvals, d2._bin[i]._keyvals, b->_cnt*2*sizeof(void*) ) )
return 0; // Key-value pairs must match
}
return 1; // All match, is OK
}
void Dict::print() {
DictI i(this); // Moved definition in iterator here because of g++.
tty->print("Dict@0x%lx[%d] = {", this, _cnt);
for( ; i.test(); ++i ) {
tty->print("(0x%lx,0x%lx),", i._key, i._value);
}
tty->print_cr("}");
}
int hashstr(const void *t) {
register char c, k = 0;
register int32 sum = 0;
register const char *s = (const char *)t;
while( ((c = *s++) != '\0') && (k < MAXID-1) ) { // Get characters till null or MAXID-1
c = (c<<1)+1; // Characters are always odd!
sum += c + (c<<shft[k++]); // Universal hash function
}
return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size
}
int hashptr(const void *key) {
#ifdef __TURBOC__
return ((intptr_t)key >> 16);
#else // __TURBOC__
return ((intptr_t)key >> 2);
#endif
}
int hashkey(const void *key) {
return (intptr_t)key;
}
int32 cmpstr(const void *k1, const void *k2) {
return strcmp((const char *)k1,(const char *)k2);
}
int32 cmpkey(const void *key1, const void *key2) {
if (key1 == key2) return 0;
intptr_t delta = (intptr_t)key1 - (intptr_t)key2;
if (delta > 0) return 1;
return -1;
}
void DictI::reset( const Dict *dict ) {
_d = dict; // The dictionary
_i = (uint)-1; // Before the first bin
_j = 0; // Nothing left in the current bin
++(*this); // Step to first real value
}
void DictI::operator ++(void) {
if( _j-- ) { // Still working in current bin?
_key = _d->_bin[_i]._keyvals[_j+_j];
_value = _d->_bin[_i]._keyvals[_j+_j+1];
return;
}
while( ++_i < _d->_size ) { // Else scan for non-zero bucket
_j = _d->_bin[_i]._cnt;
if( !_j ) continue;
_j--;
_key = _d->_bin[_i]._keyvals[_j+_j];
_value = _d->_bin[_i]._keyvals[_j+_j+1];
return;
}
_key = _value = NULL;
}
C:\hotspot-69087d08d473\src\share\vm/libadt/dict.hpp
#ifndef SHARE_VM_LIBADT_DICT_HPP
#define SHARE_VM_LIBADT_DICT_HPP
#include "libadt/port.hpp"
class ostream;
class Dict;
typedef int32 (*CmpKey)(const void *key1, const void *key2);
typedef int (*Hash)(const void *key);
typedef void (*FuncDict)(const void *key, const void *val, Dict *d);
class Dict : public ResourceObj { // Dictionary structure
private:
class Arena *_arena; // Where to draw storage from
class bucket *_bin; // Hash table is array of buckets
uint _size; // Size (# of slots) in hash table
uint32 _cnt; // Number of key-value pairs in hash table
const Hash _hash; // Hashing function
const CmpKey _cmp; // Key comparison function
void doubhash( void ); // Double hash table size
public:
friend class DictI; // Friendly iterator function
Dict( CmpKey cmp, Hash hash );
Dict( CmpKey cmp, Hash hash, Arena *arena, int size=16 );
~Dict();
Dict( const Dict & ); // Deep-copy guts
Dict &operator =( const Dict & );
void Clear();
uint32 Size(void) const { return _cnt; }
void *Insert(void *key, void *val, bool replace = true); // A new key-value
void *Delete(void *key); // Delete & return old
void *operator [](const void *key) const; // Do a lookup
int32 operator ==(const Dict &d) const; // Compare dictionaries for equal
void print();
};
int hashstr(const void *s); // Nice string hash
int hashptr(const void *key);
int hashkey(const void *key);
int32 cmpstr(const void *k1, const void *k2);
int32 cmpkey(const void *key1, const void *key2);
class DictI {
private:
const Dict *_d; // Dictionary being iterated over
uint _i; // Counter over the bins
uint _j; // Counter inside each bin
public:
const void *_key, *_value; // Easy access to the key-value pair
DictI( const Dict *d ) {reset(d);}; // Create a new iterator
void reset( const Dict *dict ); // Reset existing iterator
void operator ++(void); // Increment iterator
int test(void) { return _i<_d->_size;} // Test for end of iteration
};
#endif // SHARE_VM_LIBADT_DICT_HPP
C:\hotspot-69087d08d473\src\share\vm/libadt/port.cpp
#include "precompiled.hpp"
#include "libadt/port.hpp"
#ifdef __GNUC__
#pragma implementation
#endif
#ifdef __TURBOC__
#include <iostream.h>
#endif
#include <stdio.h>
uint32 gcd( register uint32 x, register uint32 y )
{
register uint32 tmp;
while( x ) { // While not zero
tmp = x; // Hold onto smaller x value
x = y % x; // Compute modulus; since y>=x, 0 <= mod < x
y = tmp; // y = old x
}
return y;
}
int ff1( uint32 mask )
{
unsigned i, n = 0;
for( i=1, n=0; i; i<<=1, n++)
if( mask&i ) return n;
return 32;
}
int fh1( uint32 mask )
{
unsigned i, n = 0;
for( i=((uint32)1<<31), n=31; i; i>>=1, n--)
if( mask&i ) return n;
return 32;
}
uint32 rotate32( register uint32 x, register int32 cnt )
{
if( cnt >= 0 ) { // Positive rotates left
cnt &= 31; // Mask off extra shift bits
} else { // Negative rotates right
cnt = (-cnt)&31; // Flip sign; mask extra shift bits
cnt = 32-cnt; // Rotate right by big left rotation
}
return (x << cnt) | (x >> (32-cnt));
}
This function doesn't work if used as substitute
for the existing log2. Keep around until we have
verified all uses of log2 do the correct thing!
uint log2( uint32 x )
{
register uint l = 32; // Log bits
register int32 sx = x; // Treat as signed number
while( sx >= 0 ) // While high bit is clear
sx <<= 1, l--; // Shift bits left, count down log2
return l;
}
#ifdef __TURBOC__
ostream &ostream::operator << (const void *ptr)
{
return (*this) << "0x" << hex << (uint)ptr << dec;
}
#else
{
return os << "0x" << hex << (uint)ptr << dec;
}*/
#endif
C:\hotspot-69087d08d473\src\share\vm/libadt/port.hpp
#ifndef SHARE_VM_LIBADT_PORT_HPP
#define SHARE_VM_LIBADT_PORT_HPP
#include "utilities/top.hpp"
#if defined(__GNUC__)
#define INTERFACE #pragma interface
#define IMPLEMENTATION #pragma implementation
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef void *VPTR;
#define ACCESS_VPTR(class) VPTR&vptr(){return*(VPTR*)((char*)this+sizeof(class)-sizeof(void*));}
#elif defined(__TURBOC__)
#include <mem.h>
#include <string.h>
extern "C" int stricmp(const char *, const char *);
inline void bcopy(const void *s, void *d, int l) { memmove(d,s,l); }
inline void bzero(void *p, int l) { memset(p,0,l); }
inline int bcmp(const void *s, const void *d, int l) { return memcmp(s,d,l); }
inline int min( int a, int b) { return a < b ? a : b; }
inline int max( int a, int b) { return a > b ? a : b; }
inline long abs( long x ) { return x < 0 ? -x : x; }
typedef void near *VPTR;
#define ACCESS_VPTR(class) VPTR&vptr(){return*(VPTR*)this;}
#elif defined(__hpux)
#define INTERFACE
#define IMPLEMENTATION
#define signed
#include <strings.h>
#include <stdlib.h>
inline long min( long a, long b) { return a < b ? a : b; }
inline long max( long a, long b) { return a > b ? a : b; }
inline int min( int a, int b) { return a < b ? a : b; }
inline int max( int a, int b) { return a > b ? a : b; }
inline long abs( long x ) { return x < 0 ? -x : x; }
#elif defined(__MOTO__)
#define INTERFACE
#define IMPLEMENTATION
#include <stdlib.h>
#include <memory.h>
inline int min( int a, int b) { return a < b ? a : b; }
inline int max( int a, int b) { return a > b ? a : b; }
#elif defined(_AIX)
#define INTERFACE
#define IMPLEMENTATION
#include <stdlib.h>
#include <memory.h>
#elif defined(_MSC_VER)
#define IMPLEMENTATION
#include <stdlib.h>
#undef small
#elif defined(SPARC_WORKS)
#define INTERFACE
#define IMPLEMENTATION
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#elif defined(SOLARIS)
#define INTERFACE
#define IMPLEMENTATION
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#elif defined(__TANDEM)
#include "port_tandem.hpp"
#elif defined(__cplusplus)
#define INTERFACE
#define IMPLEMENTATION
#include <unistd.h>
#define signed
inline int min( int a, int b) { return a < b ? a : b; }
inline int max( int a, int b) { return a > b ? a : b; }
#else // All other machines
#define signed
extern "C" void bcopy(void *b1, void *b2, int len);
inline int min( int a, int b) { return a < b ? a : b; }
inline int max( int a, int b) { return a > b ? a : b; }
#endif
#ifdef SAFE_MEMORY
#define malloc(size) safe_malloc(__FILE__,__LINE__,size)
#define free(ptr) safe_free(__FILE__,__LINE__,ptr)
#define realloc(ptr,size) safe_realloc(__FILE__,__LINE__,ptr,size)
#define calloc(nitems,size) safe_calloc(__FILE__,__LINE__,nitems,size)
#define strdup(ptr) safe_strdup(__FILE__,__LINE__,ptr)
extern void *safe_malloc (const char *file, unsigned line, unsigned size);
extern void safe_free (const char *file, unsigned line, void *ptr);
extern void *safe_calloc (const char *file, unsigned line, unsigned nitems, unsigned size);
extern void *safe_realloc(const char *file, unsigned line, void *ptr, unsigned size);
extern char *safe_strdup (const char *file, unsigned line, const char *src);
inline void *operator new( size_t size ) throw() { return malloc(size); }
inline void operator delete( void *ptr ) { free(ptr); }
#endif
typedef signed char int8;
typedef unsigned char uint8;
typedef unsigned char byte;
typedef unsigned int uint; // When you need a fast >=16bit unsigned value
const unsigned int max_uint = (uint)-1;
typedef int32_t int32; // Exactly 32bits signed
typedef uint32_t uint32; // Exactly 32bits unsigned
#ifndef __TANDEM
typedef float float32; // 32-bit float
typedef double float64; // 64-bit float
#endif // __TANDEM
typedef jlong int64; // Java long for my 64-bit type
typedef julong uint64; // Java long for my 64-bit type
uint32 gcd( uint32 x, uint32 y );
int ff1( uint32 mask );
int fh1( uint32 mask );
uint32 rotate32( uint32 x, int32 cnt );
extern uint32 heap_totalmem; // Current total memory allocation
extern uint32 heap_highwater; // Highwater mark to date for memory usage
#endif // SHARE_VM_LIBADT_PORT_HPP
C:\hotspot-69087d08d473\src\share\vm/libadt/set.cpp
#include "precompiled.hpp"
#include "libadt/set.hpp"
#include "memory/allocation.inline.hpp"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
class SparseSet;
Set::operator const SparseSet*() const { assert(0); return NULL; } */
const SparseSet *Set::asSparseSet() const { assert(0); return NULL; }
class VectorSet;
Set::operator const VectorSet*() const { assert(0); return NULL; } */
const VectorSet *Set::asVectorSet() const { assert(0); return NULL; }
class ListSet;
Set::operator const ListSet*() const { assert(0); return NULL; } */
const ListSet *Set::asListSet() const { assert(0); return NULL; }
class CoSet;
Set::operator const CoSet*() const { assert(0); return NULL; } */
const CoSet *Set::asCoSet() const { assert(0); return NULL; }
char *Set::setstr() const
{
if( this == NULL ) return os::strdup("{no set}");
Set &set = clone(); // Virtually copy the basic set.
set.Sort(); // Sort elements for in-order retrieval
uint len = 128; // Total string space
char *buf = NEW_C_HEAP_ARRAY(char,len, mtCompiler);// Some initial string space
register char *s = buf; // Current working string pointer
uint hi = (uint)-2, lo = (uint)-2;
for( SetI i(&set); i.test(); ++i ) {
if( hi+1 == i.elem ) { // Moving sequentially thru range?
hi = i.elem; // Yes, just update hi end of range
} else { // Else range ended
if( buf+len-s < 25 ) { // Generous trailing space for upcoming numbers
int offset = (int)(s-buf);// Not enuf space; compute offset into buffer
len <<= 1; // Double string size
buf = REALLOC_C_HEAP_ARRAY(char,buf,len, mtCompiler); // Reallocate doubled size
s = buf+offset; // Get working pointer into new bigger buffer
}
if( lo != (uint)-2 ) { // Startup? No! Then print previous range.
if( lo != hi ) sprintf(s,"%d-%d,",lo,hi);
else sprintf(s,"%d,",lo);
s += strlen(s); // Advance working string
}
hi = lo = i.elem;
}
}
if( lo != (uint)-2 ) {
if( buf+len-s < 25 ) { // Generous trailing space for upcoming numbers
int offset = (int)(s-buf);// Not enuf space; compute offset into buffer
len <<= 1; // Double string size
buf = (char*)ReallocateHeap(buf,len, mtCompiler); // Reallocate doubled size
s = buf+offset; // Get working pointer into new bigger buffer
}
if( lo != hi ) sprintf(s,"%d-%d}",lo,hi);
else sprintf(s,"%d}",lo);
} else strcat(s,"}");
return buf;
}
void Set::print() const
{
char *printable_set = setstr();
tty->print_cr("%s", printable_set);
FreeHeap(printable_set);
}
int Set::parse(const char *s)
{
register char c; // Parse character
register const char *t = s; // Save the starting position of s.
do c = *s++; // Skip characters
while( c && (c <= ' ') ); // Till no more whitespace or EOS
if( c != '{' ) return 0; // Oops, not a Set openner
if( *s == '}' ) return 2; // The empty Set
while( 1 ) { // While have elements in the Set
char *u; // Pointer to character ending parse
uint hi, i; // Needed for range handling below
uint elem = (uint)strtoul(s,&u,10);// Get element
if( u == s ) return 0; // Bogus crude
s = u; // Skip over the number
c = *s++; // Get the number seperator
switch ( c ) { // Different seperators
case '}': // Last simple element
case ',': // Simple element
(*this) <<= elem; // Insert the simple element into the Set
break; // Go get next element
case '-': // Range
hi = (uint)strtoul(s,&u,10); // Get element
if( u == s ) return 0; // Bogus crude
for( i=elem; i<=hi; i++ )
(*this) <<= i; // Insert the entire range into the Set
s = u; // Skip over the number
c = *s++; // Get the number seperator
break;
}
if( c == '}' ) break; // End of the Set
if( c != ',' ) return 0; // Bogus garbage
}
return (int)(s-t); // Return length parsed
}
SetI_::~SetI_()
{
}
C:\hotspot-69087d08d473\src\share\vm/libadt/set.hpp
#ifndef SHARE_VM_LIBADT_SET_HPP
#define SHARE_VM_LIBADT_SET_HPP
#include "libadt/port.hpp"
#include "memory/allocation.hpp"
class SparseSet;
class VectorSet;
class ListSet;
class CoSet;
class ostream;
class SetI_;
class Set : public ResourceObj {
public:
Set(Arena *arena) : _set_arena(arena) {};
Set(const Set &) {};
virtual Set &operator =(const Set &s)=0;
virtual Set &clone(void) const=0;
virtual ~Set() {};
virtual Set &operator <<=(uint elem)=0;
virtual Set &operator >>=(uint elem)=0;
virtual int operator [](uint elem) const=0;
virtual Set &operator &=(const Set &s)=0;
virtual Set &operator |=(const Set &s)=0;
virtual Set &operator -=(const Set &s)=0;
virtual int operator ==(const Set &s) const=0;
int operator !=(const Set &s) const { return !(*this == s); }
virtual int disjoint(const Set &s) const=0;
virtual int operator < (const Set &s) const=0;
int operator > (const Set &s) const { return s < *this; }
virtual int operator <=(const Set &s) const=0;
int operator >=(const Set &s) const { return s <= *this; }
virtual uint getelem(void) const=0;
virtual void Clear(void)=0;
virtual uint Size(void) const=0;
virtual void Sort(void)=0;
virtual char *setstr(void) const;
void print() const;
virtual int parse(const char *s);
virtual operator const SparseSet* (void) const;
virtual operator const VectorSet* (void) const;
virtual operator const ListSet * (void) const;
virtual operator const CoSet * (void) const; */
virtual const SparseSet *asSparseSet(void) const;
virtual const VectorSet *asVectorSet(void) const;
virtual const ListSet *asListSet (void) const;
virtual const CoSet *asCoSet (void) const;
virtual int hash() const = 0;
protected:
friend class SetI;
friend class CoSet;
virtual class SetI_ *iterate(uint&) const=0;
Arena *_set_arena;
};
typedef Set&((*Set_Constructor)(Arena *arena));
extern Set &ListSet_Construct(Arena *arena);
extern Set &VectorSet_Construct(Arena *arena);
extern Set &SparseSet_Construct(Arena *arena);
class SetI_ : public ResourceObj {
protected:
friend class SetI;
virtual ~SetI_();
virtual uint next(void)=0;
virtual int test(void)=0;
};
class SetI {
protected:
SetI_ *impl;
public:
uint elem; // The publically accessible element
SetI( const Set *s ) { impl = s->iterate(elem); }
~SetI() { delete impl; }
void reset( const Set *s ) { delete impl; impl = s->iterate(elem); }
void operator ++(void) { elem = impl->next(); }
int test(void) { return impl->test(); }
};
#endif // SHARE_VM_LIBADT_SET_HPP
C:\hotspot-69087d08d473\src\share\vm/libadt/vectset.cpp
#include "precompiled.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.inline.hpp"
uint8 bitsInByte[256] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
VectorSet::VectorSet(Arena *arena) : Set(arena) {
size = 2; // Small initial size
data = (uint32 *)_set_arena->Amalloc(size*sizeof(uint32));
data[0] = 0; // No elements
data[1] = 0;
}
Set &VectorSet_Construct(Arena *arena)
{
return *(new VectorSet(arena));
}
Set &VectorSet::operator = (const Set &set)
{
if( &set == this ) return *this;
FREE_FAST(data);
slamin(*(set.asVectorSet()));
return *this;
}
void VectorSet::slamin(const VectorSet& s)
{
size = s.size; // Use new size
data = (uint32*)s._set_arena->Amalloc(size*sizeof(uint32)); // Make array of required size
memcpy( data, s.data, size*sizeof(uint32) ); // Fill the array
}
void VectorSet::grow( uint newsize )
{
newsize = (newsize+31) >> 5; // Convert to longwords
uint x = size;
while( x < newsize ) x <<= 1;
data = (uint32 *)_set_arena->Arealloc(data, size*sizeof(uint32), x*sizeof(uint32));
memset((char *)(data + size), 0, (x - size)*sizeof(uint32));
size = x;
}
Set &VectorSet::operator <<= (uint elem)
{
register uint word = elem >> 5; // Get the longword offset
register uint32 mask = 1L << (elem & 31); // Get bit mask
if( word >= size ) // Need to grow set?
grow(elem+1); // Then grow it
data[word] |= mask; // Set new bit
return *this;
}
Set &VectorSet::operator >>= (uint elem)
{
register uint word = elem >> 5; // Get the longword offset
if( word >= size ) // Beyond the last?
return *this; // Then it's clear & return clear
register uint32 mask = 1L << (elem & 31); // Get bit mask
data[word] &= ~mask; // Clear bit
return *this;
}
VectorSet &VectorSet::operator &= (const VectorSet &s)
{
if( s.size < size ) size = s.size; // Get smaller size
register uint32 *u1 = data; // Pointer to the destination data
register uint32 *u2 = s.data; // Pointer to the source data
for( uint i=0; i<size; i++) // For data in set
return *this; // Return set
}
Set &VectorSet::operator &= (const Set &set)
{
return (*this) &= *(set.asVectorSet());
}
VectorSet &VectorSet::operator |= (const VectorSet &s)
{
register uint cnt = ((size<s.size)?size:s.size);
register uint32 *u1 = data; // Pointer to the destination data
register uint32 *u2 = s.data; // Pointer to the source data
for( uint i=0; i<cnt; i++) // Copy and OR the two sets
if( size < s.size ) { // Is set 2 larger than set 1?
grow(s.size*sizeof(uint32)*8);
memcpy(&data[cnt], u2, (s.size - cnt)*sizeof(uint32));
}
return *this; // Return result set
}
Set &VectorSet::operator |= (const Set &set)
{
return (*this) |= *(set.asVectorSet());
}
VectorSet &VectorSet::operator -= (const VectorSet &s)
{
register uint cnt = ((size<s.size)?size:s.size);
register uint32 *u1 = data; // Pointer to the destination data
register uint32 *u2 = s.data; // Pointer to the source data
for( uint i=0; i<cnt; i++ ) // For data in set
return *this; // Return new set
}
Set &VectorSet::operator -= (const Set &set)
{
return (*this) -= *(set.asVectorSet());
}
int VectorSet::compare (const VectorSet &s) const
{
register uint32 *u1 = data; // Pointer to the destination data
register uint32 *u2 = s.data; // Pointer to the source data
register uint32 AnotB = 0, BnotA = 0;
register uint cnt = ((size<s.size)?size:s.size);
uint i; // Exit value of loop
for( i=0; i<cnt; i++ ) { // For data in BOTH sets
register uint32 A = *u1++; // Data from one guy
register uint32 B = *u2++; // Data from other guy
AnotB |= (A & ~B); // Compute bits in A not B
BnotA |= (B & ~A); // Compute bits in B not A
}
if( size < s.size ) {
for( ; i<s.size; i++ ) // For data in larger set
BnotA |= *u2++; // These bits are in B not A
} else {
for( ; i<size; i++ ) // For data in larger set
AnotB |= *u1++; // These bits are in A not B
}
return ((!BnotA)<<1) + (!AnotB);
}
int VectorSet::operator == (const VectorSet &s) const
{
return compare(s) == 3; // TRUE if A and B are mutual subsets
}
int VectorSet::operator == (const Set &set) const
{
return (*this) == *(set.asVectorSet());
}
int VectorSet::disjoint(const Set &set) const
{
const VectorSet &s = *(set.asVectorSet());
register uint small_size = ((size<s.size)?size:s.size);
register uint32 *u1 = data; // Pointer to the destination data
register uint32 *u2 = s.data; // Pointer to the source data
for( uint i=0; i<small_size; i++) // For data in set
if( *u1++ & *u2++ ) // If any elements in common
return 0; // Then not disjoint
return 1; // Else disjoint
}
int VectorSet::operator < (const VectorSet &s) const
{
return compare(s) == 1; // A subset B, B not subset A
}
int VectorSet::operator < (const Set &set) const
{
return (*this) < *(set.asVectorSet());
}
int VectorSet::operator <= (const VectorSet &s) const
{
return compare(s) & 1; // A subset B
}
int VectorSet::operator <= (const Set &set) const
{
return (*this) <= *(set.asVectorSet());
}
int VectorSet::operator[](uint elem) const
{
register uint word = elem >> 5; // Get the longword offset
if( word >= size ) // Beyond the last?
return 0; // Then it's clear
register uint32 mask = 1L << (elem & 31); // Get bit mask
return ((data[word] & mask))!=0; // Return the sense of the bit
}
uint VectorSet::getelem(void) const
{
uint i; // Exit value of loop
for( i=0; i<size; i++ )
if( data[i] )
break;
uint32 word = data[i];
int j; // Exit value of loop
for( j= -1; word; j++, word>>=1 );
return (i<<5)+j;
}
void VectorSet::Clear(void)
{
if( size > 100 ) { // Reclaim storage only if huge
FREE_RESOURCE_ARRAY(uint32,data,size);
size = 2; // Small initial size
data = NEW_RESOURCE_ARRAY(uint32,size);
}
memset( data, 0, size*sizeof(uint32) );
}
uint VectorSet::Size(void) const
{
uint sum = 0; // Cumulative size so far.
uint8 *currByte = (uint8*)data;
for( uint32 i = 0; i < (size<<2); i++) // While have bytes to process
sum += bitsInByte[*currByte++]; // Add bits in current byte to size.
return sum;
}
void VectorSet::Sort(void)
{
}
int VectorSet::hash() const
{
uint32 _xor = 0;
uint lim = ((size<4)?size:4);
for( uint i = 0; i < lim; i++ )
_xor ^= data[i];
return (int)_xor;
}
class VSetI_ : public SetI_ {
VectorSetI vsi;
public:
VSetI_( const VectorSet *vset, uint &elem ) : vsi(vset) { elem = vsi.elem; }
uint next(void) { ++vsi; return vsi.elem; }
int test(void) { return vsi.test(); }
};
SetI_ *VectorSet::iterate(uint &elem) const {
return new(ResourceObj::C_HEAP, mtInternal) VSetI_(this, elem);
}
uint VectorSetI::next(void)
{
j++; // Next element in word
mask = (mask & max_jint) << 1;// Next bit in word
do { // Do While still have words
while( mask ) { // While have bits in word
if( s->data[i] & mask ) { // If found a bit
return (i<<5)+j; // Return the bit address
}
j++; // Skip to next bit
mask = (mask & max_jint) << 1;
}
j = 0; // No more bits in word; setup for next word
mask = 1;
for( i++; (i<s->size) && (!s->data[i]); i++ ); // Skip to non-zero word
} while( i<s->size );
return max_juint; // No element, iterated them all
}
C:\hotspot-69087d08d473\src\share\vm/libadt/vectset.hpp
#ifndef SHARE_VM_LIBADT_VECTSET_HPP
#define SHARE_VM_LIBADT_VECTSET_HPP
#include "libadt/set.hpp"
class VectorSet : public Set {
friend class VectorSetI; // Friendly iterator class
protected:
uint size; // Size of data IN LONGWORDS (32bits)
uint32 *data; // The data, bit packed
void slamin( const VectorSet& s ); // Initialize one set with another
int compare(const VectorSet &s) const; // Compare set contents
void grow(uint newsize); // Grow vector to required bitsize
sssssss40
最新推荐文章于 2024-08-01 15:05:06 发布