void os::set_memory_serialize_page(address page) {
int count = log2_intptr(sizeof(class JavaThread)) - log2_int(64);
_mem_serialize_page = (volatile int32_t *)page;
assert(SerializePageShiftCount == count,
"thread size changed, fix SerializePageShiftCount constant");
set_serialize_page_mask((uintptr_t)(vm_page_size() - sizeof(int32_t)));
}
static volatile intptr_t SerializePageLock = 0;
void os::block_on_serialize_page_trap() {
if (TraceSafepoint) {
tty->print_cr("Block until the serialize page permission restored");
}
Thread::muxAcquire(&SerializePageLock, "set_memory_serialize_page");
Thread::muxRelease(&SerializePageLock);
}
void os::serialize_thread_states() {
Thread::muxAcquire(&SerializePageLock, "serialize_thread_states");
os::protect_memory((char *)os::get_memory_serialize_page(),
os::vm_page_size(), MEM_PROT_READ);
os::protect_memory((char *)os::get_memory_serialize_page(),
os::vm_page_size(), MEM_PROT_RW);
Thread::muxRelease(&SerializePageLock);
}
bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) {
assert(StackRedPages > 0 && StackYellowPages > 0,"Sanity check");
address sp = current_stack_pointer();
const int framesize_in_bytes =
Interpreter::size_top_interpreter_activation(method()) * wordSize;
int reserved_area = ((StackShadowPages + StackRedPages + StackYellowPages)
address stack_limit = thread->stack_base() - thread->stack_size();
return (sp > (stack_limit + reserved_area));
}
size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) {
assert(min_pages > 0, "sanity");
if (UseLargePages) {
const size_t max_page_size = region_size / min_pages;
for (size_t i = 0; _page_sizes[i] != 0; ++i) {
const size_t page_size = _page_sizes[i];
if (page_size <= max_page_size) {
if (!must_be_aligned || is_size_aligned(region_size, page_size)) {
return page_size;
}
}
}
}
return vm_page_size();
}
size_t os::page_size_for_region_aligned(size_t region_size, size_t min_pages) {
return page_size_for_region(region_size, min_pages, true);
}
size_t os::page_size_for_region_unaligned(size_t region_size, size_t min_pages) {
return page_size_for_region(region_size, min_pages, false);
}
#ifndef PRODUCT
void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count)
{
if (TracePageSizes) {
tty->print("%s: ", str);
for (int i = 0; i < count; ++i) {
tty->print(" " SIZE_FORMAT, page_sizes[i]);
}
tty->cr();
}
}
void os::trace_page_sizes(const char* str, const size_t region_min_size,
const size_t region_max_size, const size_t page_size,
const char* base, const size_t size)
{
if (TracePageSizes) {
tty->print_cr("%s: min=" SIZE_FORMAT " max=" SIZE_FORMAT
" pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT
" size=" SIZE_FORMAT,
str, region_min_size, region_max_size,
page_size, base, size);
}
}
#endif // #ifndef PRODUCT
bool os::is_server_class_machine() {
if (NeverActAsServerClassMachine) {
return false;
}
if (AlwaysActAsServerClassMachine) {
return true;
}
bool result = false;
const unsigned int server_processors = 2;
const julong server_memory = 2UL * G;
const julong missing_memory = 256UL * M;
if ((os::active_processor_count() >= (int)server_processors) &&
(os::physical_memory() >= (server_memory - missing_memory))) {
const unsigned int logical_processors =
VM_Version::logical_processors_per_package();
if (logical_processors > 1) {
const unsigned int physical_packages =
os::active_processor_count() / logical_processors;
if (physical_packages > server_processors) {
result = true;
}
} else {
result = true;
}
}
return result;
}
void os::initialize_initial_active_processor_count() {
assert(_initial_active_processor_count == 0, "Initial active processor count already set.");
_initial_active_processor_count = active_processor_count();
}
void os::SuspendedThreadTask::run() {
assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this");
internal_do_task();
_done = true;
}
bool os::create_stack_guard_pages(char* addr, size_t bytes) {
return os::pd_create_stack_guard_pages(addr, bytes);
}
char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
char* result = pd_reserve_memory(bytes, addr, alignment_hint);
if (result != NULL) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
}
return result;
}
char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint,
MEMFLAGS flags) {
char* result = pd_reserve_memory(bytes, addr, alignment_hint);
if (result != NULL) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
MemTracker::record_virtual_memory_type((address)result, flags);
}
return result;
}
char* os::attempt_reserve_memory_at(size_t bytes, char* addr) {
char* result = pd_attempt_reserve_memory_at(bytes, addr);
if (result != NULL) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
}
return result;
}
void os::split_reserved_memory(char *base, size_t size,
size_t split, bool realloc) {
pd_split_reserved_memory(base, size, split, realloc);
}
bool os::commit_memory(char* addr, size_t bytes, bool executable) {
bool res = pd_commit_memory(addr, bytes, executable);
if (res) {
MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC);
}
return res;
}
bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
bool executable) {
bool res = os::pd_commit_memory(addr, size, alignment_hint, executable);
if (res) {
MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC);
}
return res;
}
void os::commit_memory_or_exit(char* addr, size_t bytes, bool executable,
const char* mesg) {
pd_commit_memory_or_exit(addr, bytes, executable, mesg);
MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC);
}
void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint,
bool executable, const char* mesg) {
os::pd_commit_memory_or_exit(addr, size, alignment_hint, executable, mesg);
MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC);
}
bool os::uncommit_memory(char* addr, size_t bytes) {
bool res;
if (MemTracker::tracking_level() > NMT_minimal) {
Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
res = pd_uncommit_memory(addr, bytes);
if (res) {
tkr.record((address)addr, bytes);
}
} else {
res = pd_uncommit_memory(addr, bytes);
}
return res;
}
bool os::release_memory(char* addr, size_t bytes) {
bool res;
if (MemTracker::tracking_level() > NMT_minimal) {
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
res = pd_release_memory(addr, bytes);
if (res) {
tkr.record((address)addr, bytes);
}
} else {
res = pd_release_memory(addr, bytes);
}
return res;
}
void os::pretouch_memory(char* start, char* end) {
for (volatile char *p = start; p < end; p += os::vm_page_size()) {
}
}
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec);
if (result != NULL) {
MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
}
return result;
}
char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
return pd_remap_memory(fd, file_name, file_offset, addr, bytes,
read_only, allow_exec);
}
bool os::unmap_memory(char *addr, size_t bytes) {
bool result;
if (MemTracker::tracking_level() > NMT_minimal) {
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
result = pd_unmap_memory(addr, bytes);
if (result) {
tkr.record((address)addr, bytes);
}
} else {
result = pd_unmap_memory(addr, bytes);
}
return result;
}
void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) {
pd_free_memory(addr, bytes, alignment_hint);
}
void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
pd_realign_memory(addr, bytes, alignment_hint);
}
#ifndef TARGET_OS_FAMILY_windows
os::SuspendResume::State os::SuspendResume::switch_state(os::SuspendResume::State from,
os::SuspendResume::State to)
{
os::SuspendResume::State result =
(os::SuspendResume::State) Atomic::cmpxchg((jint) to, (jint *) &_state, (jint) from);
if (result == from) {
return to;
}
return result;
}
#endif
#ifndef PRODUCT
#define assert_eq(a,b) assert(a == b, err_msg(SIZE_FORMAT " != " SIZE_FORMAT, a, b))
class TestOS : AllStatic {
static size_t small_page_size() {
return os::vm_page_size();
}
static size_t large_page_size() {
const size_t large_page_size_example = 4 * M;
return os::page_size_for_region_aligned(large_page_size_example, 1);
}
static void test_page_size_for_region_aligned() {
if (UseLargePages) {
const size_t small_page = small_page_size();
const size_t large_page = large_page_size();
if (large_page > small_page) {
size_t num_small_pages_in_large = large_page / small_page;
size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large);
assert_eq(page, small_page);
}
}
}
static void test_page_size_for_region_alignment() {
if (UseLargePages) {
const size_t small_page = small_page_size();
const size_t large_page = large_page_size();
if (large_page > small_page) {
const size_t unaligned_region = large_page + 17;
size_t page = os::page_size_for_region_aligned(unaligned_region, 1);
assert_eq(page, small_page);
const size_t num_pages = 5;
const size_t aligned_region = large_page * num_pages;
page = os::page_size_for_region_aligned(aligned_region, num_pages);
assert_eq(page, large_page);
}
}
}
static void test_page_size_for_region_unaligned() {
if (UseLargePages) {
for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
size_t expected = os::_page_sizes[i];
size_t actual = os::page_size_for_region_unaligned(expected, 1);
assert_eq(expected, actual);
}
for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
size_t expected = os::_page_sizes[i];
size_t actual = os::page_size_for_region_unaligned(expected + 17, 1);
assert_eq(expected, actual);
}
if (os::_page_sizes[1] > os::_page_sizes[0]) {
size_t expected = os::_page_sizes[0];
size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1);
assert_eq(actual, expected);
}
size_t small_page = small_page_size();
size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1);
assert_eq(small_page, actual);
}
}
public:
static void run_tests() {
test_page_size_for_region_aligned();
test_page_size_for_region_alignment();
test_page_size_for_region_unaligned();
}
};
void TestOS_test() {
TestOS::run_tests();
}
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/runtime/os.hpp
#ifndef SHARE_VM_RUNTIME_OS_HPP
#define SHARE_VM_RUNTIME_OS_HPP
#include "jvmtifiles/jvmti.h"
#include "runtime/atomic.hpp"
#include "runtime/extendedPC.hpp"
#include "runtime/handles.hpp"
#include "utilities/top.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "jvm_linux.h"
# include <setjmp.h>
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "jvm_solaris.h"
# include <setjmp.h>
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "jvm_windows.h"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "jvm_aix.h"
# include <setjmp.h>
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "jvm_bsd.h"
# include <setjmp.h>
# ifdef __APPLE__
# include <mach/mach_time.h>
# endif
#endif
class AgentLibrary;
typedef void (*dll_func)(...);
class Thread;
class JavaThread;
class Event;
class DLL;
class FileHandle;
class NativeCallStack;
template<class E> class GrowableArray;
enum OSReturn {
OS_OK = 0, // Operation was successful
OS_ERR = -1, // Operation failed
OS_INTRPT = -2, // Operation was interrupted
OS_TIMEOUT = -3, // Operation timed out
OS_NOMEM = -5, // Operation failed for lack of memory
OS_NORESOURCE = -6 // Operation failed for lack of nonmemory resource
};
enum ThreadPriority { // JLS 20.20.1-3
NoPriority = -1, // Initial non-priority value
MinPriority = 1, // Minimum priority
NormPriority = 5, // Normal (non-daemon) priority
NearMaxPriority = 9, // High priority, used for VMThread
MaxPriority = 10, // Highest priority, used for WatcherThread
CriticalPriority = 11 // Critical thread priority
};
const bool ExecMem = true;
typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
class MallocTracker;
class os: AllStatic {
friend class VMStructs;
friend class MallocTracker;
public:
enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel)
private:
static OSThread* _starting_thread;
static address _polling_page;
static volatile int32_t * _mem_serialize_page;
static uintptr_t _serialize_page_mask;
public:
static size_t _page_sizes[page_sizes_max];
private:
static void init_page_sizes(size_t default_page_size) {
_page_sizes[0] = default_page_size;
_page_sizes[1] = 0; // sentinel
}
static char* pd_reserve_memory(size_t bytes, char* addr = 0,
size_t alignment_hint = 0);
static char* pd_attempt_reserve_memory_at(size_t bytes, char* addr);
static void pd_split_reserved_memory(char *base, size_t size,
size_t split, bool realloc);
static bool pd_commit_memory(char* addr, size_t bytes, bool executable);
static bool pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
bool executable);
static void pd_commit_memory_or_exit(char* addr, size_t bytes,
bool executable, const char* mesg);
static void pd_commit_memory_or_exit(char* addr, size_t size,
size_t alignment_hint,
bool executable, const char* mesg);
static bool pd_uncommit_memory(char* addr, size_t bytes);
static bool pd_release_memory(char* addr, size_t bytes);
static char* pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only = false,
bool allow_exec = false);
static char* pd_remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec);
static bool pd_unmap_memory(char *addr, size_t bytes);
static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint);
static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint);
static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
static void initialize_initial_active_processor_count();
LINUX_ONLY(static void pd_init_container_support();)
public:
static void init(void); // Called before command line parsing
static void init_container_support() { // Called during command line parsing.
LINUX_ONLY(pd_init_container_support();)
}
static void init_before_ergo(void); // Called after command line parsing
static jint init_2(void); // Called after command line parsing
static void init_globals(void) { // Called from init_globals() in init.cpp
init_globals_ext();
}
static int file_name_strcmp(const char* s1, const char* s2);
static bool getenv(const char* name, char* buffer, int len);
static bool unsetenv(const char* name);
static bool have_special_privileges();
static jlong javaTimeMillis();
static jlong javaTimeNanos();
static void javaTimeNanos_info(jvmtiTimerInfo *info_ptr);
static void run_periodic_checks();
static double elapsedTime();
static bool getTimesSecs(double* process_real_time,
double* process_user_time,
double* process_system_time);
static jlong elapsed_counter();
static jlong elapsed_frequency();
static bool supports_vtime();
static bool enable_vtime();
static bool vtime_enabled();
static double elapsedVTime();
static char* local_time_string(char *buf, size_t buflen);
static struct tm* localtime_pd (const time_t* clock, struct tm* res);
static char* iso8601_time(char* buffer, size_t buffer_length);
static inline bool is_MP() {
return (_processor_count != 1) || AssumeMP;
}
static julong available_memory();
static julong physical_memory();
static bool has_allocatable_memory_limit(julong* limit);
static bool is_server_class_machine();
static int processor_count() {
return _processor_count;
}
static void set_processor_count(int count) { _processor_count = count; }
static int active_processor_count();
static int initial_active_processor_count() {
assert(_initial_active_processor_count > 0, "Initial active processor count not set yet.");
return _initial_active_processor_count;
}
static bool distribute_processes(uint length, uint* distribution);
static bool bind_to_processor(uint processor_id);
static void set_native_thread_name(const char *name);
static bool uses_stack_guard_pages();
static bool allocate_stack_guard_pages();
static void bang_stack_shadow_pages();
static bool stack_shadow_pages_available(Thread *thread, methodHandle method);
static int vm_page_size();
static size_t page_size_for_region_aligned(size_t region_size, size_t min_pages);
static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages);
static size_t max_page_size() {
return _page_sizes[0];
}
static void trace_page_sizes(const char* str, const size_t* page_sizes,
int count) PRODUCT_RETURN;
static void trace_page_sizes(const char* str, const size_t region_min_size,
const size_t region_max_size,
const size_t page_size,
const char* base = NULL,
const size_t size = 0) PRODUCT_RETURN;
static int vm_allocation_granularity();
static char* reserve_memory(size_t bytes, char* addr = 0,
size_t alignment_hint = 0);
static char* reserve_memory(size_t bytes, char* addr,
size_t alignment_hint, MEMFLAGS flags);
static char* reserve_memory_aligned(size_t size, size_t alignment);
static char* attempt_reserve_memory_at(size_t bytes, char* addr);
static void split_reserved_memory(char *base, size_t size,
size_t split, bool realloc);
static bool commit_memory(char* addr, size_t bytes, bool executable);
static bool commit_memory(char* addr, size_t size, size_t alignment_hint,
bool executable);
static void commit_memory_or_exit(char* addr, size_t bytes,
bool executable, const char* mesg);
static void commit_memory_or_exit(char* addr, size_t size,
size_t alignment_hint,
bool executable, const char* mesg);
static bool uncommit_memory(char* addr, size_t bytes);
static bool release_memory(char* addr, size_t bytes);
static void pretouch_memory(char* start, char* end);
enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX };
static bool protect_memory(char* addr, size_t bytes, ProtType prot,
bool is_committed = true);
static bool guard_memory(char* addr, size_t bytes);
static bool unguard_memory(char* addr, size_t bytes);
static bool create_stack_guard_pages(char* addr, size_t bytes);
static bool pd_create_stack_guard_pages(char* addr, size_t bytes);
static bool remove_stack_guard_pages(char* addr, size_t bytes);
static char* map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only = false,
bool allow_exec = false);
static char* remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec);
static bool unmap_memory(char *addr, size_t bytes);
static void free_memory(char *addr, size_t bytes, size_t alignment_hint);
static void realign_memory(char *addr, size_t bytes, size_t alignment_hint);
static bool numa_has_static_binding();
static bool numa_has_group_homing();
static void numa_make_local(char *addr, size_t bytes, int lgrp_hint);
static void numa_make_global(char *addr, size_t bytes);
static size_t numa_get_groups_num();
static size_t numa_get_leaf_groups(int *ids, size_t size);
static bool numa_topology_changed();
static int numa_get_group_id();
struct page_info {
size_t size;
int lgrp_id;
};
static bool get_page_info(char *start, page_info* info);
static char* scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found);
static char* non_memory_address_word();
static char* reserve_memory_special(size_t size, size_t alignment,
char* addr, bool executable);
static bool release_memory_special(char* addr, size_t bytes);
static void large_page_init();
static size_t large_page_size();
static bool can_commit_large_page_memory();
static bool can_execute_large_page_memory();
static address get_polling_page() { return _polling_page; }
static void set_polling_page(address page) { _polling_page = page; }
static bool is_poll_address(address addr) { return addr >= _polling_page && addr < (_polling_page + os::vm_page_size()); }
static void make_polling_page_unreadable();
static void make_polling_page_readable();
static void serialize_thread_states();
static int get_serialize_page_shift_count() {
return SerializePageShiftCount;
}
static void set_serialize_page_mask(uintptr_t mask) {
_serialize_page_mask = mask;
}
static unsigned int get_serialize_page_mask() {
return _serialize_page_mask;
}
static void set_memory_serialize_page(address page);
static address get_memory_serialize_page() {
return (address)_mem_serialize_page;
}
static inline void write_memory_serialize_page(JavaThread *thread) {
uintptr_t page_offset = ((uintptr_t)thread >>
get_serialize_page_shift_count()) &
get_serialize_page_mask();
}
static bool is_memory_serialize_page(JavaThread *thread, address addr) {
if (UseMembar) return false;
if (thread == NULL) return false;
address page = (address) _mem_serialize_page;
return addr >= page && addr < (page + os::vm_page_size());
}
static void block_on_serialize_page_trap();
enum ThreadType {
vm_thread,
cgc_thread, // Concurrent GC thread
pgc_thread, // Parallel GC thread
java_thread,
compiler_thread,
watcher_thread,
os_thread
};
static bool create_thread(Thread* thread,
ThreadType thr_type,
size_t stack_size = 0);
static bool create_main_thread(JavaThread* thread);
static bool is_primordial_thread(void)
#if defined(_WINDOWS) || defined(BSD)
{ return false; }
#else
;
#endif
static bool create_attached_thread(JavaThread* thread);
static void pd_start_thread(Thread* thread);
static void start_thread(Thread* thread);
static void initialize_thread(Thread* thr);
static void free_thread(OSThread* osthread);
static intx current_thread_id();
static int current_process_id();
static int sleep(Thread* thread, jlong ms, bool interruptable);
static void naked_short_sleep(jlong ms);
static void infinite_sleep(); // never returns, use with CAUTION
static void yield(); // Yields to all threads with same priority
enum YieldResult {
YIELD_SWITCHED = 1, // caller descheduled, other ready threads exist & ran
YIELD_NONEREADY = 0, // No other runnable/ready threads.
YIELD_UNKNOWN = -1 // Unknown: platform doesn't support _SWITCHED or _NONEREADY
} ;
static YieldResult NakedYield () ;
static void yield_all(int attempts = 0); // Yields to all other threads including lower priority
static void loop_breaker(int attempts); // called from within tight loops to possibly influence time-sharing
static OSReturn set_priority(Thread* thread, ThreadPriority priority);
static OSReturn get_priority(const Thread* const thread, ThreadPriority& priority);
static void interrupt(Thread* thread);
static bool is_interrupted(Thread* thread, bool clear_interrupted);
static int pd_self_suspend_thread(Thread* thread);
static ExtendedPC fetch_frame_from_context(void* ucVoid, intptr_t** sp, intptr_t** fp);
static frame fetch_frame_from_context(void* ucVoid);
static ExtendedPC get_thread_pc(Thread *thread);
static void breakpoint();
static address current_stack_pointer();
static address current_stack_base();
static size_t current_stack_size();
static void verify_stack_alignment() PRODUCT_RETURN;
static int message_box(const char* title, const char* message);
static char* do_you_want_to_debug(const char* message);
static int fork_and_exec(char *cmd, bool use_vfork_if_available = false);
static void shutdown();
static void abort(bool dump_core = true);
static void die();
static const int default_file_open_flags();
static int open(const char *path, int oflag, int mode);
static FILE* open(int fd, const char* mode);
static int close(int fd);
static jlong lseek(int fd, jlong offset, int whence);
static char* native_path(char *path);
static int ftruncate(int fd, jlong length);
static int fsync(int fd);
static int available(int fd, jlong *bytes);
static size_t read(int fd, void *buf, unsigned int nBytes);
static size_t read_at(int fd, void *buf, unsigned int nBytes, jlong offset);
static size_t restartable_read(int fd, void *buf, unsigned int nBytes);
static size_t write(int fd, const void *buf, unsigned int nBytes);
static DIR* opendir(const char* dirname);
static struct dirent* readdir(DIR* dirp);
static int closedir(DIR* dirp);
static const char* dll_file_extension();
static const char* get_temp_directory();
static const char* get_current_directory(char *buf, size_t buflen);
static bool dll_build_name(char* buffer, size_t size,
const char* pathname, const char* fname);
static bool dll_address_to_function_name(address addr, char* buf,
int buflen, int* offset);
static bool dll_address_to_library_name(address addr, char* buf,
int buflen, int* offset);
static bool address_is_in_vm(address addr);
static void* dll_load(const char *name, char *ebuf, int ebuflen);
static void* dll_lookup(void* handle, const char* name);
static void dll_unload(void *lib);
typedef int (*LoadedModulesCallbackFunc)(const char *, address, address, void *);
static int get_loaded_modules_info(LoadedModulesCallbackFunc callback, void *param);
static void* get_default_process_handle();
static bool find_builtin_agent(AgentLibrary *agent_lib, const char *syms[],
size_t syms_len);
static void *find_agent_function(AgentLibrary *agent_lib, bool check_lib,
const char *syms[], size_t syms_len);
static int vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0);
static int snprintf(char* buf, size_t len, const char* fmt, ...) ATTRIBUTE_PRINTF(3, 4);
static void print_os_info(outputStream* st);
static void print_os_info_brief(outputStream* st);
static void print_cpu_info(outputStream* st);
static void pd_print_cpu_info(outputStream* st);
static void print_memory_info(outputStream* st);
static void print_dll_info(outputStream* st);
static void print_environment_variables(outputStream* st, const char** env_list, char* buffer, int len);
static void print_context(outputStream* st, void* context);
static void print_register_info(outputStream* st, void* context);
static void print_siginfo(outputStream* st, void* siginfo);
static void print_signal_handlers(outputStream* st, char* buf, size_t buflen);
static void print_date_and_time(outputStream* st, char* buf, size_t buflen);
static void print_location(outputStream* st, intptr_t x, bool verbose = false);
static size_t lasterror(char *buf, size_t len);
static int get_last_error();
static bool is_debugger_attached();
static void wait_for_keypress_at_exit(void);
static bool is_first_C_frame(frame *fr);
static frame get_sender_for_C_frame(frame *fr);
static frame current_frame();
static void print_hex_dump(outputStream* st, address start, address end, int unitsize);
static const char* exception_name(int exception_code, char* buf, size_t buflen);
static void* native_java_library();
static void jvm_path(char *buf, jint buflen);
static bool is_headless_jre();
static void print_jni_name_prefix_on(outputStream* st, int args_size);
static void print_jni_name_suffix_on(outputStream* st, int args_size);
static const char* file_separator();
static const char* line_separator();
static const char* path_separator();
static void init_system_properties_values();
static int stat(const char* path, struct stat* sbuf);
static bool dir_is_empty(const char* path);
static int create_binary_file(const char* path, bool rewrite_existing);
static jlong current_file_offset(int fd);
static jlong seek_to_file_offset(int fd, jlong offset);
static int allocate_thread_local_storage();
static void thread_local_storage_at_put(int index, void* value);
static void* thread_local_storage_at(int index);
static void free_thread_local_storage(int index);
static int get_native_stack(address* stack, int size, int toSkip = 0);
static void* malloc (size_t size, MEMFLAGS flags, const NativeCallStack& stack);
static void* malloc (size_t size, MEMFLAGS flags);
static void* realloc (void *memblock, size_t size, MEMFLAGS flag, const NativeCallStack& stack);
static void* realloc (void *memblock, size_t size, MEMFLAGS flag);
static void free (void *memblock, MEMFLAGS flags = mtNone);
static bool check_heap(bool force = false); // verify C heap integrity
static char* strdup(const char *, MEMFLAGS flags = mtInternal); // Like strdup
#ifndef PRODUCT
static julong num_mallocs; // # of calls to malloc/realloc
static julong alloc_bytes; // # of bytes allocated
static julong num_frees; // # of calls to free
static julong free_bytes; // # of bytes freed
#endif
static int socket(int domain, int type, int protocol);
static int socket_close(int fd);
static int socket_shutdown(int fd, int howto);
static int recv(int fd, char* buf, size_t nBytes, uint flags);
static int send(int fd, char* buf, size_t nBytes, uint flags);
static int raw_send(int fd, char* buf, size_t nBytes, uint flags);
static int timeout(int fd, long timeout);
static int listen(int fd, int count);
static int connect(int fd, struct sockaddr* him, socklen_t len);
static int bind(int fd, struct sockaddr* him, socklen_t len);
static int accept(int fd, struct sockaddr* him, socklen_t* len);
static int recvfrom(int fd, char* buf, size_t nbytes, uint flags,
struct sockaddr* from, socklen_t* fromlen);
static int get_sock_name(int fd, struct sockaddr* him, socklen_t* len);
static int sendto(int fd, char* buf, size_t len, uint flags,
struct sockaddr* to, socklen_t tolen);
static int socket_available(int fd, jint* pbytes);
static int get_sock_opt(int fd, int level, int optname,
char* optval, socklen_t* optlen);
static int set_sock_opt(int fd, int level, int optname,
const char* optval, socklen_t optlen);
static int get_host_name(char* name, int namelen);
static struct hostent* get_host_by_name(char* name);
static void signal_init();
static void signal_init_pd();
static void signal_notify(int signal_number);
static void* signal(int signal_number, void* handler);
static void signal_raise(int signal_number);
static int signal_wait();
static int signal_lookup();
static void* user_handler();
static void terminate_signal_thread();
static int sigexitnum_pd();
static long random(); // return 32bit pseudorandom number
static void init_random(long initval); // initialize random sequence
static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
static int get_core_path(char* buffer, size_t bufferSize);
static jlong current_thread_cpu_time();
static jlong thread_cpu_time(Thread* t);
static jlong current_thread_cpu_time(bool user_sys_cpu_time);
static jlong thread_cpu_time(Thread* t, bool user_sys_cpu_time);
static void current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr);
static void thread_cpu_time_info(jvmtiTimerInfo *info_ptr);
static bool is_thread_cpu_time_supported();
static int loadavg(double loadavg[], int nelem);
static bool obsolete_option(const JavaVMOption *option);
#include "runtime/os_ext.hpp"
public:
class CrashProtectionCallback : public StackObj {
public:
virtual void call() = 0;
};
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.hpp"
# include "os_posix.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.hpp"
# include "os_posix.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.hpp"
# include "os_posix.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_posix.hpp"
# include "os_bsd.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_x86
# include "os_linux_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_aarch64
# include "os_linux_aarch64.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_sparc
# include "os_linux_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_zero
# include "os_linux_zero.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_x86
# include "os_solaris_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_sparc
# include "os_solaris_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_windows_x86
# include "os_windows_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_arm
# include "os_linux_arm.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_ppc
# include "os_linux_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_aix_ppc
# include "os_aix_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_x86
# include "os_bsd_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_zero
# include "os_bsd_zero.hpp"
#endif
public:
#ifndef PLATFORM_PRINT_NATIVE_STACK
static bool platform_print_native_stack(outputStream* st, void* context,
char *buf, int buf_size) {
return false;
}
#endif
static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address
static bool dont_yield(); // when true, JVM_Yield() is nop
static void print_statistics();
static OSReturn set_native_priority(Thread* thread, int native_prio);
static OSReturn get_native_priority(const Thread* const thread, int* priority_ptr);
static int java_to_os_priority[CriticalPriority + 1];
static void hint_no_preempt();
static void pause();
static char* build_agent_function_name(const char *sym, const char *cname,
bool is_absolute_path);
class SuspendedThreadTaskContext {
public:
SuspendedThreadTaskContext(Thread* thread, void *ucontext) : _thread(thread), _ucontext(ucontext) {}
Thread* thread() const { return _thread; }
void* ucontext() const { return _ucontext; }
private:
Thread* _thread;
void* _ucontext;
};
class SuspendedThreadTask {
public:
SuspendedThreadTask(Thread* thread) : _thread(thread), _done(false) {}
virtual ~SuspendedThreadTask() {}
void run();
bool is_done() { return _done; }
virtual void do_task(const SuspendedThreadTaskContext& context) = 0;
protected:
private:
void internal_do_task();
Thread* _thread;
bool _done;
};
#ifndef TARGET_OS_FAMILY_windows
class SuspendResume {
public:
enum State {
SR_RUNNING,
SR_SUSPEND_REQUEST,
SR_SUSPENDED,
SR_WAKEUP_REQUEST
};
private:
volatile State _state;
private:
State switch_state(State from, State to);
public:
SuspendResume() : _state(SR_RUNNING) { }
State state() const { return _state; }
State request_suspend() {
return switch_state(SR_RUNNING, SR_SUSPEND_REQUEST);
}
State cancel_suspend() {
return switch_state(SR_SUSPEND_REQUEST, SR_RUNNING);
}
State suspended() {
return switch_state(SR_SUSPEND_REQUEST, SR_SUSPENDED);
}
State request_wakeup() {
return switch_state(SR_SUSPENDED, SR_WAKEUP_REQUEST);
}
State running() {
return switch_state(SR_WAKEUP_REQUEST, SR_RUNNING);
}
bool is_running() const {
return _state == SR_RUNNING;
}
bool is_suspend_request() const {
return _state == SR_SUSPEND_REQUEST;
}
bool is_suspended() const {
return _state == SR_SUSPENDED;
}
};
#endif
protected:
static long _rand_seed; // seed for random number generator
static int _processor_count; // number of processors
static int _initial_active_processor_count; // number of active processors during initialization.
static char* format_boot_path(const char* format_string,
const char* home,
int home_len,
char fileSep,
char pathSep);
static bool set_boot_path(char fileSep, char pathSep);
static char** split_path(const char* path, int* n);
};
extern "C" int SpinPause();
#endif // SHARE_VM_RUNTIME_OS_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/osThread.cpp
#include "precompiled.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/osThread.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
OSThread::OSThread(OSThreadStartFunc start_proc, void* start_parm) {
pd_initialize();
set_start_proc(start_proc);
set_start_parm(start_parm);
set_interrupted(false);
}
OSThread::~OSThread() {
pd_destroy();
}
void OSThread::print_on(outputStream *st) const {
st->print("nid=0x%lx ", thread_id());
switch (_state) {
case ALLOCATED: st->print("allocated "); break;
case INITIALIZED: st->print("initialized "); break;
case RUNNABLE: st->print("runnable "); break;
case MONITOR_WAIT: st->print("waiting for monitor entry "); break;
case CONDVAR_WAIT: st->print("waiting on condition "); break;
case OBJECT_WAIT: st->print("in Object.wait() "); break;
case BREAKPOINTED: st->print("at breakpoint"); break;
case SLEEPING: st->print("sleeping"); break;
case ZOMBIE: st->print("zombie"); break;
default: st->print("unknown state %d", _state); break;
}
}
C:\hotspot-69087d08d473\src\share\vm/runtime/osThread.hpp
#ifndef SHARE_VM_RUNTIME_OSTHREAD_HPP
#define SHARE_VM_RUNTIME_OSTHREAD_HPP
#include "runtime/frame.hpp"
#include "runtime/handles.hpp"
#include "runtime/javaFrameAnchor.hpp"
#include "runtime/objectMonitor.hpp"
#include "utilities/top.hpp"
enum ThreadState {
ALLOCATED, // Memory has been allocated but not initialized
INITIALIZED, // The thread has been initialized but yet started
RUNNABLE, // Has been started and is runnable, but not necessarily running
MONITOR_WAIT, // Waiting on a contended monitor lock
CONDVAR_WAIT, // Waiting on a condition variable
OBJECT_WAIT, // Waiting on an Object.wait() call
BREAKPOINTED, // Suspended at breakpoint
SLEEPING, // Thread.sleep()
ZOMBIE // All done, but not reclaimed yet
};
class OSThread: public CHeapObj<mtThread> {
friend class VMStructs;
private:
OSThreadStartFunc _start_proc; // Thread start routine
void* _start_parm; // Thread start routine parameter
volatile ThreadState _state; // Thread state *hint*
volatile jint _interrupted; // Thread.isInterrupted state
public:
void set_state(ThreadState state) { _state = state; }
ThreadState get_state() { return _state; }
OSThread(OSThreadStartFunc start_proc, void* start_parm);
~OSThread();
OSThreadStartFunc start_proc() const { return _start_proc; }
void set_start_proc(OSThreadStartFunc start_proc) { _start_proc = start_proc; }
void* start_parm() const { return _start_parm; }
void set_start_parm(void* start_parm) { _start_parm = start_parm; }
volatile bool interrupted() const { return _interrupted != 0; }
void set_interrupted(bool z) { _interrupted = z ? 1 : 0; }
void print_on(outputStream* st) const;
void print() const { print_on(tty); }
static ByteSize interrupted_offset() { return byte_offset_of(OSThread, _interrupted); }
#ifdef TARGET_OS_FAMILY_linux
# include "osThread_linux.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "osThread_solaris.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "osThread_windows.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "osThread_aix.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "osThread_bsd.hpp"
#endif
public:
static ByteSize thread_id_offset() { return byte_offset_of(OSThread, _thread_id); }
static size_t thread_id_size() { return sizeof(thread_id_t); }
thread_id_t thread_id() const { return _thread_id; }
void set_thread_id(thread_id_t id) { _thread_id = id; }
private:
thread_id_t _thread_id;
};
class OSThreadWaitState : public StackObj {
OSThread* _osthread;
ThreadState _old_state;
public:
OSThreadWaitState(OSThread* osthread, bool is_object_wait) {
_osthread = osthread;
_old_state = osthread->get_state();
if (is_object_wait) {
osthread->set_state(OBJECT_WAIT);
} else {
osthread->set_state(CONDVAR_WAIT);
}
}
~OSThreadWaitState() {
_osthread->set_state(_old_state);
}
};
class OSThreadContendState : public StackObj {
OSThread* _osthread;
ThreadState _old_state;
public:
OSThreadContendState(OSThread* osthread) {
_osthread = osthread;
_old_state = osthread->get_state();
osthread->set_state(MONITOR_WAIT);
}
~OSThreadContendState() {
_osthread->set_state(_old_state);
}
};
#endif // SHARE_VM_RUNTIME_OSTHREAD_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/os_ext.hpp
#ifndef SHARE_VM_RUNTIME_OS_EXT_HPP
#define SHARE_VM_RUNTIME_OS_EXT_HPP
public:
static void init_globals_ext() {} // Run from init_globals().
private:
#endif // SHARE_VM_RUNTIME_OS_EXT_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/os_perf.hpp
#ifndef SHARE_VM_RUNTIME_OS_PERF_HPP
#define SHARE_VM_RUNTIME_OS_PERF_HPP
#include "utilities/macros.hpp"
#include "memory/allocation.inline.hpp"
#include "utilities/globalDefinitions.hpp"
#define FUNCTIONALITY_NOT_IMPLEMENTED -8
class CPUInformation : public CHeapObj<mtInternal> {
private:
int _no_of_sockets;
int _no_of_cores;
int _no_of_hw_threads;
const char* _description;
const char* _name;
public:
CPUInformation() {
_no_of_sockets = 0;
_no_of_cores = 0;
_no_of_hw_threads = 0;
_description = NULL;
_name = NULL;
}
int number_of_sockets(void) const {
return _no_of_sockets;
}
void set_number_of_sockets(int no_of_sockets) {
_no_of_sockets = no_of_sockets;
}
int number_of_cores(void) const {
return _no_of_cores;
}
void set_number_of_cores(int no_of_cores) {
_no_of_cores = no_of_cores;
}
int number_of_hardware_threads(void) const {
return _no_of_hw_threads;
}
void set_number_of_hardware_threads(int no_of_hw_threads) {
_no_of_hw_threads = no_of_hw_threads;
}
const char* cpu_name(void) const {
return _name;
}
void set_cpu_name(const char* cpu_name) {
_name = cpu_name;
}
const char* cpu_description(void) const {
return _description;
}
void set_cpu_description(const char* cpu_description) {
_description = cpu_description;
}
};
class SystemProcess : public CHeapObj<mtInternal> {
private:
int _pid;
char* _name;
char* _path;
char* _command_line;
SystemProcess* _next;
public:
SystemProcess() {
_pid = 0;
_name = NULL;
_path = NULL;
_command_line = NULL;
_next = NULL;
}
SystemProcess(int pid, char* name, char* path, char* command_line, SystemProcess* next) {
_pid = pid;
_name = name;
_path = path;
_command_line = command_line;
_next = next;
}
void set_next(SystemProcess* sys_process) {
_next = sys_process;
}
SystemProcess* next(void) const {
return _next;
}
int pid(void) const {
return _pid;
}
void set_pid(int pid) {
_pid = pid;
}
const char* name(void) const {
return _name;
}
void set_name(char* name) {
_name = name;
}
const char* path(void) const {
return _path;
}
void set_path(char* path) {
_path = path;
}
const char* command_line(void) const {
return _command_line;
}
void set_command_line(char* command_line) {
_command_line = command_line;
}
virtual ~SystemProcess(void) {
if (_name != NULL) {
FREE_C_HEAP_ARRAY(char, _name, mtInternal);
}
if (_path != NULL) {
FREE_C_HEAP_ARRAY(char, _path, mtInternal);
}
if (_command_line != NULL) {
FREE_C_HEAP_ARRAY(char, _command_line, mtInternal);
}
}
};
class NetworkInterface : public ResourceObj {
private:
char* _name;
uint64_t _bytes_in;
uint64_t _bytes_out;
NetworkInterface* _next;
NetworkInterface(); // no impl
NetworkInterface(const NetworkInterface& rhs); // no impl
NetworkInterface& operator=(const NetworkInterface& rhs); // no impl
public:
NetworkInterface(const char* name, uint64_t bytes_in, uint64_t bytes_out, NetworkInterface* next) :
_name(NULL),
_bytes_in(bytes_in),
_bytes_out(bytes_out),
_next(next) {
assert(name != NULL, "invariant");
const size_t length = strlen(name);
assert(allocated_on_res_area(), "invariant");
_name = NEW_RESOURCE_ARRAY(char, length + 1);
strncpy(_name, name, length + 1);
assert(strncmp(_name, name, length) == 0, "invariant");
}
NetworkInterface* next() const {
return _next;
}
const char* get_name() const {
return _name;
}
uint64_t get_bytes_out() const {
return _bytes_out;
}
uint64_t get_bytes_in() const {
return _bytes_in;
}
};
class CPUInformationInterface : public CHeapObj<mtInternal> {
private:
CPUInformation* _cpu_info;
public:
CPUInformationInterface();
bool initialize();
~CPUInformationInterface();
int cpu_information(CPUInformation& cpu_info);
};
class CPUPerformanceInterface : public CHeapObj<mtInternal> {
private:
class CPUPerformance;
CPUPerformance* _impl;
public:
CPUPerformanceInterface();
~CPUPerformanceInterface();
bool initialize();
int cpu_load(int which_logical_cpu, double* const cpu_load) const;
int context_switch_rate(double* const rate) const;
int cpu_load_total_process(double* const cpu_load) const;
int cpu_loads_process(double* const pjvmUserLoad,
double* const pjvmKernelLoad,
double* const psystemTotalLoad) const;
};
class SystemProcessInterface : public CHeapObj<mtInternal> {
private:
class SystemProcesses;
SystemProcesses* _impl;
public:
SystemProcessInterface();
~SystemProcessInterface();
bool initialize();
int system_processes(SystemProcess** system_procs, int* const no_of_sys_processes) const;
};
class NetworkPerformanceInterface : public CHeapObj<mtInternal> {
private:
class NetworkPerformance;
NetworkPerformance* _impl;
NetworkPerformanceInterface(const NetworkPerformanceInterface& rhs); // no impl
NetworkPerformanceInterface& operator=(const NetworkPerformanceInterface& rhs); // no impl
public:
NetworkPerformanceInterface();
bool initialize();
~NetworkPerformanceInterface();
int network_utilization(NetworkInterface** network_interfaces) const;
};
#endif // SHARE_VM_RUNTIME_OS_PERF_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/park.cpp
#include "precompiled.hpp"
#include "runtime/thread.hpp"
volatile int ParkEvent::ListLock = 0 ;
ParkEvent * volatile ParkEvent::FreeList = NULL ;
ParkEvent * ParkEvent::Allocate (Thread * t) {
ParkEvent * ev ;
Thread::SpinAcquire(&ListLock, "ParkEventFreeListAllocate");
{
ev = FreeList;
if (ev != NULL) {
FreeList = ev->FreeNext;
}
}
Thread::SpinRelease(&ListLock);
if (ev != NULL) {
guarantee (ev->AssociatedWith == NULL, "invariant") ;
} else {
ev = new ParkEvent () ;
guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ;
}
ev->reset() ; // courtesy to caller
ev->AssociatedWith = t ; // Associate ev with t
ev->FreeNext = NULL ;
return ev ;
}
void ParkEvent::Release (ParkEvent * ev) {
if (ev == NULL) return ;
guarantee (ev->FreeNext == NULL , "invariant") ;
ev->AssociatedWith = NULL ;
Thread::SpinAcquire(&ListLock, "ParkEventFreeListRelease");
{
ev->FreeNext = FreeList;
FreeList = ev;
}
Thread::SpinRelease(&ListLock);
}
void * ParkEvent::operator new (size_t sz) throw() {
return (void *) ((intptr_t (AllocateHeap(sz + 256, mtInternal, CALLER_PC)) + 256) & -256) ;
}
void ParkEvent::operator delete (void * a) {
ShouldNotReachHere();
}
volatile int Parker::ListLock = 0 ;
Parker * volatile Parker::FreeList = NULL ;
Parker * Parker::Allocate (JavaThread * t) {
guarantee (t != NULL, "invariant") ;
Parker * p ;
Thread::SpinAcquire(&ListLock, "ParkerFreeListAllocate");
{
p = FreeList;
if (p != NULL) {
FreeList = p->FreeNext;
}
}
Thread::SpinRelease(&ListLock);
if (p != NULL) {
guarantee (p->AssociatedWith == NULL, "invariant") ;
} else {
p = new Parker() ;
}
p->AssociatedWith = t ; // Associate p with t
p->FreeNext = NULL ;
return p ;
}
void Parker::Release (Parker * p) {
if (p == NULL) return ;
guarantee (p->AssociatedWith != NULL, "invariant") ;
guarantee (p->FreeNext == NULL , "invariant") ;
p->AssociatedWith = NULL ;
Thread::SpinAcquire(&ListLock, "ParkerFreeListRelease");
{
p->FreeNext = FreeList;
FreeList = p;
}
Thread::SpinRelease(&ListLock);
}
C:\hotspot-69087d08d473\src\share\vm/runtime/park.hpp
#ifndef SHARE_VM_RUNTIME_PARK_HPP
#define SHARE_VM_RUNTIME_PARK_HPP
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
class Parker : public os::PlatformParker {
private:
volatile int _counter ;
Parker * FreeNext ;
JavaThread * AssociatedWith ; // Current association
public:
Parker() : PlatformParker() {
_counter = 0 ;
FreeNext = NULL ;
AssociatedWith = NULL ;
}
protected:
~Parker() { ShouldNotReachHere(); }
public:
void park(bool isAbsolute, jlong time);
void unpark();
static Parker * Allocate (JavaThread * t) ;
static void Release (Parker * e) ;
private:
static Parker * volatile FreeList ;
static volatile int ListLock ;
};
class ParkEvent : public os::PlatformEvent {
private:
ParkEvent * FreeNext ;
Thread * AssociatedWith ;
intptr_t RawThreadIdentity ; // LWPID etc
volatile int Incarnation ;
void * LastWaker ;
public:
ParkEvent * volatile ListNext ;
ParkEvent * volatile ListPrev ;
volatile intptr_t OnList ;
volatile int TState ;
volatile int Notified ; // for native monitor construct
volatile int IsWaiting ; // Enqueued on WaitSet
private:
static ParkEvent * volatile FreeList ;
static volatile int ListLock ;
protected: // Ensure dtor is never invoked
~ParkEvent() { guarantee (0, "invariant") ; }
ParkEvent() : PlatformEvent() {
AssociatedWith = NULL ;
FreeNext = NULL ;
ListNext = NULL ;
ListPrev = NULL ;
OnList = 0 ;
TState = 0 ;
Notified = 0 ;
IsWaiting = 0 ;
}
void * operator new (size_t sz) throw();
void operator delete (void * a) ;
public:
static ParkEvent * Allocate (Thread * t) ;
static void Release (ParkEvent * e) ;
} ;
#endif // SHARE_VM_RUNTIME_PARK_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/perfData.cpp
#include "precompiled.hpp"
#include "classfile/vmSymbols.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "runtime/perfData.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/globalDefinitions.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
PerfDataList* PerfDataManager::_all = NULL;
PerfDataList* PerfDataManager::_sampled = NULL;
PerfDataList* PerfDataManager::_constants = NULL;
const char* PerfDataManager::_name_spaces[] = {
"java", // stable and supported name space
"com.sun", // unstable but supported name space
"sun", // unstable and unsupported name space
"java.gc", // Garbage Collection name spaces
"com.sun.gc",
"sun.gc",
"java.ci", // Compiler name spaces
"com.sun.ci",
"sun.ci",
"java.cls", // Class Loader name spaces
"com.sun.cls",
"sun.cls",
"java.rt", // Runtime name spaces
"com.sun.rt",
"sun.rt",
"java.os", // Operating System name spaces
"com.sun.os",
"sun.os",
"java.threads", // Threads System name spaces
"com.sun.threads",
"sun.threads",
"java.property", // Java Property name spaces
"com.sun.property",
"sun.property",
"",
};
PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v)
: _name(NULL), _u(u), _v(v), _valuep(NULL),
_on_c_heap(false) {
const char* prefix = PerfDataManager::ns_to_string(ns);
_name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2, mtInternal);
assert(_name != NULL && strlen(name) != 0, "invalid name");
if (ns == NULL_NS) {
strcpy(_name, name);
if (PerfDataManager::is_stable_supported(_name) ||
PerfDataManager::is_unstable_supported(_name)) {
_flags = F_Supported;
}
else {
_flags = F_None;
}
}
else {
sprintf(_name, "%s.%s", prefix, name);
if (PerfDataManager::is_stable_supported(ns) ||
PerfDataManager::is_unstable_supported(ns)) {
_flags = F_Supported;
}
else {
_flags = F_None;
}
}
}
PerfData::~PerfData() {
if (_name != NULL) {
FREE_C_HEAP_ARRAY(char, _name, mtInternal);
}
if (is_on_c_heap()) {
FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep, mtInternal);
}
}
void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) {
size_t dlen = vlen==0 ? 1 : vlen;
size_t namelen = strlen(name()) + 1; // include null terminator
size_t size = sizeof(PerfDataEntry) + namelen;
size_t pad_length = ((size % dsize) == 0) ? 0 : dsize - (size % dsize);
size += pad_length;
size_t data_start = size;
size += (dsize * dlen);
int align = sizeof(jlong) - 1;
size = ((size + align) & ~align);
char* psmp = PerfMemory::alloc(size);
if (psmp == NULL) {
psmp = NEW_C_HEAP_ARRAY(char, size, mtInternal);
_on_c_heap = true;
}
char* cname = psmp + sizeof(PerfDataEntry);
void* valuep = (void*) (psmp + data_start);
assert(is_on_c_heap() || PerfMemory::contains(cname), "just checking");
assert(is_on_c_heap() || PerfMemory::contains((char*)valuep), "just checking");
strcpy(cname, name());
PerfDataEntry* pdep = (PerfDataEntry*)psmp;
pdep->entry_length = (jint)size;
pdep->name_offset = (jint) ((uintptr_t) cname - (uintptr_t) psmp);
pdep->vector_length = (jint)vlen;
pdep->data_type = (jbyte) type2char(dtype);
pdep->data_units = units();
pdep->data_variability = variability();
pdep->flags = (jbyte)flags();
pdep->data_offset = (jint) data_start;
if (PerfTraceDataCreation) {
tty->print("name = %s, dtype = %d, variability = %d,"
" units = %d, dsize = %d, vlen = %d,"
" pad_length = %d, size = %d, on_c_heap = %s,"
" address = " INTPTR_FORMAT ","
" data address = " INTPTR_FORMAT "\n",
cname, dtype, variability(),
units(), dsize, vlen,
pad_length, size, is_on_c_heap() ? "TRUE":"FALSE",
psmp, valuep);
}
_pdep = pdep;
_valuep = valuep;
PerfMemory::mark_updated();
}
PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
: PerfData(ns, namep, u, v) {
create_entry(T_LONG, sizeof(jlong));
}
int PerfLong::format(char* buffer, int length) {
return jio_snprintf(buffer, length, JLONG_FORMAT, *(jlong*)_valuep);
}
PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
Variability v, jlong* sampled)
: PerfLong(ns, namep, u, v),
_sampled(sampled), _sample_helper(NULL) {
sample();
}
PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
Variability v, PerfLongSampleHelper* helper)
: PerfLong(ns, namep, u, v),
_sampled(NULL), _sample_helper(helper) {
sample();
}
void PerfLongVariant::sample() {
if (_sample_helper == NULL) return;
if (_sample_helper != NULL) {
}
else if (_sampled != NULL) {
}
}
PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u,
Variability v, jint length)
: PerfData(ns, namep, u, v), _length(length) {
create_entry(T_BYTE, sizeof(jbyte), (size_t)_length);
}
void PerfString::set_string(const char* s2) {
strncpy((char *)_valuep, s2 == NULL ? "" : s2, _length);
((char*)_valuep)[_length-1] = '\0';
}
int PerfString::format(char* buffer, int length) {
return jio_snprintf(buffer, length, "%s", (char*)_valuep);
}
PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep,
const char* initial_value)
: PerfString(ns, namep, V_Constant,
initial_value == NULL ? 1 :
MIN2((jint)(strlen((char*)initial_value)+1),
(jint)(PerfMaxStringConstLength+1)),
initial_value) {
if (PrintMiscellaneous && Verbose) {
if (is_valid() && initial_value != NULL &&
((jint)strlen(initial_value) > (jint)PerfMaxStringConstLength)) {
warning("Truncating PerfStringConstant: name = %s,"
" length = " INT32_FORMAT ","
" PerfMaxStringConstLength = " INT32_FORMAT "\n",
namep,
(jint)strlen(initial_value),
(jint)PerfMaxStringConstLength);
}
}
}
void PerfDataManager::destroy() {
if (_all == NULL)
return;
for (int index = 0; index < _all->length(); index++) {
PerfData* p = _all->at(index);
delete p;
}
delete(_all);
delete(_sampled);
delete(_constants);
_all = NULL;
_sampled = NULL;
_constants = NULL;
}
void PerfDataManager::add_item(PerfData* p, bool sampled) {
MutexLocker ml(PerfDataManager_lock);
if (_all == NULL) {
_all = new PerfDataList(100);
}
assert(!_all->contains(p->name()), "duplicate name added");
_all->append(p);
if (p->variability() == PerfData::V_Constant) {
if (_constants == NULL) {
_constants = new PerfDataList(25);
}
_constants->append(p);
return;
}
if (sampled) {
if (_sampled == NULL) {
_sampled = new PerfDataList(25);
}
_sampled->append(p);
}
}
PerfData* PerfDataManager::find_by_name(const char* name) {
return _all->find_by_name(name);
}
PerfDataList* PerfDataManager::all() {
MutexLocker ml(PerfDataManager_lock);
if (_all == NULL)
return NULL;
PerfDataList* clone = _all->clone();
return clone;
}
PerfDataList* PerfDataManager::sampled() {
MutexLocker ml(PerfDataManager_lock);
if (_sampled == NULL)
return NULL;
PerfDataList* clone = _sampled->clone();
return clone;
}
PerfDataList* PerfDataManager::constants() {
MutexLocker ml(PerfDataManager_lock);
if (_constants == NULL)
return NULL;
PerfDataList* clone = _constants->clone();
return clone;
}
char* PerfDataManager::counter_name(const char* ns, const char* name) {
assert(ns != NULL, "ns string required");
assert(name != NULL, "name string required");
size_t len = strlen(ns) + strlen(name) + 2;
char* result = NEW_RESOURCE_ARRAY(char, len);
sprintf(result, "%s.%s", ns, name);
return result;
}
char* PerfDataManager::name_space(const char* ns, const char* sub,
int instance) {
char intbuf[40];
jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
return name_space(ns, name_space(sub, intbuf));
}
char *PerfDataManager::name_space(const char* ns, int instance) {
char intbuf[40];
jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
return name_space(ns, intbuf);
}
PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns,
const char* name,
const char* s,
TRAPS) {
PerfStringConstant* p = new PerfStringConstant(ns, name, s);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, false);
return p;
}
PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns,
const char* name,
PerfData::Units u,
jlong val, TRAPS) {
PerfLongConstant* p = new PerfLongConstant(ns, name, u, val);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, false);
return p;
}
PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns,
const char* name,
jint max_length,
const char* s,
TRAPS) {
if (max_length == 0 && s != NULL) max_length = (jint)strlen(s);
assert(max_length != 0, "PerfStringVariable with length 0");
PerfStringVariable* p = new PerfStringVariable(ns, name, max_length, s);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, false);
return p;
}
PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
const char* name,
PerfData::Units u,
jlong ival, TRAPS) {
PerfLongVariable* p = new PerfLongVariable(ns, name, u, ival);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, false);
return p;
}
PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
const char* name,
PerfData::Units u,
jlong* sp, TRAPS) {
if (!UsePerfData) return NULL;
PerfLongVariable* p = new PerfLongVariable(ns, name, u, sp);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, true);
return p;
}
PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
const char* name,
PerfData::Units u,
PerfSampleHelper* sh,
TRAPS) {
if (!UsePerfData) return NULL;
PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, true);
return p;
}
PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
const char* name,
PerfData::Units u,
jlong ival, TRAPS) {
PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, false);
return p;
}
PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
const char* name,
PerfData::Units u,
jlong* sp, TRAPS) {
if (!UsePerfData) return NULL;
PerfLongCounter* p = new PerfLongCounter(ns, name, u, sp);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, true);
return p;
}
PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
const char* name,
PerfData::Units u,
PerfSampleHelper* sh,
TRAPS) {
if (!UsePerfData) return NULL;
PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh);
if (!p->is_valid()) {
delete p;
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
add_item(p, true);
return p;
}
PerfDataList::PerfDataList(int length) {
_set = new(ResourceObj::C_HEAP, mtInternal) PerfDataArray(length, true);
}
PerfDataList::PerfDataList(PerfDataList* p) {
_set = new(ResourceObj::C_HEAP, mtInternal) PerfDataArray(p->length(), true);
_set->appendAll(p->get_impl());
}
PerfDataList::~PerfDataList() {
delete _set;
}
bool PerfDataList::by_name(void* name, PerfData* pd) {
if (pd == NULL)
return false;
return strcmp((const char*)name, pd->name()) == 0;
}
PerfData* PerfDataList::find_by_name(const char* name) {
if (this == NULL)
return NULL;
int i = _set->find((void*)name, PerfDataList::by_name);
if (i >= 0 && i <= _set->length())
return _set->at(i);
else
return NULL;
}
PerfDataList* PerfDataList::clone() {
PerfDataList* copy = new PerfDataList(this);
assert(copy != NULL, "just checking");
return copy;
}
C:\hotspot-69087d08d473\src\share\vm/runtime/perfData.hpp
#ifndef SHARE_VM_RUNTIME_PERFDATA_HPP
#define SHARE_VM_RUNTIME_PERFDATA_HPP
#include "memory/allocation.inline.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/timer.hpp"
#include "utilities/growableArray.hpp"
enum CounterNS {
JAVA_NS,
COM_NS,
SUN_NS,
JAVA_GC, // Garbage Collection name spaces
COM_GC,
SUN_GC,
JAVA_CI, // Compiler name spaces
COM_CI,
SUN_CI,
JAVA_CLS, // Class Loader name spaces
COM_CLS,
SUN_CLS,
JAVA_RT, // Runtime name spaces
COM_RT,
SUN_RT,
JAVA_OS, // Operating System name spaces
COM_OS,
SUN_OS,
JAVA_THREADS, // Threads System name spaces
COM_THREADS,
SUN_THREADS,
JAVA_PROPERTY, // Java Property name spaces
COM_PROPERTY,
SUN_PROPERTY,
NULL_NS,
COUNTERNS_LAST = NULL_NS
};
.* PerfData::U_Bytes,
class PerfData : public CHeapObj<mtInternal> {
friend class StatSampler; // for access to protected void sample()
friend class PerfDataManager; // for access to protected destructor
public:
enum Variability {
V_Constant = 1,
V_Monotonic = 2,
V_Variable = 3,
V_last = V_Variable
};
enum Units {
U_None = 1,
U_Bytes = 2,
U_Ticks = 3,
U_Events = 4,
U_String = 5,
U_Hertz = 6,
U_Last = U_Hertz
};
enum Flags {
F_None = 0x0,
F_Supported = 0x1 // interface is supported - java.* and com.sun.*
};
private:
char* _name;
Variability _v;
Units _u;
bool _on_c_heap;
Flags _flags;
PerfDataEntry* _pdep;
protected:
void *_valuep;
PerfData(CounterNS ns, const char* name, Units u, Variability v);
virtual ~PerfData();
void create_entry(BasicType dtype, size_t dsize, size_t dlen = 0);
virtual void sample() = 0;
public:
inline bool is_valid() { return _valuep != NULL; }
inline bool is_on_c_heap() { return _on_c_heap; }
const char* name() { return _name; }
Variability variability() { return _v; }
Units units() { return _u; }
Flags flags() { return _flags; }
inline void* get_address() { return _valuep; }
virtual int format(char* cp, int length) = 0;
};
class PerfLongSampleHelper : public CHeapObj<mtInternal> {
public:
virtual jlong take_sample() = 0;
};
typedef PerfLongSampleHelper PerfSampleHelper;
class PerfLong : public PerfData {
protected:
PerfLong(CounterNS ns, const char* namep, Units u, Variability v);
public:
int format(char* buffer, int length);
inline jlong get_value() { return *(jlong*)_valuep; }
};
class PerfLongConstant : public PerfLong {
friend class PerfDataManager; // for access to protected constructor
private:
void sample() { }
protected:
PerfLongConstant(CounterNS ns, const char* namep, Units u,
jlong initial_value=0)
: PerfLong(ns, namep, u, V_Constant) {
if (is_valid()) *(jlong*)_valuep = initial_value;
}
};
typedef PerfLongConstant PerfConstant;
class PerfLongVariant : public PerfLong {
protected:
jlong* _sampled;
PerfLongSampleHelper* _sample_helper;
PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
jlong initial_value=0)
: PerfLong(ns, namep, u, v) {
if (is_valid()) *(jlong*)_valuep = initial_value;
}
PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
jlong* sampled);
PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
PerfLongSampleHelper* sample_helper);
void sample();
public:
inline void inc() { (*(jlong*)_valuep)++; }
inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
inline void add(jlong val) { (*(jlong*)_valuep) += val; }
void clear_sample_helper() { _sample_helper = NULL; }
};
class PerfLongCounter : public PerfLongVariant {
friend class PerfDataManager; // for access to protected constructor
protected:
PerfLongCounter(CounterNS ns, const char* namep, Units u,
jlong initial_value=0)
: PerfLongVariant(ns, namep, u, V_Monotonic,
initial_value) { }
PerfLongCounter(CounterNS ns, const char* namep, Units u, jlong* sampled)
: PerfLongVariant(ns, namep, u, V_Monotonic, sampled) { }
PerfLongCounter(CounterNS ns, const char* namep, Units u,
PerfLongSampleHelper* sample_helper)
: PerfLongVariant(ns, namep, u, V_Monotonic,
sample_helper) { }
};
typedef PerfLongCounter PerfCounter;
class PerfLongVariable : public PerfLongVariant {
friend class PerfDataManager; // for access to protected constructor
protected:
PerfLongVariable(CounterNS ns, const char* namep, Units u,
jlong initial_value=0)
: PerfLongVariant(ns, namep, u, V_Variable,
initial_value) { }
PerfLongVariable(CounterNS ns, const char* namep, Units u, jlong* sampled)
: PerfLongVariant(ns, namep, u, V_Variable, sampled) { }
PerfLongVariable(CounterNS ns, const char* namep, Units u,
PerfLongSampleHelper* sample_helper)
: PerfLongVariant(ns, namep, u, V_Variable,
sample_helper) { }
public:
inline void set_value(jlong val) { (*(jlong*)_valuep) = val; }
};
typedef PerfLongVariable PerfVariable;
class PerfByteArray : public PerfData {
protected:
jint _length;
PerfByteArray(CounterNS ns, const char* namep, Units u, Variability v,
jint length);
};
class PerfString : public PerfByteArray {
protected:
void set_string(const char* s2);
PerfString(CounterNS ns, const char* namep, Variability v, jint length,
const char* initial_value)
: PerfByteArray(ns, namep, U_String, v, length) {
if (is_valid()) set_string(initial_value);
}
public:
int format(char* buffer, int length);
};
class PerfStringConstant : public PerfString {
friend class PerfDataManager; // for access to protected constructor
private:
void sample() { }
protected:
PerfStringConstant(CounterNS ns, const char* namep,
const char* initial_value);
};
class PerfStringVariable : public PerfString {
friend class PerfDataManager; // for access to protected constructor
protected:
void sample() { }
PerfStringVariable(CounterNS ns, const char* namep, jint max_length,
const char* initial_value)
: PerfString(ns, namep, V_Variable, max_length+1,
initial_value) { }
public:
inline void set_value(const char* val) { set_string(val); }
};
class PerfDataList : public CHeapObj<mtInternal> {
private:
typedef GrowableArray<PerfData*> PerfDataArray;
PerfDataArray* _set;
static bool by_name(void* name, PerfData* pd);
protected:
PerfDataArray* get_impl() { return _set; }
public:
PerfDataList(int length);
PerfDataList(PerfDataList* p);
~PerfDataList();
PerfData* find_by_name(const char* name);
bool contains(const char* name) { return find_by_name(name) != NULL; }
int length() { return _set->length(); }
void append(PerfData *p) { _set->append(p); }
void remove(PerfData *p) { _set->remove(p); }
PerfDataList* clone();
PerfData* at(int index) { return _set->at(index); }
};
class PerfDataManager : AllStatic {
friend class StatSampler; // for access to protected PerfDataList methods
private:
static PerfDataList* _all;
static PerfDataList* _sampled;
static PerfDataList* _constants;
static const char* _name_spaces[];
static void add_item(PerfData* p, bool sampled);
protected:
static PerfDataList* all();
static int count() { return _all->length(); }
static PerfDataList* sampled();
static int sampled_count() { return _sampled->length(); }
static PerfDataList* constants();
static int constants_count() { return _constants->length(); }
public:
static bool exists(const char* name) { return _all->contains(name); }
static PerfData* find_by_name(const char* name);
static const char* ns_to_string(CounterNS ns) {
return _name_spaces[ns];
}
static bool is_stable_supported(CounterNS ns) {
return (ns != NULL_NS) && ((ns % 3) == JAVA_NS);
}
static bool is_unstable_supported(CounterNS ns) {
return (ns != NULL_NS) && ((ns % 3) == COM_NS);
}
static bool is_unstable_unsupported(CounterNS ns) {
return (ns == NULL_NS) || ((ns % 3) == SUN_NS);
}
static bool is_stable_supported(const char* name) {
const char* javadot = "java.";
return strncmp(name, javadot, strlen(javadot)) == 0;
}
static bool is_unstable_supported(const char* name) {
const char* comdot = "com.sun.";
return strncmp(name, comdot, strlen(comdot)) == 0;
}
static bool is_unstable_unsupported(const char* name) {
return !(is_stable_supported(name) && is_unstable_supported(name));
}
static char* counter_name(const char* name_space, const char* name);
static char* name_space(const char* name_space, const char* sub_space) {
return counter_name(name_space, sub_space);
}
static char* name_space(const char* name_space, const char* sub_space,
int instance);
static char* name_space(const char* name_space, int instance);
static PerfStringConstant* create_string_constant(CounterNS ns,
const char* name,
const char *s, TRAPS);
static PerfLongConstant* create_long_constant(CounterNS ns,
const char* name,
PerfData::Units u,
jlong val, TRAPS);
static PerfStringVariable* create_string_variable(CounterNS ns,
const char* name,
int max_length,
const char *s, TRAPS);
static PerfStringVariable* create_string_variable(CounterNS ns,
const char* name,
const char *s, TRAPS) {
return create_string_variable(ns, name, 0, s, THREAD);
};
static PerfLongVariable* create_long_variable(CounterNS ns,
const char* name,
PerfData::Units u,
jlong ival, TRAPS);
static PerfLongVariable* create_long_variable(CounterNS ns,
const char* name,
PerfData::Units u, TRAPS) {
return create_long_variable(ns, name, u, (jlong)0, THREAD);
};
static PerfLongVariable* create_long_variable(CounterNS, const char* name,
PerfData::Units u,
jlong* sp, TRAPS);
static PerfLongVariable* create_long_variable(CounterNS ns,
const char* name,
PerfData::Units u,
PerfLongSampleHelper* sh,
TRAPS);
static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
PerfData::Units u,
jlong ival, TRAPS);
static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
PerfData::Units u, TRAPS) {
return create_long_counter(ns, name, u, (jlong)0, THREAD);
};
static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
PerfData::Units u, jlong* sp,
TRAPS);
static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
PerfData::Units u,
PerfLongSampleHelper* sh,
TRAPS);
static PerfConstant* create_constant(CounterNS ns, const char* name,
PerfData::Units u, jlong val, TRAPS) {
return create_long_constant(ns, name, u, val, THREAD);
}
static PerfVariable* create_variable(CounterNS ns, const char* name,
PerfData::Units u, jlong ival, TRAPS) {
return create_long_variable(ns, name, u, ival, THREAD);
}
static PerfVariable* create_variable(CounterNS ns, const char* name,
PerfData::Units u, TRAPS) {
return create_long_variable(ns, name, u, (jlong)0, THREAD);
}
static PerfVariable* create_variable(CounterNS ns, const char* name,
PerfData::Units u, jlong* sp, TRAPS) {
return create_long_variable(ns, name, u, sp, THREAD);
}
static PerfVariable* create_variable(CounterNS ns, const char* name,
PerfData::Units u,
PerfSampleHelper* sh, TRAPS) {
return create_long_variable(ns, name, u, sh, THREAD);
}
static PerfCounter* create_counter(CounterNS ns, const char* name,
PerfData::Units u, jlong ival, TRAPS) {
return create_long_counter(ns, name, u, ival, THREAD);
}
static PerfCounter* create_counter(CounterNS ns, const char* name,
PerfData::Units u, TRAPS) {
return create_long_counter(ns, name, u, (jlong)0, THREAD);
}
static PerfCounter* create_counter(CounterNS ns, const char* name,
PerfData::Units u, jlong* sp, TRAPS) {
return create_long_counter(ns, name, u, sp, THREAD);
}
static PerfCounter* create_counter(CounterNS ns, const char* name,
PerfData::Units u,
PerfSampleHelper* sh, TRAPS) {
return create_long_counter(ns, name, u, sh, THREAD);
}
static void destroy();
};
#define NEWPERFTICKCOUNTER(counter, counter_ns, counter_name) \
{counter = PerfDataManager::create_counter(counter_ns, counter_name, \
PerfData::U_Ticks,CHECK);}
#define NEWPERFEVENTCOUNTER(counter, counter_ns, counter_name) \
{counter = PerfDataManager::create_counter(counter_ns, counter_name, \
PerfData::U_Events,CHECK);}
#define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
{counter = PerfDataManager::create_counter(counter_ns, counter_name, \
PerfData::U_Bytes,CHECK);}
class PerfTraceTime : public StackObj {
protected:
elapsedTimer _t;
PerfLongCounter* _timerp;
int* _recursion_counter;
public:
inline PerfTraceTime(PerfLongCounter* timerp) : _timerp(timerp), _recursion_counter(NULL) {
if (!UsePerfData) return;
_t.start();
}
inline PerfTraceTime(PerfLongCounter* timerp, int* recursion_counter) : _timerp(timerp), _recursion_counter(recursion_counter) {
if (!UsePerfData || (_recursion_counter != NULL &&
(*_recursion_counter)++ > 0)) return;
_t.start();
}
inline void suspend() { if (!UsePerfData) return; _t.stop(); }
inline void resume() { if (!UsePerfData) return; _t.start(); }
inline ~PerfTraceTime() {
if (!UsePerfData || (_recursion_counter != NULL &&
--(*_recursion_counter) > 0)) return;
_t.stop();
_timerp->inc(_t.ticks());
}
};
class PerfTraceTimedEvent : public PerfTraceTime {
protected:
PerfLongCounter* _eventp;
public:
inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) {
if (!UsePerfData) return;
_eventp->inc();
}
inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp, int* recursion_counter): PerfTraceTime(timerp, recursion_counter), _eventp(eventp) {
if (!UsePerfData) return;
_eventp->inc();
}
};
#endif // SHARE_VM_RUNTIME_PERFDATA_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/perfMemory.cpp
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/perfData.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/statSampler.hpp"
#include "utilities/globalDefinitions.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
const char PERFDATA_NAME[] = "hsperfdata";
static const size_t PERFDATA_FILENAME_LEN = sizeof(PERFDATA_NAME) +
UINT_CHARS + 1;
char* PerfMemory::_start = NULL;
char* PerfMemory::_end = NULL;
char* PerfMemory::_top = NULL;
size_t PerfMemory::_capacity = 0;
jint PerfMemory::_initialized = false;
PerfDataPrologue* PerfMemory::_prologue = NULL;
void perfMemory_init() {
if (!UsePerfData) return;
PerfMemory::initialize();
}
void perfMemory_exit() {
if (!UsePerfData) return;
if (!PerfMemory::is_initialized()) return;
if (!StatSampler::is_active())
PerfDataManager::destroy();
PerfMemory::destroy();
}
void PerfMemory::initialize() {
if (_prologue != NULL)
return;
size_t capacity = align_size_up(PerfDataMemorySize,
os::vm_allocation_granularity());
if (PerfTraceMemOps) {
tty->print("PerfDataMemorySize = " SIZE_FORMAT ","
" os::vm_allocation_granularity = " SIZE_FORMAT ","
" adjusted size = " SIZE_FORMAT "\n",
PerfDataMemorySize,
os::vm_allocation_granularity(),
capacity);
}
create_memory_region(capacity);
if (_start == NULL) {
if (PrintMiscellaneous && Verbose) {
warning("Could not create PerfData Memory region, reverting to malloc");
}
_prologue = NEW_C_HEAP_OBJ(PerfDataPrologue, mtInternal);
}
else {
if (PerfTraceMemOps) {
tty->print("PerfMemory created: address = " INTPTR_FORMAT ","
" size = " SIZE_FORMAT "\n",
(void*)_start,
_capacity);
}
_prologue = (PerfDataPrologue *)_start;
_end = _start + _capacity;
_top = _start + sizeof(PerfDataPrologue);
}
assert(_prologue != NULL, "prologue pointer must be initialized");
#ifdef VM_LITTLE_ENDIAN
_prologue->magic = (jint)0xc0c0feca;
_prologue->byte_order = PERFDATA_LITTLE_ENDIAN;
#else
_prologue->magic = (jint)0xcafec0c0;
_prologue->byte_order = PERFDATA_BIG_ENDIAN;
#endif
_prologue->major_version = PERFDATA_MAJOR_VERSION;
_prologue->minor_version = PERFDATA_MINOR_VERSION;
_prologue->accessible = 0;
_prologue->entry_offset = sizeof(PerfDataPrologue);
_prologue->num_entries = 0;
_prologue->used = 0;
_prologue->overflow = 0;
_prologue->mod_time_stamp = 0;
OrderAccess::release_store(&_initialized, 1);
}
void PerfMemory::destroy() {
if (_prologue == NULL) return;
if (_start != NULL && _prologue->overflow != 0) {
if (PrintMiscellaneous && Verbose) {
warning("PerfMemory Overflow Occurred.\n"
"\tCapacity = " SIZE_FORMAT " bytes"
" Used = " SIZE_FORMAT " bytes"
" Overflow = " INT32_FORMAT " bytes"
"\n\tUse -XX:PerfDataMemorySize=<size> to specify larger size.",
PerfMemory::capacity(),
PerfMemory::used(),
_prologue->overflow);
}
}
if (_start != NULL) {
delete_memory_region();
}
_start = NULL;
_end = NULL;
_top = NULL;
_prologue = NULL;
_capacity = 0;
}
char* PerfMemory::alloc(size_t size) {
if (!UsePerfData) return NULL;
MutexLocker ml(PerfDataMemAlloc_lock);
assert(_prologue != NULL, "called before initialization");
if ((_top + size) >= _end) {
_prologue->overflow += (jint)size;
return NULL;
}
char* result = _top;
_top += size;
assert(contains(result), "PerfData memory pointer out of range");
_prologue->used = (jint)used();
_prologue->num_entries = _prologue->num_entries + 1;
return result;
}
void PerfMemory::mark_updated() {
if (!UsePerfData) return;
_prologue->mod_time_stamp = os::elapsed_counter();
}
char* PerfMemory::get_perfdata_file_path() {
char* dest_file = NULL;
if (PerfDataSaveFile != NULL) {
dest_file = NEW_C_HEAP_ARRAY(char, JVM_MAXPATHLEN, mtInternal);
if(!Arguments::copy_expand_pid(PerfDataSaveFile, strlen(PerfDataSaveFile),
dest_file, JVM_MAXPATHLEN)) {
FREE_C_HEAP_ARRAY(char, dest_file, mtInternal);
if (PrintMiscellaneous && Verbose) {
warning("Invalid performance data file path name specified, "\
"fall back to a default name");
}
} else {
return dest_file;
}
}
dest_file = NEW_C_HEAP_ARRAY(char, PERFDATA_FILENAME_LEN, mtInternal);
jio_snprintf(dest_file, PERFDATA_FILENAME_LEN,
"%s_%d", PERFDATA_NAME, os::current_process_id());
return dest_file;
}
C:\hotspot-69087d08d473\src\share\vm/runtime/perfMemory.hpp
#ifndef SHARE_VM_RUNTIME_PERFMEMORY_HPP
#define SHARE_VM_RUNTIME_PERFMEMORY_HPP
#include "utilities/exceptions.hpp"
#define PERFDATA_MAJOR_VERSION 2
#define PERFDATA_MINOR_VERSION 0
#define PERFDATA_BIG_ENDIAN 0
#define PERFDATA_LITTLE_ENDIAN 1
typedef struct {
jint magic; // magic number - 0xcafec0c0
jbyte byte_order; // byte order of the buffer
jbyte major_version; // major and minor version numbers
jbyte minor_version;
jbyte accessible; // ready to access
jint used; // number of PerfData memory bytes used
jint overflow; // number of bytes of overflow
jlong mod_time_stamp; // time stamp of last structural modification
jint entry_offset; // offset of the first PerfDataEntry
jint num_entries; // number of allocated PerfData entries
} PerfDataPrologue;
typedef struct {
jint entry_length; // entry length in bytes
jint name_offset; // offset of the data item name
jint vector_length; // length of the vector. If 0, then scalar
jbyte data_type; // type of the data item -
jbyte flags; // flags indicating misc attributes
jbyte data_units; // unit of measure for the data type
jbyte data_variability; // variability classification of data type
jint data_offset; // offset of the data item
body of PerfData memory entry is variable length
jbyte[name_length] data_name; // name of the data item
jbyte[pad_length] data_pad; // alignment of data item
j<data_type>[data_length] data_item; // array of appropriate types.
} PerfDataEntry;
extern const char PERFDATA_NAME[];
static const size_t UINT_CHARS = 10;
class PerfMemory : AllStatic {
friend class VMStructs;
private:
static char* _start;
static char* _end;
static char* _top;
static size_t _capacity;
static PerfDataPrologue* _prologue;
static jint _initialized;
static void create_memory_region(size_t sizep);
static void delete_memory_region();
public:
enum PerfMemoryMode {
PERF_MODE_RO = 0,
PERF_MODE_RW = 1
};
static char* alloc(size_t size);
static char* start() { return _start; }
static char* end() { return _end; }
static size_t used() { return (size_t) (_top - _start); }
static size_t capacity() { return _capacity; }
static bool is_initialized() { return _initialized != 0; }
static bool contains(char* addr) {
return ((_start != NULL) && (addr >= _start) && (addr < _end));
}
static void mark_updated();
static void attach(const char* user, int vmid, PerfMemoryMode mode,
char** addrp, size_t* size, TRAPS);
static void detach(char* addr, size_t bytes, TRAPS);
static void initialize();
static void destroy();
static void set_accessible(bool value) {
if (UsePerfData) {
_prologue->accessible = value;
}
}
static char* backing_store_filename();
static char* get_perfdata_file_path();
};
void perfMemory_init();
void perfMemory_exit();
#endif // SHARE_VM_RUNTIME_PERFMEMORY_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/prefetch.hpp
#ifndef SHARE_VM_RUNTIME_PREFETCH_HPP
#define SHARE_VM_RUNTIME_PREFETCH_HPP
#include "memory/allocation.hpp"
class Prefetch : AllStatic {
public:
enum style {
do_none, // Do no prefetching
do_read, // Do read prefetching
do_write // Do write prefetching
};
static void read(void* loc, intx interval);
static void write(void* loc, intx interval);
};
#endif // SHARE_VM_RUNTIME_PREFETCH_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/prefetch.inline.hpp
#ifndef SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP
#define SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP
#include "runtime/prefetch.hpp"
#ifdef TARGET_OS_ARCH_linux_x86
# include "prefetch_linux_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_sparc
# include "prefetch_linux_sparc.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_zero
# include "prefetch_linux_zero.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_arm
# include "prefetch_linux_arm.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_aarch64
# include "prefetch_linux_aarch64.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_ppc
# include "prefetch_linux_ppc.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_x86
# include "prefetch_solaris_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_sparc
# include "prefetch_solaris_sparc.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_windows_x86
# include "prefetch_windows_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_aix_ppc
# include "prefetch_aix_ppc.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_x86
# include "prefetch_bsd_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_zero
# include "prefetch_bsd_zero.inline.hpp"
#endif
#endif // SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/reflection.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/verifier.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp"
#include "runtime/reflectionUtils.hpp"
#include "runtime/signature.hpp"
#include "runtime/vframe.hpp"
static void trace_class_resolution(Klass* to_class) {
ResourceMark rm;
int line_number = -1;
const char * source_file = NULL;
Klass* caller = NULL;
JavaThread* jthread = JavaThread::current();
if (jthread->has_last_Java_frame()) {
vframeStream vfst(jthread);
while (!vfst.at_end() &&
vfst.method()->method_holder()->name() == vmSymbols::java_lang_Class()) {
vfst.next();
}
if (!vfst.at_end()) {
caller = vfst.method()->method_holder();
line_number = vfst.method()->line_number_from_bci(vfst.bci());
Symbol* s = vfst.method()->method_holder()->source_file_name();
if (s != NULL) {
source_file = s->as_C_string();
}
}
}
if (caller != NULL) {
const char * from = caller->external_name();
const char * to = to_class->external_name();
if (source_file != NULL) {
tty->print("RESOLVE %s %s %s:%d (reflection)\n", from, to, source_file, line_number);
} else {
tty->print("RESOLVE %s %s (reflection)\n", from, to);
}
}
}
oop Reflection::box(jvalue* value, BasicType type, TRAPS) {
if (type == T_VOID) {
return NULL;
}
if (type == T_OBJECT || type == T_ARRAY) {
return (oop) value->l;
}
oop result = java_lang_boxing_object::create(type, value, CHECK_NULL);
if (result == NULL) {
THROW_(vmSymbols::java_lang_IllegalArgumentException(), result);
}
return result;
}
BasicType Reflection::unbox_for_primitive(oop box, jvalue* value, TRAPS) {
if (box == NULL) {
THROW_(vmSymbols::java_lang_IllegalArgumentException(), T_ILLEGAL);
}
return java_lang_boxing_object::get_value(box, value);
}
BasicType Reflection::unbox_for_regular_object(oop box, jvalue* value) {
value->l = (jobject) box;
return T_OBJECT;
}
void Reflection::widen(jvalue* value, BasicType current_type, BasicType wide_type, TRAPS) {
assert(wide_type != current_type, "widen should not be called with identical types");
switch (wide_type) {
case T_BOOLEAN:
case T_BYTE:
case T_CHAR:
break; // fail
case T_SHORT:
switch (current_type) {
case T_BYTE:
value->s = (jshort) value->b;
return;
}
break; // fail
case T_INT:
switch (current_type) {
case T_BYTE:
value->i = (jint) value->b;
return;
case T_CHAR:
value->i = (jint) value->c;
return;
case T_SHORT:
value->i = (jint) value->s;
return;
}
break; // fail
case T_LONG:
switch (current_type) {
case T_BYTE:
value->j = (jlong) value->b;
return;
case T_CHAR:
value->j = (jlong) value->c;
return;
case T_SHORT:
value->j = (jlong) value->s;
return;
case T_INT:
value->j = (jlong) value->i;
return;
}
break; // fail
case T_FLOAT:
switch (current_type) {
case T_BYTE:
value->f = (jfloat) value->b;
return;
case T_CHAR:
value->f = (jfloat) value->c;
return;
case T_SHORT:
value->f = (jfloat) value->s;
return;
case T_INT:
value->f = (jfloat) value->i;
return;
case T_LONG:
value->f = (jfloat) value->j;
return;
}
break; // fail
case T_DOUBLE:
switch (current_type) {
case T_BYTE:
value->d = (jdouble) value->b;
return;
case T_CHAR:
value->d = (jdouble) value->c;
return;
case T_SHORT:
value->d = (jdouble) value->s;
return;
case T_INT:
value->d = (jdouble) value->i;
return;
case T_FLOAT:
value->d = (jdouble) value->f;
return;
case T_LONG:
value->d = (jdouble) value->j;
return;
}
break; // fail
default:
break; // fail
}
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
}
BasicType Reflection::array_get(jvalue* value, arrayOop a, int index, TRAPS) {
if (!a->is_within_bounds(index)) {
THROW_(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), T_ILLEGAL);
}
if (a->is_objArray()) {
value->l = (jobject) objArrayOop(a)->obj_at(index);
return T_OBJECT;
} else {
assert(a->is_typeArray(), "just checking");
BasicType type = TypeArrayKlass::cast(a->klass())->element_type();
switch (type) {
case T_BOOLEAN:
value->z = typeArrayOop(a)->bool_at(index);
break;
case T_CHAR:
value->c = typeArrayOop(a)->char_at(index);
break;
case T_FLOAT:
value->f = typeArrayOop(a)->float_at(index);
break;
case T_DOUBLE:
value->d = typeArrayOop(a)->double_at(index);
break;
case T_BYTE:
value->b = typeArrayOop(a)->byte_at(index);
break;
case T_SHORT:
value->s = typeArrayOop(a)->short_at(index);
break;
case T_INT:
value->i = typeArrayOop(a)->int_at(index);
break;
case T_LONG:
value->j = typeArrayOop(a)->long_at(index);
break;
default:
return T_ILLEGAL;
}
return type;
}
}
void Reflection::array_set(jvalue* value, arrayOop a, int index, BasicType value_type, TRAPS) {
if (!a->is_within_bounds(index)) {
THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
}
if (a->is_objArray()) {
if (value_type == T_OBJECT) {
oop obj = (oop) value->l;
if (obj != NULL) {
Klass* element_klass = ObjArrayKlass::cast(a->klass())->element_klass();
if (!obj->is_a(element_klass)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array element type mismatch");
}
}
objArrayOop(a)->obj_at_put(index, obj);
}
} else {
assert(a->is_typeArray(), "just checking");
BasicType array_type = TypeArrayKlass::cast(a->klass())->element_type();
if (array_type != value_type) {
widen(value, value_type, array_type, CHECK);
}
switch (array_type) {
case T_BOOLEAN:
typeArrayOop(a)->bool_at_put(index, value->z);
break;
case T_CHAR:
typeArrayOop(a)->char_at_put(index, value->c);
break;
case T_FLOAT:
typeArrayOop(a)->float_at_put(index, value->f);
break;
case T_DOUBLE:
typeArrayOop(a)->double_at_put(index, value->d);
break;
case T_BYTE:
typeArrayOop(a)->byte_at_put(index, value->b);
break;
case T_SHORT:
typeArrayOop(a)->short_at_put(index, value->s);
break;
case T_INT:
typeArrayOop(a)->int_at_put(index, value->i);
break;
case T_LONG:
typeArrayOop(a)->long_at_put(index, value->j);
break;
default:
THROW(vmSymbols::java_lang_IllegalArgumentException());
}
}
}
Klass* Reflection::basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) {
assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking");
BasicType type = java_lang_Class::primitive_type(basic_type_mirror);
if (type == T_VOID) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
} else {
return Universe::typeArrayKlassObj(type);
}
}
oop Reflection:: basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS) {
BasicType type = TypeArrayKlass::cast(basic_type_arrayklass)->element_type();
return Universe::java_mirror(type);
}
arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
if (element_mirror == NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
if (length < 0) {
THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
}
if (java_lang_Class::is_primitive(element_mirror)) {
Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
} else {
Klass* k = java_lang_Class::as_Klass(element_mirror);
if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
return oopFactory::new_objArray(k, length, THREAD);
}
}
arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop dim_array, TRAPS) {
assert(dim_array->is_typeArray(), "just checking");
assert(TypeArrayKlass::cast(dim_array->klass())->element_type() == T_INT, "just checking");
if (element_mirror == NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
int len = dim_array->length();
if (len <= 0 || len > MAX_DIM) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
jint dimensions[MAX_DIM]; // C array copy of intArrayOop
for (int i = 0; i < len; i++) {
int d = dim_array->int_at(i);
if (d < 0) {
THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
}
dimensions[i] = d;
}
Klass* klass;
int dim = len;
if (java_lang_Class::is_primitive(element_mirror)) {
klass = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
} else {
klass = java_lang_Class::as_Klass(element_mirror);
if (klass->oop_is_array()) {
int k_dim = ArrayKlass::cast(klass)->dimension();
if (k_dim + len > MAX_DIM) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
dim += k_dim;
}
}
klass = klass->array_klass(dim, CHECK_NULL);
oop obj = ArrayKlass::cast(klass)->multi_allocate(len, dimensions, CHECK_NULL);
assert(obj->is_array(), "just checking");
return arrayOop(obj);
}
oop Reflection::array_component_type(oop mirror, TRAPS) {
if (java_lang_Class::is_primitive(mirror)) {
return NULL;
}
Klass* klass = java_lang_Class::as_Klass(mirror);
if (!klass->oop_is_array()) {
return NULL;
}
oop result = ArrayKlass::cast(klass)->component_mirror();
#ifdef ASSERT
oop result2 = NULL;
if (ArrayKlass::cast(klass)->dimension() == 1) {
if (klass->oop_is_typeArray()) {
result2 = basic_type_arrayklass_to_mirror(klass, CHECK_NULL);
} else {
result2 = ObjArrayKlass::cast(klass)->element_klass()->java_mirror();
}
} else {
Klass* lower_dim = ArrayKlass::cast(klass)->lower_dimension();
assert(lower_dim->oop_is_array(), "just checking");
result2 = lower_dim->java_mirror();
}
assert(result == result2, "results must be consistent");
#endif //ASSERT
return result;
}
bool Reflection::reflect_check_access(Klass* field_class, AccessFlags acc, Klass* target_class, bool is_method_invoke, TRAPS) {
ResourceMark rm(THREAD);
assert(THREAD->is_Java_thread(), "sanity check");
Klass* client_class = ((JavaThread *)THREAD)->security_get_caller_class(is_method_invoke ? 0 : 1);
if (client_class != field_class) {
if (!verify_class_access(client_class, field_class, false)
|| !verify_field_access(client_class,
field_class,
field_class,
acc,
false)) {
THROW_(vmSymbols::java_lang_IllegalAccessException(), false);
}
}
if (acc.is_protected()) {
if (target_class != client_class) {
if (!is_same_class_package(client_class, field_class)) {
if (!target_class->is_subclass_of(client_class)) {
THROW_(vmSymbols::java_lang_IllegalAccessException(), false);
}
}
}
}
return true;
}
bool Reflection::verify_class_access(Klass* current_class, Klass* new_class, bool classloader_only) {
if ((current_class == NULL) ||
(current_class == new_class) ||
(new_class->is_public()) ||
is_same_class_package(current_class, new_class)) {
return true;
}
if ( JDK_Version::is_gte_jdk14x_version()
&& UseNewReflection
&& current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
return true;
}
return can_relax_access_check_for(current_class, new_class, classloader_only);
}
static bool under_host_klass(InstanceKlass* ik, Klass* host_klass) {
DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000);
for (;;) {
Klass* hc = (Klass*) ik->host_klass();
if (hc == NULL) return false;
if (hc == host_klass) return true;
ik = InstanceKlass::cast(hc);
assert(--inf_loop_check > 0, "no host_klass loop");
}
}
bool Reflection::can_relax_access_check_for(
Klass* accessor, Klass* accessee, bool classloader_only) {
InstanceKlass* accessor_ik = InstanceKlass::cast(accessor);
InstanceKlass* accessee_ik = InstanceKlass::cast(accessee);
if (under_host_klass(accessor_ik, accessee) ||
under_host_klass(accessee_ik, accessor))
return true;
if ((RelaxAccessControlCheck &&
accessor_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION &&
accessee_ik->major_version() < Verifier::NO_RELAX_ACCESS_CTRL_CHECK_VERSION) ||
(accessor_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION &&
accessee_ik->major_version() < Verifier::STRICTER_ACCESS_CTRL_CHECK_VERSION)) {
return classloader_only &&
Verifier::relax_access_for(accessor_ik->class_loader()) &&
accessor_ik->protection_domain() == accessee_ik->protection_domain() &&
accessor_ik->class_loader() == accessee_ik->class_loader();
} else {
return false;
}
}
bool Reflection::verify_field_access(Klass* current_class,
Klass* resolved_class,
Klass* field_class,
AccessFlags access,
bool classloader_only,
bool protected_restriction) {
if ((current_class == NULL) ||
(current_class == field_class) ||
access.is_public()) {
return true;
}
Klass* host_class = current_class;
while (host_class->oop_is_instance() &&
InstanceKlass::cast(host_class)->is_anonymous()) {
Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass();
if (next_host_class == NULL) break;
host_class = next_host_class;
}
if (host_class == field_class) {
return true;
}
if (access.is_protected()) {
if (!protected_restriction) {
if (!host_class->is_interface() && host_class->is_subclass_of(field_class)) {
if (access.is_static() || // static fields are ok, see 6622385
current_class == resolved_class ||
field_class == resolved_class ||
host_class->is_subclass_of(resolved_class) ||
resolved_class->is_subclass_of(host_class)) {
return true;
}
}
}
}
if (!access.is_private() && is_same_class_package(current_class, field_class)) {
return true;
}
if ( JDK_Version::is_gte_jdk14x_version()
&& UseNewReflection
&& current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
return true;
}
return can_relax_access_check_for(
current_class, field_class, classloader_only);
}
bool Reflection::is_same_class_package(Klass* class1, Klass* class2) {
return InstanceKlass::cast(class1)->is_same_class_package(class2);
}
bool Reflection::is_same_package_member(Klass* class1, Klass* class2, TRAPS) {
return InstanceKlass::cast(class1)->is_same_package_member(class2, THREAD);
}
void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
bool inner_is_member, TRAPS) {
InnerClassesIterator iter(outer);
constantPoolHandle cp (THREAD, outer->constants());
for (; !iter.done(); iter.next()) {
int ioff = iter.inner_class_info_index();
int ooff = iter.outer_class_info_index();
if (inner_is_member && ioff != 0 && ooff != 0) {
Klass* o = cp->klass_at(ooff, CHECK);
if (o == outer()) {
Klass* i = cp->klass_at(ioff, CHECK);
if (i == inner()) {
return;
}
}
}
if (!inner_is_member && ioff != 0 && ooff == 0 &&
cp->klass_name_at_matches(inner, ioff)) {
Klass* i = cp->klass_at(ioff, CHECK);
if (i == inner()) {
return;
}
}
}
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"%s and %s disagree on InnerClasses attribute",
outer->external_name(),
inner->external_name()
);
}
oop get_mirror_from_signature(methodHandle method, SignatureStream* ss, TRAPS) {
switch (ss->type()) {
default:
assert(ss->type() != T_VOID || ss->at_return_type(), "T_VOID should only appear as return type");
return java_lang_Class::primitive_mirror(ss->type());
case T_OBJECT:
case T_ARRAY:
Symbol* name = ss->as_symbol(CHECK_NULL);
oop loader = method->method_holder()->class_loader();
oop protection_domain = method->method_holder()->protection_domain();
Klass* k = SystemDictionary::resolve_or_fail(
name,
Handle(THREAD, loader),
Handle(THREAD, protection_domain),
true, CHECK_NULL);
if (TraceClassResolution) {
trace_class_resolution(k);
}
return k->java_mirror();
};
}
objArrayHandle Reflection::get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS) {
objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle()));
objArrayHandle mirrors (THREAD, m);
int index = 0;
ResourceMark rm(THREAD);
Symbol* signature = method->signature();
SignatureStream ss(signature);
while (!ss.at_return_type()) {
oop mirror = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle()));
mirrors->obj_at_put(index++, mirror);
ss.next();
}
assert(index == parameter_count, "invalid parameter count");
if (return_type != NULL) {
assert(ss.at_return_type(), "return type should be present");
}
return mirrors;
}
objArrayHandle Reflection::get_exception_types(methodHandle method, TRAPS) {
return method->resolved_checked_exceptions(THREAD);
}
Handle Reflection::new_type(Symbol* signature, KlassHandle k, TRAPS) {
BasicType type = vmSymbols::signature_type(signature);
if (type != T_OBJECT) {
return Handle(THREAD, Universe::java_mirror(type));
}
oop loader = InstanceKlass::cast(k())->class_loader();
oop protection_domain = k()->protection_domain();
Klass* result = SystemDictionary::resolve_or_fail(signature,
Handle(THREAD, loader),
Handle(THREAD, protection_domain),
true, CHECK_(Handle()));
if (TraceClassResolution) {
trace_class_resolution(result);
}
oop nt = result->java_mirror();
return Handle(THREAD, nt);
}
oop Reflection::new_method(methodHandle method, bool intern_name, bool for_constant_pool_access, TRAPS) {
assert(!method()->is_initializer() ||
(for_constant_pool_access && method()->is_static()) ||
(method()->name() == vmSymbols::class_initializer_name()
&& method()->method_holder()->is_interface() && JDK_Version::is_jdk12x_version()), "should call new_constructor instead");
instanceKlassHandle holder (THREAD, method->method_holder());
int slot = method->method_idnum();
Symbol* signature = method->signature();
int parameter_count = ArgumentCount(signature).size();
oop return_type_oop = NULL;
objArrayHandle parameter_types = get_parameter_types(method, parameter_count, &return_type_oop, CHECK_NULL);
if (parameter_types.is_null() || return_type_oop == NULL) return NULL;
Handle return_type(THREAD, return_type_oop);
objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
if (exception_types.is_null()) return NULL;
Symbol* method_name = method->name();
Handle name;
if (intern_name) {
oop name_oop = StringTable::intern(method_name, CHECK_NULL);
name = Handle(THREAD, name_oop);
} else {
name = java_lang_String::create_from_symbol(method_name, CHECK_NULL);
}
if (name == NULL) return NULL;
int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
Handle mh = java_lang_reflect_Method::create(CHECK_NULL);
java_lang_reflect_Method::set_clazz(mh(), holder->java_mirror());
java_lang_reflect_Method::set_slot(mh(), slot);
java_lang_reflect_Method::set_name(mh(), name());
java_lang_reflect_Method::set_return_type(mh(), return_type());
java_lang_reflect_Method::set_parameter_types(mh(), parameter_types());
java_lang_reflect_Method::set_exception_types(mh(), exception_types());
java_lang_reflect_Method::set_modifiers(mh(), modifiers);
java_lang_reflect_Method::set_override(mh(), false);
if (java_lang_reflect_Method::has_signature_field() &&
method->generic_signature() != NULL) {
Symbol* gs = method->generic_signature();
Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
java_lang_reflect_Method::set_signature(mh(), sig());
}
if (java_lang_reflect_Method::has_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->annotations(), CHECK_NULL);
java_lang_reflect_Method::set_annotations(mh(), an_oop);
}
if (java_lang_reflect_Method::has_parameter_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->parameter_annotations(), CHECK_NULL);
java_lang_reflect_Method::set_parameter_annotations(mh(), an_oop);
}
if (java_lang_reflect_Method::has_annotation_default_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->annotation_default(), CHECK_NULL);
java_lang_reflect_Method::set_annotation_default(mh(), an_oop);
}
if (java_lang_reflect_Method::has_type_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->type_annotations(), CHECK_NULL);
java_lang_reflect_Method::set_type_annotations(mh(), an_oop);
}
return mh();
}
oop Reflection::new_constructor(methodHandle method, TRAPS) {
assert(method()->is_initializer(), "should call new_method instead");
instanceKlassHandle holder (THREAD, method->method_holder());
int slot = method->method_idnum();
Symbol* signature = method->signature();
int parameter_count = ArgumentCount(signature).size();
objArrayHandle parameter_types = get_parameter_types(method, parameter_count, NULL, CHECK_NULL);
if (parameter_types.is_null()) return NULL;
objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
if (exception_types.is_null()) return NULL;
int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
Handle ch = java_lang_reflect_Constructor::create(CHECK_NULL);
java_lang_reflect_Constructor::set_clazz(ch(), holder->java_mirror());
java_lang_reflect_Constructor::set_slot(ch(), slot);
java_lang_reflect_Constructor::set_parameter_types(ch(), parameter_types());
java_lang_reflect_Constructor::set_exception_types(ch(), exception_types());
java_lang_reflect_Constructor::set_modifiers(ch(), modifiers);
java_lang_reflect_Constructor::set_override(ch(), false);
if (java_lang_reflect_Constructor::has_signature_field() &&
method->generic_signature() != NULL) {
Symbol* gs = method->generic_signature();
Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
java_lang_reflect_Constructor::set_signature(ch(), sig());
}
if (java_lang_reflect_Constructor::has_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->annotations(), CHECK_NULL);
java_lang_reflect_Constructor::set_annotations(ch(), an_oop);
}
if (java_lang_reflect_Constructor::has_parameter_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->parameter_annotations(), CHECK_NULL);
java_lang_reflect_Constructor::set_parameter_annotations(ch(), an_oop);
}
if (java_lang_reflect_Constructor::has_type_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(method->type_annotations(), CHECK_NULL);
java_lang_reflect_Constructor::set_type_annotations(ch(), an_oop);
}
return ch();
}
oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) {
Symbol* field_name = fd->name();
Handle name;
if (intern_name) {
oop name_oop = StringTable::intern(field_name, CHECK_NULL);
name = Handle(THREAD, name_oop);
} else {
name = java_lang_String::create_from_symbol(field_name, CHECK_NULL);
}
Symbol* signature = fd->signature();
instanceKlassHandle holder (THREAD, fd->field_holder());
Handle type = new_type(signature, holder, CHECK_NULL);
Handle rh = java_lang_reflect_Field::create(CHECK_NULL);
java_lang_reflect_Field::set_clazz(rh(), fd->field_holder()->java_mirror());
java_lang_reflect_Field::set_slot(rh(), fd->index());
java_lang_reflect_Field::set_name(rh(), name());
java_lang_reflect_Field::set_type(rh(), type());
java_lang_reflect_Field::set_modifiers(rh(), fd->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS);
java_lang_reflect_Field::set_override(rh(), false);
if (java_lang_reflect_Field::has_signature_field() &&
fd->has_generic_signature()) {
Symbol* gs = fd->generic_signature();
Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
java_lang_reflect_Field::set_signature(rh(), sig());
}
if (java_lang_reflect_Field::has_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(fd->annotations(), CHECK_NULL);
java_lang_reflect_Field::set_annotations(rh(), an_oop);
}
if (java_lang_reflect_Field::has_type_annotations_field()) {
typeArrayOop an_oop = Annotations::make_java_array(fd->type_annotations(), CHECK_NULL);
java_lang_reflect_Field::set_type_annotations(rh(), an_oop);
}
return rh();
}
oop Reflection::new_parameter(Handle method, int index, Symbol* sym,
int flags, TRAPS) {
Handle name;
if(NULL != sym) {
name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
} else {
name = java_lang_String::create_from_str("", CHECK_NULL);
}
Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL);
java_lang_reflect_Parameter::set_name(rh(), name());
java_lang_reflect_Parameter::set_modifiers(rh(), flags);
java_lang_reflect_Parameter::set_executable(rh(), method());
java_lang_reflect_Parameter::set_index(rh(), index);
return rh();
}
methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method,
KlassHandle recv_klass, Handle receiver, TRAPS) {
assert(!method.is_null() , "method should not be null");
CallInfo info;
Symbol* signature = method->signature();
Symbol* name = method->name();
LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass,
name, signature,
KlassHandle(), false, true,
CHECK_(methodHandle()));
return info.selected_method();
}
oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method,
Handle receiver, bool override, objArrayHandle ptypes,
BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) {
ResourceMark rm(THREAD);
methodHandle method; // actual method to invoke
KlassHandle target_klass; // target klass, receiver's klass for non-static
klass->initialize(CHECK_NULL);
bool is_static = reflected_method->is_static();
if (is_static) {
method = reflected_method;
target_klass = klass;
} else {
if (receiver.is_null()) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
if (!receiver->is_a(klass())) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class");
}
target_klass = KlassHandle(THREAD, receiver->klass());
if (reflected_method->is_private() || reflected_method->name() == vmSymbols::object_initializer_name()) {
method = reflected_method;
} else {
if (reflected_method->method_holder()->is_interface()) {
if (ReflectionWrapResolutionErrors) {
method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD);
if (HAS_PENDING_EXCEPTION) {
oop resolution_exception = PENDING_EXCEPTION;
CLEAR_PENDING_EXCEPTION;
if (THREAD->is_Java_thread()) {
JvmtiExport::clear_detected_exception((JavaThread*) THREAD);
}
JavaCallArguments args(Handle(THREAD, resolution_exception));
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
vmSymbols::throwable_void_signature(),
&args);
}
} else {
method = resolve_interface_call(klass, reflected_method, target_klass, receiver, CHECK_(NULL));
}
} else {
assert(!reflected_method->has_itable_index(), "");
int index = reflected_method->vtable_index();
method = reflected_method;
if (index != Method::nonvirtual_vtable_index) {
InstanceKlass* inst = (InstanceKlass*)target_klass();
method = methodHandle(THREAD, inst->method_at_vtable(index));
}
if (!method.is_null()) {
if (method->is_abstract()) {
if (ReflectionWrapResolutionErrors) {
ResourceMark rm(THREAD);
Handle h_origexception = Exceptions::new_exception(THREAD,
vmSymbols::java_lang_AbstractMethodError(),
Method::name_and_sig_as_C_string(target_klass(),
method->name(),
method->signature()));
JavaCallArguments args(h_origexception);
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
vmSymbols::throwable_void_signature(),
&args);
} else {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_AbstractMethodError(),
Method::name_and_sig_as_C_string(target_klass(),
method->name(),
method->signature()));
}
}
}
}
}
}
if (method.is_null()) {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
Method::name_and_sig_as_C_string(klass(),
reflected_method->name(),
reflected_method->signature()));
}
if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) {
if (!override) {
if (!(klass->is_public() && reflected_method->is_public())) {
bool access = Reflection::reflect_check_access(klass(), reflected_method->access_flags(), target_klass(), is_method_invoke, CHECK_NULL);
if (!access) {
return NULL; // exception
}
}
}
} // !(Universe::is_gte_jdk14x_version() && UseNewReflection)
assert(ptypes->is_objArray(), "just checking");
int args_len = args.is_null() ? 0 : args->length();
if (ptypes->length() != args_len) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "wrong number of arguments");
}
JavaCallArguments java_args(method->size_of_parameters());
if (!is_static) {
java_args.push_oop(receiver);
}
for (int i = 0; i < args_len; i++) {
oop type_mirror = ptypes->obj_at(i);
oop arg = args->obj_at(i);
if (java_lang_Class::is_primitive(type_mirror)) {
jvalue value;
BasicType ptype = basic_type_mirror_to_basic_type(type_mirror, CHECK_NULL);
BasicType atype = unbox_for_primitive(arg, &value, CHECK_NULL);
if (ptype != atype) {
widen(&value, atype, ptype, CHECK_NULL);
}
switch (ptype) {
case T_BOOLEAN: java_args.push_int(value.z); break;
case T_CHAR: java_args.push_int(value.c); break;
case T_BYTE: java_args.push_int(value.b); break;
case T_SHORT: java_args.push_int(value.s); break;
case T_INT: java_args.push_int(value.i); break;
case T_LONG: java_args.push_long(value.j); break;
case T_FLOAT: java_args.push_float(value.f); break;
case T_DOUBLE: java_args.push_double(value.d); break;
default:
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
}
} else {
if (arg != NULL) {
Klass* k = java_lang_Class::as_Klass(type_mirror);
if (!arg->is_a(k)) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
}
}
Handle arg_handle(THREAD, arg); // Create handle for argument
java_args.push_oop(arg_handle); // Push handle
}
}
assert(java_args.size_of_parameters() == method->size_of_parameters(), "just checking");
JavaValue result(rtype);
JavaCalls::call(&result, method, &java_args, THREAD);
if (HAS_PENDING_EXCEPTION) {
oop target_exception = PENDING_EXCEPTION;
CLEAR_PENDING_EXCEPTION;
if (THREAD->is_Java_thread()) {
JvmtiExport::clear_detected_exception((JavaThread*) THREAD);
}
JavaCallArguments args(Handle(THREAD, target_exception));
THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
vmSymbols::throwable_void_signature(),
&args);
} else {
if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT)
narrow((jvalue*) result.get_value_addr(), rtype, CHECK_NULL);
return box((jvalue*) result.get_value_addr(), rtype, THREAD);
}
}
void Reflection::narrow(jvalue* value, BasicType narrow_type, TRAPS) {
switch (narrow_type) {
case T_BOOLEAN:
value->z = (jboolean) (value->i & 1);
return;
case T_BYTE:
value->b = (jbyte) value->i;
return;
case T_CHAR:
value->c = (jchar) value->i;
return;
case T_SHORT:
value->s = (jshort) value->i;
return;
default:
break; // fail
}
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch");
}
BasicType Reflection::basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) {
assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking");
return java_lang_Class::primitive_type(basic_type_mirror);
}
oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS) {
oop mirror = java_lang_reflect_Method::clazz(method_mirror);
int slot = java_lang_reflect_Method::slot(method_mirror);
bool override = java_lang_reflect_Method::override(method_mirror) != 0;
objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Method::parameter_types(method_mirror)));
oop return_type_mirror = java_lang_reflect_Method::return_type(method_mirror);
BasicType rtype;
if (java_lang_Class::is_primitive(return_type_mirror)) {
rtype = basic_type_mirror_to_basic_type(return_type_mirror, CHECK_NULL);
} else {
rtype = T_OBJECT;
}
instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(mirror));
Method* m = klass->method_with_idnum(slot);
if (m == NULL) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke");
}
methodHandle method(THREAD, m);
return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD);
}
oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, TRAPS) {
oop mirror = java_lang_reflect_Constructor::clazz(constructor_mirror);
int slot = java_lang_reflect_Constructor::slot(constructor_mirror);
bool override = java_lang_reflect_Constructor::override(constructor_mirror) != 0;
objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror)));
instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(mirror));
Method* m = klass->method_with_idnum(slot);
if (m == NULL) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke");
}
methodHandle method(THREAD, m);
assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor");
klass->initialize(CHECK_NULL);
klass->check_valid_for_instantiation(false, CHECK_NULL);
Handle receiver = klass->allocate_instance_handle(CHECK_NULL);
invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL);
return receiver();
}
C:\hotspot-69087d08d473\src\share\vm/runtime/reflection.hpp
#ifndef SHARE_VM_RUNTIME_REFLECTION_HPP
#define SHARE_VM_RUNTIME_REFLECTION_HPP
#include "oops/oop.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/growableArray.hpp"
class FieldStream;
class Reflection: public AllStatic {
private:
static bool reflect_check_access(Klass* field_class, AccessFlags acc, Klass* target_class, bool is_method_invoke, TRAPS);
static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS);
static oop basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS);
static objArrayHandle get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS);
static objArrayHandle get_exception_types(methodHandle method, TRAPS);
static Handle new_type(Symbol* signature, KlassHandle k, TRAPS);
public:
enum SomeConstants {
PUBLIC = 0,
DECLARED = 1,
MEMBER_PUBLIC = 0,
MEMBER_DECLARED = 1,
MAX_DIM = 255
};
static oop box(jvalue* v, BasicType type, TRAPS);
static BasicType unbox_for_primitive(oop boxed_value, jvalue* value, TRAPS);
static BasicType unbox_for_regular_object(oop boxed_value, jvalue* value);
static void widen(jvalue* value, BasicType current_type, BasicType wide_type, TRAPS);
static BasicType array_get(jvalue* value, arrayOop a, int index, TRAPS);
static void array_set(jvalue* value, arrayOop a, int index, BasicType value_type, TRAPS);
static oop array_component_type(oop mirror, TRAPS);
static arrayOop reflect_new_array(oop element_mirror, jint length, TRAPS);
static arrayOop reflect_new_multi_array(oop element_mirror, typeArrayOop dimensions, TRAPS);
static bool verify_class_access(Klass* current_class, Klass* new_class, bool classloader_only);
static bool verify_field_access(Klass* current_class,
Klass* resolved_class,
Klass* field_class,
AccessFlags access,
bool classloader_only,
bool protected_restriction = false);
static bool is_same_class_package(Klass* class1, Klass* class2);
static bool is_same_package_member(Klass* class1, Klass* class2, TRAPS);
static bool can_relax_access_check_for(
Klass* accessor, Klass* accesee, bool classloader_only);
static void check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
bool inner_is_member, TRAPS);
static oop new_method(methodHandle method, bool intern_name, bool for_constant_pool_access, TRAPS);
static oop new_constructor(methodHandle method, TRAPS);
static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS);
static oop new_parameter(Handle method, int index, Symbol* sym,
int flags, TRAPS);
private:
static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS);
static oop invoke(instanceKlassHandle klass, methodHandle method, Handle receiver, bool override, objArrayHandle ptypes, BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS);
static void narrow(jvalue* value, BasicType narrow_type, TRAPS);
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS);
public:
static oop invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS);
static oop invoke_constructor(oop method_mirror, objArrayHandle args, TRAPS);
};
#endif // SHARE_VM_RUNTIME_REFLECTION_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/reflectionUtils.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "memory/universe.inline.hpp"
#include "runtime/reflectionUtils.hpp"
KlassStream::KlassStream(instanceKlassHandle klass, bool local_only,
bool classes_only, bool walk_defaults) {
_klass = _base_klass = klass;
_base_class_search_defaults = false;
_defaults_checked = false;
if (classes_only) {
_interfaces = Universe::the_empty_klass_array();
} else {
_interfaces = klass->transitive_interfaces();
}
_interface_index = _interfaces->length();
_local_only = local_only;
_classes_only = classes_only;
_walk_defaults = walk_defaults;
}
bool KlassStream::eos() {
if (index() >= 0) return false;
if (_local_only) return true;
if (!_klass->is_interface() && _klass->super() != NULL) {
_klass = _klass->super();
} else if (_walk_defaults && (_defaults_checked == false) && (_base_klass->default_methods() != NULL)) {
_base_class_search_defaults = true;
_klass = _base_klass;
_defaults_checked = true;
} else {
if (_interface_index > 0) {
_klass = _interfaces->at(--_interface_index);
} else {
return true;
}
}
_index = length();
next();
return eos();
}
GrowableArray<FilteredField*> *FilteredFieldsMap::_filtered_fields =
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<FilteredField*>(3,true);
void FilteredFieldsMap::initialize() {
int offset;
offset = java_lang_Throwable::get_backtrace_offset();
_filtered_fields->append(new FilteredField(SystemDictionary::Throwable_klass(), offset));
if (JDK_Version::is_gte_jdk16x_version()) {
offset = sun_reflect_ConstantPool::oop_offset();
_filtered_fields->append(new FilteredField(SystemDictionary::reflect_ConstantPool_klass(), offset));
offset = sun_reflect_UnsafeStaticFieldAccessorImpl::base_offset();
_filtered_fields->append(new FilteredField(SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(), offset));
}
}
int FilteredFieldStream::field_count() {
int numflds = 0;
for (;!eos(); next()) {
numflds++;
}
return numflds;
}
C:\hotspot-69087d08d473\src\share\vm/runtime/reflectionUtils.hpp
#ifndef SHARE_VM_RUNTIME_REFLECTIONUTILS_HPP
#define SHARE_VM_RUNTIME_REFLECTIONUTILS_HPP
#include "memory/allocation.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/reflection.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/globalDefinitions.hpp"
class KlassStream VALUE_OBJ_CLASS_SPEC {
protected:
instanceKlassHandle _klass; // current klass/interface iterated over
instanceKlassHandle _base_klass; // initial klass/interface to iterate over
Array<Klass*>* _interfaces; // transitive interfaces for initial class
int _interface_index; // current interface being processed
bool _local_only; // process initial class/interface only
bool _classes_only; // process classes only (no interfaces)
bool _walk_defaults; // process default methods
bool _base_class_search_defaults; // time to process default methods
bool _defaults_checked; // already checked for default methods
int _index;
virtual int length() = 0;
public:
KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only, bool walk_defaults);
bool eos();
virtual void next() = 0;
instanceKlassHandle klass() const { return _klass; }
int index() const { return _index; }
bool base_class_search_defaults() const { return _base_class_search_defaults; }
void base_class_search_defaults(bool b) { _base_class_search_defaults = b; }
};
class MethodStream : public KlassStream {
private:
int length() { return methods()->length(); }
Array<Method*>* methods() {
if (base_class_search_defaults()) {
base_class_search_defaults(false);
return _klass->default_methods();
} else {
return _klass->methods();
}
}
public:
MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: KlassStream(klass, local_only, classes_only, true) {
_index = length();
next();
}
void next() { _index--; }
Method* method() { return methods()->at(index()); }
};
class FieldStream : public KlassStream {
private:
int length() { return _klass->java_fields_count(); }
fieldDescriptor _fd_buf;
public:
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: KlassStream(klass, local_only, classes_only, false) {
_index = length();
next();
}
void next() { _index -= 1; }
AccessFlags access_flags() const {
AccessFlags flags;
flags.set_flags(_klass->field_access_flags(_index));
return flags;
}
Symbol* name() const {
return _klass->field_name(_index);
}
Symbol* signature() const {
return _klass->field_signature(_index);
}
int offset() const {
return _klass->field_offset( index() );
}
fieldDescriptor& field_descriptor() const {
fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
field.reinitialize(_klass(), _index);
return field;
}
};
class FilteredField : public CHeapObj<mtInternal> {
private:
Klass* _klass;
int _field_offset;
public:
FilteredField(Klass* klass, int field_offset) {
_klass = klass;
_field_offset = field_offset;
}
Klass* klass() { return _klass; }
int field_offset() { return _field_offset; }
};
class FilteredFieldsMap : AllStatic {
private:
static GrowableArray<FilteredField *> *_filtered_fields;
public:
static void initialize();
static bool is_filtered_field(Klass* klass, int field_offset) {
for (int i=0; i < _filtered_fields->length(); i++) {
if (klass == _filtered_fields->at(i)->klass() &&
field_offset == _filtered_fields->at(i)->field_offset()) {
return true;
}
}
return false;
}
static int filtered_fields_count(Klass* klass, bool local_only) {
int nflds = 0;
for (int i=0; i < _filtered_fields->length(); i++) {
if (local_only && klass == _filtered_fields->at(i)->klass()) {
nflds++;
} else if (klass->is_subtype_of(_filtered_fields->at(i)->klass())) {
nflds++;
}
}
return nflds;
}
static void classes_do(KlassClosure* f) {
for (int i = 0; i < _filtered_fields->length(); i++) {
f->do_klass(_filtered_fields->at(i)->klass());
}
}
};
class FilteredFieldStream : public FieldStream {
private:
int _filtered_fields_count;
bool has_filtered_field() { return (_filtered_fields_count > 0); }
public:
FilteredFieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
: FieldStream(klass, local_only, classes_only) {
_filtered_fields_count = FilteredFieldsMap::filtered_fields_count((Klass*)klass(), local_only);
}
int field_count();
void next() {
_index -= 1;
if (has_filtered_field()) {
while (_index >=0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass(), offset())) {
_index -= 1;
}
}
}
};
#endif // SHARE_VM_RUNTIME_REFLECTIONUTILS_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/registerMap.hpp
#ifndef SHARE_VM_RUNTIME_REGISTERMAP_HPP
#define SHARE_VM_RUNTIME_REGISTERMAP_HPP
#include "code/vmreg.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef TARGET_ARCH_x86
# include "register_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "register_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "register_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "register_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "register_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "register_ppc.hpp"
#endif
class JavaThread;
class RegisterMap : public StackObj {
public:
typedef julong LocationValidType;
enum {
reg_count = ConcreteRegisterImpl::number_of_registers,
location_valid_type_size = sizeof(LocationValidType)*8,
location_valid_size = (reg_count+location_valid_type_size-1)/location_valid_type_size
};
private:
intptr_t* _location[reg_count]; // Location of registers (intptr_t* looks better than address in the debugger)
LocationValidType _location_valid[location_valid_size];
bool _include_argument_oops; // Should include argument_oop marked locations for compiler
JavaThread* _thread; // Reference to current thread
bool _update_map; // Tells if the register map need to be
#ifdef ASSERT
void check_location_valid();
#else
void check_location_valid() {}
#endif
public:
debug_only(intptr_t* _update_for_id;) // Assert that RegisterMap is not updated twice for same frame
RegisterMap(JavaThread *thread, bool update_map = true);
RegisterMap(const RegisterMap* map);
address location(VMReg reg) const {
int index = reg->value() / location_valid_type_size;
assert(0 <= reg->value() && reg->value() < reg_count, "range check");
assert(0 <= index && index < location_valid_size, "range check");
if (_location_valid[index] & ((LocationValidType)1 << (reg->value() % location_valid_type_size))) {
return (address) _location[reg->value()];
} else {
return pd_location(reg);
}
}
void set_location(VMReg reg, address loc) {
int index = reg->value() / location_valid_type_size;
assert(0 <= reg->value() && reg->value() < reg_count, "range check");
assert(0 <= index && index < location_valid_size, "range check");
assert(_update_map, "updating map that does not need updating");
_location[reg->value()] = (intptr_t*) loc;
_location_valid[index] |= ((LocationValidType)1 << (reg->value() % location_valid_type_size));
check_location_valid();
}
void clear();
bool include_argument_oops() const { return _include_argument_oops; }
void set_include_argument_oops(bool f) { _include_argument_oops = f; }
JavaThread *thread() const { return _thread; }
bool update_map() const { return _update_map; }
void print_on(outputStream* st) const;
void print() const;
#ifdef TARGET_ARCH_x86
# include "registerMap_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "registerMap_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "registerMap_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "registerMap_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "registerMap_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "registerMap_ppc.hpp"
#endif
};
#endif // SHARE_VM_RUNTIME_REGISTERMAP_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/relocator.cpp
#include "precompiled.hpp"
#include "classfile/stackMapTableFormat.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/relocator.hpp"
#define MAX_METHOD_LENGTH 65535
#define MAX_SHORT ((1 << 15) - 1)
#define MIN_SHORT (- (1 << 15))
class ChangeItem : public ResourceObj {
int _bci;
public:
ChangeItem(int bci) { _bci = bci; }
virtual bool handle_code_change(Relocator *r) = 0;
virtual bool is_widen() { return false; }
virtual bool is_jump_widen() { return false; }
virtual bool is_switch_pad() { return false; }
int bci() { return _bci; }
void relocate(int break_bci, int delta) { if (_bci > break_bci) { _bci += delta; } }
virtual bool adjust(int bci, int delta) { return false; }
virtual void print() = 0;
};
class ChangeWiden : public ChangeItem {
int _new_ilen; // New length of instruction at bci
u_char* _inst_buffer; // New bytecodes
public:
ChangeWiden(int bci, int new_ilen, u_char* inst_buffer) : ChangeItem(bci) {
_new_ilen = new_ilen;
_inst_buffer = inst_buffer;
}
bool handle_code_change(Relocator *r) { return r->handle_widen(bci(), _new_ilen, _inst_buffer); };
bool is_widen() { return true; }
void print() { tty->print_cr("ChangeWiden. bci: %d New_ilen: %d", bci(), _new_ilen); }
};
class ChangeJumpWiden : public ChangeItem {
int _delta; // New length of instruction at bci
public:
ChangeJumpWiden(int bci, int delta) : ChangeItem(bci) { _delta = delta; }
bool handle_code_change(Relocator *r) { return r->handle_jump_widen(bci(), _delta); };
bool is_jump_widen() { return true; }
bool adjust(int jump_bci, int delta) {
if (bci() == jump_bci) {
if (_delta > 0)
_delta += delta;
else
_delta -= delta;
return true;
}
return false;
}
void print() { tty->print_cr("ChangeJumpWiden. bci: %d Delta: %d", bci(), _delta); }
};
class ChangeSwitchPad : public ChangeItem {
int _padding;
bool _is_lookup_switch;
public:
ChangeSwitchPad(int bci, int padding, bool is_lookup_switch) : ChangeItem(bci) {
_padding = padding;
_is_lookup_switch = is_lookup_switch;
}
bool handle_code_change(Relocator *r) { return r->handle_switch_pad(bci(), _padding, _is_lookup_switch); };
bool is_switch_pad() { return true; }
int padding() { return _padding; }
bool is_lookup_switch() { return _is_lookup_switch; }
void print() { tty->print_cr("ChangeSwitchPad. bci: %d Padding: %d IsLookupSwitch: %d", bci(), _padding, _is_lookup_switch); }
};
Relocator::Relocator(methodHandle m, RelocatorListener* listener) {
set_method(m);
set_code_length(method()->code_size());
set_code_array(NULL);
if (!expand_code_array(0)) {
ShouldNotReachHere();
}
set_compressed_line_number_table(NULL);
set_compressed_line_number_table_size(0);
_listener = listener;
}
methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) {
_changes = new GrowableArray<ChangeItem*> (10);
_changes->push(new ChangeWiden(bci, size, inst_buffer));
if (TraceRelocator) {
tty->print_cr("Space at: %d Size: %d", bci, size);
_method->print();
_method->print_codes();
tty->print_cr("-------------------------------------------------");
}
if (!handle_code_changes()) return methodHandle();
methodHandle new_method = Method::clone_with_new_data(method(),
code_array(), code_length(),
compressed_line_number_table(),
compressed_line_number_table_size(),
CHECK_(methodHandle()));
ClassLoaderData* loader_data = method()->method_holder()->class_loader_data();
loader_data->add_to_deallocate_list(method()());
set_method(new_method);
if (TraceRelocator) {
tty->print_cr("-------------------------------------------------");
tty->print_cr("new method");
_method->print_codes();
}
return new_method;
}
bool Relocator::handle_code_changes() {
assert(_changes != NULL, "changes vector must be initialized");
while (!_changes->is_empty()) {
ChangeItem* ci = _changes->first();
if (TraceRelocator) {
ci->print();
}
if (!ci->handle_code_change(this)) return false;
for (int index = 1; index < _changes->length(); index++) {
_changes->at_put(index-1, _changes->at(index));
}
_changes->pop();
}
return true;
}
bool Relocator::is_opcode_lookupswitch(Bytecodes::Code bc) {
switch (bc) {
case Bytecodes::_tableswitch: return false;
case Bytecodes::_lookupswitch: // not rewritten on ia64
case Bytecodes::_fast_linearswitch: // rewritten _lookupswitch
case Bytecodes::_fast_binaryswitch: return true; // rewritten _lookupswitch
default: ShouldNotReachHere();
}
return true; // dummy
}
int Relocator::rc_instr_len(int bci) {
Bytecodes::Code bc= code_at(bci);
switch (bc) {
case Bytecodes::_tableswitch:
case Bytecodes::_lookupswitch:
case Bytecodes::_fast_linearswitch:
case Bytecodes::_fast_binaryswitch:
{
int pad = get_orig_switch_pad(bci, is_opcode_lookupswitch(bc));
if (pad == -1) {
return instruction_length_at(bci);
}
switch (bc) {
case Bytecodes::_tableswitch: {
int lo = int_at(bci + 1 + pad + 4 * 1);
int hi = int_at(bci + 1 + pad + 4 * 2);
int n = hi - lo + 1;
return 1 + pad + 4*(3 + n);
}
case Bytecodes::_lookupswitch:
case Bytecodes::_fast_linearswitch:
case Bytecodes::_fast_binaryswitch: {
int npairs = int_at(bci + 1 + pad + 4 * 1);
return 1 + pad + 4*(2 + 2*npairs);
}
default:
ShouldNotReachHere();
}
}
}
return instruction_length_at(bci);
}
int Relocator::get_orig_switch_pad(int bci, bool is_lookup_switch) {
for (int k = 0; k < _changes->length(); k++) {
ChangeItem* ci = _changes->at(k);
if (ci->is_switch_pad()) {
ChangeSwitchPad* csp = (ChangeSwitchPad*)ci;
if (csp->is_lookup_switch() == is_lookup_switch && csp->bci() == bci) {
return csp->padding();
}
}
}
return -1;
}
void Relocator::push_jump_widen(int bci, int delta, int new_delta) {
for (int j = 0; j < _changes->length(); j++) {
ChangeItem* ci = _changes->at(j);
if (ci->adjust(bci, delta)) return;
}
_changes->push(new ChangeJumpWiden(bci, new_delta));
}
void Relocator::change_jump(int bci, int offset, bool is_short, int break_bci, int delta) {
int bci_delta = (is_short) ? short_at(offset) : int_at(offset);
int targ = bci + bci_delta;
if ((bci <= break_bci && targ > break_bci) ||
(bci > break_bci && targ <= break_bci)) {
int new_delta;
if (bci_delta > 0)
new_delta = bci_delta + delta;
else
new_delta = bci_delta - delta;
if (is_short && ((new_delta > MAX_SHORT) || new_delta < MIN_SHORT)) {
push_jump_widen(bci, delta, new_delta);
} else if (is_short) {
short_at_put(offset, new_delta);
} else {
int_at_put(offset, new_delta);
}
}
}
void Relocator::change_jumps(int break_bci, int delta) {
int bci = 0;
Bytecodes::Code bc;
while (bci < code_length()) {
switch (bc= code_at(bci)) {
case Bytecodes::_ifeq:
case Bytecodes::_ifne:
case Bytecodes::_iflt:
case Bytecodes::_ifge:
case Bytecodes::_ifgt:
case Bytecodes::_ifle:
case Bytecodes::_if_icmpeq:
case Bytecodes::_if_icmpne:
case Bytecodes::_if_icmplt:
case Bytecodes::_if_icmpge:
case Bytecodes::_if_icmpgt:
case Bytecodes::_if_icmple:
case Bytecodes::_if_acmpeq:
case Bytecodes::_if_acmpne:
case Bytecodes::_ifnull:
case Bytecodes::_ifnonnull:
case Bytecodes::_goto:
case Bytecodes::_jsr:
change_jump(bci, bci+1, true, break_bci, delta);
break;
case Bytecodes::_goto_w:
case Bytecodes::_jsr_w:
change_jump(bci, bci+1, false, break_bci, delta);
break;
case Bytecodes::_tableswitch:
case Bytecodes::_lookupswitch:
case Bytecodes::_fast_linearswitch:
case Bytecodes::_fast_binaryswitch: {
int recPad = get_orig_switch_pad(bci, (bc != Bytecodes::_tableswitch));
int oldPad = (recPad != -1) ? recPad : align(bci+1) - (bci+1);
if (bci > break_bci) {
int new_bci = bci + delta;
int newPad = align(new_bci+1) - (new_bci+1);
if (newPad != oldPad) {
if (recPad == -1) {
_changes->push(new ChangeSwitchPad(bci, oldPad, (bc != Bytecodes::_tableswitch)));
}
}
}
switch (bc) {
case Bytecodes::_tableswitch: {
change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
int lo = int_at(bci + 1 + oldPad + 4 * 1);
int hi = int_at(bci + 1 + oldPad + 4 * 2);
int n = hi - lo + 1;
for (int k = 0; k < n; k++) {
change_jump(bci, bci +1 + oldPad + 4*(k+3), false, break_bci, delta);
}
bci += 1 + oldPad + (n+3)*4;
continue;
}
case Bytecodes::_lookupswitch:
case Bytecodes::_fast_linearswitch:
case Bytecodes::_fast_binaryswitch: {
change_jump(bci, bci +1 + oldPad, false, break_bci, delta);
int npairs = int_at(bci + 1 + oldPad + 4 * 1);
for (int k = 0; k < npairs; k++) {
change_jump(bci, bci + 1 + oldPad + 4*(2 + 2*k + 1), false, break_bci, delta);
}
bci += 1 + oldPad + (2 + (npairs*2))*4;
continue;
}
default:
ShouldNotReachHere();
}
}
default:
break;
}
bci += rc_instr_len(bci);
}
}
void Relocator::adjust_exception_table(int bci, int delta) {
ExceptionTable table(_method());
for (int index = 0; index < table.length(); index ++) {
if (table.start_pc(index) > bci) {
table.set_start_pc(index, table.start_pc(index) + delta);
table.set_end_pc(index, table.end_pc(index) + delta);
} else if (bci < table.end_pc(index)) {
table.set_end_pc(index, table.end_pc(index) + delta);
}
if (table.handler_pc(index) > bci)
table.set_handler_pc(index, table.handler_pc(index) + delta);
}
}
void Relocator::adjust_line_no_table(int bci, int delta) {
if (method()->has_linenumber_table()) {
CompressedLineNumberReadStream reader(method()->compressed_linenumber_table());
CompressedLineNumberWriteStream writer(64); // plenty big for most line number tables
while (reader.read_pair()) {
int adjustment = (reader.bci() > bci) ? delta : 0;
writer.write_pair(reader.bci() + adjustment, reader.line());
}
writer.write_terminator();
set_compressed_line_number_table(writer.buffer());
set_compressed_line_number_table_size(writer.position());
}
}
void Relocator::adjust_local_var_table(int bci, int delta) {
int localvariable_table_length = method()->localvariable_table_length();
if (localvariable_table_length > 0) {
LocalVariableTableElement* table = method()->localvariable_table_start();
for (int i = 0; i < localvariable_table_length; i++) {
u2 current_bci = table[i].start_bci;
if (current_bci > bci) {
table[i].start_bci = current_bci + delta;
} else {
u2 current_length = table[i].length;
if (current_bci + current_length > bci) {
table[i].length = current_length + delta;
}
}
}
}
}
static Array<u1>* insert_hole_at(ClassLoaderData* loader_data,
size_t where, int hole_sz, Array<u1>* src) {
Thread* THREAD = Thread::current();
Array<u1>* dst =
MetadataFactory::new_array<u1>(loader_data, src->length() + hole_sz, 0, CHECK_NULL);
address src_addr = (address)src->adr_at(0);
address dst_addr = (address)dst->adr_at(0);
memcpy(dst_addr, src_addr, where);
memcpy(dst_addr + where + hole_sz,
src_addr + where, src->length() - where);
return dst;
}
void Relocator::adjust_stack_map_table(int bci, int delta) {
if (method()->has_stackmap_table()) {
Array<u1>* data = method()->stackmap_data();
stack_map_table* sm_table =
stack_map_table::at((address)data->adr_at(0));
int count = sm_table->number_of_entries();
stack_map_frame* frame = sm_table->entries();
int bci_iter = -1;
bool offset_adjusted = false; // only need to adjust one offset
for (int i = 0; i < count; ++i) {
int offset_delta = frame->offset_delta();
bci_iter += offset_delta;
if (!offset_adjusted && bci_iter > bci) {
int new_offset_delta = offset_delta + delta;
if (frame->is_valid_offset(new_offset_delta)) {
frame->set_offset_delta(new_offset_delta);
} else {
assert(frame->is_same_frame() ||
frame->is_same_locals_1_stack_item_frame(),
"Frame must be one of the compressed forms");
size_t frame_offset = (address)frame - (address)data->adr_at(0);
ClassLoaderData* loader_data = method()->method_holder()->class_loader_data();
Array<u1>* new_data = insert_hole_at(loader_data, frame_offset + 1, 2, data);
if (new_data == NULL) {
return; // out-of-memory?
}
MetadataFactory::free_array<u1>(loader_data, data);
data = new_data;
address frame_addr = (address)(data->adr_at(0) + frame_offset);
frame = stack_map_frame::at(frame_addr);
if (frame->is_same_frame()) {
same_frame_extended::create_at(frame_addr, new_offset_delta);
} else {
same_locals_1_stack_item_extended::create_at(
frame_addr, new_offset_delta, NULL);
}
}
offset_adjusted = true; // needs to be done only once, since subsequent
}
int number_of_types = frame->number_of_types();
verification_type_info* types = frame->types();
for (int i = 0; i < number_of_types; ++i) {
if (types->is_uninitialized() && types->bci() > bci) {
types->set_bci(types->bci() + delta);
}
types = types->next();
}
full_frame* ff = frame->as_full_frame();
if (ff != NULL) {
address eol = (address)types;
number_of_types = ff->stack_slots(eol);
types = ff->stack(eol);
for (int i = 0; i < number_of_types; ++i) {
if (types->is_uninitialized() && types->bci() > bci) {
types->set_bci(types->bci() + delta);
}
types = types->next();
}
}
frame = frame->next();
}
method()->set_stackmap_data(data); // in case it has changed
}
}
bool Relocator::expand_code_array(int delta) {
int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
if (length > MAX_METHOD_LENGTH) {
if (delta == 0 && code_length() <= MAX_METHOD_LENGTH) {
length = MAX_METHOD_LENGTH;
} else {
return false;
}
}
unsigned char* new_code_array = NEW_RESOURCE_ARRAY(unsigned char, length);
if (!new_code_array) return false;
if (code_array() != NULL) {
memcpy(new_code_array, code_array(), code_length());
} else {
memcpy(new_code_array, method()->code_base(), code_length());
}
set_code_array(new_code_array);
set_code_array_length(length);
return true;
}
bool Relocator::relocate_code(int bci, int ilen, int delta) {
int next_bci = bci + ilen;
if (delta > 0 && code_length() + delta > code_array_length()) {
if (!expand_code_array(delta)) {
return false;
}
}
assert(((intptr_t)code_array() & 3) == 0, "check code alignment");
change_jumps(bci, delta);
if (delta < 0) {
assert(delta>=-3, "we cannot overwrite more than 3 bytes");
memcpy(_overwrite, addr_at(bci + ilen + delta), -delta);
}
memmove(addr_at(next_bci + delta), addr_at(next_bci), code_length() - next_bci);
set_code_length(code_length() + delta);
adjust_exception_table(bci, delta);
adjust_line_no_table(bci, delta);
adjust_local_var_table(bci, delta);
adjust_stack_map_table(bci, delta);
for (int j = 0; j < _changes->length(); j++) {
ChangeItem* ci = _changes->at(j);
ci->relocate(bci, delta);
}
notify(bci, delta, code_length());
return true;
}
bool Relocator::handle_widen(int bci, int new_ilen, u_char inst_buffer[]) {
int ilen = rc_instr_len(bci);
if (!relocate_code(bci, ilen, new_ilen - ilen))
return false;
for(int k = 0; k < new_ilen; k++) {
code_at_put(bci + k, (Bytecodes::Code)inst_buffer[k]);
}
return true;
}
bool Relocator::handle_jump_widen(int bci, int delta) {
int ilen = rc_instr_len(bci);
Bytecodes::Code bc = code_at(bci);
switch (bc) {
case Bytecodes::_ifeq:
case Bytecodes::_ifne:
case Bytecodes::_iflt:
case Bytecodes::_ifge:
case Bytecodes::_ifgt:
case Bytecodes::_ifle:
case Bytecodes::_if_icmpeq:
case Bytecodes::_if_icmpne:
case Bytecodes::_if_icmplt:
case Bytecodes::_if_icmpge:
case Bytecodes::_if_icmpgt:
case Bytecodes::_if_icmple:
case Bytecodes::_if_acmpeq:
case Bytecodes::_if_acmpne:
case Bytecodes::_ifnull:
case Bytecodes::_ifnonnull: {
const int goto_length = Bytecodes::length_for(Bytecodes::_goto);
assert (short_at(bci+1) != ilen+goto_length, "if relocation already handled");
assert(ilen == 3, "check length");
const int goto_w_length = Bytecodes::length_for(Bytecodes::_goto_w);
const int add_bci = goto_length + goto_w_length;
if (!relocate_code(bci, 3, /*delta*/add_bci)) return false;
short_at_put(bci + 1, ilen + goto_length);
int cbci = bci + ilen;
code_at_put(cbci, Bytecodes::_goto);
short_at_put(cbci + 1, add_bci);
cbci = cbci + goto_length;
code_at_put(cbci, Bytecodes::_goto_w);
if (delta > 0) {
delta += 2; // goto_w is 2 bytes more than "if" code
} else {
delta -= ilen+goto_length; // branch starts at goto_w offset
}
int_at_put(cbci + 1, delta);
break;
}
case Bytecodes::_goto:
case Bytecodes::_jsr:
assert(ilen == 3, "check length");
if (!relocate_code(bci, 3, 2)) return false;
if (bc == Bytecodes::_goto)
code_at_put(bci, Bytecodes::_goto_w);
else
code_at_put(bci, Bytecodes::_jsr_w);
if (delta > 0) delta += 2;
int_at_put(bci + 1, delta);
break;
default: ShouldNotReachHere();
}
return true;
}
bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) {
int ilen = rc_instr_len(bci);
int new_pad = align(bci+1) - (bci+1);
int pad_delta = new_pad - old_pad;
if (pad_delta != 0) {
int len;
if (!is_lookup_switch) {
int low = int_at(bci+1+old_pad+4);
int high = int_at(bci+1+old_pad+8);
len = high-low+1 + 3; // 3 for default, hi, lo.
} else {
int npairs = int_at(bci+1+old_pad+4);
len = npairs*2 + 2; // 2 for default, npairs.
}
if (!relocate_code(bci, ilen, pad_delta)) return false;
if (pad_delta < 0) {
memmove(addr_at(bci + 1 + new_pad),
addr_at(bci + 1 + old_pad),
len * 4 + pad_delta);
memmove(addr_at(bci + 1 + new_pad + len*4 + pad_delta),
_overwrite, -pad_delta);
} else {
assert(pad_delta > 0, "check");
memmove(addr_at(bci +1 + new_pad),
addr_at(bci +1 + old_pad),
len * 4);
memset(addr_at(bci + 1), 0, new_pad); // pad must be 0
}
}
return true;
}
C:\hotspot-69087d08d473\src\share\vm/runtime/relocator.hpp
#ifndef SHARE_VM_RUNTIME_RELOCATOR_HPP
#define SHARE_VM_RUNTIME_RELOCATOR_HPP
#include "interpreter/bytecodes.hpp"
#include "oops/method.hpp"
#ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "bytes_aarch64.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
class ChangeItem;
class RelocatorListener : public StackObj {
public:
RelocatorListener() {};
virtual void relocated(int bci, int delta, int new_method_size) = 0;
};
class Relocator : public ResourceObj {
public:
Relocator(methodHandle method, RelocatorListener* listener);
methodHandle insert_space_at(int bci, int space, u_char inst_buffer[], TRAPS);
bool handle_code_changes();
bool handle_widen (int bci, int new_ilen, u_char inst_buffer[]); // handles general instructions
void push_jump_widen (int bci, int delta, int new_delta); // pushes jumps
bool handle_jump_widen (int bci, int delta); // handles jumps
bool handle_switch_pad (int bci, int old_pad, bool is_lookup_switch); // handles table and lookup switches
private:
unsigned char* _code_array;
int _code_array_length;
int _code_length;
unsigned char* _compressed_line_number_table;
int _compressed_line_number_table_size;
methodHandle _method;
u_char _overwrite[3]; // stores overwritten bytes for shrunken instructions
GrowableArray<ChangeItem*>* _changes;
unsigned char* code_array() const { return _code_array; }
void set_code_array(unsigned char* array) { _code_array = array; }
int code_length() const { return _code_length; }
void set_code_length(int length) { _code_length = length; }
int code_array_length() const { return _code_array_length; }
void set_code_array_length(int length) { _code_array_length = length; }
unsigned char* compressed_line_number_table() const { return _compressed_line_number_table; }
void set_compressed_line_number_table(unsigned char* table) { _compressed_line_number_table = table; }
int compressed_line_number_table_size() const { return _compressed_line_number_table_size; }
void set_compressed_line_number_table_size(int size) { _compressed_line_number_table_size = size; }
methodHandle method() const { return _method; }
void set_method(methodHandle method) { _method = method; }
Bytecodes::Code code_at(int bci) const { return (Bytecodes::Code) code_array()[bci]; }
void code_at_put(int bci, Bytecodes::Code code) { code_array()[bci] = (char) code; }
inline int int_at(int bci) const { return Bytes::get_Java_u4(&code_array()[bci]); }
inline void int_at_put(int bci, int value) { Bytes::put_Java_u4(&code_array()[bci], value); }
inline short short_at(int bci) const { return (short)Bytes::get_Java_u2(&code_array()[bci]); }
inline void short_at_put(int bci, short value) { Bytes::put_Java_u2((address) &code_array()[bci], value); }
inline char* addr_at(int bci) const { return (char*) &code_array()[bci]; }
int instruction_length_at(int bci) { return Bytecodes::length_at(NULL, code_array() + bci); }
int align(int n) const { return (n+3) & ~3; }
int code_slop_pct() const { return 25; }
bool is_opcode_lookupswitch(Bytecodes::Code bc);
bool relocate_code (int bci, int ilen, int delta);
void change_jumps (int break_bci, int delta);
void change_jump (int bci, int offset, bool is_short, int break_bci, int delta);
void adjust_exception_table(int bci, int delta);
void adjust_line_no_table (int bci, int delta);
void adjust_local_var_table(int bci, int delta);
void adjust_stack_map_table(int bci, int delta);
int get_orig_switch_pad (int bci, bool is_lookup_switch);
int rc_instr_len (int bci);
bool expand_code_array (int delta);
RelocatorListener *_listener;
void notify(int bci, int delta, int new_code_length) {
if (_listener != NULL)
_listener->relocated(bci, delta, new_code_length);
}
};
#endif // SHARE_VM_RUNTIME_RELOCATOR_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/rframe.cpp
#include "precompiled.hpp"
#include "interpreter/interpreter.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/rframe.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframe_hp.hpp"
static RFrame*const noCaller = (RFrame*) 0x1; // no caller (i.e., initial frame)
static RFrame*const noCallerYet = (RFrame*) 0x0; // caller not yet computed
RFrame::RFrame(frame fr, JavaThread* thread, RFrame*const callee) :
_fr(fr), _thread(thread), _callee(callee), _num(callee ? callee->num() + 1 : 0) {
_caller = (RFrame*)noCallerYet;
_invocations = 0;
_distance = 0;
}
void RFrame::set_distance(int d) {
assert(is_compiled() || d >= 0, "should be positive");
_distance = d;
}
InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee)
: RFrame(fr, thread, callee) {
RegisterMap map(thread, false);
_vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread));
_method = methodHandle(thread, _vf->method());
assert( _vf->is_interpreted_frame(), "must be interpreted");
init();
}
InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m)
: RFrame(fr, thread, NULL) {
RegisterMap map(thread, false);
_vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread));
_method = m;
assert( _vf->is_interpreted_frame(), "must be interpreted");
init();
}
CompiledRFrame::CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee)
: RFrame(fr, thread, callee) {
init();
}
CompiledRFrame::CompiledRFrame(frame fr, JavaThread* thread)
: RFrame(fr, thread, NULL) {
init();
}
DeoptimizedRFrame::DeoptimizedRFrame(frame fr, JavaThread* thread, RFrame*const callee)
: InterpretedRFrame(fr, thread, callee) {}
RFrame* RFrame::new_RFrame(frame fr, JavaThread* thread, RFrame*const callee) {
RFrame* rf;
int dist = callee ? callee->distance() : -1;
if (fr.is_interpreted_frame()) {
rf = new InterpretedRFrame(fr, thread, callee);
dist++;
} else if (fr.is_compiled_frame()) {
rf = new CompiledRFrame(fr, thread, callee);
} else {
assert(false, "Unhandled frame type");
}
rf->set_distance(dist);
rf->init();
return rf;
}
RFrame* RFrame::caller() {
if (_caller != noCallerYet) return (_caller == noCaller) ? NULL : _caller; // already computed caller
if (_fr.is_first_java_frame()) {
_caller = (RFrame*)noCaller;
return NULL;
}
RegisterMap map(_thread, false);
frame sender = _fr.real_sender(&map);
if (sender.is_java_frame()) {
_caller = new_RFrame(sender, thread(), this);
return _caller;
}
_caller = (RFrame*)noCaller;
return NULL;
}
int InterpretedRFrame::cost() const {
return _method->code_size(); // fix this
}
int CompiledRFrame::cost() const {
nmethod* nm = top_method()->code();
if (nm != NULL) {
return nm->insts_size();
} else {
return top_method()->code_size();
}
}
void CompiledRFrame::init() {
RegisterMap map(thread(), false);
vframe* vf = vframe::new_vframe(&_fr, &map, thread());
assert(vf->is_compiled_frame(), "must be compiled");
_nm = compiledVFrame::cast(vf)->code();
vf = vf->top();
_vf = javaVFrame::cast(vf);
_method = methodHandle(thread(), CodeCache::find_nmethod(_fr.pc())->method());
assert(_method(), "should have found a method");
#ifndef PRODUCT
_invocations = _method->compiled_invocation_count();
#endif
}
void InterpretedRFrame::init() {
_invocations = _method->invocation_count() + _method->backedge_count();
}
void RFrame::print(const char* kind) {
#ifndef PRODUCT
#ifdef COMPILER2
int cnt = top_method()->interpreter_invocation_count();
#else
int cnt = top_method()->invocation_count();
#endif
tty->print("%3d %s ", _num, is_interpreted() ? "I" : "C");
top_method()->print_short_name(tty);
tty->print_cr(": inv=%5d(%d) cst=%4d", _invocations, cnt, cost());
#endif
}
void CompiledRFrame::print() {
RFrame::print("comp");
}
void InterpretedRFrame::print() {
RFrame::print("int.");
}
void DeoptimizedRFrame::print() {
RFrame::print("deopt.");
}
C:\hotspot-69087d08d473\src\share\vm/runtime/rframe.hpp
#ifndef SHARE_VM_RUNTIME_RFRAME_HPP
#define SHARE_VM_RUNTIME_RFRAME_HPP
#include "memory/allocation.hpp"
#include "runtime/frame.inline.hpp"
class RFrame : public ResourceObj {
protected:
const frame _fr; // my frame
JavaThread* const _thread; // thread where frame resides.
RFrame* _caller; // caller / callee rframes (or NULL)
RFrame*const _callee;
const int _num; // stack frame number (0 = most recent)
int _invocations; // current invocation estimate (for this frame)
int _distance; // recompilation search "distance" (measured in # of interpreted frames)
RFrame(frame fr, JavaThread* thread, RFrame*const callee);
virtual void init() = 0; // compute invocations, loopDepth, etc.
void print(const char* name);
public:
static RFrame* new_RFrame(frame fr, JavaThread* thread, RFrame*const callee);
virtual bool is_interpreted() const { return false; }
virtual bool is_compiled() const { return false; }
int distance() const { return _distance; }
void set_distance(int d);
int invocations() const { return _invocations; }
int num() const { return _num; }
frame fr() const { return _fr; }
JavaThread* thread() const { return _thread; }
virtual int cost() const = 0; // estimated inlining cost (size)
virtual methodHandle top_method() const = 0;
virtual javaVFrame* top_vframe() const = 0;
virtual nmethod* nm() const { ShouldNotCallThis(); return NULL; }
RFrame* caller();
RFrame* callee() const { return _callee; }
RFrame* parent() const; // rframe containing lexical scope (if any)
virtual void print() = 0;
static int computeSends(Method* m);
static int computeSends(nmethod* nm);
static int computeCumulSends(Method* m);
static int computeCumulSends(nmethod* nm);
};
class CompiledRFrame : public RFrame { // frame containing a compiled method
protected:
nmethod* _nm;
javaVFrame* _vf; // top vframe; may be NULL (for most recent frame)
methodHandle _method; // top method
CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee);
void init();
friend class RFrame;
public:
CompiledRFrame(frame fr, JavaThread* thread); // for nmethod triggering its counter (callee == NULL)
bool is_compiled() const { return true; }
methodHandle top_method() const { return _method; }
javaVFrame* top_vframe() const { return _vf; }
nmethod* nm() const { return _nm; }
int cost() const;
void print();
};
class InterpretedRFrame : public RFrame { // interpreter frame
protected:
javaVFrame* _vf; // may be NULL (for most recent frame)
methodHandle _method;
InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee);
void init();
friend class RFrame;
public:
InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m); // constructor for method triggering its invocation counter
bool is_interpreted() const { return true; }
methodHandle top_method() const { return _method; }
javaVFrame* top_vframe() const { return _vf; }
int cost() const;
void print();
};
class DeoptimizedRFrame : public InterpretedRFrame {
protected:
DeoptimizedRFrame(frame fr, JavaThread* thread, RFrame*const callee);
friend class RFrame;
public:
void print();
};
#endif // SHARE_VM_RUNTIME_RFRAME_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/rtmLocking.hpp
#ifndef SHARE_VM_RUNTIME_RTMLOCKING_HPP
#define SHARE_VM_RUNTIME_RTMLOCKING_HPP
class RTMLockingCounters VALUE_OBJ_CLASS_SPEC {
private:
uintx _total_count; // Total RTM locks count
uintx _abort_count; // Total aborts count
public:
enum { ABORT_STATUS_LIMIT = 6 };
private:
uintx _abortX_count[ABORT_STATUS_LIMIT];
public:
static uintx _calculation_flag;
static uintx* rtm_calculation_flag_addr() { return &_calculation_flag; }
static void init();
RTMLockingCounters() : _total_count(0), _abort_count(0) {
for (int i = 0; i < ABORT_STATUS_LIMIT; i++) {
_abortX_count[i] = 0;
}
}
uintx* total_count_addr() { return &_total_count; }
uintx* abort_count_addr() { return &_abort_count; }
uintx* abortX_count_addr() { return &_abortX_count[0]; }
static int total_count_offset() { return (int)offset_of(RTMLockingCounters, _total_count); }
static int abort_count_offset() { return (int)offset_of(RTMLockingCounters, _abort_count); }
static int abortX_count_offset() { return (int)offset_of(RTMLockingCounters, _abortX_count[0]); }
bool nonzero() { return (_abort_count + _total_count) > 0; }
void print_on(outputStream* st);
void print() { print_on(tty); }
};
#endif // SHARE_VM_RUNTIME_RTMLOCKING_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/safepoint.cpp
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "interpreter/interpreter.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/sweeper.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"
#include "services/runtimeService.hpp"
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
#ifdef TARGET_ARCH_x86
# include "nativeInst_x86.hpp"
# include "vmreg_x86.inline.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "nativeInst_aarch64.hpp"
# include "vmreg_aarch64.inline.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "nativeInst_sparc.hpp"
# include "vmreg_sparc.inline.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "nativeInst_zero.hpp"
# include "vmreg_zero.inline.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "nativeInst_arm.hpp"
# include "vmreg_arm.inline.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "nativeInst_ppc.hpp"
# include "vmreg_ppc.inline.hpp"
#endif
#if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
#include "gc_implementation/shared/suspendibleThreadSet.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef COMPILER1
#include "c1/c1_globals.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
template <typename E>
static void set_current_safepoint_id(E* event, int adjustment = 0) {
assert(event != NULL, "invariant");
event->set_safepointId(SafepointSynchronize::safepoint_counter() + adjustment);
}
static void post_safepoint_begin_event(EventSafepointBegin* event,
int thread_count,
int critical_thread_count) {
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
set_current_safepoint_id(event);
event->set_totalThreadCount(thread_count);
event->set_jniCriticalThreadCount(critical_thread_count);
event->commit();
}
static void post_safepoint_cleanup_event(EventSafepointCleanup* event) {
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
set_current_safepoint_id(event);
event->commit();
}
static void post_safepoint_synchronize_event(EventSafepointStateSynchronization* event,
int initial_number_of_threads,
int threads_waiting_to_block,
unsigned int iterations) {
assert(event != NULL, "invariant");
if (event->should_commit()) {
set_current_safepoint_id(event, 1);
event->set_initialThreadCount(initial_number_of_threads);
event->set_runningThreadCount(threads_waiting_to_block);
event->set_iterations(iterations);
event->commit();
}
}
static void post_safepoint_wait_blocked_event(EventSafepointWaitBlocked* event,
int initial_threads_waiting_to_block) {
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
set_current_safepoint_id(event);
event->set_runningThreadCount(initial_threads_waiting_to_block);
event->commit();
}
static void post_safepoint_cleanup_task_event(EventSafepointCleanupTask* event,
const char* name) {
assert(event != NULL, "invariant");
if (event->should_commit()) {
set_current_safepoint_id(event);
event->set_name(name);
event->commit();
}
}
static void post_safepoint_end_event(EventSafepointEnd* event) {
assert(event != NULL, "invariant");
if (event->should_commit()) {
set_current_safepoint_id(event, -1);
event->commit();
}
}
SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized;
volatile int SafepointSynchronize::_waiting_to_block = 0;
volatile int SafepointSynchronize::_safepoint_counter = 0;
int SafepointSynchronize::_current_jni_active_count = 0;
long SafepointSynchronize::_end_of_last_safepoint = 0;
static volatile int PageArmed = 0 ; // safepoint polling page is RO|RW vs PROT_NONE
static volatile int TryingToBlock = 0 ; // proximate value -- for advisory use only
static bool timeout_error_printed = false;
void SafepointSynchronize::begin() {
EventSafepointBegin begin_event;
Thread* myThread = Thread::current();
assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint");
if (PrintSafepointStatistics || PrintSafepointStatisticsTimeout > 0) {
_safepoint_begin_time = os::javaTimeNanos();
_ts_of_current_safepoint = tty->time_stamp().seconds();
}
#if INCLUDE_ALL_GCS
if (UseConcMarkSweepGC) {
ConcurrentMarkSweepThread::synchronize(false);
} else if (UseG1GC) {
SuspendibleThreadSet::synchronize();
}
#endif // INCLUDE_ALL_GCS
Threads_lock->lock();
assert( _state == _not_synchronized, "trying to safepoint synchronize with wrong state");
int nof_threads = Threads::number_of_threads();
if (TraceSafepoint) {
tty->print_cr("Safepoint synchronization initiated. (%d)", nof_threads);
}
RuntimeService::record_safepoint_begin();
MutexLocker mu(Safepoint_lock);
_current_jni_active_count = 0;
_waiting_to_block = nof_threads;
TryingToBlock = 0 ;
int still_running = nof_threads;
jlong safepoint_limit_time = 0;
timeout_error_printed = false;
if (PrintSafepointStatistics || PrintSafepointStatisticsTimeout > 0) {
deferred_initialize_stat();
}
EventSafepointStateSynchronization sync_event;
int initial_running = 0;
_state = _synchronizing;
OrderAccess::fence();
if (!UseMembar) {
os::serialize_thread_states();
}
Interpreter::notice_safepoints();
if (UseCompilerSafepoints && DeferPollingPageLoopCount < 0) {
guarantee (PageArmed == 0, "invariant") ;
PageArmed = 1 ;
os::make_polling_page_unreadable();
}
int ncpus = os::processor_count() ;
#ifdef ASSERT
for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
assert(cur->safepoint_state()->is_running(), "Illegal initial state");
cur->set_visited_for_critical_count(false);
}
#endif // ASSERT
if (SafepointTimeout)
safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS;
unsigned int iterations = 0;
int steps = 0 ;
while(still_running > 0) {
for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended");
ThreadSafepointState *cur_state = cur->safepoint_state();
if (cur_state->is_running()) {
cur_state->examine_state_of_thread();
if (!cur_state->is_running()) {
still_running--;
}
if (TraceSafepoint && Verbose) cur_state->print();
}
}
if (iterations == 0) {
initial_running = still_running;
if (PrintSafepointStatistics) {
begin_statistics(nof_threads, still_running);
}
}
if (still_running > 0) {
if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
print_safepoint_timeout(_spinning_timeout);
}
if (UseCompilerSafepoints && int(iterations) == DeferPollingPageLoopCount) {
guarantee (PageArmed == 0, "invariant") ;
PageArmed = 1 ;
os::make_polling_page_unreadable();
}
++steps ;
if (ncpus > 1 && steps < SafepointSpinBeforeYield) {
SpinPause() ; // MP-Polite spin
} else
if (steps < DeferThrSuspendLoopCount) {
os::NakedYield() ;
} else {
os::yield_all(steps) ;
}
iterations ++ ;
}
assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long");
}
assert(still_running == 0, "sanity check");
if (PrintSafepointStatistics) {
update_statistics_on_spin_end();
}
if (sync_event.should_commit()) {
post_safepoint_synchronize_event(&sync_event, initial_running, _waiting_to_block, iterations);
}
{
EventSafepointWaitBlocked wait_blocked_event;
int initial_waiting_to_block = _waiting_to_block;
while (_waiting_to_block > 0) {
if (TraceSafepoint) tty->print_cr("Waiting for %d thread(s) to block", _waiting_to_block);
if (!SafepointTimeout || timeout_error_printed) {
Safepoint_lock->wait(true); // true, means with no safepoint checks
} else {
jlong remaining_time = safepoint_limit_time - os::javaTimeNanos();
if (remaining_time < 0 || Safepoint_lock->wait(true, remaining_time / MICROUNITS)) {
print_safepoint_timeout(_blocking_timeout);
}
}
}
assert(_waiting_to_block == 0, "sanity check");
#ifndef PRODUCT
if (SafepointTimeout) {
jlong current_time = os::javaTimeNanos();
if (safepoint_limit_time < current_time) {
tty->print_cr("# SafepointSynchronize: Finished after "
INT64_FORMAT_W(6) " ms",
((current_time - safepoint_limit_time) / MICROUNITS +
SafepointTimeoutDelay));
}
}
#endif
assert((_safepoint_counter & 0x1) == 0, "must be even");
assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
_safepoint_counter ++;
_state = _synchronized;
OrderAccess::fence();
if (wait_blocked_event.should_commit()) {
post_safepoint_wait_blocked_event(&wait_blocked_event, initial_waiting_to_block);
}
}
#ifdef ASSERT
for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
assert(cur->was_visited_for_critical_count(), "missed a thread");
}
#endif // ASSERT
GC_locker::set_jni_lock_count(_current_jni_active_count);
if (TraceSafepoint) {
VM_Operation *op = VMThread::vm_operation();
tty->print_cr("Entering safepoint region: %s", (op != NULL) ? op->name() : "no vm operation");
}
RuntimeService::record_safepoint_synchronized();
if (PrintSafepointStatistics) {
update_statistics_on_sync_end(os::javaTimeNanos());
}
{
EventSafepointCleanup cleanup_event;
do_cleanup_tasks();
if (cleanup_event.should_commit()) {
post_safepoint_cleanup_event(&cleanup_event);
}
}
if (PrintSafepointStatistics) {
update_statistics_on_cleanup_end(os::javaTimeNanos());
}
if (begin_event.should_commit()) {
post_safepoint_begin_event(&begin_event, nof_threads, _current_jni_active_count);
}
}
void SafepointSynchronize::end() {
assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
assert((_safepoint_counter & 0x1) == 1, "must be odd");
EventSafepointEnd event;
_safepoint_counter ++;
DEBUG_ONLY(Thread* myThread = Thread::current();)
assert(myThread->is_VM_thread(), "Only VM thread can execute a safepoint");
if (PrintSafepointStatistics) {
end_statistics(os::javaTimeNanos());
}
#ifdef ASSERT
for(JavaThread *cur = Threads::first(); cur; cur = cur->next()) {
assert (!(cur->has_pending_exception() &&
cur->safepoint_state()->is_at_poll_safepoint()),
"safepoint installed a pending exception");
}
#endif // ASSERT
if (PageArmed) {
os::make_polling_page_readable();
PageArmed = 0 ;
}
Interpreter::ignore_safepoints();
{
MutexLocker mu(Safepoint_lock);
assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization");
_state = _not_synchronized;
OrderAccess::fence();
if (TraceSafepoint) {
tty->print_cr("Leaving safepoint region");
}
for(JavaThread *current = Threads::first(); current; current = current->next()) {
if (VMThreadHintNoPreempt) {
os::hint_no_preempt();
}
ThreadSafepointState* cur_state = current->safepoint_state();
assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint");
cur_state->restart();
assert(cur_state->is_running(), "safepoint state has not been reset");
}
RuntimeService::record_safepoint_end();
Threads_lock->unlock();
}
#if INCLUDE_ALL_GCS
if (UseConcMarkSweepGC) {
ConcurrentMarkSweepThread::desynchronize(false);
} else if (UseG1GC) {
SuspendibleThreadSet::desynchronize();
}
#endif // INCLUDE_ALL_GCS
_end_of_last_safepoint = os::javaTimeMillis();
if (event.should_commit()) {
post_safepoint_end_event(&event);
}
}
bool SafepointSynchronize::is_cleanup_needed() {
if (!InlineCacheBuffer::is_empty()) return true;
return false;
}
ssssssssss74
最新推荐文章于 2024-09-08 12:41:07 发布