From 06d05b7c47ffb26ad09c874d1b25256a0ffc74d2 Mon Sep 17 00:00:00 2001 From: Tom Deneau Date: Thu, 25 Aug 2011 02:57:46 -0700 Subject: [PATCH 001/214] 7082969: NUMA interleaving Support interleaving on NUMA systems for collectors that don't have NUMA-awareness. Reviewed-by: iveresov, ysr --- hotspot/src/os/linux/vm/os_linux.cpp | 20 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 17 +- hotspot/src/os/windows/vm/os_windows.cpp | 430 ++++++++++++++++----- hotspot/src/os/windows/vm/os_windows.hpp | 12 + hotspot/src/share/vm/runtime/arguments.cpp | 3 + hotspot/src/share/vm/runtime/globals.hpp | 6 + 6 files changed, 383 insertions(+), 105 deletions(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 363d5f44067..a55111e8160 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2502,7 +2502,13 @@ bool os::commit_memory(char* addr, size_t size, bool exec) { int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); - return res != (uintptr_t) MAP_FAILED; + if (res != (uintptr_t) MAP_FAILED) { + if (UseNUMAInterleaving) { + numa_make_global(addr, size); + } + return true; + } + return false; } // Define MAP_HUGETLB here so we can build HotSpot on old systems. @@ -2523,7 +2529,13 @@ bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, (uintptr_t) ::mmap(addr, size, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0); - return res != (uintptr_t) MAP_FAILED; + if (res != (uintptr_t) MAP_FAILED) { + if (UseNUMAInterleaving) { + numa_make_global(addr, size); + } + return true; + } + return false; } return commit_memory(addr, size, exec); @@ -3115,6 +3127,10 @@ char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) { return NULL; } + if ((addr != NULL) && UseNUMAInterleaving) { + numa_make_global(addr, bytes); + } + return addr; } diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 4fa64a284a0..ad02278969d 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2777,8 +2777,14 @@ int os::vm_allocation_granularity() { bool os::commit_memory(char* addr, size_t bytes, bool exec) { int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; size_t size = bytes; - return - NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); + char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); + if (res != NULL) { + if (UseNUMAInterleaving) { + numa_make_global(addr, bytes); + } + return true; + } + return false; } bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint, @@ -3389,12 +3395,11 @@ bool os::Solaris::set_mpss_range(caddr_t start, size_t bytes, size_t align) { return true; } -char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { +char* os::reserve_memory_special(size_t size, char* addr, bool exec) { // "exec" is passed in but not used. Creating the shared image for // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages && UseISM, "only for ISM large pages"); - size_t size = bytes; char* retAddr = NULL; int shmid; key_t ismKey; @@ -3436,7 +3441,9 @@ char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { } return NULL; } - + if ((retAddr != NULL) && UseNUMAInterleaving) { + numa_make_global(retAddr, size); + } return retAddr; } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 3db2442247b..28a464169ef 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2614,6 +2614,57 @@ int os::vm_allocation_granularity() { static HANDLE _hProcess; static HANDLE _hToken; +// Container for NUMA node list info +class NUMANodeListHolder { +private: + int *_numa_used_node_list; // allocated below + int _numa_used_node_count; + + void free_node_list() { + if (_numa_used_node_list != NULL) { + FREE_C_HEAP_ARRAY(int, _numa_used_node_list); + } + } + +public: + NUMANodeListHolder() { + _numa_used_node_count = 0; + _numa_used_node_list = NULL; + // do rest of initialization in build routine (after function pointers are set up) + } + + ~NUMANodeListHolder() { + free_node_list(); + } + + bool build() { + DWORD_PTR proc_aff_mask; + DWORD_PTR sys_aff_mask; + if (!GetProcessAffinityMask(GetCurrentProcess(), &proc_aff_mask, &sys_aff_mask)) return false; + ULONG highest_node_number; + if (!os::Kernel32Dll::GetNumaHighestNodeNumber(&highest_node_number)) return false; + free_node_list(); + _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number); + for (unsigned int i = 0; i <= highest_node_number; i++) { + ULONGLONG proc_mask_numa_node; + if (!os::Kernel32Dll::GetNumaNodeProcessorMask(i, &proc_mask_numa_node)) return false; + if ((proc_aff_mask & proc_mask_numa_node)!=0) { + _numa_used_node_list[_numa_used_node_count++] = i; + } + } + return (_numa_used_node_count > 1); + } + + int get_count() {return _numa_used_node_count;} + int get_node_list_entry(int n) { + // for indexes out of range, returns -1 + return (n < _numa_used_node_count ? _numa_used_node_list[n] : -1); + } + +} numa_node_list_holder; + + + static size_t _large_page_size = 0; static bool resolve_functions_for_large_page_init() { @@ -2653,6 +2704,154 @@ static void cleanup_after_large_page_init() { _hToken = NULL; } +static bool numa_interleaving_init() { + bool success = false; + bool use_numa_specified = !FLAG_IS_DEFAULT(UseNUMA); + bool use_numa_interleaving_specified = !FLAG_IS_DEFAULT(UseNUMAInterleaving); + + // print a warning if UseNUMA or UseNUMAInterleaving flag is specified on command line + bool warn_on_failure = use_numa_specified || use_numa_interleaving_specified; +# define WARN(msg) if (warn_on_failure) { warning(msg); } + + // NUMAInterleaveGranularity cannot be less than vm_allocation_granularity (or _large_page_size if using large pages) + size_t min_interleave_granularity = UseLargePages ? _large_page_size : os::vm_allocation_granularity(); + NUMAInterleaveGranularity = align_size_up(NUMAInterleaveGranularity, min_interleave_granularity); + + if (os::Kernel32Dll::NumaCallsAvailable()) { + if (numa_node_list_holder.build()) { + if (PrintMiscellaneous && Verbose) { + tty->print("NUMA UsedNodeCount=%d, namely ", os::numa_get_groups_num()); + for (int i = 0; i < numa_node_list_holder.get_count(); i++) { + tty->print("%d ", numa_node_list_holder.get_node_list_entry(i)); + } + tty->print("\n"); + } + success = true; + } else { + WARN("Process does not cover multiple NUMA nodes."); + } + } else { + WARN("NUMA Interleaving is not supported by the operating system."); + } + if (!success) { + if (use_numa_specified) WARN("...Ignoring UseNUMA flag."); + if (use_numa_interleaving_specified) WARN("...Ignoring UseNUMAInterleaving flag."); + } + return success; +#undef WARN +} + +// this routine is used whenever we need to reserve a contiguous VA range +// but we need to make separate VirtualAlloc calls for each piece of the range +// Reasons for doing this: +// * UseLargePagesIndividualAllocation was set (normally only needed on WS2003 but possible to be set otherwise) +// * UseNUMAInterleaving requires a separate node for each piece +static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, DWORD prot, + bool should_inject_error=false) { + char * p_buf; + // note: at setup time we guaranteed that NUMAInterleaveGranularity was aligned up to a page size + size_t page_size = UseLargePages ? _large_page_size : os::vm_allocation_granularity(); + size_t chunk_size = UseNUMAInterleaving ? NUMAInterleaveGranularity : page_size; + + // first reserve enough address space in advance since we want to be + // able to break a single contiguous virtual address range into multiple + // large page commits but WS2003 does not allow reserving large page space + // so we just use 4K pages for reserve, this gives us a legal contiguous + // address space. then we will deallocate that reservation, and re alloc + // using large pages + const size_t size_of_reserve = bytes + chunk_size; + if (bytes > size_of_reserve) { + // Overflowed. + return NULL; + } + p_buf = (char *) VirtualAlloc(addr, + size_of_reserve, // size of Reserve + MEM_RESERVE, + PAGE_READWRITE); + // If reservation failed, return NULL + if (p_buf == NULL) return NULL; + + os::release_memory(p_buf, bytes + chunk_size); + + // we still need to round up to a page boundary (in case we are using large pages) + // but not to a chunk boundary (in case InterleavingGranularity doesn't align with page size) + // instead we handle this in the bytes_to_rq computation below + p_buf = (char *) align_size_up((size_t)p_buf, page_size); + + // now go through and allocate one chunk at a time until all bytes are + // allocated + size_t bytes_remaining = bytes; + // An overflow of align_size_up() would have been caught above + // in the calculation of size_of_reserve. + char * next_alloc_addr = p_buf; + HANDLE hProc = GetCurrentProcess(); + +#ifdef ASSERT + // Variable for the failure injection + long ran_num = os::random(); + size_t fail_after = ran_num % bytes; +#endif + + int count=0; + while (bytes_remaining) { + // select bytes_to_rq to get to the next chunk_size boundary + + size_t bytes_to_rq = MIN2(bytes_remaining, chunk_size - ((size_t)next_alloc_addr % chunk_size)); + // Note allocate and commit + char * p_new; + +#ifdef ASSERT + bool inject_error_now = should_inject_error && (bytes_remaining <= fail_after); +#else + const bool inject_error_now = false; +#endif + + if (inject_error_now) { + p_new = NULL; + } else { + if (!UseNUMAInterleaving) { + p_new = (char *) VirtualAlloc(next_alloc_addr, + bytes_to_rq, + flags, + prot); + } else { + // get the next node to use from the used_node_list + DWORD node = numa_node_list_holder.get_node_list_entry(count % os::numa_get_groups_num()); + p_new = (char *)os::Kernel32Dll::VirtualAllocExNuma(hProc, + next_alloc_addr, + bytes_to_rq, + flags, + prot, + node); + } + } + + if (p_new == NULL) { + // Free any allocated pages + if (next_alloc_addr > p_buf) { + // Some memory was committed so release it. + size_t bytes_to_release = bytes - bytes_remaining; + os::release_memory(p_buf, bytes_to_release); + } +#ifdef ASSERT + if (should_inject_error) { + if (TracePageSizes && Verbose) { + tty->print_cr("Reserving pages individually failed."); + } + } +#endif + return NULL; + } + bytes_remaining -= bytes_to_rq; + next_alloc_addr += bytes_to_rq; + count++; + } + // made it this far, success + return p_buf; +} + + + void os::large_page_init() { if (!UseLargePages) return; @@ -2722,9 +2921,30 @@ char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); - char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); + char* res; + // note that if UseLargePages is on, all the areas that require interleaving + // will go thru reserve_memory_special rather than thru here. + bool use_individual = (UseNUMAInterleaving && !UseLargePages); + if (!use_individual) { + res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); + } else { + elapsedTimer reserveTimer; + if( Verbose && PrintMiscellaneous ) reserveTimer.start(); + // in numa interleaving, we have to allocate pages individually + // (well really chunks of NUMAInterleaveGranularity size) + res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE); + if (res == NULL) { + warning("NUMA page allocation failed"); + } + if( Verbose && PrintMiscellaneous ) { + reserveTimer.stop(); + tty->print_cr("reserve_memory of %Ix bytes took %ld ms (%ld ticks)", bytes, + reserveTimer.milliseconds(), reserveTimer.ticks()); + } + } assert(res == NULL || addr == NULL || addr == res, "Unexpected address from reserve."); + return res; } @@ -2754,92 +2974,27 @@ bool os::can_execute_large_page_memory() { char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; + const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; - if (UseLargePagesIndividualAllocation) { + // with large pages, there are two cases where we need to use Individual Allocation + // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) + // 2) NUMA Interleaving is enabled, in which case we use a different node for each page + if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { if (TracePageSizes && Verbose) { tty->print_cr("Reserving large pages individually."); } - char * p_buf; - // first reserve enough address space in advance since we want to be - // able to break a single contiguous virtual address range into multiple - // large page commits but WS2003 does not allow reserving large page space - // so we just use 4K pages for reserve, this gives us a legal contiguous - // address space. then we will deallocate that reservation, and re alloc - // using large pages - const size_t size_of_reserve = bytes + _large_page_size; - if (bytes > size_of_reserve) { - // Overflowed. - warning("Individually allocated large pages failed, " - "use -XX:-UseLargePagesIndividualAllocation to turn off"); + char * p_buf = allocate_pages_individually(bytes, addr, flags, prot, LargePagesIndividualAllocationInjectError); + if (p_buf == NULL) { + // give an appropriate warning message + if (UseNUMAInterleaving) { + warning("NUMA large page allocation failed, UseLargePages flag ignored"); + } + if (UseLargePagesIndividualAllocation) { + warning("Individually allocated large pages failed, " + "use -XX:-UseLargePagesIndividualAllocation to turn off"); + } return NULL; } - p_buf = (char *) VirtualAlloc(addr, - size_of_reserve, // size of Reserve - MEM_RESERVE, - PAGE_READWRITE); - // If reservation failed, return NULL - if (p_buf == NULL) return NULL; - - release_memory(p_buf, bytes + _large_page_size); - // round up to page boundary. If the size_of_reserve did not - // overflow and the reservation did not fail, this align up - // should not overflow. - p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size); - - // now go through and allocate one page at a time until all bytes are - // allocated - size_t bytes_remaining = align_size_up(bytes, _large_page_size); - // An overflow of align_size_up() would have been caught above - // in the calculation of size_of_reserve. - char * next_alloc_addr = p_buf; - -#ifdef ASSERT - // Variable for the failure injection - long ran_num = os::random(); - size_t fail_after = ran_num % bytes; -#endif - - while (bytes_remaining) { - size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size); - // Note allocate and commit - char * p_new; - -#ifdef ASSERT - bool inject_error = LargePagesIndividualAllocationInjectError && - (bytes_remaining <= fail_after); -#else - const bool inject_error = false; -#endif - - if (inject_error) { - p_new = NULL; - } else { - p_new = (char *) VirtualAlloc(next_alloc_addr, - bytes_to_rq, - MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, - prot); - } - - if (p_new == NULL) { - // Free any allocated pages - if (next_alloc_addr > p_buf) { - // Some memory was committed so release it. - size_t bytes_to_release = bytes - bytes_remaining; - release_memory(p_buf, bytes_to_release); - } -#ifdef ASSERT - if (UseLargePagesIndividualAllocation && - LargePagesIndividualAllocationInjectError) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages individually failed."); - } - } -#endif - return NULL; - } - bytes_remaining -= bytes_to_rq; - next_alloc_addr += bytes_to_rq; - } return p_buf; @@ -2867,14 +3022,43 @@ bool os::commit_memory(char* addr, size_t bytes, bool exec) { assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks"); // Don't attempt to print anything if the OS call fails. We're // probably low on resources, so the print itself may cause crashes. - bool result = VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) != 0; - if (result != NULL && exec) { - DWORD oldprot; - // Windows doc says to use VirtualProtect to get execute permissions - return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot) != 0; + + // unless we have NUMAInterleaving enabled, the range of a commit + // is always within a reserve covered by a single VirtualAlloc + // in that case we can just do a single commit for the requested size + if (!UseNUMAInterleaving) { + if (VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) == NULL) return false; + if (exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + if (!VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot)) return false; + } + return true; } else { - return result; + + // when NUMAInterleaving is enabled, the commit might cover a range that + // came from multiple VirtualAlloc reserves (using allocate_pages_individually). + // VirtualQuery can help us determine that. The RegionSize that VirtualQuery + // returns represents the number of bytes that can be committed in one step. + size_t bytes_remaining = bytes; + char * next_alloc_addr = addr; + while (bytes_remaining > 0) { + MEMORY_BASIC_INFORMATION alloc_info; + VirtualQuery(next_alloc_addr, &alloc_info, sizeof(alloc_info)); + size_t bytes_to_rq = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize); + if (VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_COMMIT, PAGE_READWRITE) == NULL) + return false; + if (exec) { + DWORD oldprot; + if (!VirtualProtect(next_alloc_addr, bytes_to_rq, PAGE_EXECUTE_READWRITE, &oldprot)) + return false; + } + bytes_remaining -= bytes_to_rq; + next_alloc_addr += bytes_to_rq; + } } + // if we made it this far, return true + return true; } bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, @@ -2948,14 +3132,15 @@ void os::free_memory(char *addr, size_t bytes) { } void os::numa_make_global(char *addr, size_t bytes) { } void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { } bool os::numa_topology_changed() { return false; } -size_t os::numa_get_groups_num() { return 1; } +size_t os::numa_get_groups_num() { return numa_node_list_holder.get_count(); } int os::numa_get_group_id() { return 0; } size_t os::numa_get_leaf_groups(int *ids, size_t size) { - if (size > 0) { - ids[0] = 0; - return 1; + // check for size bigger than actual groups_num + size = MIN2(size, numa_get_groups_num()); + for (int i = 0; i < (int)size; i++) { + ids[i] = numa_node_list_holder.get_node_list_entry(i); } - return 0; + return size; } bool os::get_page_info(char *start, page_info* info) { @@ -3480,7 +3665,7 @@ jint os::init_2(void) { if(Verbose && PrintMiscellaneous) tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); #endif -} + } os::large_page_init(); @@ -3583,8 +3768,10 @@ jint os::init_2(void) { // initialize thread priority policy prio_init(); - if (UseNUMA && !ForceNUMA) { - UseNUMA = false; // Currently unsupported. + if (UseNUMAInterleaving) { + // first check whether this Windows OS supports VirtualAllocExNuma, if not ignore this flag + bool success = numa_interleaving_init(); + if (!success) UseNUMAInterleaving = false; } return JNI_OK; @@ -4758,7 +4945,14 @@ int os::set_sock_opt(int fd, int level, int optname, // Kernel32 API typedef SIZE_T (WINAPI* GetLargePageMinimum_Fn)(void); +typedef LPVOID (WINAPI *VirtualAllocExNuma_Fn) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); +typedef BOOL (WINAPI *GetNumaHighestNodeNumber_Fn) (PULONG); +typedef BOOL (WINAPI *GetNumaNodeProcessorMask_Fn) (UCHAR, PULONGLONG); + GetLargePageMinimum_Fn os::Kernel32Dll::_GetLargePageMinimum = NULL; +VirtualAllocExNuma_Fn os::Kernel32Dll::_VirtualAllocExNuma = NULL; +GetNumaHighestNodeNumber_Fn os::Kernel32Dll::_GetNumaHighestNodeNumber = NULL; +GetNumaNodeProcessorMask_Fn os::Kernel32Dll::_GetNumaNodeProcessorMask = NULL; BOOL os::Kernel32Dll::initialized = FALSE; SIZE_T os::Kernel32Dll::GetLargePageMinimum() { assert(initialized && _GetLargePageMinimum != NULL, @@ -4773,19 +4967,56 @@ BOOL os::Kernel32Dll::GetLargePageMinimumAvailable() { return _GetLargePageMinimum != NULL; } +BOOL os::Kernel32Dll::NumaCallsAvailable() { + if (!initialized) { + initialize(); + } + return _VirtualAllocExNuma != NULL; +} -#ifndef JDK6_OR_EARLIER +LPVOID os::Kernel32Dll::VirtualAllocExNuma(HANDLE hProc, LPVOID addr, SIZE_T bytes, DWORD flags, DWORD prot, DWORD node) { + assert(initialized && _VirtualAllocExNuma != NULL, + "NUMACallsAvailable() not yet called"); -void os::Kernel32Dll::initialize() { + return _VirtualAllocExNuma(hProc, addr, bytes, flags, prot, node); +} + +BOOL os::Kernel32Dll::GetNumaHighestNodeNumber(PULONG ptr_highest_node_number) { + assert(initialized && _GetNumaHighestNodeNumber != NULL, + "NUMACallsAvailable() not yet called"); + + return _GetNumaHighestNodeNumber(ptr_highest_node_number); +} + +BOOL os::Kernel32Dll::GetNumaNodeProcessorMask(UCHAR node, PULONGLONG proc_mask) { + assert(initialized && _GetNumaNodeProcessorMask != NULL, + "NUMACallsAvailable() not yet called"); + + return _GetNumaNodeProcessorMask(node, proc_mask); +} + + +void os::Kernel32Dll::initializeCommon() { if (!initialized) { HMODULE handle = ::GetModuleHandle("Kernel32.dll"); assert(handle != NULL, "Just check"); _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum"); + _VirtualAllocExNuma = (VirtualAllocExNuma_Fn)::GetProcAddress(handle, "VirtualAllocExNuma"); + _GetNumaHighestNodeNumber = (GetNumaHighestNodeNumber_Fn)::GetProcAddress(handle, "GetNumaHighestNodeNumber"); + _GetNumaNodeProcessorMask = (GetNumaNodeProcessorMask_Fn)::GetProcAddress(handle, "GetNumaNodeProcessorMask"); initialized = TRUE; } } + +#ifndef JDK6_OR_EARLIER + +void os::Kernel32Dll::initialize() { + initializeCommon(); +} + + // Kernel32 API inline BOOL os::Kernel32Dll::SwitchToThread() { return ::SwitchToThread(); @@ -4887,18 +5118,19 @@ Module32First_Fn os::Kernel32Dll::_Module32First = NULL; Module32Next_Fn os::Kernel32Dll::_Module32Next = NULL; GetNativeSystemInfo_Fn os::Kernel32Dll::_GetNativeSystemInfo = NULL; + void os::Kernel32Dll::initialize() { if (!initialized) { HMODULE handle = ::GetModuleHandle("Kernel32.dll"); assert(handle != NULL, "Just check"); _SwitchToThread = (SwitchToThread_Fn)::GetProcAddress(handle, "SwitchToThread"); - _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum"); _CreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_Fn) ::GetProcAddress(handle, "CreateToolhelp32Snapshot"); _Module32First = (Module32First_Fn)::GetProcAddress(handle, "Module32First"); _Module32Next = (Module32Next_Fn)::GetProcAddress(handle, "Module32Next"); _GetNativeSystemInfo = (GetNativeSystemInfo_Fn)::GetProcAddress(handle, "GetNativeSystemInfo"); + initializeCommon(); // resolve the functions that always need resolving initialized = TRUE; } @@ -4964,6 +5196,8 @@ void os::Kernel32Dll::GetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo) { _GetNativeSystemInfo(lpSystemInfo); } + + // PSAPI API diff --git a/hotspot/src/os/windows/vm/os_windows.hpp b/hotspot/src/os/windows/vm/os_windows.hpp index a4ba31701f6..353d595ebc7 100644 --- a/hotspot/src/os/windows/vm/os_windows.hpp +++ b/hotspot/src/os/windows/vm/os_windows.hpp @@ -173,13 +173,25 @@ public: static BOOL GetNativeSystemInfoAvailable(); static void GetNativeSystemInfo(LPSYSTEM_INFO); + // NUMA calls + static BOOL NumaCallsAvailable(); + static LPVOID VirtualAllocExNuma(HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); + static BOOL GetNumaHighestNodeNumber(PULONG); + static BOOL GetNumaNodeProcessorMask(UCHAR, PULONGLONG); + private: // GetLargePageMinimum available on Windows Vista/Windows Server 2003 // and later + // NUMA calls available Windows Vista/WS2008 and later + static SIZE_T (WINAPI *_GetLargePageMinimum)(void); + static LPVOID (WINAPI *_VirtualAllocExNuma) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); + static BOOL (WINAPI *_GetNumaHighestNodeNumber) (PULONG); + static BOOL (WINAPI *_GetNumaNodeProcessorMask) (UCHAR, PULONGLONG); static BOOL initialized; static void initialize(); + static void initializeCommon(); #ifdef JDK6_OR_EARLIER private: diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index c159e48f0be..ed9a14b2909 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1423,6 +1423,9 @@ void Arguments::set_parallel_gc_flags() { if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M); } + // For those collectors or operating systems (eg, Windows) that do + // not support full UseNUMA, we will map to UseNUMAInterleaving for now + UseNUMAInterleaving = true; } } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index e044933344a..8a5dbc38ae7 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -475,6 +475,12 @@ class CommandLineFlags { product(bool, UseNUMA, false, \ "Use NUMA if available") \ \ + product(bool, UseNUMAInterleaving, false, \ + "Interleave memory across NUMA nodes if available") \ + \ + product(uintx, NUMAInterleaveGranularity, 2*M, \ + "Granularity to use for NUMA interleaving on Windows OS") \ + \ product(bool, ForceNUMA, false, \ "Force NUMA optimizations on single-node/UMA systems") \ \ From 19f7fb98b8a2f9c31451fbd4c39203976e372f54 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 25 Aug 2011 20:29:30 -0700 Subject: [PATCH 002/214] 7082949: JSR 292: missing ResourceMark in methodOopDesc::make_invoke_method Reviewed-by: kvn, twisti --- hotspot/src/share/vm/oops/methodOop.cpp | 1 + .../test/compiler/7082949/Test7082949.java | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 hotspot/test/compiler/7082949/Test7082949.java diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 6575679ea69..0f03ae43c66 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -914,6 +914,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, Symbol* name, Symbol* signature, Handle method_type, TRAPS) { + ResourceMark rm; methodHandle empty; assert(holder() == SystemDictionary::MethodHandle_klass(), diff --git a/hotspot/test/compiler/7082949/Test7082949.java b/hotspot/test/compiler/7082949/Test7082949.java new file mode 100644 index 00000000000..41b79114f62 --- /dev/null +++ b/hotspot/test/compiler/7082949/Test7082949.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7082949 + * @summary JSR 292: missing ResourceMark in methodOopDesc::make_invoke_method + * + * @run main Test7082949 + */ + +import java.lang.invoke.*; +import static java.lang.invoke.MethodHandles.*; +import static java.lang.invoke.MethodType.*; + +public class Test7082949 implements Runnable { + public static void main(String... args) throws Throwable { + new Thread(new Test7082949()).start(); + } + + public static Test7082949 test() { + return null; + } + + public void run() { + try { + MethodHandle m1 = MethodHandles.lookup().findStatic(Test7082949.class, "test", methodType(Test7082949.class)); + Test7082949 v = (Test7082949)m1.invokeExact(); + } catch (Throwable t) { + t.printStackTrace(); + } + } +} From 644620568827ddd5f5a4dc130d615ed6fd915c2d Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 26 Aug 2011 08:52:22 -0700 Subject: [PATCH 003/214] 7059037: Use BIS for zeroing on T4 Use BIS for zeroing new allocated big (2Kb and more) objects and arrays. Reviewed-by: never, twisti, ysr --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 62 ++++++++++++ hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 14 ++- hotspot/src/cpu/sparc/vm/copy_sparc.hpp | 8 ++ hotspot/src/cpu/sparc/vm/sparc.ad | 97 ++++++++++++++----- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 32 ++++++ .../src/cpu/sparc/vm/templateTable_sparc.cpp | 8 +- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 10 ++ hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp | 4 +- .../share/vm/gc_interface/collectedHeap.cpp | 10 +- .../vm/gc_interface/collectedHeap.inline.hpp | 5 +- hotspot/src/share/vm/oops/cpCacheKlass.cpp | 6 +- hotspot/src/share/vm/runtime/globals.hpp | 6 ++ hotspot/src/share/vm/runtime/stubRoutines.cpp | 1 + hotspot/src/share/vm/runtime/stubRoutines.hpp | 4 + 14 files changed, 232 insertions(+), 35 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 4e5d90eaabe..3ee5b72ca92 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -4973,3 +4973,65 @@ void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, // Caller should set it: // add(G0, 1, result); // equals } + +// Use BIS for zeroing (count is in bytes). +void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { + assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); + Register end = count; + int cache_line_size = VM_Version::prefetch_data_size(); + // Minimum count when BIS zeroing can be used since + // it needs membar which is expensive. + int block_zero_size = MAX2(cache_line_size*3, (int)BlockZeroingLowLimit); + + Label small_loop; + // Check if count is negative (dead code) or zero. + // Note, count uses 64bit in 64 bit VM. + cmp_and_brx_short(count, 0, Assembler::lessEqual, Assembler::pn, Ldone); + + // Use BIS zeroing only for big arrays since it requires membar. + if (Assembler::is_simm13(block_zero_size)) { // < 4096 + cmp(count, block_zero_size); + } else { + set(block_zero_size, temp); + cmp(count, temp); + } + br(Assembler::lessUnsigned, false, Assembler::pt, small_loop); + delayed()->add(to, count, end); + + // Note: size is >= three (32 bytes) cache lines. + + // Clean the beginning of space up to next cache line. + for (int offs = 0; offs < cache_line_size; offs += 8) { + stx(G0, to, offs); + } + + // align to next cache line + add(to, cache_line_size, to); + and3(to, -cache_line_size, to); + + // Note: size left >= two (32 bytes) cache lines. + + // BIS should not be used to zero tail (64 bytes) + // to avoid zeroing a header of the following object. + sub(end, (cache_line_size*2)-8, end); + + Label bis_loop; + bind(bis_loop); + stxa(G0, to, G0, Assembler::ASI_ST_BLKINIT_PRIMARY); + add(to, cache_line_size, to); + cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, bis_loop); + + // BIS needs membar. + membar(Assembler::StoreLoad); + + add(end, (cache_line_size*2)-8, end); // restore end + cmp_and_brx_short(to, end, Assembler::greaterEqualUnsigned, Assembler::pn, Ldone); + + // Clean the tail. + bind(small_loop); + stx(G0, to, 0); + add(to, 8, to); + cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); + nop(); // Separate short branches +} + diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 4462ee5d00f..f82d29a4a3b 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -885,8 +885,9 @@ class Assembler : public AbstractAssembler { } enum ASIs { // page 72, v9 - ASI_PRIMARY = 0x80, - ASI_PRIMARY_LITTLE = 0x88, + ASI_PRIMARY = 0x80, + ASI_PRIMARY_NOFAULT = 0x82, + ASI_PRIMARY_LITTLE = 0x88, // Block initializing store ASI_ST_BLKINIT_PRIMARY = 0xE2, // Most-Recently-Used (MRU) BIS variant @@ -1786,9 +1787,12 @@ public: rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25) | - u_field(1, 13, 13) | + immed(true) | simm(simm13a, 13)); } - inline void wrasi( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } + inline void wrasi(Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } + // wrasi(d, imm) stores (d xor imm) to asi + inline void wrasi(Register d, int simm13a) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | + u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); } inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); } @@ -2631,6 +2635,8 @@ public: void char_arrays_equals(Register ary1, Register ary2, Register limit, Register result, Register chr1, Register chr2, Label& Ldone); + // Use BIS for zeroing + void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); #undef VIRTUAL diff --git a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp index 0267d25a670..176ed041c61 100644 --- a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp @@ -156,9 +156,16 @@ static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { #endif // _LP64 } +typedef void (*_zero_Fn)(HeapWord* to, size_t count); + static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) { assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); + if (value == 0 && UseBlockZeroing && + (count > (BlockZeroingLowLimit >> LogHeapWordSize))) { + // Call it only when block zeroing is used + ((_zero_Fn)StubRoutines::zero_aligned_words())(tohw, count); + } else { julong* to = (julong*)tohw; julong v = ((julong)value << 32) | value; // If count is odd, odd will be equal to 1 on 32-bit platform @@ -176,6 +183,7 @@ static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) *((juint*)to) = value; } + } } static void pd_fill_to_bytes(void* to, size_t count, jubyte value) { diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index cd57f2c7d74..b999716c068 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -460,6 +460,8 @@ source_hpp %{ // Must be visible to the DFA in dfa_sparc.cpp extern bool can_branch_register( Node *bol, Node *cmp ); +extern bool use_block_zeroing(Node* count); + // Macros to extract hi & lo halves from a long pair. // G0 is not part of any long pair, so assert on that. // Prevents accidentally using G1 instead of G0. @@ -521,6 +523,12 @@ bool can_branch_register( Node *bol, Node *cmp ) { return false; } +bool use_block_zeroing(Node* count) { + // Use BIS for zeroing if count is not constant + // or it is >= BlockZeroingLowLimit. + return UseBlockZeroing && (count->find_intptr_t_con(BlockZeroingLowLimit) >= BlockZeroingLowLimit); +} + // **************************************************************************** // REQUIRED FUNCTIONALITY @@ -2810,25 +2818,6 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); %} - // Compiler ensures base is doubleword aligned and cnt is count of doublewords - enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{ - MacroAssembler _masm(&cbuf); - Register nof_bytes_arg = reg_to_register_object($cnt$$reg); - Register nof_bytes_tmp = reg_to_register_object($temp$$reg); - Register base_pointer_arg = reg_to_register_object($base$$reg); - - Label loop; - __ mov(nof_bytes_arg, nof_bytes_tmp); - - // Loop and clear, walking backwards through the array. - // nof_bytes_tmp (if >0) is always the number of bytes to zero - __ bind(loop); - __ deccc(nof_bytes_tmp, 8); - __ br(Assembler::greaterEqual, true, Assembler::pt, loop); - __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); - // %%%% this mini-loop must not cross a cache boundary! - %} - enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ Label Ldone, Lloop; @@ -10257,9 +10246,9 @@ instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, o ins_pipe(long_memory_op); %} -// Count and Base registers are fixed because the allocator cannot -// kill unknown registers. The encodings are generic. +// The encodings are generic. instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg ccr) %{ + predicate(!use_block_zeroing(n->in(2)) ); match(Set dummy (ClearArray cnt base)); effect(TEMP temp, KILL ccr); ins_cost(300); @@ -10267,7 +10256,71 @@ instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg "loop: SUBcc $temp,8,$temp\t! Count down a dword of bytes\n" " BRge loop\t\t! Clearing loop\n" " STX G0,[$base+$temp]\t! delay slot" %} - ins_encode( enc_Clear_Array(cnt, base, temp) ); + + ins_encode %{ + // Compiler ensures base is doubleword aligned and cnt is count of doublewords + Register nof_bytes_arg = $cnt$$Register; + Register nof_bytes_tmp = $temp$$Register; + Register base_pointer_arg = $base$$Register; + + Label loop; + __ mov(nof_bytes_arg, nof_bytes_tmp); + + // Loop and clear, walking backwards through the array. + // nof_bytes_tmp (if >0) is always the number of bytes to zero + __ bind(loop); + __ deccc(nof_bytes_tmp, 8); + __ br(Assembler::greaterEqual, true, Assembler::pt, loop); + __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); + // %%%% this mini-loop must not cross a cache boundary! + %} + ins_pipe(long_memory_op); +%} + +instruct clear_array_bis(g1RegX cnt, o0RegP base, Universe dummy, flagsReg ccr) %{ + predicate(use_block_zeroing(n->in(2))); + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL cnt, USE_KILL base, KILL ccr); + ins_cost(300); + format %{ "CLEAR [$base, $cnt]\t! ClearArray" %} + + ins_encode %{ + + assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); + Register to = $base$$Register; + Register count = $cnt$$Register; + + Label Ldone; + __ nop(); // Separate short branches + // Use BIS for zeroing (temp is not used). + __ bis_zeroing(to, count, G0, Ldone); + __ bind(Ldone); + + %} + ins_pipe(long_memory_op); +%} + +instruct clear_array_bis_2(g1RegX cnt, o0RegP base, iRegX tmp, Universe dummy, flagsReg ccr) %{ + predicate(use_block_zeroing(n->in(2)) && !Assembler::is_simm13((int)BlockZeroingLowLimit)); + match(Set dummy (ClearArray cnt base)); + effect(TEMP tmp, USE_KILL cnt, USE_KILL base, KILL ccr); + ins_cost(300); + format %{ "CLEAR [$base, $cnt]\t! ClearArray" %} + + ins_encode %{ + + assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); + Register to = $base$$Register; + Register count = $cnt$$Register; + Register temp = $tmp$$Register; + + Label Ldone; + __ nop(); // Separate short branches + // Use BIS for zeroing + __ bis_zeroing(to, count, temp, Ldone); + __ bind(Ldone); + + %} ins_pipe(long_memory_op); %} diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 3c149bf942a..9f6274d5aae 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -3069,6 +3069,34 @@ class StubGenerator: public StubCodeGenerator { return start; } + // + // Generate stub for heap zeroing. + // "to" address is aligned to jlong (8 bytes). + // + // Arguments for generated stub: + // to: O0 + // count: O1 treated as signed (count of HeapWord) + // count could be 0 + // + address generate_zero_aligned_words(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + const Register to = O0; // source array address + const Register count = O1; // HeapWords count + const Register temp = O2; // scratch + + Label Ldone; + __ sllx(count, LogHeapWordSize, count); // to bytes count + // Use BIS for zeroing + __ bis_zeroing(to, count, temp, Ldone); + __ bind(Ldone); + __ retl(); + __ delayed()->nop(); + return start; +} + void generate_arraycopy_stubs() { address entry; address entry_jbyte_arraycopy; @@ -3195,6 +3223,10 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); + + if (UseBlockZeroing) { + StubRoutines::_zero_aligned_words = generate_zero_aligned_words("zero_aligned_words"); + } } void generate_initial() { diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 25b2256ff44..850dbe62a25 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -3374,7 +3374,7 @@ void TemplateTable::_new() { if(UseTLAB) { Register RoldTopValue = RallocatedObject; - Register RtopAddr = G3_scratch, RtlabWasteLimitValue = G3_scratch; + Register RtlabWasteLimitValue = G3_scratch; Register RnewTopValue = G1_scratch; Register RendValue = Rscratch; Register RfreeValue = RnewTopValue; @@ -3455,7 +3455,11 @@ void TemplateTable::_new() { __ delayed()->add(RallocatedObject, sizeof(oopDesc), G3_scratch); // initialize remaining object fields - { Label loop; + if (UseBlockZeroing) { + // Use BIS for zeroing + __ bis_zeroing(G3_scratch, Roffset, G1_scratch, initialize_header); + } else { + Label loop; __ subcc(Roffset, wordSize, Roffset); __ bind(loop); //__ subcc(Roffset, wordSize, Roffset); // executed above loop or in delay slot diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 6f9ca4ea9c2..2aae43c281a 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -170,6 +170,16 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseCBCond, false); } + assert(BlockZeroingLowLimit > 0, "invalid value"); + if (has_block_zeroing()) { + if (FLAG_IS_DEFAULT(UseBlockZeroing)) { + FLAG_SET_DEFAULT(UseBlockZeroing, true); + } + } else if (UseBlockZeroing) { + warning("BIS zeroing instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseBlockZeroing, false); + } + #ifdef COMPILER2 // T4 and newer Sparc cpus have fast RDPC. if (has_fast_rdpc() && FLAG_IS_DEFAULT(UseRDPCForConstantTableBase)) { diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index 9c9b8fc6f3e..db3343b5157 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -135,8 +135,8 @@ public: // T4 and newer Sparc have fast RDPC instruction. static bool has_fast_rdpc() { return is_T4(); } - // T4 and newer Sparc have Most-Recently-Used (MRU) BIS. - static bool has_mru_blk_init() { return has_blk_init() && is_T4(); } + // On T4 and newer Sparc BIS to the beginning of cache line always zeros it. + static bool has_block_zeroing() { return has_blk_init() && is_T4(); } static const char* cpu_features() { return _features_str; } diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp index 6b99a8f6298..1ead9eef759 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp @@ -157,8 +157,14 @@ HeapWord* CollectedHeap::allocate_from_tlab_slow(Thread* thread, size_t size) { // ..and clear it. Copy::zero_to_words(obj, new_tlab_size); } else { - // ...and clear just the allocated object. - Copy::zero_to_words(obj, size); + // ...and zap just allocated object. +#ifdef ASSERT + // Skip mangling the space corresponding to the object header to + // ensure that the returned space is not considered parsable by + // any concurrent GC thread. + size_t hdr_size = oopDesc::header_size(); + Copy::fill_to_words(obj + hdr_size, new_tlab_size - hdr_size, badHeapWordVal); +#endif // ASSERT } thread->tlab().fill(obj, obj + size, new_tlab_size); return obj; diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp index 68003b75beb..cf9946d79e9 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp @@ -287,7 +287,10 @@ oop CollectedHeap::permanent_obj_allocate_no_klass_install(KlassHandle klass, assert(size >= 0, "int won't convert to size_t"); HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL); post_allocation_setup_no_klass_install(klass, obj, size); - NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); +#ifndef PRODUCT + const size_t hs = oopDesc::header_size(); + Universe::heap()->check_for_bad_heap_word_value(obj+hs, size-hs); +#endif return (oop)obj; } diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.cpp b/hotspot/src/share/vm/oops/cpCacheKlass.cpp index 86d9dc083b7..843f095d8d7 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp @@ -63,8 +63,10 @@ constantPoolCacheOop constantPoolCacheKlass::allocate(int length, // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); - NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, - size)); +#ifndef PRODUCT + const size_t hs = oopDesc::header_size(); + Universe::heap()->check_for_bad_heap_word_value(((HeapWord*) obj)+hs, size-hs); +#endif constantPoolCacheOop cache = (constantPoolCacheOop) obj; assert(!UseConcMarkSweepGC || obj->klass_or_null() == NULL, "klass should be NULL here when using CMS"); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index e044933344a..905379a727d 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1979,6 +1979,12 @@ class CommandLineFlags { product(bool, TLABStats, true, \ "Print various TLAB related information") \ \ + product(bool, UseBlockZeroing, false, \ + "Use special cpu instructions for block zeroing") \ + \ + product(intx, BlockZeroingLowLimit, 2048, \ + "Minimum size in bytes when block zeroing will be used") \ + \ product(bool, PrintRevisitStats, false, \ "Print revisit (klass and MDO) stack related information") \ \ diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index 6dd3a9f17bd..5f77761a249 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -108,6 +108,7 @@ address StubRoutines::_arrayof_jlong_disjoint_arraycopy = CAST_FROM_FN_PTR(addr address StubRoutines::_arrayof_oop_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy); address StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit); +address StubRoutines::_zero_aligned_words = CAST_FROM_FN_PTR(address, Copy::zero_to_words); address StubRoutines::_checkcast_arraycopy = NULL; address StubRoutines::_checkcast_arraycopy_uninit = NULL; diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index fff494e313f..e2ca75c812a 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -199,6 +199,9 @@ class StubRoutines: AllStatic { static address _arrayof_jshort_fill; static address _arrayof_jint_fill; + // zero heap space aligned to jlong (8 bytes) + static address _zero_aligned_words; + // These are versions of the java.lang.Math methods which perform // the same operations as the intrinsic version. They are used for // constant folding in the compiler to ensure equivalence. If the @@ -332,6 +335,7 @@ class StubRoutines: AllStatic { static address select_fill_function(BasicType t, bool aligned, const char* &name); + static address zero_aligned_words() { return _zero_aligned_words; } static double intrinsic_log(double d) { assert(_intrinsic_log != NULL, "must be defined"); From ec3f90d1b4984e7a7e808559f1563ed738eb95ce Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Sat, 27 Aug 2011 00:23:47 -0700 Subject: [PATCH 004/214] 6591247: C2 cleans up the merge point too early during SplitIf Remove region self reference last Reviewed-by: kvn, never --- hotspot/src/share/vm/opto/split_if.cpp | 39 ++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/hotspot/src/share/vm/opto/split_if.cpp b/hotspot/src/share/vm/opto/split_if.cpp index dba6ed1f29a..55de3d70ef8 100644 --- a/hotspot/src/share/vm/opto/split_if.cpp +++ b/hotspot/src/share/vm/opto/split_if.cpp @@ -500,19 +500,14 @@ void PhaseIdealLoop::do_split_if( Node *iff ) { region_cache.lru_insert( new_false, new_false ); region_cache.lru_insert( new_true , new_true ); // Now handle all uses of the splitting block - for (DUIterator_Last kmin, k = region->last_outs(kmin); k >= kmin; --k) { - Node* phi = region->last_out(k); - if( !phi->in(0) ) { // Dead phi? Remove it + for (DUIterator k = region->outs(); region->has_out(k); k++) { + Node* phi = region->out(k); + if (!phi->in(0)) { // Dead phi? Remove it _igvn.remove_dead_node(phi); - continue; - } - assert( phi->in(0) == region, "" ); - if( phi == region ) { // Found the self-reference - phi->set_req(0, NULL); - continue; // Break the self-cycle - } - // Expected common case: Phi hanging off of Region - if( phi->is_Phi() ) { + } else if (phi == region) { // Found the self-reference + continue; // No roll-back of DUIterator + } else if (phi->is_Phi()) { // Expected common case: Phi hanging off of Region + assert(phi->in(0) == region, "Inconsistent graph"); // Need a per-def cache. Phi represents a def, so make a cache small_cache phi_cache; @@ -524,23 +519,25 @@ void PhaseIdealLoop::do_split_if( Node *iff ) { // collection of PHI's merging values from different paths. The Phis // inserted depend only on the location of the USE. We use a // 2-element cache to handle multiple uses from the same block. - handle_use( use, phi, &phi_cache, region_dom, new_false, new_true, old_false, old_true ); + handle_use(use, phi, &phi_cache, region_dom, new_false, new_true, old_false, old_true); } // End of while phi has uses - - // Because handle_use might relocate region->_out, - // we must refresh the iterator. - k = region->last_outs(kmin); - // Remove the dead Phi _igvn.remove_dead_node( phi ); - } else { + assert(phi->in(0) == region, "Inconsistent graph"); // Random memory op guarded by Region. Compute new DEF for USE. - handle_use( phi, region, ®ion_cache, region_dom, new_false, new_true, old_false, old_true ); + handle_use(phi, region, ®ion_cache, region_dom, new_false, new_true, old_false, old_true); } - + // Every path above deletes a use of the region, except for the region + // self-cycle (which is needed by handle_use calling find_use_block + // calling get_ctrl calling get_ctrl_no_update looking for dead + // regions). So roll back the DUIterator innards. + --k; } // End of while merge point has phis + assert(region->outcnt() == 1, "Only self reference should remain"); // Just Self on the Region + region->set_req(0, NULL); // Break the self-cycle + // Any leftover bits in the splitting block must not have depended on local // Phi inputs (these have already been split-up). Hence it's safe to hoist // these guys to the dominating point. From e3342531b46b5180176d040ac5e908de17ca19bd Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 29 Aug 2011 05:07:35 -0700 Subject: [PATCH 005/214] 7083184: JSR 292: don't store context class argument with call site dependencies Reviewed-by: jrose, never --- hotspot/src/share/vm/ci/ciEnv.cpp | 49 +++++---- hotspot/src/share/vm/ci/ciEnv.hpp | 6 +- hotspot/src/share/vm/code/dependencies.cpp | 108 ++++++++++++-------- hotspot/src/share/vm/code/dependencies.hpp | 33 ++++-- hotspot/src/share/vm/memory/universe.cpp | 6 +- hotspot/src/share/vm/opto/callGenerator.cpp | 16 +-- 6 files changed, 135 insertions(+), 83 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 58f1aa03f47..97423169370 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -884,19 +884,31 @@ bool ciEnv::system_dictionary_modification_counter_changed() { } // ------------------------------------------------------------------ -// ciEnv::check_for_system_dictionary_modification -// Check for changes to the system dictionary during compilation -// class loads, evolution, breakpoints -void ciEnv::check_for_system_dictionary_modification(ciMethod* target) { +// ciEnv::validate_compile_task_dependencies +// +// Check for changes during compilation (e.g. class loads, evolution, +// breakpoints, call site invalidation). +void ciEnv::validate_compile_task_dependencies(ciMethod* target) { if (failing()) return; // no need for further checks - // Dependencies must be checked when the system dictionary changes. - // If logging is enabled all violated dependences will be recorded in - // the log. In debug mode check dependencies even if the system - // dictionary hasn't changed to verify that no invalid dependencies - // were inserted. Any violated dependences in this case are dumped to - // the tty. + // First, check non-klass dependencies as we might return early and + // not check klass dependencies if the system dictionary + // modification counter hasn't changed (see below). + for (Dependencies::DepStream deps(dependencies()); deps.next(); ) { + if (deps.is_klass_type()) continue; // skip klass dependencies + klassOop witness = deps.check_dependency(); + if (witness != NULL) { + record_failure("invalid non-klass dependency"); + return; + } + } + // Klass dependencies must be checked when the system dictionary + // changes. If logging is enabled all violated dependences will be + // recorded in the log. In debug mode check dependencies even if + // the system dictionary hasn't changed to verify that no invalid + // dependencies were inserted. Any violated dependences in this + // case are dumped to the tty. bool counter_changed = system_dictionary_modification_counter_changed(); bool test_deps = counter_changed; DEBUG_ONLY(test_deps = true); @@ -904,22 +916,21 @@ void ciEnv::check_for_system_dictionary_modification(ciMethod* target) { bool print_failures = false; DEBUG_ONLY(print_failures = !counter_changed); - bool keep_going = (print_failures || xtty != NULL); - - int violated = 0; + int klass_violations = 0; for (Dependencies::DepStream deps(dependencies()); deps.next(); ) { + if (!deps.is_klass_type()) continue; // skip non-klass dependencies klassOop witness = deps.check_dependency(); if (witness != NULL) { - ++violated; + klass_violations++; if (print_failures) deps.print_dependency(witness, /*verbose=*/ true); - // If there's no log and we're not sanity-checking, we're done. - if (!keep_going) break; } + // If there's no log and we're not sanity-checking, we're done. + if (!keep_going) break; } - if (violated != 0) { + if (klass_violations != 0) { assert(counter_changed, "failed dependencies, but counter didn't change"); record_failure("concurrent class loading"); } @@ -978,8 +989,8 @@ void ciEnv::register_method(ciMethod* target, // Encode the dependencies now, so we can check them right away. dependencies()->encode_content_bytes(); - // Check for {class loads, evolution, breakpoints} during compilation - check_for_system_dictionary_modification(target); + // Check for {class loads, evolution, breakpoints, ...} during compilation + validate_compile_task_dependencies(target); } methodHandle method(THREAD, target->get_methodOop()); diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index fb6647ccfe1..681531b5027 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -247,9 +247,9 @@ private: // Is this thread currently in the VM state? static bool is_in_vm(); - // Helper routine for determining the validity of a compilation - // with respect to concurrent class loading. - void check_for_system_dictionary_modification(ciMethod* target); + // Helper routine for determining the validity of a compilation with + // respect to method dependencies (e.g. concurrent class loading). + void validate_compile_task_dependencies(ciMethod* target); public: enum { diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp index 4579b1e95da..0a19acf74e3 100644 --- a/hotspot/src/share/vm/code/dependencies.cpp +++ b/hotspot/src/share/vm/code/dependencies.cpp @@ -113,9 +113,9 @@ void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { assert_common_1(no_finalizable_subclasses, ctxk); } -void Dependencies::assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle) { - check_ctxk(ctxk); - assert_common_3(call_site_target_value, ctxk, call_site, method_handle); +void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) { + check_ctxk(call_site->klass()); + assert_common_2(call_site_target_value, call_site, method_handle); } // Helper function. If we are adding a new dep. under ctxk2, @@ -135,7 +135,7 @@ bool Dependencies::maybe_merge_ctxk(GrowableArray* deps, } } -void Dependencies::assert_common_1(Dependencies::DepType dept, ciObject* x) { +void Dependencies::assert_common_1(DepType dept, ciObject* x) { assert(dep_args(dept) == 1, "sanity"); log_dependency(dept, x); GrowableArray* deps = _deps[dept]; @@ -148,21 +148,37 @@ void Dependencies::assert_common_1(Dependencies::DepType dept, ciObject* x) { } } -void Dependencies::assert_common_2(Dependencies::DepType dept, - ciKlass* ctxk, ciObject* x) { - assert(dep_context_arg(dept) == 0, "sanity"); +void Dependencies::assert_common_2(DepType dept, + ciObject* x0, ciObject* x1) { assert(dep_args(dept) == 2, "sanity"); - log_dependency(dept, ctxk, x); + log_dependency(dept, x0, x1); GrowableArray* deps = _deps[dept]; // see if the same (or a similar) dep is already recorded - if (note_dep_seen(dept, x)) { - // look in this bucket for redundant assertions - const int stride = 2; - for (int i = deps->length(); (i -= stride) >= 0; ) { - ciObject* x1 = deps->at(i+1); - if (x == x1) { // same subject; check the context - if (maybe_merge_ctxk(deps, i+0, ctxk)) { + bool has_ctxk = has_explicit_context_arg(dept); + if (has_ctxk) { + assert(dep_context_arg(dept) == 0, "sanity"); + if (note_dep_seen(dept, x1)) { + // look in this bucket for redundant assertions + const int stride = 2; + for (int i = deps->length(); (i -= stride) >= 0; ) { + ciObject* y1 = deps->at(i+1); + if (x1 == y1) { // same subject; check the context + if (maybe_merge_ctxk(deps, i+0, x0->as_klass())) { + return; + } + } + } + } + } else { + assert(dep_implicit_context_arg(dept) == 0, "sanity"); + if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) { + // look in this bucket for redundant assertions + const int stride = 2; + for (int i = deps->length(); (i -= stride) >= 0; ) { + ciObject* y0 = deps->at(i+0); + ciObject* y1 = deps->at(i+1); + if (x0 == y0 && x1 == y1) { return; } } @@ -170,11 +186,11 @@ void Dependencies::assert_common_2(Dependencies::DepType dept, } // append the assertion in the correct bucket: - deps->append(ctxk); - deps->append(x); + deps->append(x0); + deps->append(x1); } -void Dependencies::assert_common_3(Dependencies::DepType dept, +void Dependencies::assert_common_3(DepType dept, ciKlass* ctxk, ciObject* x, ciObject* x2) { assert(dep_context_arg(dept) == 0, "sanity"); assert(dep_args(dept) == 3, "sanity"); @@ -361,7 +377,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = { 3, // unique_concrete_subtypes_2 ctxk, k1, k2 3, // unique_concrete_methods_2 ctxk, m1, m2 1, // no_finalizable_subclasses ctxk - 3 // call_site_target_value ctxk, call_site, method_handle + 2 // call_site_target_value call_site, method_handle }; const char* Dependencies::dep_name(Dependencies::DepType dept) { @@ -375,10 +391,7 @@ int Dependencies::dep_args(Dependencies::DepType dept) { } void Dependencies::check_valid_dependency_type(DepType dept) { - for (int deptv = (int) FIRST_TYPE; deptv < (int) TYPE_LIMIT; deptv++) { - if (dept == ((DepType) deptv)) return; - } - ShouldNotReachHere(); + guarantee(FIRST_TYPE <= dept && dept < TYPE_LIMIT, err_msg("invalid dependency type: %d", (int) dept)); } // for the sake of the compiler log, print out current dependencies: @@ -586,8 +599,7 @@ bool Dependencies::DepStream::next() { code_byte -= ctxk_bit; DepType dept = (DepType)code_byte; _type = dept; - guarantee((dept - FIRST_TYPE) < (TYPE_LIMIT - FIRST_TYPE), - "bad dependency type tag"); + Dependencies::check_valid_dependency_type(dept); int stride = _dep_args[dept]; assert(stride == dep_args(dept), "sanity"); int skipj = -1; @@ -615,18 +627,35 @@ oop Dependencies::DepStream::argument(int i) { klassOop Dependencies::DepStream::context_type() { assert(must_be_in_vm(), "raw oops here"); - int ctxkj = dep_context_arg(_type); // -1 if no context arg - if (ctxkj < 0) { - return NULL; // for example, evol_method - } else { - oop k = recorded_oop_at(_xi[ctxkj]); - if (k != NULL) { // context type was not compressed away - assert(k->is_klass(), "type check"); - return (klassOop) k; - } else { // recompute "default" context type - return ctxk_encoded_as_null(_type, recorded_oop_at(_xi[ctxkj+1])); + + // Most dependencies have an explicit context type argument. + { + int ctxkj = dep_context_arg(_type); // -1 if no explicit context arg + if (ctxkj >= 0) { + oop k = argument(ctxkj); + if (k != NULL) { // context type was not compressed away + assert(k->is_klass(), "type check"); + return (klassOop) k; + } + // recompute "default" context type + return ctxk_encoded_as_null(_type, argument(ctxkj+1)); } } + + // Some dependencies are using the klass of the first object + // argument as implicit context type (e.g. call_site_target_value). + { + int ctxkj = dep_implicit_context_arg(_type); + if (ctxkj >= 0) { + oop k = argument(ctxkj)->klass(); + assert(k->is_klass(), "type check"); + return (klassOop) k; + } + } + + // And some dependencies don't have a context type at all, + // e.g. evol_method. + return NULL; } /// Checking dependencies: @@ -1409,21 +1438,20 @@ klassOop Dependencies::check_has_no_finalizable_subclasses(klassOop ctxk, KlassD } -klassOop Dependencies::check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) { +klassOop Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) { assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity"); assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity"); if (changes == NULL) { // Validate all CallSites if (java_lang_invoke_CallSite::target(call_site) != method_handle) - return ctxk; // assertion failed + return call_site->klass(); // assertion failed } else { // Validate the given CallSite if (call_site == changes->call_site() && java_lang_invoke_CallSite::target(call_site) != changes->method_handle()) { assert(method_handle != changes->method_handle(), "must be"); - return ctxk; // assertion failed + return call_site->klass(); // assertion failed } } - assert(java_lang_invoke_CallSite::target(call_site) == method_handle, "should still be valid"); return NULL; // assertion still valid } @@ -1488,7 +1516,7 @@ klassOop Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* klassOop witness = NULL; switch (type()) { case call_site_target_value: - witness = check_call_site_target_value(context_type(), argument(1), argument(2), changes); + witness = check_call_site_target_value(argument(0), argument(1), changes); break; default: witness = NULL; diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp index b4d930332c0..2b8b2afed10 100644 --- a/hotspot/src/share/vm/code/dependencies.hpp +++ b/hotspot/src/share/vm/code/dependencies.hpp @@ -166,9 +166,14 @@ class Dependencies: public ResourceObj { LG2_TYPE_LIMIT = 4, // assert(TYPE_LIMIT <= (1< recorded_oop_at(argument_index(i)) klassOop context_type(); + bool is_klass_type() { return Dependencies::is_klass_type(type()); } + methodOop method_argument(int i) { oop x = argument(i); assert(x->is_method(), "type"); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 146307b11d3..355341c430e 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -1203,12 +1203,12 @@ void Universe::flush_dependents_on(Handle call_site, Handle method_handle) { // Compute the dependent nmethods that have a reference to a // CallSite object. We use instanceKlass::mark_dependent_nmethod // directly instead of CodeCache::mark_for_deoptimization because we - // want dependents on the class CallSite only not all classes in the - // ContextStream. + // want dependents on the call site class only not all classes in + // the ContextStream. int marked = 0; { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - instanceKlass* call_site_klass = instanceKlass::cast(SystemDictionary::CallSite_klass()); + instanceKlass* call_site_klass = instanceKlass::cast(call_site->klass()); marked = call_site_klass->mark_dependent_nmethods(changes); } if (marked > 0) { diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 58426ddee09..b9defcdde36 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -336,7 +336,7 @@ CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj } CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { - assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch"); + assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch"); return new DynamicCallGenerator(m); } @@ -715,9 +715,9 @@ CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMS // Get an adapter for the MethodHandle. ciMethod* target_method = method_handle->get_method_handle_adapter(); if (target_method != NULL) { - CallGenerator* hit_cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, 1); - if (hit_cg != NULL && hit_cg->is_inline()) - return hit_cg; + CallGenerator* cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); + if (cg != NULL && cg->is_inline()) + return cg; } } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) { @@ -754,13 +754,13 @@ CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JV ciMethod* target_method = method_handle->get_invokedynamic_adapter(); if (target_method != NULL) { Compile *C = Compile::current(); - CallGenerator* hit_cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); - if (hit_cg != NULL && hit_cg->is_inline()) { + CallGenerator* cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); + if (cg != NULL && cg->is_inline()) { // Add a dependence for invalidation of the optimization. if (call_site->is_mutable_call_site()) { - C->dependencies()->assert_call_site_target_value(C->env()->CallSite_klass(), call_site, method_handle); + C->dependencies()->assert_call_site_target_value(call_site, method_handle); } - return hit_cg; + return cg; } } return NULL; From 1bec3a1bd3760386c09ca62f44aa70dbf830ac7d Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Mon, 29 Aug 2011 10:13:06 -0700 Subject: [PATCH 006/214] 7080389: G1: refactor marking code in evacuation pause copy closures Refactor code marking code in the evacuation pause copy closures so that an evacuated object is only marked by the thread that successfully copies it. Reviewed-by: stefank, brutisso, tonyp --- .../gc_implementation/g1/g1CollectedHeap.cpp | 82 ++++++++++++++++--- .../gc_implementation/g1/g1CollectedHeap.hpp | 16 ++-- .../vm/gc_implementation/g1/g1OopClosures.hpp | 10 +-- .../g1/g1_specialized_oop_closures.hpp | 2 +- 4 files changed, 81 insertions(+), 29 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 48b017dc64f..52b85d011bd 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4069,6 +4069,23 @@ bool GCLabBitMapClosure::do_bit(size_t offset) { } #endif // PRODUCT +G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : + ParGCAllocBuffer(gclab_word_size), + _should_mark_objects(false), + _bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size), + _retired(false) +{ + //_should_mark_objects is set to true when G1ParCopyHelper needs to + // mark the forwarded location of an evacuated object. + // We set _should_mark_objects to true if marking is active, i.e. when we + // need to propagate a mark, or during an initial mark pause, i.e. when we + // need to mark objects immediately reachable by the roots. + if (G1CollectedHeap::heap()->mark_in_progress() || + G1CollectedHeap::heap()->g1_policy()->during_initial_mark_pause()) { + _should_mark_objects = true; + } +} + G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) : _g1h(g1h), _refs(g1h->task_queue(queue_num)), @@ -4184,12 +4201,14 @@ void G1ParScanThreadState::trim_queue() { G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), - _par_scan_state(par_scan_state) { } + _par_scan_state(par_scan_state), + _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()), + _mark_in_progress(_g1->mark_in_progress()) { } -template void G1ParCopyHelper::mark_forwardee(T* p) { - // This is called _after_ do_oop_work has been called, hence after - // the object has been relocated to its new location and *p points - // to its new location. +template void G1ParCopyHelper::mark_object(T* p) { + // This is called from do_oop_work for objects that are not + // in the collection set. Objects in the collection set + // are marked after they have been evacuated. T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { @@ -4201,7 +4220,7 @@ template void G1ParCopyHelper::mark_forwardee(T* p) { } } -oop G1ParCopyHelper::copy_to_survivor_space(oop old) { +oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) { size_t word_sz = old->size(); HeapRegion* from_region = _g1->heap_region_containing_raw(old); // +1 to make the -1 indexes valid... @@ -4257,8 +4276,8 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { obj->set_mark(m); } - // preserve "next" mark bit - if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { + // Mark the evacuated object or propagate "next" mark bit + if (should_mark_copy) { if (!use_local_bitmaps || !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) { // if we couldn't mark it on the local bitmap (this happens when @@ -4266,11 +4285,12 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { // the bullet and do the standard parallel mark _cm->markAndGrayObjectIfNecessary(obj); } -#if 1 + if (_g1->isMarkedNext(old)) { + // Unmark the object's old location so that marking + // doesn't think the old object is alive. _cm->nextMarkBitMap()->parClear((HeapWord*)old); } -#endif } size_t* surv_young_words = _par_scan_state->surviving_young_words(); @@ -4293,26 +4313,62 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { return obj; } -template +template template -void G1ParCopyClosure +void G1ParCopyClosure ::do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); assert(barrier != G1BarrierRS || obj != NULL, "Precondition: G1BarrierRS implies obj is nonNull"); + // Marking: + // If the object is in the collection set, then the thread + // that copies the object should mark, or propagate the + // mark to, the evacuated object. + // If the object is not in the collection set then we + // should call the mark_object() method depending on the + // value of the template parameter do_mark_object (which will + // be true for root scanning closures during an initial mark + // pause). + // The mark_object() method first checks whether the object + // is marked and, if not, attempts to mark the object. + // here the null check is implicit in the cset_fast_test() test if (_g1->in_cset_fast_test(obj)) { if (obj->is_forwarded()) { oopDesc::encode_store_heap_oop(p, obj->forwardee()); + // If we are a root scanning closure during an initial + // mark pause (i.e. do_mark_object will be true) then + // we also need to handle marking of roots in the + // event of an evacuation failure. In the event of an + // evacuation failure, the object is forwarded to itself + // and not copied so let's mark it here. + if (do_mark_object && obj->forwardee() == obj) { + mark_object(p); + } } else { - oop copy_oop = copy_to_survivor_space(obj); + // We need to mark the copied object if we're a root scanning + // closure during an initial mark pause (i.e. do_mark_object + // will be true), or the object is already marked and we need + // to propagate the mark to the evacuated copy. + bool should_mark_copy = do_mark_object || + _during_initial_mark || + (_mark_in_progress && !_g1->is_obj_ill(obj)); + + oop copy_oop = copy_to_survivor_space(obj, should_mark_copy); oopDesc::encode_store_heap_oop(p, copy_oop); } // When scanning the RS, we only care about objs in CS. if (barrier == G1BarrierRS) { _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); } + } else { + // The object is not in collection set. If we're a root scanning + // closure during an initial mark pause (i.e. do_mark_object will + // be true) then attempt to mark the object. + if (do_mark_object) { + mark_object(p); + } } if (barrier == G1BarrierEvac && obj != NULL) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 154fc8c7a49..650e43887f6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1715,26 +1715,22 @@ public: class G1ParGCAllocBuffer: public ParGCAllocBuffer { private: bool _retired; - bool _during_marking; + bool _should_mark_objects; GCLabBitMap _bitmap; public: - G1ParGCAllocBuffer(size_t gclab_word_size) : - ParGCAllocBuffer(gclab_word_size), - _during_marking(G1CollectedHeap::heap()->mark_in_progress()), - _bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size), - _retired(false) - { } + G1ParGCAllocBuffer(size_t gclab_word_size); inline bool mark(HeapWord* addr) { guarantee(use_local_bitmaps, "invariant"); - assert(_during_marking, "invariant"); + assert(_should_mark_objects, "invariant"); return _bitmap.mark(addr); } inline void set_buf(HeapWord* buf) { - if (use_local_bitmaps && _during_marking) + if (use_local_bitmaps && _should_mark_objects) { _bitmap.set_buffer(buf); + } ParGCAllocBuffer::set_buf(buf); _retired = false; } @@ -1742,7 +1738,7 @@ public: inline void retire(bool end_of_gc, bool retain) { if (_retired) return; - if (use_local_bitmaps && _during_marking) { + if (use_local_bitmaps && _should_mark_objects) { _bitmap.retire(); } ParGCAllocBuffer::retire(end_of_gc, retain); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 8eaaa9d1e8a..d3f1ce24c62 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -50,6 +50,8 @@ protected: G1RemSet* _g1_rem; ConcurrentMark* _cm; G1ParScanThreadState* _par_scan_state; + bool _during_initial_mark; + bool _mark_in_progress; public: G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state); bool apply_to_weak_ref_discovered_field() { return true; } @@ -102,8 +104,8 @@ public: class G1ParCopyHelper : public G1ParClosureSuper { G1ParScanClosure *_scanner; protected: - template void mark_forwardee(T* p); - oop copy_to_survivor_space(oop obj); + template void mark_object(T* p); + oop copy_to_survivor_space(oop obj, bool should_mark_copy); public: G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, G1ParScanClosure *scanner) : @@ -111,7 +113,7 @@ public: }; template + bool do_mark_object> class G1ParCopyClosure : public G1ParCopyHelper { G1ParScanClosure _scanner; template void do_oop_work(T* p); @@ -120,8 +122,6 @@ public: _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { } template void do_oop_nv(T* p) { do_oop_work(p); - if (do_mark_forwardee) - mark_forwardee(p); } virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp index 5fcd66f1cbd..fea3e076d5e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp @@ -36,7 +36,7 @@ enum G1Barrier { }; template + bool do_mark_object> class G1ParCopyClosure; class G1ParScanClosure; class G1ParPushHeapRSClosure; From d8fd276e35155f74a185c9191727fb9c429f9324 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 29 Aug 2011 17:42:39 -0700 Subject: [PATCH 007/214] 7082645: Hotspot doesn't compile on old linuxes after 7060836 Move syscall ids definitions into os_linux.cpp Reviewed-by: johnc --- hotspot/src/os/linux/vm/os_linux.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index a55111e8160..3b0996a9875 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -125,10 +125,6 @@ # include # include -#ifdef AMD64 -#include -#endif - #define MAX_PATH (2 * K) // for timer info max values which include all bits @@ -2600,8 +2596,17 @@ int os::Linux::sched_getcpu_syscall(void) { int retval = -1; #if defined(IA32) +# ifndef SYS_getcpu +# define SYS_getcpu 318 +# endif retval = syscall(SYS_getcpu, &cpu, NULL, NULL); #elif defined(AMD64) +// Unfortunately we have to bring all these macros here from vsyscall.h +// to be able to compile on old linuxes. +# define __NR_vgetcpu 2 +# define VSYSCALL_START (-10UL << 20) +# define VSYSCALL_SIZE 1024 +# define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr)) typedef long (*vgetcpu_t)(unsigned int *cpu, unsigned int *node, unsigned long *tcache); vgetcpu_t vgetcpu = (vgetcpu_t)VSYSCALL_ADDR(__NR_vgetcpu); retval = vgetcpu(&cpu, NULL, NULL); From cebdce4479a2a02b22d07441be7a0f7d51f53e42 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 30 Aug 2011 00:54:09 -0700 Subject: [PATCH 008/214] 7082263: Reflection::resolve_field/field_get/field_set are broken Reviewed-by: kvn, dholmes, stefank, coleenp --- .../make/linux/makefiles/mapfile-vers-debug | 18 - .../make/linux/makefiles/mapfile-vers-product | 18 - hotspot/make/solaris/makefiles/debug.make | 3 +- hotspot/make/solaris/makefiles/fastdebug.make | 3 +- hotspot/make/solaris/makefiles/jvmg.make | 3 +- .../solaris/makefiles/mapfile-vers-nonproduct | 48 -- hotspot/make/solaris/makefiles/optimized.make | 4 +- hotspot/make/solaris/makefiles/product.make | 6 +- hotspot/src/share/vm/precompiled.hpp | 1 - hotspot/src/share/vm/prims/jvm.cpp | 245 -------- hotspot/src/share/vm/prims/jvm.h | 73 +-- hotspot/src/share/vm/prims/unsafe.cpp | 1 - hotspot/src/share/vm/runtime/reflection.cpp | 526 ------------------ hotspot/src/share/vm/runtime/reflection.hpp | 35 -- .../src/share/vm/runtime/reflectionCompat.hpp | 47 -- 15 files changed, 6 insertions(+), 1025 deletions(-) delete mode 100644 hotspot/make/solaris/makefiles/mapfile-vers-nonproduct delete mode 100644 hotspot/src/share/vm/runtime/reflectionCompat.hpp diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index 332c8af9329..620b4c52979 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -244,24 +244,6 @@ SUNWprivate_1.1 { JVM_Yield; JVM_handle_linux_signal; - # Old reflection routines - # These do not need to be present in the product build in JDK 1.4 - # but their code has not been removed yet because there will not - # be a substantial code savings until JVM_InvokeMethod and - # JVM_NewInstanceFromConstructor can also be removed; see - # reflectionCompat.hpp. - JVM_GetClassConstructor; - JVM_GetClassConstructors; - JVM_GetClassField; - JVM_GetClassFields; - JVM_GetClassMethod; - JVM_GetClassMethods; - JVM_GetField; - JVM_GetPrimitiveField; - JVM_NewInstance; - JVM_SetField; - JVM_SetPrimitiveField; - # debug JVM JVM_AccessVMBooleanFlag; JVM_AccessVMIntFlag; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 052da7c3c7e..fd9b4bc84ba 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -244,24 +244,6 @@ SUNWprivate_1.1 { JVM_Yield; JVM_handle_linux_signal; - # Old reflection routines - # These do not need to be present in the product build in JDK 1.4 - # but their code has not been removed yet because there will not - # be a substantial code savings until JVM_InvokeMethod and - # JVM_NewInstanceFromConstructor can also be removed; see - # reflectionCompat.hpp. - JVM_GetClassConstructor; - JVM_GetClassConstructors; - JVM_GetClassField; - JVM_GetClassFields; - JVM_GetClassMethod; - JVM_GetClassMethods; - JVM_GetField; - JVM_GetPrimitiveField; - JVM_NewInstance; - JVM_SetField; - JVM_SetPrimitiveField; - # miscellaneous functions jio_fprintf; jio_printf; diff --git a/hotspot/make/solaris/makefiles/debug.make b/hotspot/make/solaris/makefiles/debug.make index 57b6a11953b..60dc21b8a6a 100644 --- a/hotspot/make/solaris/makefiles/debug.make +++ b/hotspot/make/solaris/makefiles/debug.make @@ -41,8 +41,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE) # Linker mapfiles MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. diff --git a/hotspot/make/solaris/makefiles/fastdebug.make b/hotspot/make/solaris/makefiles/fastdebug.make index 1a033f0cba4..28410559007 100644 --- a/hotspot/make/solaris/makefiles/fastdebug.make +++ b/hotspot/make/solaris/makefiles/fastdebug.make @@ -107,8 +107,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE) # Linker mapfiles MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. diff --git a/hotspot/make/solaris/makefiles/jvmg.make b/hotspot/make/solaris/makefiles/jvmg.make index a5cc37fabd4..8e1db865e33 100644 --- a/hotspot/make/solaris/makefiles/jvmg.make +++ b/hotspot/make/solaris/makefiles/jvmg.make @@ -44,8 +44,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE) # Linker mapfiles MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. diff --git a/hotspot/make/solaris/makefiles/mapfile-vers-nonproduct b/hotspot/make/solaris/makefiles/mapfile-vers-nonproduct deleted file mode 100644 index e360472c98e..00000000000 --- a/hotspot/make/solaris/makefiles/mapfile-vers-nonproduct +++ /dev/null @@ -1,48 +0,0 @@ -# - -# -# Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -# Define public interface. - -SUNWprivate_1.1 { - global: - # Old reflection routines - # These do not need to be present in the product build in JDK 1.4 - # but their code has not been removed yet because there will not - # be a substantial code savings until JVM_InvokeMethod and - # JVM_NewInstanceFromConstructor can also be removed; see - # reflectionCompat.hpp. - JVM_GetClassConstructor; - JVM_GetClassConstructors; - JVM_GetClassField; - JVM_GetClassFields; - JVM_GetClassMethod; - JVM_GetClassMethods; - JVM_GetField; - JVM_GetPrimitiveField; - JVM_NewInstance; - JVM_SetField; - JVM_SetPrimitiveField; -}; diff --git a/hotspot/make/solaris/makefiles/optimized.make b/hotspot/make/solaris/makefiles/optimized.make index 563bd4c4a09..6919578600c 100644 --- a/hotspot/make/solaris/makefiles/optimized.make +++ b/hotspot/make/solaris/makefiles/optimized.make @@ -48,9 +48,7 @@ endif # Platform_compiler == sparcWorks CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # Linker mapfiles -# NOTE: inclusion of nonproduct mapfile not necessary; read it for details -MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. diff --git a/hotspot/make/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make index e6ebeea7580..122c8f37b58 100644 --- a/hotspot/make/solaris/makefiles/product.make +++ b/hotspot/make/solaris/makefiles/product.make @@ -58,13 +58,9 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # to inhibit the effect of the previous line on CFLAGS. # Linker mapfiles -# NOTE: inclusion of nonproduct mapfile not necessary; read it for details -ifdef USE_GCC MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers -else -MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct +ifndef USE_GCC # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) diff --git a/hotspot/src/share/vm/precompiled.hpp b/hotspot/src/share/vm/precompiled.hpp index 87129d11847..686f256695b 100644 --- a/hotspot/src/share/vm/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled.hpp @@ -206,7 +206,6 @@ # include "runtime/perfMemory.hpp" # include "runtime/prefetch.hpp" # include "runtime/reflection.hpp" -# include "runtime/reflectionCompat.hpp" # include "runtime/reflectionUtils.hpp" # include "runtime/registerMap.hpp" # include "runtime/safepoint.hpp" diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 4ee600f94bf..6a28179c3cc 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -4020,249 +4020,6 @@ JVM_END #endif -//--------------------------------------------------------------------------- -// -// Support for old native code-based reflection (pre-JDK 1.4) -// Disabled by default in the product build. -// -// See reflection.hpp for information on SUPPORT_OLD_REFLECTION -// -//--------------------------------------------------------------------------- - -#ifdef SUPPORT_OLD_REFLECTION - -JVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which)) - JVMWrapper("JVM_GetClassFields"); - JvmtiVMObjectAllocEventCollector oam; - oop mirror = JNIHandles::resolve_non_null(cls); - objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL); - return (jobjectArray) JNIHandles::make_local(env, result); -JVM_END - - -JVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which)) - JVMWrapper("JVM_GetClassMethods"); - JvmtiVMObjectAllocEventCollector oam; - oop mirror = JNIHandles::resolve_non_null(cls); - objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL); - //%note jvm_r4 - return (jobjectArray) JNIHandles::make_local(env, result); -JVM_END - - -JVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which)) - JVMWrapper("JVM_GetClassConstructors"); - JvmtiVMObjectAllocEventCollector oam; - oop mirror = JNIHandles::resolve_non_null(cls); - objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL); - //%note jvm_r4 - return (jobjectArray) JNIHandles::make_local(env, result); -JVM_END - - -JVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which)) - JVMWrapper("JVM_GetClassField"); - JvmtiVMObjectAllocEventCollector oam; - if (name == NULL) return NULL; - Handle str (THREAD, JNIHandles::resolve_non_null(name)); - - const char* cstr = java_lang_String::as_utf8_string(str()); - TempNewSymbol field_name = SymbolTable::probe(cstr, (int)strlen(cstr)); - if (field_name == NULL) { - THROW_0(vmSymbols::java_lang_NoSuchFieldException()); - } - - oop mirror = JNIHandles::resolve_non_null(cls); - oop result = Reflection::reflect_field(mirror, field_name, which, CHECK_NULL); - if (result == NULL) { - THROW_0(vmSymbols::java_lang_NoSuchFieldException()); - } - return JNIHandles::make_local(env, result); -JVM_END - - -JVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which)) - JVMWrapper("JVM_GetClassMethod"); - JvmtiVMObjectAllocEventCollector oam; - if (name == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); - } - Handle str (THREAD, JNIHandles::resolve_non_null(name)); - - const char* cstr = java_lang_String::as_utf8_string(str()); - TempNewSymbol method_name = SymbolTable::probe(cstr, (int)strlen(cstr)); - if (method_name == NULL) { - THROW_0(vmSymbols::java_lang_NoSuchMethodException()); - } - - oop mirror = JNIHandles::resolve_non_null(cls); - objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types))); - oop result = Reflection::reflect_method(mirror, method_name, tarray, - which, CHECK_NULL); - if (result == NULL) { - THROW_0(vmSymbols::java_lang_NoSuchMethodException()); - } - return JNIHandles::make_local(env, result); -JVM_END - - -JVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which)) - JVMWrapper("JVM_GetClassConstructor"); - JvmtiVMObjectAllocEventCollector oam; - oop mirror = JNIHandles::resolve_non_null(cls); - objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types))); - oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL); - if (result == NULL) { - THROW_0(vmSymbols::java_lang_NoSuchMethodException()); - } - return (jobject) JNIHandles::make_local(env, result); -JVM_END - - -// Instantiation /////////////////////////////////////////////////////////////////////////////// - -JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls)) - JVMWrapper("JVM_NewInstance"); - Handle mirror(THREAD, JNIHandles::resolve_non_null(cls)); - - methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror()); - if (resolved_constructor == NULL) { - klassOop k = java_lang_Class::as_klassOop(mirror()); - // The java.lang.Class object caches a resolved constructor if all the checks - // below were done successfully and a constructor was found. - - // Do class based checks - if (java_lang_Class::is_primitive(mirror())) { - const char* msg = ""; - if (mirror == Universe::bool_mirror()) msg = "java/lang/Boolean"; - else if (mirror == Universe::char_mirror()) msg = "java/lang/Character"; - else if (mirror == Universe::float_mirror()) msg = "java/lang/Float"; - else if (mirror == Universe::double_mirror()) msg = "java/lang/Double"; - else if (mirror == Universe::byte_mirror()) msg = "java/lang/Byte"; - else if (mirror == Universe::short_mirror()) msg = "java/lang/Short"; - else if (mirror == Universe::int_mirror()) msg = "java/lang/Integer"; - else if (mirror == Universe::long_mirror()) msg = "java/lang/Long"; - THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg); - } - - // Check whether we are allowed to instantiate this class - Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here - instanceKlassHandle klass(THREAD, k); - // Make sure class is initialized (also so all methods are rewritten) - klass->initialize(CHECK_NULL); - - // Lookup default constructor - resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); - if (resolved_constructor == NULL) { - ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name()); - } - - // Cache result in java.lang.Class object. Does not have to be MT safe. - java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor); - } - - assert(resolved_constructor != NULL, "sanity check"); - methodHandle constructor = methodHandle(THREAD, resolved_constructor); - - // We have an initialized instanceKlass with a default constructor - instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls))); - assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check"); - - // Do security check - klassOop caller_klass = NULL; - if (UsePrivilegedStack) { - caller_klass = thread->security_get_caller_class(2); - - if (!Reflection::verify_class_access(caller_klass, klass(), false) || - !Reflection::verify_field_access(caller_klass, - klass(), - klass(), - constructor->access_flags(), - false, - true)) { - ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name()); - } - } - - // Allocate object and call constructor - Handle receiver = klass->allocate_instance_handle(CHECK_NULL); - JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL); - - jobject res = JNIHandles::make_local(env, receiver()); - if (JvmtiExport::should_post_vm_object_alloc()) { - JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver()); - } - return res; -JVM_END - - -// Field //////////////////////////////////////////////////////////////////////////////////////////// - -JVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj)) - JVMWrapper("JVM_GetField"); - JvmtiVMObjectAllocEventCollector oam; - Handle field_mirror(thread, JNIHandles::resolve(field)); - Handle receiver (thread, JNIHandles::resolve(obj)); - fieldDescriptor fd; - Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL); - jvalue value; - BasicType type = Reflection::field_get(&value, &fd, receiver); - oop box = Reflection::box(&value, type, CHECK_NULL); - return JNIHandles::make_local(env, box); -JVM_END - - -JVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode)) - JVMWrapper("JVM_GetPrimitiveField"); - Handle field_mirror(thread, JNIHandles::resolve(field)); - Handle receiver (thread, JNIHandles::resolve(obj)); - fieldDescriptor fd; - jvalue value; - value.j = 0; - Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value)); - BasicType type = Reflection::field_get(&value, &fd, receiver); - BasicType wide_type = (BasicType) wCode; - if (type != wide_type) { - Reflection::widen(&value, type, wide_type, CHECK_(value)); - } - return value; -JVM_END // should really be JVM_END, but that doesn't work for union types! - - -JVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val)) - JVMWrapper("JVM_SetField"); - Handle field_mirror(thread, JNIHandles::resolve(field)); - Handle receiver (thread, JNIHandles::resolve(obj)); - oop box = JNIHandles::resolve(val); - fieldDescriptor fd; - Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK); - BasicType field_type = fd.field_type(); - jvalue value; - BasicType value_type; - if (field_type == T_OBJECT || field_type == T_ARRAY) { - // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array - value_type = Reflection::unbox_for_regular_object(box, &value); - Reflection::field_set(&value, &fd, receiver, field_type, CHECK); - } else { - value_type = Reflection::unbox_for_primitive(box, &value, CHECK); - Reflection::field_set(&value, &fd, receiver, value_type, CHECK); - } -JVM_END - - -JVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode)) - JVMWrapper("JVM_SetPrimitiveField"); - Handle field_mirror(thread, JNIHandles::resolve(field)); - Handle receiver (thread, JNIHandles::resolve(obj)); - fieldDescriptor fd; - Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK); - BasicType value_type = (BasicType) vCode; - Reflection::field_set(&v, &fd, receiver, value_type, CHECK); -JVM_END - - // Method /////////////////////////////////////////////////////////////////////////////////////////// JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) @@ -4302,8 +4059,6 @@ JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjec return res; JVM_END -#endif /* SUPPORT_OLD_REFLECTION */ - // Atomic /////////////////////////////////////////////////////////////////////////////////////////// JVM_LEAF(jboolean, JVM_SupportsCX8()) diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index f37d83342f8..5758b540267 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -26,7 +26,6 @@ #define SHARE_VM_PRIMS_JVM_H #include "prims/jni.h" -#include "runtime/reflectionCompat.hpp" #ifdef TARGET_OS_FAMILY_linux # include "jvm_linux.h" #endif @@ -43,8 +42,7 @@ // HotSpot integration note: // // This file and jvm.h used with the JDK are identical, -// except for the three includes removed below and the -// SUPPORT_OLD_REFLECTION sections cut out of the JDK's jvm.h. +// except for the three includes removed below // #include // #include "jni.h" @@ -443,14 +441,6 @@ JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name, jsize len, jobject pd, const char *source, jboolean verify); -/* Define a class with a source (MLVM) */ -JNIEXPORT jclass JNICALL -JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader, - const jbyte *buf, jsize len, jobject pd, - const char *source, - // same args as JVM_DefineClassWithSource to this point - jobjectArray constants); - /* * Reflection support functions */ @@ -1442,65 +1432,6 @@ JVM_RawMonitorEnter(void *mon); JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon); - -#ifdef SUPPORT_OLD_REFLECTION - -/* - * Support for old native code-based (pre-JDK 1.4) reflection implementation. - * Disabled by default in the product build. - * - * See reflection.hpp for information on SUPPORT_OLD_REFLECTION - */ - -/* - * reflecting fields and methods. - * which: 0 --- MEMBER_PUBLIC - * 1 --- MEMBER_DECLARED - * NOTE: absent in product build by default - */ - -JNIEXPORT jobjectArray JNICALL -JVM_GetClassFields(JNIEnv *env, jclass cls, jint which); - -JNIEXPORT jobjectArray JNICALL -JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which); - -JNIEXPORT jobjectArray JNICALL -JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which); - -JNIEXPORT jobject JNICALL -JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which); - -JNIEXPORT jobject JNICALL -JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, - jint which); -JNIEXPORT jobject JNICALL -JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, - jint which); - -/* - * Implements Class.newInstance - */ -JNIEXPORT jobject JNICALL -JVM_NewInstance(JNIEnv *env, jclass cls); - -/* - * java.lang.reflect.Field - */ -JNIEXPORT jobject JNICALL -JVM_GetField(JNIEnv *env, jobject field, jobject obj); - -JNIEXPORT jvalue JNICALL -JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, - unsigned char wCode); - -JNIEXPORT void JNICALL -JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val); - -JNIEXPORT void JNICALL -JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, - unsigned char vCode); - /* * java.lang.reflect.Method */ @@ -1513,8 +1444,6 @@ JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0); JNIEXPORT jobject JNICALL JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0); -#endif /* SUPPORT_OLD_REFLECTION */ - /* * java.lang.management support */ diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index e1a21f030fc..4652059434f 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -33,7 +33,6 @@ #include "runtime/globals.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/reflection.hpp" -#include "runtime/reflectionCompat.hpp" #include "runtime/synchronizer.hpp" #include "services/threadService.hpp" #include "utilities/copy.hpp" diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index e25c1afb050..29858bedfc1 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -844,16 +844,6 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) { } -//--------------------------------------------------------------------------- -// -// Supporting routines for old native code-based reflection (pre-JDK 1.4). -// -// See reflection.hpp for details. -// -//--------------------------------------------------------------------------- - -#ifdef SUPPORT_OLD_REFLECTION - methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS) { assert(!method.is_null() , "method should not be null"); @@ -1081,519 +1071,6 @@ BasicType Reflection::basic_type_mirror_to_basic_type(oop basic_type_mirror, TRA return java_lang_Class::primitive_type(basic_type_mirror); } - -bool Reflection::match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS) { - int types_len = types.is_null() ? 0 : types->length(); - if (types_len != parameter_count) return false; - if (parameter_count > 0) { - objArrayHandle method_types = get_parameter_types(method, parameter_count, NULL, CHECK_false); - for (int index = 0; index < parameter_count; index++) { - if (types->obj_at(index) != method_types->obj_at(index)) { - return false; - } - } - } - return true; -} - - -oop Reflection::new_field(FieldStream* st, TRAPS) { - Symbol* field_name = st->name(); - Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL); - Symbol* signature = st->signature(); - Handle type = new_type(signature, st->klass(), CHECK_NULL); - Handle rh = java_lang_reflect_Field::create(CHECK_NULL); - oop result = rh(); - - java_lang_reflect_Field::set_clazz(result, st->klass()->java_mirror()); - java_lang_reflect_Field::set_slot(result, st->index()); - java_lang_reflect_Field::set_name(result, name()); - java_lang_reflect_Field::set_type(result, type()); - // Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here. - java_lang_reflect_Field::set_modifiers(result, st->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); - java_lang_reflect_Field::set_override(result, false); - return result; -} - - -bool Reflection::resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS) { - if (field_mirror.is_null()) { - THROW_(vmSymbols::java_lang_NullPointerException(), false); - } - - instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(java_lang_reflect_Field::clazz(field_mirror()))); - int slot = java_lang_reflect_Field::slot(field_mirror()); - - // Ensure klass is initialized - klass->initialize(CHECK_false); - fd->initialize(klass(), slot); - - bool is_static = fd->is_static(); - KlassHandle receiver_klass; - - if (is_static) { - receiver = KlassHandle(THREAD, klass()); - receiver_klass = klass; - } else { - // Check object is a non-null instance of declaring class - if (receiver.is_null()) { - THROW_(vmSymbols::java_lang_NullPointerException(), false); - } - if (!receiver->is_a(klass())) { - THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class", false); - } - receiver_klass = KlassHandle(THREAD, receiver->klass()); - } - - // Access checking (unless overridden by Field) - if (!java_lang_reflect_Field::override(field_mirror())) { - if (!(klass->is_public() && fd->is_public())) { - bool access_check = reflect_check_access(klass(), fd->access_flags(), receiver_klass(), false, CHECK_false); - if (!access_check) { - return false; // exception - } - } - } - - if (check_final && fd->is_final()) { - // In 1.3 we always throw an error when attempting to set a final field. - // In 1.2.x, this was allowed in the override bit was set by calling Field.setAccessible(true). - // We currently maintain backwards compatibility. See bug 4250960. - bool strict_final_check = !JDK_Version::is_jdk12x_version(); - if (strict_final_check || !java_lang_reflect_Field::override(field_mirror())) { - THROW_MSG_(vmSymbols::java_lang_IllegalAccessException(), "field is final", false); - } - } - return true; -} - - -BasicType Reflection::field_get(jvalue* value, fieldDescriptor* fd, Handle receiver) { - BasicType field_type = fd->field_type(); - int offset = fd->offset(); - switch (field_type) { - case T_BOOLEAN: - value->z = receiver->bool_field(offset); - break; - case T_CHAR: - value->c = receiver->char_field(offset); - break; - case T_FLOAT: - value->f = receiver->float_field(offset); - break; - case T_DOUBLE: - value->d = receiver->double_field(offset); - break; - case T_BYTE: - value->b = receiver->byte_field(offset); - break; - case T_SHORT: - value->s = receiver->short_field(offset); - break; - case T_INT: - value->i = receiver->int_field(offset); - break; - case T_LONG: - value->j = receiver->long_field(offset); - break; - case T_OBJECT: - case T_ARRAY: - value->l = (jobject) receiver->obj_field(offset); - break; - default: - return T_ILLEGAL; - } - return field_type; -} - - -void Reflection::field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS) { - BasicType field_type = fd->field_type(); - if (field_type != value_type) { - widen(value, value_type, field_type, CHECK); - } - - int offset = fd->offset(); - switch (field_type) { - case T_BOOLEAN: - receiver->bool_field_put(offset, value->z); - break; - case T_CHAR: - receiver->char_field_put(offset, value->c); - break; - case T_FLOAT: - receiver->float_field_put(offset, value->f); - break; - case T_DOUBLE: - receiver->double_field_put(offset, value->d); - break; - case T_BYTE: - receiver->byte_field_put(offset, value->b); - break; - case T_SHORT: - receiver->short_field_put(offset, value->s); - break; - case T_INT: - receiver->int_field_put(offset, value->i); - break; - case T_LONG: - receiver->long_field_put(offset, value->j); - break; - case T_OBJECT: - case T_ARRAY: { - Handle obj(THREAD, (oop) value->l); - if (obj.not_null()) { - Symbol* signature = fd->signature(); - Handle loader (THREAD, fd->loader()); - Handle protect (THREAD, Klass::cast(fd->field_holder())->protection_domain()); - klassOop k = SystemDictionary::resolve_or_fail(signature, loader, protect, true, CHECK); // may block - if (!obj->is_a(k)) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch"); - } - } - receiver->obj_field_put(offset, obj()); - break; - } - default: - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch"); - } -} - - -oop Reflection::reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS) { - // Exclude primitive types and array types - if (java_lang_Class::is_primitive(mirror)) return NULL; - if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) return NULL; - - instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror)); - bool local_fields_only = (which == DECLARED); - - // Ensure class is linked - k->link_class(CHECK_NULL); - - // Search class and interface fields - for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { - if (st.name() == field_name) { - if (local_fields_only || st.access_flags().is_public()) { - return new_field(&st, THREAD); - } - } - } - - return NULL; -} - - -objArrayOop Reflection::reflect_fields(oop mirror, jint which, TRAPS) { - // Exclude primitive types and array types - if (java_lang_Class::is_primitive(mirror) - || Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - Symbol* name = vmSymbols::java_lang_reflect_Field(); - klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); - return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array - } - - instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror)); - - // Ensure class is linked - k->link_class(CHECK_NULL); - - bool local_fields_only = (which == DECLARED); - int count = 0; - { // Compute fields count for class and interface fields - for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { - if (local_fields_only || st.access_flags().is_public()) { - count++; - } - } - } - - // Allocate result - Symbol* name = vmSymbols::java_lang_reflect_Field(); - klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); - objArrayHandle result (THREAD, r); - - // Fill in results backwards - { - for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { - if (local_fields_only || st.access_flags().is_public()) { - oop field = new_field(&st, CHECK_NULL); - result->obj_at_put(--count, field); - } - } - assert(count == 0, "just checking"); - } - return result(); -} - - -oop Reflection::reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS) { - if (java_lang_Class::is_primitive(mirror)) return NULL; - klassOop klass = java_lang_Class::as_klassOop(mirror); - if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED) return NULL; - - if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - klass = SystemDictionary::Object_klass(); - } - instanceKlassHandle h_k(THREAD, klass); - - // Ensure klass is linked (need not be initialized) - h_k->link_class(CHECK_NULL); - - // For interfaces include static initializers under jdk1.2.x (since classic does that) - bool include_clinit = JDK_Version::is_jdk12x_version() && h_k->is_interface(); - - switch (which) { - case MEMBER_PUBLIC: - // First the public non-static methods (works if method holder is an interface) - // Note that we can ignore checks for overridden methods, since we go up the hierarchy. - { - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { - methodHandle m(THREAD, st.method()); - // For interfaces include static initializers since classic does that! - if (method_name == m->name() && (include_clinit || (m->is_public() && !m->is_static() && !m->is_initializer()))) { - Symbol* signature = m->signature(); - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); - if (parameter_match) { - return new_method(m, false, false, THREAD); - } - } - } - } - // Then the public static methods (works if method holder is an interface) - { - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { - methodHandle m(THREAD, st.method()); - if (method_name == m->name() && m->is_public() && m->is_static() && !m->is_initializer()) { - Symbol* signature = m->signature(); - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); - if (parameter_match) { - return new_method(m, false, false, THREAD); - } - } - } - } - break; - case MEMBER_DECLARED: - // All local methods - { - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { - methodHandle m(THREAD, st.method()); - if (method_name == m->name() && !m->is_initializer()) { - Symbol* signature = m->signature(); - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); - if (parameter_match) { - return new_method(m, false, false, THREAD); - } - } - } - } - break; - default: - break; - } - return NULL; -} - - -objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) { - // Exclude primitive types - if (java_lang_Class::is_primitive(mirror) || - (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array() && (which == MEMBER_DECLARED))) { - klassOop klass = SystemDictionary::reflect_Method_klass(); - return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array - } - - klassOop klass = java_lang_Class::as_klassOop(mirror); - if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - klass = SystemDictionary::Object_klass(); - } - instanceKlassHandle h_k(THREAD, klass); - - // Ensure klass is linked (need not be initialized) - h_k->link_class(CHECK_NULL); - - // We search the (super)interfaces only if h_k is an interface itself - bool is_interface = h_k->is_interface(); - - // For interfaces include static initializers under jdk1.2.x (since classic does that) - bool include_clinit = JDK_Version::is_jdk12x_version() && is_interface; - - switch (which) { - case MEMBER_PUBLIC: - { - - // Count public methods (non-static and static) - int count = 0; - { - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { - methodOop m = st.method(); - // For interfaces include static initializers since classic does that! - if (include_clinit || (!m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k()))) { - count++; - } - } - } - - // Allocate result - klassOop klass = SystemDictionary::reflect_Method_klass(); - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); - objArrayHandle h_result (THREAD, r); - - // Fill in results backwards - { - // First the non-static public methods - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { - methodHandle m (THREAD, st.method()); - if (!m->is_static() && !m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k())) { - oop method = new_method(m, false, false, CHECK_NULL); - if (method == NULL) { - return NULL; - } else { - h_result->obj_at_put(--count, method); - } - } - } - } - { - // Then the static public methods - for (MethodStream st(h_k, false, !is_interface); !st.eos(); st.next()) { - methodHandle m (THREAD, st.method()); - if (m->is_static() && (include_clinit || (!m->is_initializer()) && m->is_public() && !m->is_overridden_in(h_k()))) { - oop method = new_method(m, false, false, CHECK_NULL); - if (method == NULL) { - return NULL; - } else { - h_result->obj_at_put(--count, method); - } - } - } - } - - assert(count == 0, "just checking"); - return h_result(); - } - - case MEMBER_DECLARED: - { - // Count all methods - int count = 0; - { - for (MethodStream st(h_k, true, !is_interface); !st.eos(); st.next()) { - methodOop m = st.method(); - if (!m->is_initializer()) { - count++; - } - } - } - // Allocate result - klassOop klass = SystemDictionary::reflect_Method_klass(); - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); - objArrayHandle h_result (THREAD, r); - - // Fill in results backwards - { - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { - methodHandle m (THREAD, st.method()); - if (!m->is_initializer()) { - oop method = new_method(m, false, false, CHECK_NULL); - if (method == NULL) { - return NULL; - } else { - h_result->obj_at_put(--count, method); - } - } - } - } - assert(count == 0, "just checking"); - return h_result(); - } - } - ShouldNotReachHere(); - return NULL; -} - - -oop Reflection::reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS) { - - // Exclude primitive, interface and array types - bool prim = java_lang_Class::is_primitive(mirror); - Klass* klass = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); - if (prim || klass->is_interface() || klass->oop_is_array()) return NULL; - - // Must be instance klass - instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror)); - - // Ensure klass is linked (need not be initialized) - h_k->link_class(CHECK_NULL); - - bool local_only = (which == MEMBER_DECLARED); - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { - methodHandle m(THREAD, st.method()); - if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { - Symbol* signature = m->signature(); - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); - if (parameter_match) { - return new_constructor(m, THREAD); - } - } - } - - return NULL; -} - - -objArrayOop Reflection::reflect_constructors(oop mirror, jint which, TRAPS) { - // Exclude primitive, interface and array types - bool prim = java_lang_Class::is_primitive(mirror); - Klass* k = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); - if (prim || k->is_interface() || k->oop_is_array()) { - return oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0, CHECK_NULL); // Return empty array - } - - // Must be instanceKlass at this point - instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror)); - - // Ensure klass is linked (need not be initialized) - h_k->link_class(CHECK_NULL); - - bool local_only = (which == MEMBER_DECLARED); - int count = 0; - { - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { - methodOop m = st.method(); - if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { - count++; - } - } - } - - // Allocate result - Symbol* name = vmSymbols::java_lang_reflect_Constructor(); - klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); - objArrayHandle h_result (THREAD, r); - - // Fill in results backwards - { - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { - methodHandle m (THREAD, st.method()); - if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { - oop constr = new_constructor(m, CHECK_NULL); - if (constr == NULL) { - return NULL; - } else { - h_result->obj_at_put(--count, constr); - } - } - } - assert(count == 0, "just checking"); - } - return h_result(); -} - - // This would be nicer if, say, java.lang.reflect.Method was a subclass // of java.lang.reflect.Constructor @@ -1647,6 +1124,3 @@ oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args, invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL); return receiver(); } - - -#endif /* SUPPORT_OLD_REFLECTION */ diff --git a/hotspot/src/share/vm/runtime/reflection.hpp b/hotspot/src/share/vm/runtime/reflection.hpp index 90a3c0c0e3c..cf542539450 100644 --- a/hotspot/src/share/vm/runtime/reflection.hpp +++ b/hotspot/src/share/vm/runtime/reflection.hpp @@ -27,7 +27,6 @@ #include "oops/oop.hpp" #include "runtime/fieldDescriptor.hpp" -#include "runtime/reflectionCompat.hpp" #include "utilities/accessFlags.hpp" #include "utilities/growableArray.hpp" @@ -120,16 +119,6 @@ class Reflection: public AllStatic { // Create a java.lang.reflect.Field object based on a field descriptor static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS); - //--------------------------------------------------------------------------- - // - // Support for old native code-based reflection (pre-JDK 1.4) - // - // NOTE: the method and constructor invocation code is still used - // for startup time reasons; see reflectionCompat.hpp. - // - //--------------------------------------------------------------------------- - -#ifdef SUPPORT_OLD_REFLECTION private: // method resolution for invoke static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS); @@ -144,35 +133,11 @@ private: // Conversion static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS); - static bool match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS); - // Creating new java.lang.reflect.xxx wrappers - static oop new_field(FieldStream* st, TRAPS); - public: - // Field lookup and verification. - static bool resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS); - - // Reflective field access. Returns type code. Throws IllegalArgumentException. - static BasicType field_get(jvalue* value, fieldDescriptor* fd, Handle receiver); - static void field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS); - - // Reflective lookup of fields. Returns java.lang.reflect.Field instances. - static oop reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS); - static objArrayOop reflect_fields(oop mirror, jint which, TRAPS); - - // Reflective lookup of methods. Returns java.lang.reflect.Method instances. - static oop reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS); - static objArrayOop reflect_methods(oop mirror, jint which, TRAPS); - - // Reflective lookup of constructors. Returns java.lang.reflect.Constructor instances. - static oop reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS); - static objArrayOop reflect_constructors(oop mirror, jint which, TRAPS); - // Method invokation through java.lang.reflect.Method static oop invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS); // Method invokation through java.lang.reflect.Constructor static oop invoke_constructor(oop method_mirror, objArrayHandle args, TRAPS); -#endif /* SUPPORT_OLD_REFLECTION */ }; diff --git a/hotspot/src/share/vm/runtime/reflectionCompat.hpp b/hotspot/src/share/vm/runtime/reflectionCompat.hpp deleted file mode 100644 index 9551ad598a5..00000000000 --- a/hotspot/src/share/vm/runtime/reflectionCompat.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP -#define SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP - -// During the development of the JDK 1.4 reflection implementation -// based on dynamic bytecode generation, it was hoped that the bulk of -// the native code for reflection could be removed. Unfortunately -// there is currently a significant cost associated with loading the -// stub classes which impacts startup time. Until this cost can be -// reduced, the JVM entry points JVM_InvokeMethod and -// JVM_NewInstanceFromConstructor are still needed; these and their -// dependents currently constitute the bulk of the native code for -// reflection. If this cost is reduced in the future, the -// NativeMethodAccessorImpl and NativeConstructorAccessorImpl classes -// can be removed from sun.reflect and all of the code guarded by this -// flag removed from the product build. (Non-product builds, -// specifically the "optimized" target, would retain the code so they -// could be dropped into earlier JDKs for comparative benchmarking.) - -//#ifndef PRODUCT -# define SUPPORT_OLD_REFLECTION -//#endif - -#endif // SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP From 5903a384b434c95a9f58485e5340c4b63001560d Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 30 Aug 2011 19:01:58 -0700 Subject: [PATCH 009/214] 7085279: C1 overflows code buffer with VerifyOops and CompressedOops Increase the limit of code emitted per LIR instruction, increase the max size of the nmethod generated by C1 Reviewed-by: never, kvn, johnc --- hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 2 +- hotspot/src/share/vm/c1/c1_globals.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index d3b853bedca..258fde28308 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -121,7 +121,7 @@ void LIR_Assembler::append_patching_stub(PatchingStub* stub) { void LIR_Assembler::check_codespace() { CodeSection* cs = _masm->code_section(); - if (cs->remaining() < (int)(1*K)) { + if (cs->remaining() < (int)(NOT_LP64(1*K)LP64_ONLY(2*K))) { BAILOUT("CodeBuffer overflow"); } } diff --git a/hotspot/src/share/vm/c1/c1_globals.hpp b/hotspot/src/share/vm/c1/c1_globals.hpp index 110371d19e2..60fe6d08051 100644 --- a/hotspot/src/share/vm/c1/c1_globals.hpp +++ b/hotspot/src/share/vm/c1/c1_globals.hpp @@ -278,7 +278,7 @@ product(intx, CompilationRepeat, 0, \ "Number of times to recompile method before returning result") \ \ - develop(intx, NMethodSizeLimit, (32*K)*wordSize, \ + develop(intx, NMethodSizeLimit, (64*K)*wordSize, \ "Maximum size of a compiled method.") \ \ develop(bool, TraceFPUStack, false, \ From 05b60b3662da8a4c71ac942508248aa09502e039 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Wed, 31 Aug 2011 01:40:45 -0700 Subject: [PATCH 010/214] 7078382: JSR 292: don't count method handle adapters against inlining budgets Reviewed-by: kvn, never --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 2 +- hotspot/src/share/vm/ci/ciMethod.cpp | 28 +++++++++++++++++++ hotspot/src/share/vm/ci/ciMethod.hpp | 3 ++ hotspot/src/share/vm/ci/ciStreams.hpp | 3 +- .../src/share/vm/interpreter/bytecodes.hpp | 2 ++ hotspot/src/share/vm/opto/bytecodeInfo.cpp | 10 +++---- 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 266f75f5327..3de0adc277a 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3430,7 +3430,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { } else { if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining"); - if (callee->code_size() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); + if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); // don't inline throwable methods unless the inlining tree is rooted in a throwable class if (callee->name() == ciSymbol::object_initializer_name() && diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 89fb4aa5fbd..a985d5e28df 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1016,6 +1016,34 @@ int ciMethod::highest_osr_comp_level() { return get_methodOop()->highest_osr_comp_level(); } +// ------------------------------------------------------------------ +// ciMethod::code_size_for_inlining +// +// Code size for inlining decisions. +// +// Don't fully count method handle adapters against inlining budgets: +// the metric we use here is the number of call sites in the adapter +// as they are probably the instructions which generate some code. +int ciMethod::code_size_for_inlining() { + check_is_loaded(); + + // Method handle adapters + if (is_method_handle_adapter()) { + // Count call sites + int call_site_count = 0; + ciBytecodeStream iter(this); + while (iter.next() != ciBytecodeStream::EOBC()) { + if (Bytecodes::is_invoke(iter.cur_bc())) { + call_site_count++; + } + } + return call_site_count; + } + + // Normal method + return code_size(); +} + // ------------------------------------------------------------------ // ciMethod::instructions_size // diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index feab1e69c00..db717528406 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -157,6 +157,9 @@ class ciMethod : public ciObject { int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; } int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; } + // Code size for inlining decisions. + int code_size_for_inlining(); + int comp_level(); int highest_osr_comp_level(); diff --git a/hotspot/src/share/vm/ci/ciStreams.hpp b/hotspot/src/share/vm/ci/ciStreams.hpp index 7ad6ef082e9..b03642cd1b2 100644 --- a/hotspot/src/share/vm/ci/ciStreams.hpp +++ b/hotspot/src/share/vm/ci/ciStreams.hpp @@ -129,7 +129,8 @@ public: // Return current ByteCode and increment PC to next bytecode, skipping all // intermediate constants. Returns EOBC at end. // Expected usage: - // while( (bc = iter.next()) != EOBC() ) { ... } + // ciBytecodeStream iter(m); + // while (iter.next() != ciBytecodeStream::EOBC()) { ... } Bytecodes::Code next() { _bc_start = _pc; // Capture start of bc if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 6194ad62134..2ea733660bf 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -419,6 +419,8 @@ class Bytecodes: AllStatic { static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0 || code == _fconst_0 || code == _dconst_0); } + static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); } + static int compute_flags (const char* format, int more_flags = 0); // compute the flags static int flags (int code, bool is_wide) { assert(code == (u_char)code, "must be a byte"); diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 398f8f88965..12ba7c21dc8 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -45,7 +45,7 @@ InlineTree::InlineTree(Compile* c, _method(callee), _site_invoke_ratio(site_invoke_ratio), _max_inline_level(max_inline_level), - _count_inline_bcs(method()->code_size()) + _count_inline_bcs(method()->code_size_for_inlining()) { NOT_PRODUCT(_count_inlines = 0;) if (_caller_jvms != NULL) { @@ -107,7 +107,7 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_ // positive filter: should send be inlined? returns NULL (--> yes) // or rejection msg - int size = callee_method->code_size(); + int size = callee_method->code_size_for_inlining(); // Check for too many throws (and not too huge) if(callee_method->interpreter_throwout_count() > InlineThrowCount && @@ -244,7 +244,7 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal } // use frequency-based objections only for non-trivial methods - if (callee_method->code_size() <= MaxTrivialSize) return NULL; + if (callee_method->code_size_for_inlining() <= MaxTrivialSize) return NULL; // don't use counts with -Xcomp or CTW if (UseInterpreter && !CompileTheWorld) { @@ -305,7 +305,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_ } // suppress a few checks for accessors and trivial methods - if (callee_method->code_size() > MaxTrivialSize) { + if (callee_method->code_size_for_inlining() > MaxTrivialSize) { // don't inline into giant methods if (C->unique() > (uint)NodeCountInliningCutoff) { @@ -349,7 +349,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_ } } - int size = callee_method->code_size(); + int size = callee_method->code_size_for_inlining(); if (UseOldInlining && ClipInlining && (int)count_inline_bcs() + size >= DesiredMethodLimit) { From 9c87ea9062a8f5a2ab94246cf2dee81cc584873e Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 31 Aug 2011 09:48:21 -0700 Subject: [PATCH 011/214] 7085137: -XX:+VerifyOops is broken Replace set() with patchable_set() to generate 8 instructions always. Reviewed-by: iveresov, never, roland --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 12 ++++++++---- hotspot/src/cpu/sparc/vm/sparc.ad | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 3ee5b72ca92..732ece24513 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -1794,7 +1794,8 @@ void MacroAssembler::_verify_oop(Register reg, const char* msg, const char * fil mov(reg,O0); // Move arg into O0; arg might be in O7 which is about to be crushed stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); - set((intptr_t)real_msg, O1); + // Size of set() should stay the same + patchable_set((intptr_t)real_msg, O1); // Load address to call to into O7 load_ptr_contents(a, O7); // Register call to verify_oop_subroutine @@ -1831,7 +1832,8 @@ void MacroAssembler::_verify_oop_addr(Address addr, const char* msg, const char ld_ptr(addr.base(), addr.disp() + 8*8, O0); // Load arg into O0; arg might be in O7 which is about to be crushed stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); - set((intptr_t)real_msg, O1); + // Size of set() should stay the same + patchable_set((intptr_t)real_msg, O1); // Load address to call to into O7 load_ptr_contents(a, O7); // Register call to verify_oop_subroutine @@ -1976,7 +1978,8 @@ void MacroAssembler::stop(const char* msg) { save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); // stop_subroutine expects message pointer in I1. - set((intptr_t)msg, O1); + // Size of set() should stay the same + patchable_set((intptr_t)msg, O1); // factor long stop-sequence into subroutine to save space assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); @@ -1998,7 +2001,8 @@ void MacroAssembler::warn(const char* msg) { save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); RegistersForDebugging::save_registers(this); mov(O0, L0); - set((intptr_t)msg, O0); + // Size of set() should stay the same + patchable_set((intptr_t)msg, O0); call( CAST_FROM_FN_PTR(address, warning) ); delayed()->nop(); // ret(); diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index b999716c068..d7bf2d85fe8 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -840,6 +840,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, const MachNode* n, int primary, int te !(n->ideal_Opcode()==Op_ConvI2D && ld_op==Op_LoadF) && !(n->ideal_Opcode()==Op_PrefetchRead && ld_op==Op_LoadI) && !(n->ideal_Opcode()==Op_PrefetchWrite && ld_op==Op_LoadI) && + !(n->ideal_Opcode()==Op_PrefetchAllocation && ld_op==Op_LoadI) && !(n->ideal_Opcode()==Op_Load2I && ld_op==Op_LoadD) && !(n->ideal_Opcode()==Op_Load4C && ld_op==Op_LoadD) && !(n->ideal_Opcode()==Op_Load4S && ld_op==Op_LoadD) && From 6c8c4fb32149a7d2d9af4d0fb1837cca06adbbb2 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Wed, 31 Aug 2011 10:16:02 -0700 Subject: [PATCH 012/214] 7066841: remove MacroAssembler::br_on_reg_cond() on sparc Remove the macro assembler routine br_on_reg_cond() and replace the remaining calls to that routine with an equivalent. Reviewed-by: kvn, iveresov --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 132 ++++-------------- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 6 - .../src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp | 32 ++--- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 33 +++-- .../vm/gc_implementation/g1/g1_globals.hpp | 3 - 5 files changed, 60 insertions(+), 146 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 4e5d90eaabe..e70328bd9d2 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -2161,29 +2161,6 @@ void MacroAssembler::br_notnull( Register s1, bool a, Predict p, Label& L ) { #endif } -void MacroAssembler::br_on_reg_cond( RCondition rc, bool a, Predict p, - Register s1, address d, - relocInfo::relocType rt ) { - assert_not_delayed(); - if (VM_Version::v9_instructions_work()) { - bpr(rc, a, p, s1, d, rt); - } else { - tst(s1); - br(reg_cond_to_cc_cond(rc), a, p, d, rt); - } -} - -void MacroAssembler::br_on_reg_cond( RCondition rc, bool a, Predict p, - Register s1, Label& L ) { - assert_not_delayed(); - if (VM_Version::v9_instructions_work()) { - bpr(rc, a, p, s1, L); - } else { - tst(s1); - br(reg_cond_to_cc_cond(rc), a, p, L); - } -} - // Compare registers and branch with nop in delay slot or cbcond without delay slot. // Compare integer (32 bit) values (icc only). @@ -4340,22 +4317,29 @@ static void generate_satb_log_enqueue(bool with_frame) { } else { pre_val = O0; } + int satb_q_index_byte_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_index()); + int satb_q_buf_byte_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()); + assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), "check sizes in assembly below"); __ bind(restart); + + // Load the index into the SATB buffer. PtrQueue::_index is a size_t + // so ld_ptr is appropriate. __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, L0, refill); - // If the branch is taken, no harm in executing this in the delay slot. - __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); + // index == 0? + __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); + + __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); __ sub(L0, oopSize, L0); __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 @@ -4466,9 +4450,8 @@ void MacroAssembler::g1_write_barrier_pre(Register obj, tmp); } - // Check on whether to annul. - br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); - delayed()->nop(); + // Is marking active? + cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); // Do we need to load the previous value? if (obj != noreg) { @@ -4490,9 +4473,7 @@ void MacroAssembler::g1_write_barrier_pre(Register obj, assert(pre_val != noreg, "must have a real register"); // Is the previous value null? - // Check on whether to annul. - br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, pre_val, filtered); - delayed()->nop(); + cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); // OK, it's not filtered, so we'll need to call enqueue. In the normal // case, pre_val will be a scratch G-reg, but there are some cases in @@ -4519,39 +4500,6 @@ void MacroAssembler::g1_write_barrier_pre(Register obj, bind(filtered); } -static jint num_ct_writes = 0; -static jint num_ct_writes_filtered_in_hr = 0; -static jint num_ct_writes_filtered_null = 0; -static G1CollectedHeap* g1 = NULL; - -static Thread* count_ct_writes(void* filter_val, void* new_val) { - Atomic::inc(&num_ct_writes); - if (filter_val == NULL) { - Atomic::inc(&num_ct_writes_filtered_in_hr); - } else if (new_val == NULL) { - Atomic::inc(&num_ct_writes_filtered_null); - } else { - if (g1 == NULL) { - g1 = G1CollectedHeap::heap(); - } - } - if ((num_ct_writes % 1000000) == 0) { - jint num_ct_writes_filtered = - num_ct_writes_filtered_in_hr + - num_ct_writes_filtered_null; - - tty->print_cr("%d potential CT writes: %5.2f%% filtered\n" - " (%5.2f%% intra-HR, %5.2f%% null).", - num_ct_writes, - 100.0*(float)num_ct_writes_filtered/(float)num_ct_writes, - 100.0*(float)num_ct_writes_filtered_in_hr/ - (float)num_ct_writes, - 100.0*(float)num_ct_writes_filtered_null/ - (float)num_ct_writes); - } - return Thread::current(); -} - static address dirty_card_log_enqueue = 0; static u_char* dirty_card_log_enqueue_end = 0; @@ -4574,11 +4522,8 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { __ set(addrlit, O1); // O1 := __ ldub(O0, O1, O2); // O2 := [O0 + O1] - __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, - O2, not_already_dirty); - // Get O1 + O2 into a reg by itself -- useful in the take-the-branch - // case, harmless if not. - __ delayed()->add(O0, O1, O3); + assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); + __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); // We didn't take the branch, so we're already dirty: return. // Use return-from-leaf @@ -4587,8 +4532,13 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { // Not dirty. __ bind(not_already_dirty); + + // Get O0 + O1 into a reg by itself + __ add(O0, O1, O3); + // First, dirty it. __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). + int dirty_card_q_index_byte_offset = in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()); @@ -4596,12 +4546,15 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()); __ bind(restart); + + // Load the index into the update buffer. PtrQueue::_index is + // a size_t so ld_ptr is appropriate here. __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, - L0, refill); - // If the branch is taken, no harm in executing this in the delay slot. - __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); + // index == 0? + __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); + + __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); __ sub(L0, oopSize, L0); __ st_ptr(O3, L1, L0); // [_buf + index] := I0 @@ -4664,6 +4617,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); assert(bs->kind() == BarrierSet::G1SATBCT || bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); + if (G1RSBarrierRegionFilter) { xor3(store_addr, new_val, tmp); #ifdef _LP64 @@ -4672,33 +4626,8 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); #endif - if (G1PrintCTFilterStats) { - guarantee(tmp->is_global(), "Or stats won't work..."); - // This is a sleazy hack: I'm temporarily hijacking G2, which I - // promise to restore. - mov(new_val, G2); - save_frame(0); - mov(tmp, O0); - mov(G2, O1); - // Save G-regs that target may use. - mov(G1, L1); - mov(G2, L2); - mov(G3, L3); - mov(G4, L4); - mov(G5, L5); - call(CAST_FROM_FN_PTR(address, &count_ct_writes)); - delayed()->nop(); - mov(O0, G2); - // Restore G-regs that target may have used. - mov(L1, G1); - mov(L3, G3); - mov(L4, G4); - mov(L5, G5); - restore(G0, G0, G0); - } - // XXX Should I predict this taken or not? Does it mattern? - br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); - delayed()->nop(); + // XXX Should I predict this taken or not? Does it matter? + cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); } // If the "store_addr" register is an "in" or "local" register, move it to @@ -4723,7 +4652,6 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val restore(); bind(filtered); - } #endif // SERIALGC diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 4462ee5d00f..0b3c258abfa 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1940,12 +1940,6 @@ class MacroAssembler: public Assembler { void br_null ( Register s1, bool a, Predict p, Label& L ); void br_notnull( Register s1, bool a, Predict p, Label& L ); - // These versions will do the most efficient thing on v8 and v9. Perhaps - // this is what the routine above was meant to do, but it didn't (and - // didn't cover both target address kinds.) - void br_on_reg_cond( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none ); - void br_on_reg_cond( RCondition c, bool a, Predict p, Register s1, Label& L); - // // Compare registers and branch with nop in delay slot or cbcond without delay slot. // diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index 9124e8eaff1..e155153045f 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -421,8 +421,7 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { } if (__ is_in_wdisp16_range(_continuation)) { - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, - pre_val_reg, _continuation); + __ br_null(pre_val_reg, /*annul*/false, Assembler::pt, _continuation); } else { __ cmp(pre_val_reg, G0); __ brx(Assembler::equal, false, Assembler::pn, _continuation); @@ -458,8 +457,7 @@ void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { // The original src operand was not a constant. // Generate src == null? if (__ is_in_wdisp16_range(_continuation)) { - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, - src_reg, _continuation); + __ br_null(src_reg, /*annul*/false, Assembler::pt, _continuation); } else { __ cmp(src_reg, G0); __ brx(Assembler::equal, false, Assembler::pt, _continuation); @@ -476,13 +474,9 @@ void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset_in_bytes() + sizeof(oopDesc)); __ ld(ref_type_adr, tmp_reg); - if (__ is_in_wdisp16_range(_continuation)) { - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, - tmp_reg, _continuation); - } else { - __ cmp(tmp_reg, G0); - __ brx(Assembler::equal, false, Assembler::pt, _continuation); - } + // _reference_type field is of type ReferenceType (enum) + assert(REF_NONE == 0, "check this code"); + __ cmp_zero_and_br(Assembler::equal, tmp_reg, _continuation, /*annul*/false, Assembler::pt); __ delayed()->nop(); // Is marking active? @@ -498,13 +492,8 @@ void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); __ ldsb(in_progress, tmp_reg); } - if (__ is_in_wdisp16_range(_continuation)) { - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, - tmp_reg, _continuation); - } else { - __ cmp(tmp_reg, G0); - __ brx(Assembler::equal, false, Assembler::pt, _continuation); - } + + __ cmp_zero_and_br(Assembler::equal, tmp_reg, _continuation, /*annul*/false, Assembler::pt); __ delayed()->nop(); // val == null? @@ -512,8 +501,7 @@ void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { Register val_reg = val()->as_register(); if (__ is_in_wdisp16_range(_continuation)) { - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, - val_reg, _continuation); + __ br_null(val_reg, /*annul*/false, Assembler::pt, _continuation); } else { __ cmp(val_reg, G0); __ brx(Assembler::equal, false, Assembler::pt, _continuation); @@ -542,9 +530,9 @@ void G1PostBarrierStub::emit_code(LIR_Assembler* ce) { assert(new_val()->is_register(), "Precondition."); Register addr_reg = addr()->as_pointer_register(); Register new_val_reg = new_val()->as_register(); + if (__ is_in_wdisp16_range(_continuation)) { - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, - new_val_reg, _continuation); + __ br_null(new_val_reg, /*annul*/false, Assembler::pt, _continuation); } else { __ cmp(new_val_reg, G0); __ brx(Assembler::equal, false, Assembler::pn, _continuation); diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index f95756b1fcd..f2cfbdc1ba2 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -834,14 +834,16 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { int satb_q_buf_byte_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()); + __ bind(restart); + // Load the index into the SATB buffer. PtrQueue::_index is a + // size_t so ld_ptr is appropriate __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, - Assembler::pn, tmp, refill); + // index == 0? + __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill); - // If the branch is taken, no harm in executing this in the delay slot. - __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); + __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); __ sub(tmp, oopSize, tmp); __ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := @@ -901,11 +903,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ set(rs, cardtable); // cardtable := __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] - __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, - tmp, not_already_dirty); - // Get cardtable + tmp into a reg by itself -- useful in the take-the-branch - // case, harmless if not. - __ delayed()->add(addr, cardtable, tmp2); + assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); + __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); // We didn't take the branch, so we're already dirty: return. // Use return-from-leaf @@ -914,6 +913,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // Not dirty. __ bind(not_already_dirty); + + // Get cardtable + tmp into a reg by itself + __ add(addr, cardtable, tmp2); + // First, dirty it. __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). @@ -929,13 +932,17 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { int dirty_card_q_buf_byte_offset = in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()); + __ bind(restart); + + // Get the index into the update buffer. PtrQueue::_index is + // a size_t so ld_ptr is appropriate here. __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, - tmp3, refill); - // If the branch is taken, no harm in executing this in the delay slot. - __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); + // index == 0? + __ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill); + + __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); __ sub(tmp3, oopSize, tmp3); __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 0daabdb5dff..94f0ada6920 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -124,9 +124,6 @@ develop(bool, G1RSBarrierNullFilter, true, \ "If true, generate null-pointer filtering code in RS barrier") \ \ - develop(bool, G1PrintCTFilterStats, false, \ - "If true, print stats on RS filtering effectiveness") \ - \ develop(bool, G1DeferredRSUpdate, true, \ "If true, use deferred RS updates") \ \ From fa7c124af1ee9da9962c2e6d06f6edceb482fb3f Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 31 Aug 2011 16:46:11 -0700 Subject: [PATCH 013/214] 7083786: dead various dead chunks of code Reviewed-by: iveresov, kvn --- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 5 -- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 7 --- hotspot/src/cpu/sparc/vm/frame_sparc.hpp | 24 +-------- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 53 ------------------- .../src/cpu/x86/vm/c1_LIRAssembler_x86.hpp | 2 - hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp | 13 ----- hotspot/src/share/vm/c1/c1_Compilation.cpp | 1 - hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 1 - hotspot/src/share/vm/c1/c1_Runtime1.cpp | 8 --- hotspot/src/share/vm/c1/c1_Runtime1.hpp | 2 - hotspot/src/share/vm/ci/ciConstant.hpp | 3 -- hotspot/src/share/vm/ci/ciEnv.cpp | 2 - hotspot/src/share/vm/ci/ciEnv.hpp | 3 +- hotspot/src/share/vm/ci/ciField.hpp | 3 -- hotspot/src/share/vm/code/nmethod.cpp | 1 - hotspot/src/share/vm/code/nmethod.hpp | 7 --- .../src/share/vm/oops/constMethodKlass.cpp | 5 -- hotspot/src/share/vm/opto/compile.cpp | 1 - hotspot/src/share/vm/opto/connode.hpp | 8 --- hotspot/src/share/vm/opto/parse2.cpp | 8 --- hotspot/src/share/vm/opto/runtime.cpp | 1 - hotspot/src/share/vm/prims/forte.cpp | 19 ------- hotspot/src/share/vm/runtime/thread.cpp | 1 - hotspot/src/share/vm/runtime/thread.hpp | 4 -- 24 files changed, 2 insertions(+), 180 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 25c1be78ba2..7a8b5551254 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -142,11 +142,6 @@ LIR_Opr LIR_Assembler::receiverOpr() { } -LIR_Opr LIR_Assembler::incomingReceiverOpr() { - return FrameMap::I0_oop_opr; -} - - LIR_Opr LIR_Assembler::osrBufferPointer() { return FrameMap::I0_opr; } diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index f95756b1fcd..98f68d07001 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -782,13 +782,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; - case jvmti_exception_throw_id: - { // Oexception : exception - __ set_info("jvmti_exception_throw", dont_gc_arguments); - oop_maps = generate_stub_call(sasm, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), I0); - } - break; - case dtrace_object_alloc_id: { // O0: object __ set_info("dtrace_object_alloc", dont_gc_arguments); diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index ed30d40e284..fb0eee67a39 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -259,13 +259,8 @@ }; #endif /* CC_INTERP */ - // the compiler frame has many of the same fields as the interpreter frame - // %%%%% factor out declarations of the shared fields enum compiler_frame_fixed_locals { - compiler_frame_d_scratch_fp_offset = -2, - compiler_frame_vm_locals_fp_offset = -2, // should be same as above - - compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset + compiler_frame_vm_locals_fp_offset = -2 }; private: @@ -283,9 +278,6 @@ inline void interpreter_frame_set_tos_address(intptr_t* x); - - // %%%%% Another idea: instead of defining 3 fns per item, just define one returning a ref - // monitors: // next two fns read and write Lmonitors value, @@ -298,22 +290,8 @@ return ((interpreterState)sp_at(interpreter_state_ptr_offset)); } - #endif /* CC_INTERP */ - - - // Compiled frames - public: - // Tells if this register can hold 64 bits on V9 (really, V8+). - static bool holds_a_doubleword(Register reg) { -#ifdef _LP64 - // return true; - return reg->is_out() || reg->is_global(); -#else - return reg->is_out() || reg->is_global(); -#endif - } #endif // CPU_SPARC_VM_FRAME_SPARC_HPP diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 982d33dc732..407f0fc58fc 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -129,10 +129,6 @@ LIR_Opr LIR_Assembler::receiverOpr() { return FrameMap::receiver_opr; } -LIR_Opr LIR_Assembler::incomingReceiverOpr() { - return receiverOpr(); -} - LIR_Opr LIR_Assembler::osrBufferPointer() { return FrameMap::as_pointer_opr(receiverOpr()->as_register()); } @@ -371,55 +367,6 @@ void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) } -void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register new_hdr, int monitor_no, Register exception) { - if (exception->is_valid()) { - // preserve exception - // note: the monitor_exit runtime call is a leaf routine - // and cannot block => no GC can happen - // The slow case (MonitorAccessStub) uses the first two stack slots - // ([esp+0] and [esp+4]), therefore we store the exception at [esp+8] - __ movptr (Address(rsp, 2*wordSize), exception); - } - - Register obj_reg = obj_opr->as_register(); - Register lock_reg = lock_opr->as_register(); - - // setup registers (lock_reg must be rax, for lock_object) - assert(obj_reg != SYNC_header && lock_reg != SYNC_header, "rax, must be available here"); - Register hdr = lock_reg; - assert(new_hdr == SYNC_header, "wrong register"); - lock_reg = new_hdr; - // compute pointer to BasicLock - Address lock_addr = frame_map()->address_for_monitor_lock(monitor_no); - __ lea(lock_reg, lock_addr); - // unlock object - MonitorAccessStub* slow_case = new MonitorExitStub(lock_opr, true, monitor_no); - // _slow_case_stubs->append(slow_case); - // temporary fix: must be created after exceptionhandler, therefore as call stub - _slow_case_stubs->append(slow_case); - if (UseFastLocking) { - // try inlined fast unlocking first, revert to slow locking if it fails - // note: lock_reg points to the displaced header since the displaced header offset is 0! - assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); - __ unlock_object(hdr, obj_reg, lock_reg, *slow_case->entry()); - } else { - // always do slow unlocking - // note: the slow unlocking code could be inlined here, however if we use - // slow unlocking, speed doesn't matter anyway and this solution is - // simpler and requires less duplicated code - additionally, the - // slow unlocking code is the same in either case which simplifies - // debugging - __ jmp(*slow_case->entry()); - } - // done - __ bind(*slow_case->continuation()); - - if (exception->is_valid()) { - // restore exception - __ movptr (exception, Address(rsp, 2 * wordSize)); - } -} - // This specifies the rsp decrement needed to build the frame int LIR_Assembler::initial_frame_size_in_bytes() { // if rounding, must let FrameMap know! diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp index daccb39e0f2..6ed351033bc 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp @@ -29,8 +29,6 @@ Address::ScaleFactor array_element_size(BasicType type) const; - void monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register new_hdr, int monitor_no, Register exception); - void arith_fpu_implementation(LIR_Code code, int left_index, int right_index, int dest_index, bool pop_fpu_stack); // helper functions which checks for overflow and sets bailout if it diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index 055bb93c4cd..9ad2e58c67b 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1465,19 +1465,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; - case jvmti_exception_throw_id: - { // rax,: exception oop - StubFrame f(sasm, "jvmti_exception_throw", dont_gc_arguments); - // Preserve all registers across this potentially blocking call - const int num_rt_args = 2; // thread, exception oop - OopMap* map = save_live_registers(sasm, num_rt_args); - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), rax); - oop_maps = new OopMapSet(); - oop_maps->add_gc_map(call_offset, map); - restore_live_registers(sasm); - } - break; - case dtrace_object_alloc_id: { // rax,: object StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); diff --git a/hotspot/src/share/vm/c1/c1_Compilation.cpp b/hotspot/src/share/vm/c1/c1_Compilation.cpp index 4521b0f623b..ab3930ccae2 100644 --- a/hotspot/src/share/vm/c1/c1_Compilation.cpp +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp @@ -346,7 +346,6 @@ void Compilation::install_code(int frame_size) { implicit_exception_table(), compiler(), _env->comp_level(), - true, has_unsafe_access() ); } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 857b663f7cf..14b62985833 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -133,7 +133,6 @@ class LIR_Assembler: public CompilationResourceObj { static bool is_small_constant(LIR_Opr opr); static LIR_Opr receiverOpr(); - static LIR_Opr incomingReceiverOpr(); static LIR_Opr osrBufferPointer(); // stubs diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index d806b8346d7..675d389933c 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -375,14 +375,6 @@ JRT_ENTRY(void, Runtime1::throw_array_store_exception(JavaThread* thread, oopDes JRT_END -JRT_ENTRY(void, Runtime1::post_jvmti_exception_throw(JavaThread* thread)) - if (JvmtiExport::can_post_on_exceptions()) { - vframeStream vfst(thread, true); - address bcp = vfst.method()->bcp_from(vfst.bci()); - JvmtiExport::post_exception_throw(thread, vfst.method(), bcp, thread->exception_oop()); - } -JRT_END - // counter_overflow() is called from within C1-compiled methods. The enclosing method is the method // associated with the top activation record. The inlinee (that is possibly included in the enclosing // method) method oop is passed as an argument. In order to do that it is embedded in the code as diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.hpp b/hotspot/src/share/vm/c1/c1_Runtime1.hpp index 78f73bf6209..5499740f1f4 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.hpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.hpp @@ -65,7 +65,6 @@ class StubAssembler; stub(monitorexit_nofpu) /* optimized version that does not preserve fpu registers */ \ stub(access_field_patching) \ stub(load_klass_patching) \ - stub(jvmti_exception_throw) \ stub(g1_pre_barrier_slow) \ stub(g1_post_barrier_slow) \ stub(fpu2long_stub) \ @@ -141,7 +140,6 @@ class Runtime1: public AllStatic { static void unimplemented_entry (JavaThread* thread, StubID id); static address exception_handler_for_pc(JavaThread* thread); - static void post_jvmti_exception_throw(JavaThread* thread); static void throw_range_check_exception(JavaThread* thread, int index); static void throw_index_exception(JavaThread* thread, int index); diff --git a/hotspot/src/share/vm/ci/ciConstant.hpp b/hotspot/src/share/vm/ci/ciConstant.hpp index f217faa24b0..392c6bbd12a 100644 --- a/hotspot/src/share/vm/ci/ciConstant.hpp +++ b/hotspot/src/share/vm/ci/ciConstant.hpp @@ -46,9 +46,6 @@ private: ciObject* _object; } _value; - // Implementation of the print method. - void print_impl(outputStream* st); - public: ciConstant() { diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 97423169370..2fd712d066a 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -949,7 +949,6 @@ void ciEnv::register_method(ciMethod* target, ImplicitExceptionTable* inc_table, AbstractCompiler* compiler, int comp_level, - bool has_debug_info, bool has_unsafe_access) { VM_ENTRY_MARK; nmethod* nm = NULL; @@ -1044,7 +1043,6 @@ void ciEnv::register_method(ciMethod* target, CompileBroker::handle_full_code_cache(); } } else { - NOT_PRODUCT(nm->set_has_debug_info(has_debug_info); ) nm->set_has_unsafe_access(has_unsafe_access); // Record successful registration. diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index 681531b5027..f5242ca024d 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -317,8 +317,7 @@ public: ImplicitExceptionTable* inc_table, AbstractCompiler* compiler, int comp_level, - bool has_debug_info = true, - bool has_unsafe_access = false); + bool has_unsafe_access); // Access to certain well known ciObjects. diff --git a/hotspot/src/share/vm/ci/ciField.hpp b/hotspot/src/share/vm/ci/ciField.hpp index 88b6aade05b..1b481d93cac 100644 --- a/hotspot/src/share/vm/ci/ciField.hpp +++ b/hotspot/src/share/vm/ci/ciField.hpp @@ -64,9 +64,6 @@ private: // shared constructor code void initialize_from(fieldDescriptor* fd); - // The implementation of the print method. - void print_impl(outputStream* st); - public: ciFlags flags() { return _flags; } diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 2449ca3ce16..f375bdca2d3 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -451,7 +451,6 @@ void nmethod::init_defaults() { _stack_traversal_mark = 0; _unload_reported = false; // jvmti state - NOT_PRODUCT(_has_debug_info = false); #ifdef ASSERT _oops_are_stale = false; #endif diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index ae90de6d035..47c5a28cc85 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -191,8 +191,6 @@ class nmethod : public CodeBlob { jbyte _scavenge_root_state; - NOT_PRODUCT(bool _has_debug_info; ) - // Nmethod Flushing lock. If non-zero, then the nmethod is not removed // and is not made into a zombie. However, once the nmethod is made into // a zombie, it will be locked one final time if CompiledMethodUnload @@ -329,11 +327,6 @@ class nmethod : public CodeBlob { methodOop method() const { return _method; } AbstractCompiler* compiler() const { return _compiler; } -#ifndef PRODUCT - bool has_debug_info() const { return _has_debug_info; } - void set_has_debug_info(bool f) { _has_debug_info = false; } -#endif // NOT PRODUCT - // type info bool is_nmethod() const { return true; } bool is_java_method() const { return !method()->is_native(); } diff --git a/hotspot/src/share/vm/oops/constMethodKlass.cpp b/hotspot/src/share/vm/oops/constMethodKlass.cpp index 6e065317d5d..509b4118b74 100644 --- a/hotspot/src/share/vm/oops/constMethodKlass.cpp +++ b/hotspot/src/share/vm/oops/constMethodKlass.cpp @@ -172,11 +172,6 @@ void constMethodKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { int constMethodKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { assert(obj->is_constMethod(), "should be constMethod"); constMethodOop cm_oop = constMethodOop(obj); -#if 0 - PSParallelCompact::adjust_pointer(cm_oop->adr_method()); - PSParallelCompact::adjust_pointer(cm_oop->adr_exception_table()); - PSParallelCompact::adjust_pointer(cm_oop->adr_stackmap_data()); -#endif oop* const beg_oop = cm_oop->oop_block_beg(); oop* const end_oop = cm_oop->oop_block_end(); for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 89559f2e597..2f0f294bed3 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -817,7 +817,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr &_handler_table, &_inc_table, compiler, env()->comp_level(), - true, /*has_debug_info*/ has_unsafe_access() ); } diff --git a/hotspot/src/share/vm/opto/connode.hpp b/hotspot/src/share/vm/opto/connode.hpp index 9d3e094c1ac..78a4427f23f 100644 --- a/hotspot/src/share/vm/opto/connode.hpp +++ b/hotspot/src/share/vm/opto/connode.hpp @@ -496,14 +496,6 @@ public: virtual bool depends_only_on_test() const { return false; } }; -//------------------------------MemMoveNode------------------------------------ -// Memory to memory move. Inserted very late, after allocation. -class MemMoveNode : public Node { -public: - MemMoveNode( Node *dst, Node *src ) : Node(0,dst,src) {} - virtual int Opcode() const; -}; - //------------------------------ThreadLocalNode-------------------------------- // Ideal Node which returns the base of ThreadLocalStorage. class ThreadLocalNode : public Node { diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 26684eaede8..5e8007da298 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -752,20 +752,12 @@ void Parse::do_jsr() { // Handle ret bytecode void Parse::do_ret() { // Find to whom we return. -#if 0 // %%%% MAKE THIS WORK - Node* con = local(); - const TypePtr* tp = con->bottom_type()->isa_ptr(); - assert(tp && tp->singleton(), ""); - int return_bci = (int) tp->get_con(); - merge(return_bci); -#else assert(block()->num_successors() == 1, "a ret can only go one place now"); Block* target = block()->successor_at(0); assert(!target->is_ready(), "our arrival must be expected"); profile_ret(target->flow()->start()); int pnum = target->next_path_num(); merge_common(target, pnum); -#endif } //--------------------------dynamic_branch_prediction-------------------------- diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 4c55ca0d606..49c55212fa2 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -978,7 +978,6 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t thread->set_exception_pc(pc); thread->set_exception_handler_pc(handler_address); - thread->set_exception_stack_size(0); // Check if the exception PC is a MethodHandle call site. thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); diff --git a/hotspot/src/share/vm/prims/forte.cpp b/hotspot/src/share/vm/prims/forte.cpp index 023921c33b6..f3a08782a23 100644 --- a/hotspot/src/share/vm/prims/forte.cpp +++ b/hotspot/src/share/vm/prims/forte.cpp @@ -522,25 +522,6 @@ static void forte_fill_call_trace_given_top(JavaThread* thd, extern "C" { JNIEXPORT void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { - -// This is if'd out because we no longer use thread suspension. -// However if someone wanted to backport this to a 5.0 jvm then this -// code would be important. -#if 0 - if (SafepointSynchronize::is_synchronizing()) { - // The safepoint mechanism is trying to synchronize all the threads. - // Since this can involve thread suspension, it is not safe for us - // to be here. We can reduce the deadlock risk window by quickly - // returning to the SIGPROF handler. However, it is still possible - // for VMThread to catch us here or in the SIGPROF handler. If we - // are suspended while holding a resource and another thread blocks - // on that resource in the SIGPROF handler, then we will have a - // three-thread deadlock (VMThread, this thread, the other thread). - trace->num_frames = ticks_safepoint; // -10 - return; - } -#endif - JavaThread* thread; if (trace->env_id == NULL || diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index efad706b104..18465a30782 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1272,7 +1272,6 @@ void JavaThread::initialize() { _exception_oop = NULL; _exception_pc = 0; _exception_handler_pc = 0; - _exception_stack_size = 0; _is_method_handle_return = 0; _jvmti_thread_state= NULL; _should_post_on_exceptions_flag = JNI_FALSE; diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 8387ab0f0e6..532ca1a5576 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -841,7 +841,6 @@ class JavaThread: public Thread { volatile oop _exception_oop; // Exception thrown in compiled code volatile address _exception_pc; // PC where exception happened volatile address _exception_handler_pc; // PC for handler of exception - volatile int _exception_stack_size; // Size of frame where exception happened volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. // support for compilation @@ -1182,7 +1181,6 @@ class JavaThread: public Thread { // Exception handling for compiled methods oop exception_oop() const { return _exception_oop; } - int exception_stack_size() const { return _exception_stack_size; } address exception_pc() const { return _exception_pc; } address exception_handler_pc() const { return _exception_handler_pc; } bool is_method_handle_return() const { return _is_method_handle_return == 1; } @@ -1190,7 +1188,6 @@ class JavaThread: public Thread { void set_exception_oop(oop o) { _exception_oop = o; } void set_exception_pc(address a) { _exception_pc = a; } void set_exception_handler_pc(address a) { _exception_handler_pc = a; } - void set_exception_stack_size(int size) { _exception_stack_size = size; } void set_is_method_handle_return(bool value) { _is_method_handle_return = value ? 1 : 0; } // Stack overflow support @@ -1264,7 +1261,6 @@ class JavaThread: public Thread { static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop ); } static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } - static ByteSize exception_stack_size_offset() { return byte_offset_of(JavaThread, _exception_stack_size); } static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); } static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } From fcc2a865828c03ac80c7b623f3cdce901e8cc4f3 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 1 Sep 2011 01:31:25 -0700 Subject: [PATCH 014/214] 7079673: JSR 292: C1 should inline bytecoded method handle adapters Reviewed-by: never --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 199 ++++++++++++++---- hotspot/src/share/vm/c1/c1_GraphBuilder.hpp | 18 +- hotspot/src/share/vm/c1/c1_Instruction.cpp | 35 +-- hotspot/src/share/vm/c1/c1_Instruction.hpp | 1 + .../src/share/vm/classfile/javaClasses.cpp | 12 ++ hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 + hotspot/src/share/vm/opto/bytecodeInfo.cpp | 28 ++- hotspot/src/share/vm/opto/callGenerator.cpp | 21 +- hotspot/src/share/vm/opto/parse.hpp | 2 + 9 files changed, 241 insertions(+), 78 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 3de0adc277a..3faa312dd68 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -28,8 +28,10 @@ #include "c1/c1_Compilation.hpp" #include "c1/c1_GraphBuilder.hpp" #include "c1/c1_InstructionPrinter.hpp" +#include "ci/ciCallSite.hpp" #include "ci/ciField.hpp" #include "ci/ciKlass.hpp" +#include "ci/ciMethodHandle.hpp" #include "compiler/compileBroker.hpp" #include "interpreter/bytecode.hpp" #include "runtime/sharedRuntime.hpp" @@ -1424,7 +1426,7 @@ void GraphBuilder::method_return(Value x) { // See whether this is the first return; if so, store off some // of the state for later examination if (num_returns() == 0) { - set_inline_cleanup_info(_block, _last, state()); + set_inline_cleanup_info(); } // The current bci() is in the wrong scope, so use the bci() of @@ -1582,6 +1584,8 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code = Bytecodes::_invokespecial; } + bool is_invokedynamic = code == Bytecodes::_invokedynamic; + // NEEDS_CLEANUP // I've added the target-is_loaded() test below but I don't really understand // how klass->is_loaded() can be true and yet target->is_loaded() is false. @@ -1693,26 +1697,31 @@ void GraphBuilder::invoke(Bytecodes::Code code) { && target->will_link(klass, callee_holder, code)) { // callee is known => check if we have static binding assert(target->is_loaded(), "callee must be known"); - if (code == Bytecodes::_invokestatic - || code == Bytecodes::_invokespecial - || code == Bytecodes::_invokevirtual && target->is_final_method() - ) { - // static binding => check if callee is ok - ciMethod* inline_target = (cha_monomorphic_target != NULL) - ? cha_monomorphic_target - : target; - bool res = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); + if (code == Bytecodes::_invokestatic || + code == Bytecodes::_invokespecial || + code == Bytecodes::_invokevirtual && target->is_final_method() || + code == Bytecodes::_invokedynamic) { + ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target; + bool success = false; + if (target->is_method_handle_invoke()) { + // method handle invokes + success = !is_invokedynamic ? for_method_handle_inline(target) : for_invokedynamic_inline(target); + } + if (!success) { + // static binding => check if callee is ok + success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); + } CHECK_BAILOUT(); #ifndef PRODUCT // printing - if (PrintInlining && !res) { + if (PrintInlining && !success) { // if it was successfully inlined, then it was already printed. - print_inline_result(inline_target, res); + print_inline_result(inline_target, success); } #endif clear_inline_bailout(); - if (res) { + if (success) { // Register dependence if JVMTI has either breakpoint // setting or hotswapping of methods capabilities since they may // cause deoptimization. @@ -1740,7 +1749,6 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code == Bytecodes::_invokespecial || code == Bytecodes::_invokevirtual || code == Bytecodes::_invokeinterface; - bool is_invokedynamic = code == Bytecodes::_invokedynamic; ValueType* result_type = as_ValueType(target->return_type()); // We require the debug info to be the "state before" because @@ -3038,7 +3046,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { INLINE_BAILOUT("disallowed by CompilerOracle") } else if (!callee->can_be_compiled()) { // callee is not compilable (prob. has breakpoints) - INLINE_BAILOUT("not compilable") + INLINE_BAILOUT("not compilable (disabled)") } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) { // intrinsics can be native or not return true; @@ -3397,7 +3405,7 @@ void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool } -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) { assert(!callee->is_native(), "callee must not be native"); if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { INLINE_BAILOUT("inlining prohibited by policy"); @@ -3468,7 +3476,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { // Insert null check if necessary Value recv = NULL; - if (code() != Bytecodes::_invokestatic) { + if (code() != Bytecodes::_invokestatic && + code() != Bytecodes::_invokedynamic) { // note: null check must happen even if first instruction of callee does // an implicit null check since the callee is in a different scope // and we must make sure exception handling does the right thing @@ -3496,7 +3505,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { // fall-through of control flow, all return instructions of the // callee will need to be replaced by Goto's pointing to this // continuation point. - BlockBegin* cont = block_at(next_bci()); + BlockBegin* cont = cont_block != NULL ? cont_block : block_at(next_bci()); bool continuation_existed = true; if (cont == NULL) { cont = new BlockBegin(next_bci()); @@ -3608,27 +3617,29 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { // block merging. This allows load elimination and CSE to take place // across multiple callee scopes if they are relatively simple, and // is currently essential to making inlining profitable. - if ( num_returns() == 1 - && block() == orig_block - && block() == inline_cleanup_block()) { - _last = inline_cleanup_return_prev(); - _state = inline_cleanup_state(); - } else if (continuation_preds == cont->number_of_preds()) { - // Inlining caused that the instructions after the invoke in the - // caller are not reachable any more. So skip filling this block - // with instructions! - assert (cont == continuation(), ""); - assert(_last && _last->as_BlockEnd(), ""); - _skip_block = true; - } else { - // Resume parsing in continuation block unless it was already parsed. - // Note that if we don't change _last here, iteration in - // iterate_bytecodes_for_block will stop when we return. - if (!continuation()->is_set(BlockBegin::was_visited_flag)) { - // add continuation to work list instead of parsing it immediately + if (cont_block == NULL) { + if (num_returns() == 1 + && block() == orig_block + && block() == inline_cleanup_block()) { + _last = inline_cleanup_return_prev(); + _state = inline_cleanup_state(); + } else if (continuation_preds == cont->number_of_preds()) { + // Inlining caused that the instructions after the invoke in the + // caller are not reachable any more. So skip filling this block + // with instructions! + assert(cont == continuation(), ""); assert(_last && _last->as_BlockEnd(), ""); - scope_data()->parent()->add_to_work_list(continuation()); _skip_block = true; + } else { + // Resume parsing in continuation block unless it was already parsed. + // Note that if we don't change _last here, iteration in + // iterate_bytecodes_for_block will stop when we return. + if (!continuation()->is_set(BlockBegin::was_visited_flag)) { + // add continuation to work list instead of parsing it immediately + assert(_last && _last->as_BlockEnd(), ""); + scope_data()->parent()->add_to_work_list(continuation()); + _skip_block = true; + } } } @@ -3645,6 +3656,120 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { } +bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { + assert(!callee->is_static(), "change next line"); + int index = state()->stack_size() - (callee->arg_size_no_receiver() + 1); + Value receiver = state()->stack_at(index); + + if (receiver->type()->is_constant()) { + ciMethodHandle* method_handle = receiver->type()->as_ObjectType()->constant_value()->as_method_handle(); + + // Set the callee to have access to the class and signature in + // the MethodHandleCompiler. + method_handle->set_callee(callee); + method_handle->set_caller(method()); + + // Get an adapter for the MethodHandle. + ciMethod* method_handle_adapter = method_handle->get_method_handle_adapter(); + if (method_handle_adapter != NULL) { + return try_inline(method_handle_adapter, /*holder_known=*/ true); + } + } else if (receiver->as_CheckCast()) { + // Match MethodHandle.selectAlternative idiom + Phi* phi = receiver->as_CheckCast()->obj()->as_Phi(); + + if (phi != NULL && phi->operand_count() == 2) { + // Get the two MethodHandle inputs from the Phi. + Value op1 = phi->operand_at(0); + Value op2 = phi->operand_at(1); + ciMethodHandle* mh1 = op1->type()->as_ObjectType()->constant_value()->as_method_handle(); + ciMethodHandle* mh2 = op2->type()->as_ObjectType()->constant_value()->as_method_handle(); + + // Set the callee to have access to the class and signature in + // the MethodHandleCompiler. + mh1->set_callee(callee); + mh1->set_caller(method()); + mh2->set_callee(callee); + mh2->set_caller(method()); + + // Get adapters for the MethodHandles. + ciMethod* mh1_adapter = mh1->get_method_handle_adapter(); + ciMethod* mh2_adapter = mh2->get_method_handle_adapter(); + + if (mh1_adapter != NULL && mh2_adapter != NULL) { + set_inline_cleanup_info(); + + // Build the If guard + BlockBegin* one = new BlockBegin(next_bci()); + BlockBegin* two = new BlockBegin(next_bci()); + BlockBegin* end = new BlockBegin(next_bci()); + Instruction* iff = append(new If(phi, If::eql, false, op1, one, two, NULL, false)); + block()->set_end(iff->as_BlockEnd()); + + // Connect up the states + one->merge(block()->end()->state()); + two->merge(block()->end()->state()); + + // Save the state for the second inlinee + ValueStack* state_before = copy_state_before(); + + // Parse first adapter + _last = _block = one; + if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) { + restore_inline_cleanup_info(); + block()->clear_end(); // remove appended iff + return false; + } + + // Parse second adapter + _last = _block = two; + _state = state_before; + if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) { + restore_inline_cleanup_info(); + block()->clear_end(); // remove appended iff + return false; + } + + connect_to_end(end); + return true; + } + } + } + return false; +} + + +bool GraphBuilder::for_invokedynamic_inline(ciMethod* callee) { + // Get the MethodHandle from the CallSite. + ciCallSite* call_site = stream()->get_call_site(); + ciMethodHandle* method_handle = call_site->get_target(); + + // Inline constant and mutable call sites. We don't inline + // volatile call sites optimistically since they are specified + // to change their value often and that would result in a lot of + // deoptimizations and recompiles. + if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) { + // Set the callee to have access to the class and signature in the + // MethodHandleCompiler. + method_handle->set_callee(callee); + method_handle->set_caller(method()); + + // Get an adapter for the MethodHandle. + ciMethod* method_handle_adapter = method_handle->get_invokedynamic_adapter(); + if (method_handle_adapter != NULL) { + if (try_inline(method_handle_adapter, /*holder_known=*/ true)) { + // Add a dependence for invalidation of the optimization. + if (!call_site->is_constant_call_site()) { + dependency_recorder()->assert_call_site_target_value(call_site, method_handle); + } + return true; + } + } + } + return false; +} + + void GraphBuilder::inline_bailout(const char* msg) { assert(msg != NULL, "inline bailout msg must exist"); _inline_bailout_msg = msg; diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp index b41d94721ac..8b8800e7448 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -315,9 +315,17 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { ValueStack* return_state) { scope_data()->set_inline_cleanup_info(block, return_prev, return_state); } + void set_inline_cleanup_info() { + set_inline_cleanup_info(_block, _last, _state); + } BlockBegin* inline_cleanup_block() const { return scope_data()->inline_cleanup_block(); } Instruction* inline_cleanup_return_prev() const { return scope_data()->inline_cleanup_return_prev(); } ValueStack* inline_cleanup_state() const { return scope_data()->inline_cleanup_state(); } + void restore_inline_cleanup_info() { + _block = inline_cleanup_block(); + _last = inline_cleanup_return_prev(); + _state = inline_cleanup_state(); + } void incr_num_returns() { scope_data()->incr_num_returns(); } int num_returns() const { return scope_data()->num_returns(); } intx max_inline_size() const { return scope_data()->max_inline_size(); } @@ -329,11 +337,15 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false); // inliners - bool try_inline(ciMethod* callee, bool holder_known); + bool try_inline( ciMethod* callee, bool holder_known); bool try_inline_intrinsics(ciMethod* callee); - bool try_inline_full (ciMethod* callee, bool holder_known); + bool try_inline_full( ciMethod* callee, bool holder_known, BlockBegin* cont_block = NULL); bool try_inline_jsr(int jsr_dest_bci); + // JSR 292 support + bool for_method_handle_inline(ciMethod* callee); + bool for_invokedynamic_inline(ciMethod* callee); + // helpers void inline_bailout(const char* msg); BlockBegin* header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state); diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 46857e16cbb..c723193bba2 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -514,28 +514,17 @@ Constant::CompareResult Constant::compare(Instruction::Condition cond, Value rig void BlockBegin::set_end(BlockEnd* end) { assert(end != NULL, "should not reset block end to NULL"); - BlockEnd* old_end = _end; - if (end == old_end) { + if (end == _end) { return; } - // Must make the predecessors/successors match up with the - // BlockEnd's notion. - int i, n; - if (old_end != NULL) { - // disconnect from the old end - old_end->set_begin(NULL); + clear_end(); - // disconnect this block from it's current successors - for (i = 0; i < _successors.length(); i++) { - _successors.at(i)->remove_predecessor(this); - } - } + // Set the new end _end = end; _successors.clear(); // Now reset successors list based on BlockEnd - n = end->number_of_sux(); - for (i = 0; i < n; i++) { + for (int i = 0; i < end->number_of_sux(); i++) { BlockBegin* sux = end->sux_at(i); _successors.append(sux); sux->_predecessors.append(this); @@ -544,6 +533,22 @@ void BlockBegin::set_end(BlockEnd* end) { } +void BlockBegin::clear_end() { + // Must make the predecessors/successors match up with the + // BlockEnd's notion. + if (_end != NULL) { + // disconnect from the old end + _end->set_begin(NULL); + + // disconnect this block from it's current successors + for (int i = 0; i < _successors.length(); i++) { + _successors.at(i)->remove_predecessor(this); + } + _end = NULL; + } +} + + void BlockBegin::disconnect_edge(BlockBegin* from, BlockBegin* to) { // disconnect any edges between from and to #ifndef PRODUCT diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 719c1f2fb7c..44022c261e7 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -1601,6 +1601,7 @@ LEAF(BlockBegin, StateSplit) void set_depth_first_number(int dfn) { _depth_first_number = dfn; } void set_linear_scan_number(int lsn) { _linear_scan_number = lsn; } void set_end(BlockEnd* end); + void clear_end(); void disconnect_from_graph(); static void disconnect_edge(BlockBegin* from, BlockBegin* to); BlockBegin* insert_block_between(BlockBegin* sux); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index d32ac8f6f19..696d9c9f3ff 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -28,6 +28,7 @@ #include "classfile/vmSymbols.hpp" #include "code/debugInfo.hpp" #include "code/pcDesc.hpp" +#include "compiler/compilerOracle.hpp" #include "interpreter/interpreter.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -2674,6 +2675,17 @@ void java_lang_invoke_CallSite::compute_offsets() { if (k != NULL) { compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); } + + // Disallow compilation of CallSite.setTargetNormal and CallSite.setTargetVolatile + // (For C2: keep this until we have throttling logic for uncommon traps.) + if (k != NULL) { + instanceKlass* ik = instanceKlass::cast(k); + methodOop m_normal = ik->lookup_method(vmSymbols::setTargetNormal_name(), vmSymbols::setTarget_signature()); + methodOop m_volatile = ik->lookup_method(vmSymbols::setTargetVolatile_name(), vmSymbols::setTarget_signature()); + guarantee(m_normal && m_volatile, "must exist"); + m_normal->set_not_compilable_quietly(); + m_volatile->set_not_compilable_quietly(); + } } oop java_lang_invoke_CallSite::target(oop site) { diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index f78be8c8566..79c7ac111de 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -258,6 +258,9 @@ template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \ template(makeDynamicCallSite_name, "makeDynamicCallSite") \ template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \ + template(setTargetNormal_name, "setTargetNormal") \ + template(setTargetVolatile_name, "setTargetVolatile") \ + template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ \ diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 12ba7c21dc8..d21f6d04a85 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -394,6 +394,16 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call return true; } +//------------------------------check_can_parse-------------------------------- +const char* InlineTree::check_can_parse(ciMethod* callee) { + // Certain methods cannot be parsed at all: + if ( callee->is_native()) return "native method"; + if (!callee->can_be_compiled()) return "not compilable (disabled)"; + if (!callee->has_balanced_monitors()) return "not compilable (unbalanced monitors)"; + if ( callee->get_flow_analysis()->failing()) return "not compilable (flow analysis failed)"; + return NULL; +} + //------------------------------print_inlining--------------------------------- // Really, the failure_msg can be a success message also. void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { @@ -423,14 +433,22 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, int caller_bci = jvms->bci(); ciMethod *caller_method = jvms->method(); - if( !pass_initial_checks(caller_method, caller_bci, callee_method)) { - if( PrintInlining ) { + // Do some initial checks. + if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { + if (PrintInlining) { failure_msg = "failed_initial_checks"; - print_inlining( callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, failure_msg); } return NULL; } + // Do some parse checks. + failure_msg = check_can_parse(callee_method); + if (failure_msg != NULL) { + if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + return NULL; + } + // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci); @@ -471,7 +489,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, if (failure_msg == NULL) failure_msg = "inline (hot)"; // Inline! - if( PrintInlining ) print_inlining( callee_method, caller_bci, failure_msg); + if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); if (UseOldInlining) build_inline_tree_for_callee(callee_method, jvms, caller_bci); if (InlineWarmCalls && !wci.is_hot()) @@ -481,7 +499,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, // Do not inline if (failure_msg == NULL) failure_msg = "too cold to inline"; - if( PrintInlining ) print_inlining( callee_method, caller_bci, failure_msg); + if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); return NULL; } diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index b9defcdde36..e01e8fb3aba 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -61,12 +61,9 @@ public: { _is_osr = is_osr; _expected_uses = expected_uses; - assert(can_parse(method, is_osr), "parse must be possible"); + assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible"); } - // Can we build either an OSR or a regular parser for this method? - static bool can_parse(ciMethod* method, int is_osr = false); - virtual bool is_parse() const { return true; } virtual JVMState* generate(JVMState* jvms); int is_osr() { return _is_osr; } @@ -303,20 +300,8 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) { return kit.transfer_exceptions_into_jvms(); } -bool ParseGenerator::can_parse(ciMethod* m, int entry_bci) { - // Certain methods cannot be parsed at all: - if (!m->can_be_compiled()) return false; - if (!m->has_balanced_monitors()) return false; - if (m->get_flow_analysis()->failing()) return false; - - // (Methods may bail out for other reasons, after the parser is run. - // We try to avoid this, but if forced, we must return (Node*)NULL. - // The user of the CallGenerator must check for this condition.) - return true; -} - CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) { - if (!ParseGenerator::can_parse(m)) return NULL; + if (InlineTree::check_can_parse(m) != NULL) return NULL; return new ParseGenerator(m, expected_uses); } @@ -324,7 +309,7 @@ CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) { // for the method execution already in progress, not just the JVMS // of the caller. Thus, this CallGenerator cannot be mixed with others! CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) { - if (!ParseGenerator::can_parse(m, true)) return NULL; + if (InlineTree::check_can_parse(m) != NULL) return NULL; float past_uses = m->interpreter_invocation_count(); float expected_uses = past_uses; return new ParseGenerator(m, expected_uses, true); diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index 0b657827706..ea793f02908 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -78,6 +78,8 @@ protected: int stack_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; } public: + static const char* check_can_parse(ciMethod* callee); + static InlineTree* build_inline_tree_root(); static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found = false); From 5b6ba4e61178c0322ffdb3f7f75fe770a6f81391 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 1 Sep 2011 16:18:17 +0200 Subject: [PATCH 015/214] 7085906: Replace the permgen allocated sentinelRef with a self-looped end Remove the sentinelRef and let the last Reference in a discovered chain point back to itself. Reviewed-by: ysr, jmasa --- .../gc_implementation/g1/g1CollectedHeap.cpp | 1 - .../parallelScavenge/parallelScavengeHeap.cpp | 4 - .../parallelScavenge/pcTasks.cpp | 4 - .../parallelScavenge/pcTasks.hpp | 3 +- .../parallelScavenge/psMarkSweep.cpp | 2 - .../parallelScavenge/psParallelCompact.cpp | 1 - .../parallelScavenge/psTasks.cpp | 1 - .../src/share/vm/memory/genCollectedHeap.cpp | 4 - .../share/vm/memory/referenceProcessor.cpp | 168 ++++++++++-------- .../share/vm/memory/referenceProcessor.hpp | 10 +- hotspot/src/share/vm/memory/sharedHeap.cpp | 1 - 11 files changed, 96 insertions(+), 103 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 52b85d011bd..fa373b70f69 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4613,7 +4613,6 @@ g1_process_strong_roots(bool collecting_perm_gen, // keep entries (which are added by the marking threads) on them // live until they can be processed at the end of marking. ref_processor()->weak_oops_do(&buf_scan_non_heap_roots); - ref_processor()->oops_do(&buf_scan_non_heap_roots); } // Finish up any enqueued closure apps (attributed as object copy time). diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 37190f4db19..42e65f1adb0 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -909,10 +909,6 @@ void ParallelScavengeHeap::verify(bool allow_dirty, bool silent, VerifyOption op } young_gen()->verify(allow_dirty); } - if (!silent) { - gclog_or_tty->print("ref_proc "); - } - ReferenceProcessor::verify(); } void ParallelScavengeHeap::print_heap_change(size_t prev_used) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp index c7a651f03fe..75ee0b3a97a 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp @@ -80,10 +80,6 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) { Universe::oops_do(&mark_and_push_closure); break; - case reference_processing: - ReferenceProcessor::oops_do(&mark_and_push_closure); - break; - case jni_handles: JNIHandles::oops_do(&mark_and_push_closure); break; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp index 4c8b1159526..c79bc7c3a14 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp @@ -98,8 +98,7 @@ class MarkFromRootsTask : public GCTask { management = 6, jvmti = 7, system_dictionary = 8, - reference_processing = 9, - code_cache = 10 + code_cache = 9 }; private: RootType _root_type; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index f5414723335..3d7e0ba4c2d 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -516,7 +516,6 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { { ParallelScavengeHeap::ParStrongRootsScope psrs; Universe::oops_do(mark_and_push_closure()); - ReferenceProcessor::oops_do(mark_and_push_closure()); JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles CodeBlobToOopClosure each_active_code_blob(mark_and_push_closure(), /*do_marking=*/ true); Threads::oops_do(mark_and_push_closure(), &each_active_code_blob); @@ -623,7 +622,6 @@ void PSMarkSweep::mark_sweep_phase3() { // General strong roots. Universe::oops_do(adjust_root_pointer_closure()); - ReferenceProcessor::oops_do(adjust_root_pointer_closure()); JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles Threads::oops_do(adjust_root_pointer_closure(), NULL); ObjectSynchronizer::oops_do(adjust_root_pointer_closure()); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 08b723c7c03..55cb34350b2 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -2445,7 +2445,6 @@ void PSParallelCompact::adjust_roots() { // General strong roots. Universe::oops_do(adjust_root_pointer_closure()); - ReferenceProcessor::oops_do(adjust_root_pointer_closure()); JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles Threads::oops_do(adjust_root_pointer_closure(), NULL); ObjectSynchronizer::oops_do(adjust_root_pointer_closure()); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp index c297477fd60..f3011a82416 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp @@ -55,7 +55,6 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) { switch (_root_type) { case universe: Universe::oops_do(&roots_closure); - ReferenceProcessor::oops_do(&roots_closure); break; case jni_handles: diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index c1acb8d3893..f233cbc7b59 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -1269,10 +1269,6 @@ void GenCollectedHeap::verify(bool allow_dirty, bool silent, VerifyOption option gclog_or_tty->print("remset "); } rem_set()->verify(); - if (!silent) { - gclog_or_tty->print("ref_proc "); - } - ReferenceProcessor::verify(); } void GenCollectedHeap::print() const { print_on(tty); } diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 8a4da9a3602..022d3754576 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -35,7 +35,6 @@ ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; -oop ReferenceProcessor::_sentinelRef = NULL; const int subclasses_of_ref = REF_PHANTOM - REF_OTHER; // List of discovered references. @@ -43,7 +42,7 @@ class DiscoveredList { public: DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } oop head() const { - return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) : + return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : _oop_head; } HeapWord* adr_head() { @@ -53,12 +52,12 @@ public: void set_head(oop o) { if (UseCompressedOops) { // Must compress the head ptr. - _compressed_head = oopDesc::encode_heap_oop_not_null(o); + _compressed_head = oopDesc::encode_heap_oop(o); } else { _oop_head = o; } } - bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } + bool empty() const { return head() == NULL; } size_t length() { return _len; } void set_length(size_t len) { _len = len; } void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } @@ -76,21 +75,9 @@ void referenceProcessor_init() { } void ReferenceProcessor::init_statics() { - assert(_sentinelRef == NULL, "should be initialized precisely once"); - EXCEPTION_MARK; - _sentinelRef = instanceKlass::cast( - SystemDictionary::Reference_klass())-> - allocate_permanent_instance(THREAD); - // Initialize the master soft ref clock. java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); - if (HAS_PENDING_EXCEPTION) { - Handle ex(THREAD, PENDING_EXCEPTION); - vm_exit_during_initialization(ex); - } - assert(_sentinelRef != NULL && _sentinelRef->is_oop(), - "Just constructed it!"); _always_clear_soft_ref_policy = new AlwaysClearPolicy(); _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy()) NOT_COMPILER2(LRUCurrentHeapPolicy()); @@ -130,10 +117,9 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; - assert(sentinel_ref() != NULL, "_sentinelRef is NULL"); - // Initialized all entries to _sentinelRef + // Initialized all entries to NULL for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - _discoveredSoftRefs[i].set_head(sentinel_ref()); + _discoveredSoftRefs[i].set_head(NULL); _discoveredSoftRefs[i].set_length(0); } // If we do barreirs, cache a copy of the barrier set. @@ -167,10 +153,6 @@ void ReferenceProcessor::weak_oops_do(OopClosure* f) { } } -void ReferenceProcessor::oops_do(OopClosure* f) { - f->do_oop(adr_sentinel_ref()); -} - void ReferenceProcessor::update_soft_ref_master_clock() { // Update (advance) the soft ref master clock field. This must be done // after processing the soft ref list. @@ -283,8 +265,6 @@ void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive, } #endif JNIHandles::weak_oops_do(is_alive, keep_alive); - // Finally remember to keep sentinel around - keep_alive->do_oop(adr_sentinel_ref()); complete_gc->do_void(); } @@ -334,21 +314,22 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, (address)refs_list.head()); } - oop obj = refs_list.head(); + + oop obj = NULL; + oop next = refs_list.head(); // Walk down the list, copying the discovered field into - // the next field and clearing it (except for the last - // non-sentinel object which is treated specially to avoid - // confusion with an active reference). - while (obj != sentinel_ref()) { + // the next field and clearing it. + while (obj != next) { + obj = next; assert(obj->is_instanceRef(), "should be reference object"); - oop next = java_lang_ref_Reference::discovered(obj); + next = java_lang_ref_Reference::discovered(obj); if (TraceReferenceGC && PrintGCDetails) { gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, obj, next); } assert(java_lang_ref_Reference::next(obj) == NULL, "The reference should not be enqueued"); - if (next == sentinel_ref()) { // obj is last + if (next == obj) { // obj is last // Swap refs_list into pendling_list_addr and // set obj's next to what we read from pending_list_addr. oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); @@ -366,7 +347,6 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, java_lang_ref_Reference::set_next(obj, next); } java_lang_ref_Reference::set_discovered(obj, (oop) NULL); - obj = next; } } @@ -376,10 +356,9 @@ public: RefProcEnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList discovered_refs[], HeapWord* pending_list_addr, - oop sentinel_ref, int n_queues) : EnqueueTask(ref_processor, discovered_refs, - pending_list_addr, sentinel_ref, n_queues) + pending_list_addr, n_queues) { } virtual void work(unsigned int work_id) { @@ -396,7 +375,7 @@ public: j++, index += _n_queues) { _ref_processor.enqueue_discovered_reflist( _refs_lists[index], _pending_list_addr); - _refs_lists[index].set_head(_sentinel_ref); + _refs_lists[index].set_head(NULL); _refs_lists[index].set_length(0); } } @@ -408,13 +387,13 @@ void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr if (_processing_is_mt && task_executor != NULL) { // Parallel code RefProcEnqueueTask tsk(*this, _discoveredSoftRefs, - pending_list_addr, sentinel_ref(), _max_num_q); + pending_list_addr, _max_num_q); task_executor->execute(tsk); } else { // Serial code: call the parent class's implementation for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); - _discoveredSoftRefs[i].set_head(sentinel_ref()); + _discoveredSoftRefs[i].set_head(NULL); _discoveredSoftRefs[i].set_length(0); } } @@ -428,7 +407,7 @@ public: BoolObjectClosure* is_alive); // End Of List. - inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); } + inline bool has_next() const { return _ref != NULL; } // Get oop to the Reference object. inline oop obj() const { return _ref; } @@ -468,9 +447,13 @@ public: inline void update_discovered() { // First _prev_next ref actually points into DiscoveredList (gross). if (UseCompressedOops) { - _keep_alive->do_oop((narrowOop*)_prev_next); + if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { + _keep_alive->do_oop((narrowOop*)_prev_next); + } } else { - _keep_alive->do_oop((oop*)_prev_next); + if (!oopDesc::is_null(*(oop*)_prev_next)) { + _keep_alive->do_oop((oop*)_prev_next); + } } } @@ -488,6 +471,7 @@ public: private: DiscoveredList& _refs_list; HeapWord* _prev_next; + oop _prev; oop _ref; HeapWord* _discovered_addr; oop _next; @@ -509,6 +493,7 @@ inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_li BoolObjectClosure* is_alive) : _refs_list(refs_list), _prev_next(refs_list.adr_head()), + _prev(NULL), _ref(refs_list.head()), #ifdef ASSERT _first_seen(refs_list.head()), @@ -517,7 +502,7 @@ inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_li _processed(0), _removed(0), #endif - _next(refs_list.head()), + _next(NULL), _keep_alive(keep_alive), _is_alive(is_alive) { } @@ -544,26 +529,43 @@ inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referen inline void DiscoveredListIterator::next() { _prev_next = _discovered_addr; + _prev = _ref; move_to_next(); } inline void DiscoveredListIterator::remove() { assert(_ref->is_oop(), "Dropping a bad reference"); oop_store_raw(_discovered_addr, NULL); + // First _prev_next ref actually points into DiscoveredList (gross). + oop new_next; + if (_next == _ref) { + // At the end of the list, we should make _prev point to itself. + // If _ref is the first ref, then _prev_next will be in the DiscoveredList, + // and _prev will be NULL. + new_next = _prev; + } else { + new_next = _next; + } + if (UseCompressedOops) { // Remove Reference object from list. - oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next); + oopDesc::encode_store_heap_oop((narrowOop*)_prev_next, new_next); } else { // Remove Reference object from list. - oopDesc::store_heap_oop((oop*)_prev_next, _next); + oopDesc::store_heap_oop((oop*)_prev_next, new_next); } NOT_PRODUCT(_removed++); _refs_list.dec_length(1); } inline void DiscoveredListIterator::move_to_next() { - _ref = _next; + if (_ref == _next) { + // End of the list. + _ref = NULL; + } else { + _ref = _next; + } assert(_ref != _first_seen, "cyclic ref_list found"); NOT_PRODUCT(_processed++); } @@ -725,24 +727,30 @@ ReferenceProcessor::process_phase3(DiscoveredList& refs_list, assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); iter.next(); } - // Remember to keep sentinel pointer around + // Remember to update the next pointer of the last ref. iter.update_discovered(); // Close the reachable set complete_gc->do_void(); } void -ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { - oop obj = refs_list.head(); - while (obj != sentinel_ref()) { - oop discovered = java_lang_ref_Reference::discovered(obj); +ReferenceProcessor::clear_discovered_references(DiscoveredList& refs_list) { + oop obj = NULL; + oop next = refs_list.head(); + while (next != obj) { + obj = next; + next = java_lang_ref_Reference::discovered(obj); java_lang_ref_Reference::set_discovered_raw(obj, NULL); - obj = discovered; } - refs_list.set_head(sentinel_ref()); + refs_list.set_head(NULL); refs_list.set_length(0); } +void +ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { + clear_discovered_references(refs_list); +} + void ReferenceProcessor::abandon_partial_discovery() { // loop over the lists for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { @@ -859,6 +867,9 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) refs_to_move = MIN2(ref_lists[from_idx].length() - avg_refs, avg_refs - ref_lists[to_idx].length()); } + + assert(refs_to_move > 0, "otherwise the code below will fail"); + oop move_head = ref_lists[from_idx].head(); oop move_tail = move_head; oop new_head = move_head; @@ -867,10 +878,24 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) move_tail = new_head; new_head = java_lang_ref_Reference::discovered(new_head); } - java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); + + // Add the chain to the to list. + if (ref_lists[to_idx].head() == NULL) { + // to list is empty. Make a loop at the end. + java_lang_ref_Reference::set_discovered(move_tail, move_tail); + } else { + java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); + } ref_lists[to_idx].set_head(move_head); ref_lists[to_idx].inc_length(refs_to_move); - ref_lists[from_idx].set_head(new_head); + + // Remove the chain from the from list. + if (move_tail == new_head) { + // We found the end of the from list. + ref_lists[from_idx].set_head(NULL); + } else { + ref_lists[from_idx].set_head(new_head); + } ref_lists[from_idx].dec_length(refs_to_move); if (ref_lists[from_idx].length() == 0) { break; @@ -1082,6 +1107,8 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, // First we must make sure this object is only enqueued once. CAS in a non null // discovered_addr. oop current_head = refs_list.head(); + // The last ref must have its discovered field pointing to itself. + oop next_discovered = (current_head != NULL) ? current_head : obj; // Note: In the case of G1, this specific pre-barrier is strictly // not necessary because the only case we are interested in @@ -1091,13 +1118,13 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, // collector that might have need for a pre-barrier here. if (_discovered_list_needs_barrier && !UseG1GC) { if (UseCompressedOops) { - _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head); + _bs->write_ref_field_pre((narrowOop*)discovered_addr, next_discovered); } else { - _bs->write_ref_field_pre((oop*)discovered_addr, current_head); + _bs->write_ref_field_pre((oop*)discovered_addr, next_discovered); } guarantee(false, "Need to check non-G1 collector"); } - oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr, + oop retest = oopDesc::atomic_compare_exchange_oop(next_discovered, discovered_addr, NULL); if (retest == NULL) { // This thread just won the right to enqueue the object. @@ -1106,7 +1133,7 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, refs_list.set_head(obj); refs_list.inc_length(1); if (_discovered_list_needs_barrier) { - _bs->write_ref_field((void*)discovered_addr, current_head); + _bs->write_ref_field((void*)discovered_addr, next_discovered); } if (TraceReferenceGC) { @@ -1262,20 +1289,23 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { // here: the field will be visited later when processing the discovered // references. oop current_head = list->head(); + // The last ref must have its discovered field pointing to itself. + oop next_discovered = (current_head != NULL) ? current_head : obj; + // As in the case further above, since we are over-writing a NULL // pre-value, we can safely elide the pre-barrier here for the case of G1. assert(discovered == NULL, "control point invariant"); if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1 if (UseCompressedOops) { - _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head); + _bs->write_ref_field_pre((narrowOop*)discovered_addr, next_discovered); } else { - _bs->write_ref_field_pre((oop*)discovered_addr, current_head); + _bs->write_ref_field_pre((oop*)discovered_addr, next_discovered); } guarantee(false, "Need to check non-G1 collector"); } - oop_store_raw(discovered_addr, current_head); + oop_store_raw(discovered_addr, next_discovered); if (_discovered_list_needs_barrier) { - _bs->write_ref_field((void*)discovered_addr, current_head); + _bs->write_ref_field((void*)discovered_addr, next_discovered); } list->set_head(obj); list->inc_length(1); @@ -1437,22 +1467,12 @@ void ReferenceProcessor::verify_ok_to_handle_reflists() { } #endif -void ReferenceProcessor::verify() { - guarantee(sentinel_ref() != NULL && sentinel_ref()->is_oop(), "Lost _sentinelRef"); -} - #ifndef PRODUCT void ReferenceProcessor::clear_discovered_references() { guarantee(!_discovering_refs, "Discovering refs?"); for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - oop obj = _discoveredSoftRefs[i].head(); - while (obj != sentinel_ref()) { - oop next = java_lang_ref_Reference::discovered(obj); - java_lang_ref_Reference::set_discovered(obj, (oop) NULL); - obj = next; - } - _discoveredSoftRefs[i].set_head(sentinel_ref()); - _discoveredSoftRefs[i].set_length(0); + clear_discovered_references(_discoveredSoftRefs[i]); } } + #endif // PRODUCT diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index fceb4c4ec1e..56f262eb47e 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -52,8 +52,6 @@ class DiscoveredList; class ReferenceProcessor : public CHeapObj { protected: - // End of list marker - static oop _sentinelRef; MemRegion _span; // (right-open) interval of heap // subject to wkref discovery bool _discovering_refs; // true when discovery enabled @@ -106,8 +104,6 @@ class ReferenceProcessor : public CHeapObj { int max_num_q() { return _max_num_q; } void set_active_mt_degree(int v) { _num_q = v; } DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } - static oop sentinel_ref() { return _sentinelRef; } - static oop* adr_sentinel_ref() { return &_sentinelRef; } ReferencePolicy* setup_policy(bool always_clear) { _current_soft_ref_policy = always_clear ? _always_clear_soft_ref_policy : _default_soft_ref_policy; @@ -230,6 +226,7 @@ class ReferenceProcessor : public CHeapObj { HeapWord* discovered_addr); void verify_ok_to_handle_reflists() PRODUCT_RETURN; + void clear_discovered_references(DiscoveredList& refs_list); void abandon_partial_discovered_list(DiscoveredList& refs_list); // Calculate the number of jni handles. @@ -314,7 +311,6 @@ class ReferenceProcessor : public CHeapObj { // iterate over oops void weak_oops_do(OopClosure* f); // weak roots - static void oops_do(OopClosure* f); // strong root(s) // Balance each of the discovered lists. void balance_all_queues(); @@ -340,7 +336,6 @@ class ReferenceProcessor : public CHeapObj { // debugging void verify_no_references_recorded() PRODUCT_RETURN; void verify_referent(oop obj) PRODUCT_RETURN; - static void verify(); // clear the discovered lists (unlinking each entry). void clear_discovered_references() PRODUCT_RETURN; @@ -524,12 +519,10 @@ protected: EnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList refs_lists[], HeapWord* pending_list_addr, - oop sentinel_ref, int n_queues) : _ref_processor(ref_processor), _refs_lists(refs_lists), _pending_list_addr(pending_list_addr), - _sentinel_ref(sentinel_ref), _n_queues(n_queues) { } @@ -540,7 +533,6 @@ protected: ReferenceProcessor& _ref_processor; DiscoveredList* _refs_lists; HeapWord* _pending_list_addr; - oop _sentinel_ref; int _n_queues; }; diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp index e386e726993..15d8eaa5406 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.cpp +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp @@ -146,7 +146,6 @@ void SharedHeap::process_strong_roots(bool activate_scope, assert(_strong_roots_parity != 0, "must have called prologue code"); if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) { Universe::oops_do(roots); - ReferenceProcessor::oops_do(roots); // Consider perm-gen discovered lists to be strong. perm_gen()->ref_processor()->weak_oops_do(roots); } From db44acbeb41c9412c88c712c6d1ca7d819af8663 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 2 Sep 2011 00:36:18 -0700 Subject: [PATCH 016/214] 7085404: JSR 292: VolatileCallSites should have push notification too Reviewed-by: never, kvn --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 30 ++++++++----------- hotspot/src/share/vm/ci/ciField.hpp | 4 ++- .../vm/interpreter/interpreterRuntime.cpp | 2 +- hotspot/src/share/vm/opto/callGenerator.cpp | 3 +- hotspot/src/share/vm/opto/doCall.cpp | 12 ++------ hotspot/src/share/vm/opto/parse3.cpp | 4 +-- hotspot/src/share/vm/prims/unsafe.cpp | 13 ++++++++ 7 files changed, 35 insertions(+), 33 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 3faa312dd68..e103fbf44e2 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3744,26 +3744,20 @@ bool GraphBuilder::for_invokedynamic_inline(ciMethod* callee) { ciCallSite* call_site = stream()->get_call_site(); ciMethodHandle* method_handle = call_site->get_target(); - // Inline constant and mutable call sites. We don't inline - // volatile call sites optimistically since they are specified - // to change their value often and that would result in a lot of - // deoptimizations and recompiles. - if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) { - // Set the callee to have access to the class and signature in the - // MethodHandleCompiler. - method_handle->set_callee(callee); - method_handle->set_caller(method()); + // Set the callee to have access to the class and signature in the + // MethodHandleCompiler. + method_handle->set_callee(callee); + method_handle->set_caller(method()); - // Get an adapter for the MethodHandle. - ciMethod* method_handle_adapter = method_handle->get_invokedynamic_adapter(); - if (method_handle_adapter != NULL) { - if (try_inline(method_handle_adapter, /*holder_known=*/ true)) { - // Add a dependence for invalidation of the optimization. - if (!call_site->is_constant_call_site()) { - dependency_recorder()->assert_call_site_target_value(call_site, method_handle); - } - return true; + // Get an adapter for the MethodHandle. + ciMethod* method_handle_adapter = method_handle->get_invokedynamic_adapter(); + if (method_handle_adapter != NULL) { + if (try_inline(method_handle_adapter, /*holder_known=*/ true)) { + // Add a dependence for invalidation of the optimization. + if (!call_site->is_constant_call_site()) { + dependency_recorder()->assert_call_site_target_value(call_site, method_handle); } + return true; } } return false; diff --git a/hotspot/src/share/vm/ci/ciField.hpp b/hotspot/src/share/vm/ci/ciField.hpp index 1b481d93cac..71145969f2b 100644 --- a/hotspot/src/share/vm/ci/ciField.hpp +++ b/hotspot/src/share/vm/ci/ciField.hpp @@ -175,7 +175,9 @@ public: bool is_volatile () { return flags().is_volatile(); } bool is_transient () { return flags().is_transient(); } - bool is_call_site_target() { return ((holder() == CURRENT_ENV->CallSite_klass()) && (name() == ciSymbol::target_name())); } + bool is_call_site_target() { + return (holder()->is_subclass_of(CURRENT_ENV->CallSite_klass()) && (name() == ciSymbol::target_name())); + } // Debugging output void print(); diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 87bbcd3932a..3898078ec2d 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -555,7 +555,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be"); { - // Walk all nmethods depending on CallSite + // Walk all nmethods depending on this call site. MutexLocker mu(Compile_lock, thread); Universe::flush_dependents_on(call_site, method_handle); } diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index e01e8fb3aba..dc02770a9c7 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -726,7 +726,6 @@ CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMS CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile) { - assert(call_site->is_constant_call_site() || call_site->is_mutable_call_site(), "must be"); ciMethodHandle* method_handle = call_site->get_target(); // Set the callee to have access to the class and signature in the @@ -742,7 +741,7 @@ CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JV CallGenerator* cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); if (cg != NULL && cg->is_inline()) { // Add a dependence for invalidation of the optimization. - if (call_site->is_mutable_call_site()) { + if (!call_site->is_constant_call_site()) { C->dependencies()->assert_call_site_target_value(call_site, method_handle); } return cg; diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index de51329e822..b3c405ff527 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -136,15 +136,9 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. ciCallSite* call_site = str.get_call_site(); - // Inline constant and mutable call sites. We don't inline - // volatile call sites optimistically since they are specified - // to change their value often and that would result in a lot of - // deoptimizations and recompiles. - if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) { - CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile); - if (cg != NULL) { - return cg; - } + CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile); + if (cg != NULL) { + return cg; } // If something failed, generate a normal dynamic call. return CallGenerator::for_dynamic_call(call_method); diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 1f0335cfe0e..4c482fbaed1 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -100,11 +100,11 @@ void Parse::do_field_access(bool is_get, bool is_field) { } } - // Deoptimize on putfield writes to CallSite.target + // Deoptimize on putfield writes to call site target field. if (!is_get && field->is_call_site_target()) { uncommon_trap(Deoptimization::Reason_unhandled, Deoptimization::Action_reinterpret, - NULL, "put to CallSite.target field"); + NULL, "put to call site target field"); return; } diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 4652059434f..fbb723b77b2 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -302,6 +302,19 @@ UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject UnsafeWrapper("Unsafe_SetObjectVolatile"); oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); + // Catch VolatileCallSite.target stores (via + // CallSite.setTargetVolatile) and check call site dependencies. + if ((offset == java_lang_invoke_CallSite::target_offset_in_bytes()) && p->is_a(SystemDictionary::CallSite_klass())) { + oop call_site = p; + oop method_handle = x; + assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "must be"); + assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be"); + { + // Walk all nmethods depending on this call site. + MutexLocker mu(Compile_lock, thread); + Universe::flush_dependents_on(call_site, method_handle); + } + } void* addr = index_oop_from_field_offset_long(p, offset); OrderAccess::release(); if (UseCompressedOops) { From b57839cc49ed6bb834bbda41dfde8304381950af Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 2 Sep 2011 15:47:42 -0700 Subject: [PATCH 017/214] Added tag hs22-b01 for changeset 2143c41c2a90 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 8b06316e463..3fa092f4b0f 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -177,3 +177,4 @@ c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143 0cc8a70952c368e06de2adab1f2649a408f5e577 jdk8-b01 31e253c1da429124bb87570ab095d9bc89850d0a jdk8-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03 +0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01 From 87501184d9f1fd27adb4440a04737a6129f61c3b Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 2 Sep 2011 15:47:43 -0700 Subject: [PATCH 018/214] Added tag hs22-b02 for changeset 7adf55aec150 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 3fa092f4b0f..49d1eba4b04 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -178,3 +178,4 @@ c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143 31e253c1da429124bb87570ab095d9bc89850d0a jdk8-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03 0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01 +7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02 From d42d7de7fff375af282556c0b1803a020964a02e Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 2 Sep 2011 15:47:43 -0700 Subject: [PATCH 019/214] Added tag hs22-b03 for changeset 52cac2467a60 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 49d1eba4b04..1f16864cac3 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -179,3 +179,4 @@ c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03 0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01 7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02 +3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03 From 096ba80aea67fe0020cada2671bbf8ab6add6ef3 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 2 Sep 2011 03:49:30 -0700 Subject: [PATCH 020/214] 7086589: bump the hs22 build number to 04 Reviewed-by: johnc --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 55aecb700c0..0be8bcd1946 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=22 HS_MINOR_VER=0 -HS_BUILD_NUMBER=03 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 1038fed51d2b9866a00b1e6b9f23c54e7640c811 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 2 Sep 2011 04:28:59 -0700 Subject: [PATCH 021/214] 7071709: JSR 292: switchpoint invalidation should be pushed not pulled Reviewed-by: never --- hotspot/src/share/vm/opto/memnode.cpp | 36 ++++++++++++++++++++++++--- hotspot/src/share/vm/opto/parse3.cpp | 8 +++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index b27b1337f0e..ba0960116fc 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1493,6 +1493,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { if (tp == NULL || tp->empty()) return Type::TOP; int off = tp->offset(); assert(off != Type::OffsetTop, "case covered by TypePtr::empty"); + Compile* C = phase->C; // Try to guess loaded type from pointer type if (tp->base() == Type::AryPtr) { @@ -1536,7 +1537,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { Node* base = adr->in(AddPNode::Base); if (base != NULL && !phase->type(base)->higher_equal(TypePtr::NULL_PTR)) { - Compile::AliasType* atp = phase->C->alias_type(base->adr_type()); + Compile::AliasType* atp = C->alias_type(base->adr_type()); if (is_autobox_cache(atp)) { return jt->join(TypePtr::NOTNULL)->is_ptr(); } @@ -1546,22 +1547,23 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { } } } else if (tp->base() == Type::InstPtr) { + ciEnv* env = C->env(); const TypeInstPtr* tinst = tp->is_instptr(); ciKlass* klass = tinst->klass(); assert( off != Type::OffsetBot || // arrays can be cast to Objects tp->is_oopptr()->klass()->is_java_lang_Object() || // unsafe field access may not have a constant offset - phase->C->has_unsafe_access(), + C->has_unsafe_access(), "Field accesses must be precise" ); // For oop loads, we expect the _type to be precise - if (klass == phase->C->env()->String_klass() && + if (klass == env->String_klass() && adr->is_AddP() && off != Type::OffsetBot) { // For constant Strings treat the final fields as compile time constants. Node* base = adr->in(AddPNode::Base); const TypeOopPtr* t = phase->type(base)->isa_oopptr(); if (t != NULL && t->singleton()) { - ciField* field = phase->C->env()->String_klass()->get_field_by_offset(off, false); + ciField* field = env->String_klass()->get_field_by_offset(off, false); if (field != NULL && field->is_final()) { ciObject* string = t->const_oop(); ciConstant constant = string->as_instance()->field_value(field); @@ -1577,6 +1579,32 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { } } } + // Optimizations for constant objects + ciObject* const_oop = tinst->const_oop(); + if (const_oop != NULL) { + // For constant CallSites treat the target field as a compile time constant. + if (const_oop->is_call_site()) { + ciCallSite* call_site = const_oop->as_call_site(); + ciField* field = call_site->klass()->as_instance_klass()->get_field_by_offset(off, /*is_static=*/ false); + if (field != NULL && field->is_call_site_target()) { + ciMethodHandle* target = call_site->get_target(); + if (target != NULL) { // just in case + ciConstant constant(T_OBJECT, target); + const Type* t; + if (adr->bottom_type()->is_ptr_to_narrowoop()) { + t = TypeNarrowOop::make_from_constant(constant.as_object(), true); + } else { + t = TypeOopPtr::make_from_constant(constant.as_object(), true); + } + // Add a dependence for invalidation of the optimization. + if (!call_site->is_constant_call_site()) { + C->dependencies()->assert_call_site_target_value(call_site, target); + } + return t; + } + } + } + } } else if (tp->base() == Type::KlassPtr) { assert( off != Type::OffsetBot || // arrays can be cast to Objects diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 4c482fbaed1..6d6fd07c6d9 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -147,19 +147,21 @@ void Parse::do_field_access(bool is_get, bool is_field) { void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { // Does this field have a constant value? If so, just push the value. if (field->is_constant()) { + // final field if (field->is_static()) { // final static field if (push_constant(field->constant_value())) return; } else { - // final non-static field of a trusted class (classes in - // java.lang.invoke and sun.invoke packages and subpackages). + // final non-static field + // Treat final non-static fields of trusted classes (classes in + // java.lang.invoke and sun.invoke packages and subpackages) as + // compile time constants. if (obj->is_Con()) { const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); ciObject* constant_oop = oop_ptr->const_oop(); ciConstant constant = field->constant_value_of(constant_oop); - if (push_constant(constant, true)) return; } From f7d7a6071a571edb13defa2c1d595989f714e77f Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 2 Sep 2011 12:13:33 -0700 Subject: [PATCH 022/214] 7039731: arraycopy could use prefetch on SPARC Use BIS and prefetch in arraycopy stubs for Sparc (BIS for T4 only). Reviewed-by: never, iveresov --- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 330 +++++++++++++----- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 28 ++ hotspot/src/share/vm/runtime/globals.hpp | 12 + 3 files changed, 282 insertions(+), 88 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 9f6274d5aae..a7fe854e069 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -1124,6 +1124,126 @@ class StubGenerator: public StubCodeGenerator { } } + // + // Generate main code for disjoint arraycopy + // + typedef void (StubGenerator::*CopyLoopFunc)(Register from, Register to, Register count, int count_dec, + Label& L_loop, bool use_prefetch, bool use_bis); + + void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size, + int iter_size, CopyLoopFunc copy_loop_func) { + Label L_copy; + + assert(log2_elem_size <= 3, "the following code should be changed"); + int count_dec = 16>>log2_elem_size; + + int prefetch_dist = MAX2(ArraycopySrcPrefetchDistance, ArraycopyDstPrefetchDistance); + assert(prefetch_dist < 4096, "invalid value"); + prefetch_dist = (prefetch_dist + (iter_size-1)) & (-iter_size); // round up to one iteration copy size + int prefetch_count = (prefetch_dist >> log2_elem_size); // elements count + + if (UseBlockCopy) { + Label L_block_copy, L_block_copy_prefetch, L_skip_block_copy; + + // 64 bytes tail + bytes copied in one loop iteration + int tail_size = 64 + iter_size; + int block_copy_count = (MAX2(tail_size, (int)BlockCopyLowLimit)) >> log2_elem_size; + // Use BIS copy only for big arrays since it requires membar. + __ set(block_copy_count, O4); + __ cmp_and_br_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_skip_block_copy); + // This code is for disjoint source and destination: + // to <= from || to >= from+count + // but BIS will stomp over 'from' if (to > from-tail_size && to <= from) + __ sub(from, to, O4); + __ srax(O4, 4, O4); // divide by 16 since following short branch have only 5 bits for imm. + __ cmp_and_br_short(O4, (tail_size>>4), Assembler::lessEqualUnsigned, Assembler::pn, L_skip_block_copy); + + __ wrasi(G0, Assembler::ASI_ST_BLKINIT_PRIMARY); + // BIS should not be used to copy tail (64 bytes+iter_size) + // to avoid zeroing of following values. + __ sub(count, (tail_size>>log2_elem_size), count); // count is still positive >= 0 + + if (prefetch_count > 0) { // rounded up to one iteration count + // Do prefetching only if copy size is bigger + // than prefetch distance. + __ set(prefetch_count, O4); + __ cmp_and_brx_short(count, O4, Assembler::less, Assembler::pt, L_block_copy); + __ sub(count, prefetch_count, count); + + (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy_prefetch, true, true); + __ add(count, prefetch_count, count); // restore count + + } // prefetch_count > 0 + + (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy, false, true); + __ add(count, (tail_size>>log2_elem_size), count); // restore count + + __ wrasi(G0, Assembler::ASI_PRIMARY_NOFAULT); + // BIS needs membar. + __ membar(Assembler::StoreLoad); + // Copy tail + __ ba_short(L_copy); + + __ BIND(L_skip_block_copy); + } // UseBlockCopy + + if (prefetch_count > 0) { // rounded up to one iteration count + // Do prefetching only if copy size is bigger + // than prefetch distance. + __ set(prefetch_count, O4); + __ cmp_and_brx_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_copy); + __ sub(count, prefetch_count, count); + + Label L_copy_prefetch; + (this->*copy_loop_func)(from, to, count, count_dec, L_copy_prefetch, true, false); + __ add(count, prefetch_count, count); // restore count + + } // prefetch_count > 0 + + (this->*copy_loop_func)(from, to, count, count_dec, L_copy, false, false); + } + + + + // + // Helper methods for copy_16_bytes_forward_with_shift() + // + void copy_16_bytes_shift_loop(Register from, Register to, Register count, int count_dec, + Label& L_loop, bool use_prefetch, bool use_bis) { + + const Register left_shift = G1; // left shift bit counter + const Register right_shift = G5; // right shift bit counter + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + if (use_prefetch) { + if (ArraycopySrcPrefetchDistance > 0) { + __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); + } + if (ArraycopyDstPrefetchDistance > 0) { + __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); + } + } + __ ldx(from, 0, O4); + __ ldx(from, 8, G4); + __ inc(to, 16); + __ inc(from, 16); + __ deccc(count, count_dec); // Can we do next iteration after this one? + __ srlx(O4, right_shift, G3); + __ bset(G3, O3); + __ sllx(O4, left_shift, O4); + __ srlx(G4, right_shift, G3); + __ bset(G3, O4); + if (use_bis) { + __ stxa(O3, to, -16); + __ stxa(O4, to, -8); + } else { + __ stx(O3, to, -16); + __ stx(O4, to, -8); + } + __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); + __ delayed()->sllx(G4, left_shift, O3); + } // Copy big chunks forward with shift // @@ -1135,64 +1255,51 @@ class StubGenerator: public StubCodeGenerator { // L_copy_bytes - copy exit label // void copy_16_bytes_forward_with_shift(Register from, Register to, - Register count, int count_dec, Label& L_copy_bytes) { - Label L_loop, L_aligned_copy, L_copy_last_bytes; + Register count, int log2_elem_size, Label& L_copy_bytes) { + Label L_aligned_copy, L_copy_last_bytes; + assert(log2_elem_size <= 3, "the following code should be changed"); + int count_dec = 16>>log2_elem_size; // if both arrays have the same alignment mod 8, do 8 bytes aligned copy - __ andcc(from, 7, G1); // misaligned bytes - __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy); - __ delayed()->nop(); + __ andcc(from, 7, G1); // misaligned bytes + __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy); + __ delayed()->nop(); const Register left_shift = G1; // left shift bit counter const Register right_shift = G5; // right shift bit counter - __ sll(G1, LogBitsPerByte, left_shift); - __ mov(64, right_shift); - __ sub(right_shift, left_shift, right_shift); + __ sll(G1, LogBitsPerByte, left_shift); + __ mov(64, right_shift); + __ sub(right_shift, left_shift, right_shift); // // Load 2 aligned 8-bytes chunks and use one from previous iteration // to form 2 aligned 8-bytes chunks to store. // - __ deccc(count, count_dec); // Pre-decrement 'count' - __ andn(from, 7, from); // Align address - __ ldx(from, 0, O3); - __ inc(from, 8); - __ align(OptoLoopAlignment); - __ BIND(L_loop); - __ ldx(from, 0, O4); - __ deccc(count, count_dec); // Can we do next iteration after this one? - __ ldx(from, 8, G4); - __ inc(to, 16); - __ inc(from, 16); - __ sllx(O3, left_shift, O3); - __ srlx(O4, right_shift, G3); - __ bset(G3, O3); - __ stx(O3, to, -16); - __ sllx(O4, left_shift, O4); - __ srlx(G4, right_shift, G3); - __ bset(G3, O4); - __ stx(O4, to, -8); - __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); - __ delayed()->mov(G4, O3); + __ dec(count, count_dec); // Pre-decrement 'count' + __ andn(from, 7, from); // Align address + __ ldx(from, 0, O3); + __ inc(from, 8); + __ sllx(O3, left_shift, O3); - __ inccc(count, count_dec>>1 ); // + 8 bytes - __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes); - __ delayed()->inc(count, count_dec>>1); // restore 'count' + disjoint_copy_core(from, to, count, log2_elem_size, 16, copy_16_bytes_shift_loop); - // copy 8 bytes, part of them already loaded in O3 - __ ldx(from, 0, O4); - __ inc(to, 8); - __ inc(from, 8); - __ sllx(O3, left_shift, O3); - __ srlx(O4, right_shift, G3); - __ bset(O3, G3); - __ stx(G3, to, -8); + __ inccc(count, count_dec>>1 ); // + 8 bytes + __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes); + __ delayed()->inc(count, count_dec>>1); // restore 'count' + + // copy 8 bytes, part of them already loaded in O3 + __ ldx(from, 0, O4); + __ inc(to, 8); + __ inc(from, 8); + __ srlx(O4, right_shift, G3); + __ bset(O3, G3); + __ stx(G3, to, -8); __ BIND(L_copy_last_bytes); - __ srl(right_shift, LogBitsPerByte, right_shift); // misaligned bytes - __ br(Assembler::always, false, Assembler::pt, L_copy_bytes); - __ delayed()->sub(from, right_shift, from); // restore address + __ srl(right_shift, LogBitsPerByte, right_shift); // misaligned bytes + __ br(Assembler::always, false, Assembler::pt, L_copy_bytes); + __ delayed()->sub(from, right_shift, from); // restore address __ BIND(L_aligned_copy); } @@ -1348,7 +1455,7 @@ class StubGenerator: public StubCodeGenerator { // The compare above (count >= 23) guarantes 'count' >= 16 bytes. // Also jump over aligned copy after the copy with shift completed. - copy_16_bytes_forward_with_shift(from, to, count, 16, L_copy_byte); + copy_16_bytes_forward_with_shift(from, to, count, 0, L_copy_byte); } // Both array are 8 bytes aligned, copy 16 bytes at a time @@ -1576,7 +1683,7 @@ class StubGenerator: public StubCodeGenerator { // The compare above (count >= 11) guarantes 'count' >= 16 bytes. // Also jump over aligned copy after the copy with shift completed. - copy_16_bytes_forward_with_shift(from, to, count, 8, L_copy_2_bytes); + copy_16_bytes_forward_with_shift(from, to, count, 1, L_copy_2_bytes); } // Both array are 8 bytes aligned, copy 16 bytes at a time @@ -1949,6 +2056,45 @@ class StubGenerator: public StubCodeGenerator { return start; } + // + // Helper methods for generate_disjoint_int_copy_core() + // + void copy_16_bytes_loop(Register from, Register to, Register count, int count_dec, + Label& L_loop, bool use_prefetch, bool use_bis) { + + __ align(OptoLoopAlignment); + __ BIND(L_loop); + if (use_prefetch) { + if (ArraycopySrcPrefetchDistance > 0) { + __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); + } + if (ArraycopyDstPrefetchDistance > 0) { + __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); + } + } + __ ldx(from, 4, O4); + __ ldx(from, 12, G4); + __ inc(to, 16); + __ inc(from, 16); + __ deccc(count, 4); // Can we do next iteration after this one? + + __ srlx(O4, 32, G3); + __ bset(G3, O3); + __ sllx(O4, 32, O4); + __ srlx(G4, 32, G3); + __ bset(G3, O4); + if (use_bis) { + __ stxa(O3, to, -16); + __ stxa(O4, to, -8); + } else { + __ stx(O3, to, -16); + __ stx(O4, to, -8); + } + __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); + __ delayed()->sllx(G4, 32, O3); + + } + // // Generate core code for disjoint int copy (and oop copy on 32-bit). // If "aligned" is true, the "from" and "to" addresses are assumed @@ -1962,7 +2108,7 @@ class StubGenerator: public StubCodeGenerator { void generate_disjoint_int_copy_core(bool aligned) { Label L_skip_alignment, L_aligned_copy; - Label L_copy_16_bytes, L_copy_4_bytes, L_copy_4_bytes_loop, L_exit; + Label L_copy_4_bytes, L_copy_4_bytes_loop, L_exit; const Register from = O0; // source array address const Register to = O1; // destination array address @@ -2013,30 +2159,16 @@ class StubGenerator: public StubCodeGenerator { // copy with shift 4 elements (16 bytes) at a time __ dec(count, 4); // The cmp at the beginning guaranty count >= 4 + __ sllx(O3, 32, O3); - __ align(OptoLoopAlignment); - __ BIND(L_copy_16_bytes); - __ ldx(from, 4, O4); - __ deccc(count, 4); // Can we do next iteration after this one? - __ ldx(from, 12, G4); - __ inc(to, 16); - __ inc(from, 16); - __ sllx(O3, 32, O3); - __ srlx(O4, 32, G3); - __ bset(G3, O3); - __ stx(O3, to, -16); - __ sllx(O4, 32, O4); - __ srlx(G4, 32, G3); - __ bset(G3, O4); - __ stx(O4, to, -8); - __ brx(Assembler::greaterEqual, false, Assembler::pt, L_copy_16_bytes); - __ delayed()->mov(G4, O3); + disjoint_copy_core(from, to, count, 2, 16, copy_16_bytes_loop); __ br(Assembler::always, false, Assembler::pt, L_copy_4_bytes); __ delayed()->inc(count, 4); // restore 'count' __ BIND(L_aligned_copy); - } + } // !aligned + // copy 4 elements (16 bytes) at a time __ and3(count, 1, G4); // Save __ srl(count, 1, count); @@ -2222,6 +2354,38 @@ class StubGenerator: public StubCodeGenerator { return start; } + // + // Helper methods for generate_disjoint_long_copy_core() + // + void copy_64_bytes_loop(Register from, Register to, Register count, int count_dec, + Label& L_loop, bool use_prefetch, bool use_bis) { + __ align(OptoLoopAlignment); + __ BIND(L_loop); + for (int off = 0; off < 64; off += 16) { + if (use_prefetch && (off & 31) == 0) { + if (ArraycopySrcPrefetchDistance > 0) { + __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); + } + if (ArraycopyDstPrefetchDistance > 0) { + __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); + } + } + __ ldx(from, off+0, O4); + __ ldx(from, off+8, O5); + if (use_bis) { + __ stxa(O4, to, off+0); + __ stxa(O5, to, off+8); + } else { + __ stx(O4, to, off+0); + __ stx(O5, to, off+8); + } + } + __ deccc(count, 8); + __ inc(from, 64); + __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); + __ delayed()->inc(to, 64); + } + // // Generate core code for disjoint long copy (and oop copy on 64-bit). // "aligned" is ignored, because we must make the stronger @@ -2261,38 +2425,28 @@ class StubGenerator: public StubCodeGenerator { const Register offset0 = O4; // element offset const Register offset8 = O5; // next element offset - __ deccc(count, 2); - __ mov(G0, offset0); // offset from start of arrays (0) - __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes ); - __ delayed()->add(offset0, 8, offset8); + __ deccc(count, 2); + __ mov(G0, offset0); // offset from start of arrays (0) + __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes ); + __ delayed()->add(offset0, 8, offset8); // Copy by 64 bytes chunks - Label L_copy_64_bytes; + const Register from64 = O3; // source address const Register to64 = G3; // destination address - __ subcc(count, 6, O3); - __ brx(Assembler::negative, false, Assembler::pt, L_copy_16_bytes ); - __ delayed()->mov(to, to64); - // Now we can use O4(offset0), O5(offset8) as temps - __ mov(O3, count); - __ mov(from, from64); + __ subcc(count, 6, O3); + __ brx(Assembler::negative, false, Assembler::pt, L_copy_16_bytes ); + __ delayed()->mov(to, to64); + // Now we can use O4(offset0), O5(offset8) as temps + __ mov(O3, count); + // count >= 0 (original count - 8) + __ mov(from, from64); - __ align(OptoLoopAlignment); - __ BIND(L_copy_64_bytes); - for( int off = 0; off < 64; off += 16 ) { - __ ldx(from64, off+0, O4); - __ ldx(from64, off+8, O5); - __ stx(O4, to64, off+0); - __ stx(O5, to64, off+8); - } - __ deccc(count, 8); - __ inc(from64, 64); - __ brx(Assembler::greaterEqual, false, Assembler::pt, L_copy_64_bytes); - __ delayed()->inc(to64, 64); + disjoint_copy_core(from64, to64, count, 3, 64, copy_64_bytes_loop); // Restore O4(offset0), O5(offset8) __ sub(from64, from, offset0); - __ inccc(count, 6); + __ inccc(count, 6); // restore count __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes ); __ delayed()->add(offset0, 8, offset8); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 2aae43c281a..e1429c68d97 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -75,6 +75,24 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1); } + if (has_v9()) { + assert(ArraycopySrcPrefetchDistance < 4096, "invalid value"); + if (ArraycopySrcPrefetchDistance >= 4096) + ArraycopySrcPrefetchDistance = 4064; + assert(ArraycopyDstPrefetchDistance < 4096, "invalid value"); + if (ArraycopyDstPrefetchDistance >= 4096) + ArraycopyDstPrefetchDistance = 4064; + } else { + if (ArraycopySrcPrefetchDistance > 0) { + warning("prefetch instructions are not available on this CPU"); + FLAG_SET_DEFAULT(ArraycopySrcPrefetchDistance, 0); + } + if (ArraycopyDstPrefetchDistance > 0) { + warning("prefetch instructions are not available on this CPU"); + FLAG_SET_DEFAULT(ArraycopyDstPrefetchDistance, 0); + } + } + UseSSE = 0; // Only on x86 and x64 _supports_cx8 = has_v9(); @@ -180,6 +198,16 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseBlockZeroing, false); } + assert(BlockCopyLowLimit > 0, "invalid value"); + if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache + if (FLAG_IS_DEFAULT(UseBlockCopy)) { + FLAG_SET_DEFAULT(UseBlockCopy, true); + } + } else if (UseBlockCopy) { + warning("BIS instructions are not available or expensive on this CPU"); + FLAG_SET_DEFAULT(UseBlockCopy, false); + } + #ifdef COMPILER2 // T4 and newer Sparc cpus have fast RDPC. if (has_fast_rdpc() && FLAG_IS_DEFAULT(UseRDPCForConstantTableBase)) { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 905379a727d..1f3d086fb97 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1985,6 +1985,12 @@ class CommandLineFlags { product(intx, BlockZeroingLowLimit, 2048, \ "Minimum size in bytes when block zeroing will be used") \ \ + product(bool, UseBlockCopy, false, \ + "Use special cpu instructions for block copy") \ + \ + product(intx, BlockCopyLowLimit, 2048, \ + "Minimum size in bytes when block copy will be used") \ + \ product(bool, PrintRevisitStats, false, \ "Print revisit (klass and MDO) stack related information") \ \ @@ -2918,6 +2924,12 @@ class CommandLineFlags { product(intx, ReadPrefetchInstr, 0, \ "Prefetch instruction to prefetch ahead") \ \ + product(uintx, ArraycopySrcPrefetchDistance, 0, \ + "Distance to prefetch source array in arracopy") \ + \ + product(uintx, ArraycopyDstPrefetchDistance, 0, \ + "Distance to prefetch destination array in arracopy") \ + \ /* deoptimization */ \ develop(bool, TraceDeoptimization, false, \ "Trace deoptimization") \ From c8c58542b3421d5fc0b14f32028d4258b511a7ec Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 2 Sep 2011 15:52:03 -0700 Subject: [PATCH 023/214] Added tag hs22-b04 for changeset 741bcb34b337 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 1f16864cac3..edae1458fbf 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -180,3 +180,4 @@ c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143 0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01 7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03 +ce9bde819dcba4a5d2822229d9183e69c74326ca hs22-b04 From 32fd1b087d6afd767d7eb70bb815da8a4a296f53 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 2 Sep 2011 20:58:21 -0700 Subject: [PATCH 024/214] 7071307: MethodHandle bimorphic inlining should consider the frequency Reviewed-by: twisti, roland, kvn, iveresov --- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 9 ++ hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 7 + hotspot/src/share/vm/ci/ciCallProfile.hpp | 11 ++ hotspot/src/share/vm/ci/ciMethodHandle.cpp | 23 +++- hotspot/src/share/vm/ci/ciMethodHandle.hpp | 28 +++- hotspot/src/share/vm/ci/ciObject.cpp | 14 +- .../src/share/vm/classfile/javaClasses.cpp | 20 +++ .../src/share/vm/classfile/javaClasses.hpp | 28 ++++ .../share/vm/classfile/systemDictionary.hpp | 17 +-- hotspot/src/share/vm/classfile/vmSymbols.hpp | 7 + hotspot/src/share/vm/oops/methodDataOop.hpp | 9 ++ hotspot/src/share/vm/opto/bytecodeInfo.cpp | 16 ++- hotspot/src/share/vm/opto/callGenerator.cpp | 28 ++-- .../src/share/vm/opto/idealGraphPrinter.cpp | 23 ++-- .../src/share/vm/opto/idealGraphPrinter.hpp | 4 +- hotspot/src/share/vm/opto/matcher.cpp | 3 + .../src/share/vm/prims/methodHandleWalk.cpp | 126 ++++++++++++++++-- .../src/share/vm/prims/methodHandleWalk.hpp | 14 +- hotspot/src/share/vm/prims/methodHandles.cpp | 15 ++- hotspot/src/share/vm/prims/methodHandles.hpp | 5 + 20 files changed, 346 insertions(+), 61 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 400ec0f0020..14030c0840f 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1262,6 +1262,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } break; + case _adapter_opt_profiling: + if (java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes() != 0) { + Address G3_mh_vmcount(G3_method_handle, java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes()); + __ ld(G3_mh_vmcount, O1_scratch); + __ add(O1_scratch, 1, O1_scratch); + __ st(O1_scratch, G3_mh_vmcount); + } + // fall through + case _adapter_retype_only: case _adapter_retype_raw: // Immediately jump to the next MH layer: diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 7febe3ae6c4..0e5d1599e5e 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1343,6 +1343,13 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } break; + case _adapter_opt_profiling: + if (java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes() != 0) { + Address rcx_mh_vmcount(rcx_recv, java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes()); + __ incrementl(rcx_mh_vmcount); + } + // fall through + case _adapter_retype_only: case _adapter_retype_raw: // immediately jump to the next MH layer: diff --git a/hotspot/src/share/vm/ci/ciCallProfile.hpp b/hotspot/src/share/vm/ci/ciCallProfile.hpp index 438067a7061..081014954db 100644 --- a/hotspot/src/share/vm/ci/ciCallProfile.hpp +++ b/hotspot/src/share/vm/ci/ciCallProfile.hpp @@ -79,6 +79,17 @@ public: assert(i < _limit, "out of Call Profile MorphismLimit"); return _receiver[i]; } + + // Rescale the current profile based on the incoming scale + ciCallProfile rescale(double scale) { + assert(scale >= 0 && scale <= 1.0, "out of range"); + ciCallProfile call = *this; + call._count = (int)(call._count * scale); + for (int i = 0; i < _morphism; i++) { + call._receiver_count[i] = (int)(call._receiver_count[i] * scale); + } + return call; + } }; #endif // SHARE_VM_CI_CICALLPROFILE_HPP diff --git a/hotspot/src/share/vm/ci/ciMethodHandle.cpp b/hotspot/src/share/vm/ci/ciMethodHandle.cpp index 0e73abca047..b4c91617d53 100644 --- a/hotspot/src/share/vm/ci/ciMethodHandle.cpp +++ b/hotspot/src/share/vm/ci/ciMethodHandle.cpp @@ -37,7 +37,7 @@ // ciMethodHandle::get_adapter // // Return an adapter for this MethodHandle. -ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const { +ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) { VM_ENTRY_MARK; Handle h(get_oop()); methodHandle callee(_callee->get_methodOop()); @@ -73,7 +73,7 @@ ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const { // ciMethodHandle::get_adapter // // Return an adapter for this MethodHandle. -ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { +ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) { ciMethod* result = get_adapter_impl(is_invokedynamic); if (result) { // Fake up the MDO maturity. @@ -86,11 +86,22 @@ ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { } +#ifndef PRODUCT // ------------------------------------------------------------------ -// ciMethodHandle::print_impl +// ciMethodHandle::print_chain_impl // // Implementation of the print method. -void ciMethodHandle::print_impl(outputStream* st) { - st->print(" type="); - get_oop()->print(); +void ciMethodHandle::print_chain_impl(outputStream* st) { + ASSERT_IN_VM; + MethodHandleChain::print(get_oop()); } + + +// ------------------------------------------------------------------ +// ciMethodHandle::print_chain +// +// Implementation of the print_chain method. +void ciMethodHandle::print_chain(outputStream* st) { + GUARDED_VM_ENTRY(print_chain_impl(st);); +} +#endif diff --git a/hotspot/src/share/vm/ci/ciMethodHandle.hpp b/hotspot/src/share/vm/ci/ciMethodHandle.hpp index b8919fe9241..e19d053f38d 100644 --- a/hotspot/src/share/vm/ci/ciMethodHandle.hpp +++ b/hotspot/src/share/vm/ci/ciMethodHandle.hpp @@ -37,19 +37,23 @@ private: ciMethod* _callee; ciMethod* _caller; ciCallProfile _profile; + ciMethod* _method_handle_adapter; + ciMethod* _invokedynamic_adapter; // Return an adapter for this MethodHandle. - ciMethod* get_adapter_impl(bool is_invokedynamic) const; - ciMethod* get_adapter( bool is_invokedynamic) const; + ciMethod* get_adapter_impl(bool is_invokedynamic); + ciMethod* get_adapter( bool is_invokedynamic); protected: - void print_impl(outputStream* st); + void print_chain_impl(outputStream* st) PRODUCT_RETURN; public: ciMethodHandle(instanceHandle h_i) : ciInstance(h_i), _callee(NULL), - _caller(NULL) + _caller(NULL), + _method_handle_adapter(NULL), + _invokedynamic_adapter(NULL) {} // What kind of ciObject is this? @@ -60,10 +64,22 @@ public: void set_call_profile(ciCallProfile profile) { _profile = profile; } // Return an adapter for a MethodHandle call. - ciMethod* get_method_handle_adapter() const { return get_adapter(false); } + ciMethod* get_method_handle_adapter() { + if (_method_handle_adapter == NULL) { + _method_handle_adapter = get_adapter(false); + } + return _method_handle_adapter; + } // Return an adapter for an invokedynamic call. - ciMethod* get_invokedynamic_adapter() const { return get_adapter(true); } + ciMethod* get_invokedynamic_adapter() { + if (_invokedynamic_adapter == NULL) { + _invokedynamic_adapter = get_adapter(true); + } + return _invokedynamic_adapter; + } + + void print_chain(outputStream* st = tty) PRODUCT_RETURN; }; #endif // SHARE_VM_CI_CIMETHODHANDLE_HPP diff --git a/hotspot/src/share/vm/ci/ciObject.cpp b/hotspot/src/share/vm/ci/ciObject.cpp index b7dd1e5e537..0f96f5b186b 100644 --- a/hotspot/src/share/vm/ci/ciObject.cpp +++ b/hotspot/src/share/vm/ci/ciObject.cpp @@ -194,16 +194,26 @@ bool ciObject::can_be_constant() { // ciObject::should_be_constant() bool ciObject::should_be_constant() { if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant - if (!JavaObjectsInPerm && !is_null_object()) { + if (is_null_object()) return true; + + ciEnv* env = CURRENT_ENV; + if (!JavaObjectsInPerm) { // We want Strings and Classes to be embeddable by default since // they used to be in the perm world. Not all Strings used to be // embeddable but there's no easy way to distinguish the interned // from the regulars ones so just treat them all that way. - ciEnv* env = CURRENT_ENV; if (klass() == env->String_klass() || klass() == env->Class_klass()) { return true; } } + if (EnableInvokeDynamic && + (klass()->is_subclass_of(env->MethodHandle_klass()) || + klass()->is_subclass_of(env->CallSite_klass()))) { + assert(ScavengeRootsInCode >= 1, "must be"); + // We want to treat these aggressively. + return true; + } + return handle() == NULL || is_perm(); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 696d9c9f3ff..b7455b81b91 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2324,6 +2324,8 @@ int java_lang_invoke_BoundMethodHandle::_vmargslot_offset; int java_lang_invoke_AdapterMethodHandle::_conversion_offset; +int java_lang_invoke_CountingMethodHandle::_vmcount_offset; + void java_lang_invoke_MethodHandle::compute_offsets() { klassOop k = SystemDictionary::MethodHandle_klass(); if (k != NULL && EnableInvokeDynamic) { @@ -2372,6 +2374,23 @@ void java_lang_invoke_AdapterMethodHandle::compute_offsets() { } } +void java_lang_invoke_CountingMethodHandle::compute_offsets() { + klassOop k = SystemDictionary::CountingMethodHandle_klass(); + if (k != NULL && EnableInvokeDynamic) { + compute_offset(_vmcount_offset, k, vmSymbols::vmcount_name(), vmSymbols::int_signature(), true); + } +} + +int java_lang_invoke_CountingMethodHandle::vmcount(oop mh) { + assert(is_instance(mh), "CMH only"); + return mh->int_field(_vmcount_offset); +} + +void java_lang_invoke_CountingMethodHandle::set_vmcount(oop mh, int count) { + assert(is_instance(mh), "CMH only"); + mh->int_field_put(_vmcount_offset, count); +} + oop java_lang_invoke_MethodHandle::type(oop mh) { return mh->obj_field(_type_offset); } @@ -3043,6 +3062,7 @@ void JavaClasses::compute_offsets() { java_lang_invoke_MethodType::compute_offsets(); java_lang_invoke_MethodTypeForm::compute_offsets(); java_lang_invoke_CallSite::compute_offsets(); + java_lang_invoke_CountingMethodHandle::compute_offsets(); } java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 716125295f3..6e144635f4d 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -981,6 +981,34 @@ class java_lang_invoke_AdapterMethodHandle: public java_lang_invoke_BoundMethodH }; +// A simple class that maintains an invocation count +class java_lang_invoke_CountingMethodHandle: public java_lang_invoke_MethodHandle { + friend class JavaClasses; + + private: + static int _vmcount_offset; + static void compute_offsets(); + + public: + // Accessors + static int vmcount(oop mh); + static void set_vmcount(oop mh, int count); + + // Testers + static bool is_subclass(klassOop klass) { + return SystemDictionary::CountingMethodHandle_klass() != NULL && + Klass::cast(klass)->is_subclass_of(SystemDictionary::CountingMethodHandle_klass()); + } + static bool is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); + } + + // Accessors for code generation: + static int vmcount_offset_in_bytes() { return _vmcount_offset; } +}; + + + // Interface to java.lang.invoke.MemberName objects // (These are a private interface for Java code to query the class hierarchy.) diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 4e33c425f3e..f6538dda2fc 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -133,14 +133,14 @@ class SymbolPropertyTable; template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ \ - /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ - /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ - /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ - template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ - template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ + /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ + /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ + /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ + template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ + template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ + template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ @@ -155,6 +155,7 @@ class SymbolPropertyTable; template(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292) \ template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \ template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \ + template(CountingMethodHandle_klass, java_lang_invoke_CountingMethodHandle, Opt) \ template(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre_JSR292) \ template(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre_JSR292) \ template(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre_JSR292) \ diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 79c7ac111de..c621da24092 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -218,6 +218,7 @@ template(returnType_name, "returnType") \ template(signature_name, "signature") \ template(slot_name, "slot") \ + template(selectAlternative_name, "selectAlternative") \ \ /* Support for annotations (JDK 1.5 and above) */ \ \ @@ -246,9 +247,11 @@ template(java_lang_invoke_MethodTypeForm_signature, "Ljava/lang/invoke/MethodTypeForm;") \ template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \ template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \ + template(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \ template(java_lang_invoke_AdapterMethodHandle, "java/lang/invoke/AdapterMethodHandle") \ template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \ template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ + template(java_lang_invoke_CountingMethodHandle, "java/lang/invoke/CountingMethodHandle") \ /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ @@ -263,6 +266,7 @@ template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ + template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ \ /* common method and field names */ \ template(object_initializer_name, "") \ @@ -347,6 +351,7 @@ template(vmmethod_name, "vmmethod") \ template(vmtarget_name, "vmtarget") \ template(vmentry_name, "vmentry") \ + template(vmcount_name, "vmcount") \ template(vmslots_name, "vmslots") \ template(vmlayout_name, "vmlayout") \ template(vmindex_name, "vmindex") \ @@ -910,6 +915,8 @@ do_intrinsic(_invokeVarargs, java_lang_invoke_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ do_intrinsic(_invokeDynamic, java_lang_invoke_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ \ + do_intrinsic(_selectAlternative, java_lang_invoke_MethodHandleImpl, selectAlternative_name, selectAlternative_signature, F_S) \ + \ /* unboxing methods: */ \ do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ do_name( booleanValue_name, "booleanValue") \ diff --git a/hotspot/src/share/vm/oops/methodDataOop.hpp b/hotspot/src/share/vm/oops/methodDataOop.hpp index 97c80a9e773..350590a16c5 100644 --- a/hotspot/src/share/vm/oops/methodDataOop.hpp +++ b/hotspot/src/share/vm/oops/methodDataOop.hpp @@ -600,6 +600,11 @@ public: uint taken() { return uint_at(taken_off_set); } + + void set_taken(uint cnt) { + set_uint_at(taken_off_set, cnt); + } + // Saturating counter uint inc_taken() { uint cnt = taken() + 1; @@ -926,6 +931,10 @@ public: return uint_at(not_taken_off_set); } + void set_not_taken(uint cnt) { + set_uint_at(not_taken_off_set, cnt); + } + uint inc_not_taken() { uint cnt = not_taken() + 1; // Did we wrap? Will compiler screw us?? diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index d21f6d04a85..a29159686e4 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -141,7 +141,21 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_ assert(mha_profile, "must exist"); CounterData* cd = mha_profile->as_CounterData(); invoke_count = cd->count(); - call_site_count = invoke_count; // use the same value + if (invoke_count == 0) { + return "method handle not reached"; + } + + if (_caller_jvms != NULL && _caller_jvms->method() != NULL && + _caller_jvms->method()->method_data() != NULL && + !_caller_jvms->method()->method_data()->is_empty()) { + ciMethodData* mdo = _caller_jvms->method()->method_data(); + ciProfileData* mha_profile = mdo->bci_to_data(_caller_jvms->bci()); + assert(mha_profile, "must exist"); + CounterData* cd = mha_profile->as_CounterData(); + call_site_count = cd->count(); + } else { + call_site_count = invoke_count; // use the same value + } } assert(invoke_count != 0, "require invocation count greater than zero"); diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index dc02770a9c7..150aa923d43 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -149,7 +149,6 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { call->set_optimized_virtual(true); if (method()->is_method_handle_invoke()) { call->set_method_handle_invoke(true); - kit.C->set_has_method_handle_invokes(true); } } kit.set_arguments_for_java_call(call); @@ -207,7 +206,6 @@ JVMState* DynamicCallGenerator::generate(JVMState* jvms) { call->set_optimized_virtual(true); // Take extra care (in the presence of argument motion) not to trash the SP: call->set_method_handle_invoke(true); - kit.C->set_has_method_handle_invokes(true); // Pass the target MethodHandle as first argument and shift the // other arguments. @@ -706,18 +704,30 @@ CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMS } } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) { + float prob = PROB_FAIR; + Node* meth_region = method_handle->in(0); + if (meth_region->is_Region() && + meth_region->in(1)->is_Proj() && meth_region->in(2)->is_Proj() && + meth_region->in(1)->in(0) == meth_region->in(2)->in(0) && + meth_region->in(1)->in(0)->is_If()) { + // If diamond, so grab the probability of the test to drive the inlining below + prob = meth_region->in(1)->in(0)->as_If()->_prob; + if (meth_region->in(1)->is_IfTrue()) { + prob = 1 - prob; + } + } + // selectAlternative idiom merging two constant MethodHandles. // Generate a guard so that each can be inlined. We might want to // do more inputs at later point but this gets the most common // case. - const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); - ciObject* const_oop = oop_ptr->const_oop(); - ciMethodHandle* mh = const_oop->as_method_handle(); - - CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile); - CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile); + CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); + CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); if (cg1 != NULL && cg2 != NULL) { - return new PredictedDynamicCallGenerator(mh, cg2, cg1, PROB_FAIR); + const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); + ciObject* const_oop = oop_ptr->const_oop(); + ciMethodHandle* mh = const_oop->as_method_handle(); + return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob); } } return NULL; diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 74595348f14..a5a0c65887e 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -375,9 +375,9 @@ intptr_t IdealGraphPrinter::get_node_id(Node *n) { return (intptr_t)(n); } -void IdealGraphPrinter::visit_node(Node *n, void *param) { +void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { - if(param) { + if (edges) { // Output edge intptr_t dest_id = get_node_id(n); @@ -599,16 +599,11 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { #ifdef ASSERT if (node->debug_orig() != NULL) { + temp_set->Clear(); stringStream dorigStream; Node* dorig = node->debug_orig(); - if (dorig) { + while (dorig && temp_set->test_set(dorig->_idx)) { dorigStream.print("%d ", dorig->_idx); - Node* first = dorig; - dorig = first->debug_orig(); - while (dorig && dorig != first) { - dorigStream.print("%d ", dorig->_idx); - dorig = dorig->debug_orig(); - } } print_prop("debug_orig", dorigStream.as_string()); } @@ -629,7 +624,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { } } -void IdealGraphPrinter::walk_nodes(Node *start, void *param) { +void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { VectorSet visited(Thread::current()->resource_area()); @@ -650,7 +645,7 @@ void IdealGraphPrinter::walk_nodes(Node *start, void *param) { while(nodeStack.length() > 0) { Node *n = nodeStack.pop(); - visit_node(n, param); + visit_node(n, edges, temp_set); if (_traverse_outs) { for (DUIterator i = n->outs(); n->has_out(i); i++) { @@ -689,12 +684,14 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in print_attr(GRAPH_NAME_PROPERTY, (const char *)name); end_head(); + VectorSet temp_set(Thread::current()->resource_area()); + head(NODES_ELEMENT); - walk_nodes(node, NULL); + walk_nodes(node, false, &temp_set); tail(NODES_ELEMENT); head(EDGES_ELEMENT); - walk_nodes(node, (void *)1); + walk_nodes(node, true, &temp_set); tail(EDGES_ELEMENT); if (C->cfg() != NULL) { head(CONTROL_FLOW_ELEMENT); diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp index 6115e6d385c..7d1863f4a2a 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp @@ -104,8 +104,8 @@ private: void print_indent(); void print_method(ciMethod *method, int bci, InlineTree *tree); void print_inline_tree(InlineTree *tree); - void visit_node(Node *n, void *param); - void walk_nodes(Node *start, void *param); + void visit_node(Node *n, bool edges, VectorSet* temp_set); + void walk_nodes(Node *start, bool edges, VectorSet* temp_set); void begin_elem(const char *s); void end_elem(); void begin_head(const char *s); diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 1faf3b90808..4b16bbad286 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -1106,6 +1106,9 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); is_method_handle_invoke = call_java->is_method_handle_invoke(); mcall_java->_method_handle_invoke = is_method_handle_invoke; + if (is_method_handle_invoke) { + C->set_has_method_handle_invokes(true); + } if( mcall_java->is_MachCallStaticJava() ) mcall_java->as_MachCallStaticJava()->_name = call_java->as_CallStaticJava()->_name; diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index 504b9003b56..3f313074b8f 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -182,10 +182,6 @@ void MethodHandleChain::print(oopDesc* m) { HandleMark hm; ResourceMark rm; Handle mh(m); - print(mh); -} - -void MethodHandleChain::print(Handle mh) { EXCEPTION_MARK; MethodHandleChain mhc(mh, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -222,16 +218,33 @@ void MethodHandleChain::print_impl(TRAPS) { if (o != NULL) { if (o->is_instance()) { tty->print(" instance %s", o->klass()->klass_part()->internal_name()); + if (java_lang_invoke_CountingMethodHandle::is_instance(o)) { + tty->print(" vmcount: %d", java_lang_invoke_CountingMethodHandle::vmcount(o)); + } } else { o->print(); } } + oop vmt = chain.vmtarget_oop(); + if (vmt != NULL) { + if (vmt->is_method()) { + tty->print(" "); + methodOop(vmt)->print_short_name(tty); + } else if (java_lang_invoke_MethodHandle::is_instance(vmt)) { + tty->print(" method handle " INTPTR_FORMAT, vmt); + } else { + ShouldNotReachHere(); + } + } } else if (chain.is_adapter()) { tty->print("adapter: arg_slot %d conversion op %s", chain.adapter_arg_slot(), adapter_op_to_string(chain.adapter_conversion_op())); switch (chain.adapter_conversion_op()) { case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: + if (java_lang_invoke_CountingMethodHandle::is_instance(chain.method_handle_oop())) { + tty->print(" vmcount: %d", java_lang_invoke_CountingMethodHandle::vmcount(chain.method_handle_oop())); + } case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: @@ -907,7 +920,10 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, Symbol* name, Symbol* si _non_bcp_klasses(THREAD, 5), _cur_stack(0), _max_stack(0), - _rtype(T_ILLEGAL) + _rtype(T_ILLEGAL), + _selectAlternative_bci(-1), + _taken_count(0), + _not_taken_count(0) { // Element zero is always the null constant. @@ -1115,11 +1131,50 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index, int args_size) _bytecode.push(0); break; + case Bytecodes::_ifeq: + assert((unsigned short) index == index, "index does not fit in 16-bit"); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + break; + default: ShouldNotReachHere(); } } +void MethodHandleCompiler::update_branch_dest(int src, int dst) { + switch (_bytecode.at(src)) { + case Bytecodes::_ifeq: + dst -= src; // compute the offset + assert((unsigned short) dst == dst, "index does not fit in 16-bit"); + _bytecode.at_put(src + 1, dst >> 8); + _bytecode.at_put(src + 2, dst); + break; + default: + ShouldNotReachHere(); + } +} + +void MethodHandleCompiler::emit_load(ArgToken arg) { + TokenType tt = arg.token_type(); + BasicType bt = arg.basic_type(); + + switch (tt) { + case tt_parameter: + case tt_temporary: + emit_load(bt, arg.index()); + break; + case tt_constant: + emit_load_constant(arg); + break; + case tt_illegal: + case tt_void: + default: + ShouldNotReachHere(); + } +} + void MethodHandleCompiler::emit_load(BasicType bt, int index) { if (index <= 3) { @@ -1318,6 +1373,29 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co jvalue MethodHandleCompiler::zero_jvalue = { 0 }; jvalue MethodHandleCompiler::one_jvalue = { 1 }; +// Fetch any values from CountingMethodHandles and capture them for profiles +bool MethodHandleCompiler::fetch_counts(ArgToken arg1, ArgToken arg2) { + int count1 = -1, count2 = -1; + if (arg1.token_type() == tt_constant && arg1.basic_type() == T_OBJECT && + java_lang_invoke_CountingMethodHandle::is_instance(arg1.object()())) { + count1 = java_lang_invoke_CountingMethodHandle::vmcount(arg1.object()()); + } + if (arg2.token_type() == tt_constant && arg2.basic_type() == T_OBJECT && + java_lang_invoke_CountingMethodHandle::is_instance(arg2.object()())) { + count2 = java_lang_invoke_CountingMethodHandle::vmcount(arg2.object()()); + } + int total = count1 + count2; + if (count1 != -1 && count2 != -1 && total != 0) { + // Normalize the collect counts to the invoke_count + tty->print("counts %d %d scaled by %d = ", count2, count1, _invoke_count); + if (count1 != 0) _not_taken_count = (int)(_invoke_count * count1 / (double)total); + if (count2 != 0) _taken_count = (int)(_invoke_count * count2 / (double)total); + tty->print_cr("%d %d", _taken_count, _not_taken_count); + return true; + } + return false; +} + // Emit bytecodes for the given invoke instruction. MethodHandleWalker::ArgToken MethodHandleCompiler::make_invoke(methodHandle m, vmIntrinsics::ID iid, @@ -1367,6 +1445,29 @@ MethodHandleCompiler::make_invoke(methodHandle m, vmIntrinsics::ID iid, } } + if (m->intrinsic_id() == vmIntrinsics::_selectAlternative && + fetch_counts(argv[1], argv[2])) { + assert(argc == 3, "three arguments"); + assert(tailcall, "only"); + + // do inline bytecodes so we can drop profile data into it, + // 0: iload_0 + emit_load(argv[0]); + // 1: ifeq 8 + _selectAlternative_bci = _bytecode.length(); + emit_bc(Bytecodes::_ifeq, 0); // emit placeholder offset + // 4: aload_1 + emit_load(argv[1]); + // 5: areturn; + emit_bc(Bytecodes::_areturn); + // 8: aload_2 + update_branch_dest(_selectAlternative_bci, cur_bci()); + emit_load(argv[2]); + // 9: areturn + emit_bc(Bytecodes::_areturn); + return ArgToken(); // Dummy return value. + } + check_non_bcp_klass(klass, CHECK_(zero)); if (m->is_method_handle_invoke()) { check_non_bcp_klasses(m->method_handle_type(), CHECK_(zero)); @@ -1377,10 +1478,6 @@ MethodHandleCompiler::make_invoke(methodHandle m, vmIntrinsics::ID iid, assert(argc == asc.size() + ((op == Bytecodes::_invokestatic || op == Bytecodes::_invokedynamic) ? 0 : 1), "argc mismatch"); - // Inline the method. - InvocationCounter* ic = m->invocation_counter(); - ic->set_carry_flag(); - for (int i = 0; i < argc; i++) { ArgToken arg = argv[i]; TokenType tt = arg.token_type(); @@ -1686,7 +1783,7 @@ constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const { } -methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { +methodHandle MethodHandleCompiler::get_method_oop(TRAPS) { methodHandle empty; // Create a method that holds the generated bytecode. invokedynamic // has no receiver, normal MH calls do. @@ -1765,6 +1862,7 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { assert(m->method_data() == NULL, "there should not be an MDO yet"); m->set_method_data(mdo); + bool found_selectAlternative = false; // Iterate over all profile data and set the count of the counter // data entries to the original call site counter. for (ProfileData* profile_data = mdo->first_data(); @@ -1774,7 +1872,15 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { CounterData* counter_data = profile_data->as_CounterData(); counter_data->set_count(_invoke_count); } + if (profile_data->is_BranchData() && + profile_data->bci() == _selectAlternative_bci) { + BranchData* bd = profile_data->as_BranchData(); + bd->set_taken(_taken_count); + bd->set_not_taken(_not_taken_count); + found_selectAlternative = true; + } } + assert(_selectAlternative_bci == -1 || found_selectAlternative, "must have found profile entry"); } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.hpp b/hotspot/src/share/vm/prims/methodHandleWalk.hpp index 783b55b7848..8697c0b691c 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp @@ -74,6 +74,7 @@ public: set_method_handle(MethodHandle_vmtarget_oop(), THREAD); } + Handle root() { return _root; } Handle method_handle() { return _method_handle; } oop method_handle_oop() { return _method_handle(); } oop method_type_oop() { return MethodHandle_type_oop(); } @@ -110,7 +111,6 @@ public: // the signature for each method. The signatures are printed in // slot order to make it easier to understand. void print(); - static void print(Handle mh); static void print(oopDesc* mh); #endif }; @@ -277,6 +277,10 @@ private: KlassHandle _target_klass; Thread* _thread; + int _selectAlternative_bci; // These are used for capturing profiles from GWTs + int _taken_count; + int _not_taken_count; + // Values used by the compiler. static jvalue zero_jvalue; static jvalue one_jvalue; @@ -372,6 +376,7 @@ private: unsigned char* bytecode() const { return _bytecode.adr_at(0); } int bytecode_length() const { return _bytecode.length(); } + int cur_bci() const { return _bytecode.length(); } // Fake constant pool. int cpool_oop_put(int tag, Handle con) { @@ -436,6 +441,8 @@ private: } void emit_bc(Bytecodes::Code op, int index = 0, int args_size = -1); + void update_branch_dest(int src, int dst); + void emit_load(ArgToken arg); void emit_load(BasicType bt, int index); void emit_store(BasicType bt, int index); void emit_load_constant(ArgToken arg); @@ -455,11 +462,14 @@ private: virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS); virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); + // Check for profiling information on a GWT and return true if it's found + bool fetch_counts(ArgToken a1, ArgToken a2); + // Get a real constant pool. constantPoolHandle get_constant_pool(TRAPS) const; // Get a real methodOop. - methodHandle get_method_oop(TRAPS) const; + methodHandle get_method_oop(TRAPS); public: MethodHandleCompiler(Handle root, Symbol* name, Symbol* signature, int invoke_count, bool for_invokedynamic, TRAPS); diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 172e5ef17f1..3978f47f4ff 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -158,6 +158,8 @@ const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { "adapter_fold/4/ref", "adapter_fold/5/ref", + "adapter_opt_profiling", + NULL }; @@ -2653,6 +2655,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu // Finalize the conversion field. (Note that it is final to Java code.) java_lang_invoke_AdapterMethodHandle::set_conversion(mh(), new_conversion); + if (java_lang_invoke_CountingMethodHandle::is_instance(mh())) { + assert(ek_orig == _adapter_retype_only, "only one handled"); + ek_opt = _adapter_opt_profiling; + } + // Done! java_lang_invoke_MethodHandle::set_vmentry(mh(), entry(ek_opt)); @@ -2905,8 +2912,12 @@ JVM_ENTRY(jint, MHN_getConstant(JNIEnv *env, jobject igcls, jint which)) { return MethodHandles::stack_move_unit(); case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK: return MethodHandles::adapter_conversion_ops_supported_mask(); - case MethodHandles::GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS: - return MethodHandles::OP_ROT_ARGS_DOWN_LIMIT_BIAS; + case MethodHandles::GC_COUNT_GWT: +#ifdef COMPILER2 + return true; +#else + return false; +#endif } return 0; } diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index dbf64166849..216a6ede210 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -187,6 +187,8 @@ class MethodHandles: AllStatic { _adapter_opt_fold_FIRST = _adapter_opt_fold_ref, _adapter_opt_fold_LAST = _adapter_opt_fold_5_ref, + _adapter_opt_profiling, + _EK_LIMIT, _EK_FIRST = 0 }; @@ -266,6 +268,8 @@ class MethodHandles: AllStatic { return _adapter_fold_args; if (ek >= _adapter_opt_return_FIRST && ek <= _adapter_opt_return_LAST) return _adapter_opt_return_any; + if (ek == _adapter_opt_profiling) + return _adapter_retype_only; assert(false, "oob"); return _EK_LIMIT; } @@ -582,6 +586,7 @@ class MethodHandles: AllStatic { GC_JVM_STACK_MOVE_UNIT = 1, GC_CONV_OP_IMPLEMENTED_MASK = 2, GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS = 3, + GC_COUNT_GWT = 4, // format of result from getTarget / encode_target: ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) From d4d5856fd4228639e3ef5c723df7b75a6262ea5e Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 2 Sep 2011 22:00:49 -0700 Subject: [PATCH 025/214] 7016881: JSR 292: JDI: sun.jvm.hotspot.utilities.AssertionFailure: index out of bounds Reviewed-by: kvn, twisti --- .../sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java index 051f8556cdf..2c27e3dbc76 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java @@ -90,7 +90,7 @@ public class BytecodeLoadConstant extends Bytecode { jcode == Bytecodes._ldc2_w; if (! codeOk) return false; - ConstantTag ctag = method().getConstants().getTagAt(rawIndex()); + ConstantTag ctag = method().getConstants().getTagAt(poolIndex()); if (jcode == Bytecodes._ldc2_w) { // has to be double or long return (ctag.isDouble() || ctag.isLong()) ? true: false; From dece7fbfecec624346be9d28bfe31dbffba6b0a8 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Sat, 3 Sep 2011 14:03:54 -0700 Subject: [PATCH 026/214] 7086560: 7085404 changes broke VM with -XX:-EnableInvokeDynamic Add check that ciEnv::_CallSite_klass is initialized. Reviewed-by: jrose --- hotspot/src/share/vm/ci/ciField.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/ci/ciField.hpp b/hotspot/src/share/vm/ci/ciField.hpp index 71145969f2b..bd65abe9893 100644 --- a/hotspot/src/share/vm/ci/ciField.hpp +++ b/hotspot/src/share/vm/ci/ciField.hpp @@ -176,7 +176,10 @@ public: bool is_transient () { return flags().is_transient(); } bool is_call_site_target() { - return (holder()->is_subclass_of(CURRENT_ENV->CallSite_klass()) && (name() == ciSymbol::target_name())); + ciInstanceKlass* callsite_klass = CURRENT_ENV->CallSite_klass(); + if (callsite_klass == NULL) + return false; + return (holder()->is_subclass_of(callsite_klass) && (name() == ciSymbol::target_name())); } // Debugging output From edb7b9514ac95868c095887307ffd89485629706 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 5 Sep 2011 17:09:05 -0700 Subject: [PATCH 027/214] 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244) Reviewed-by: kvn --- .../share/classes/sun/jvm/hotspot/HSDB.java | 2 +- .../sun/jvm/hotspot/code/CodeBlob.java | 7 +- .../sun/jvm/hotspot/code/CodeCache.java | 5 + .../MethodHandlesAdapterBlob.java} | 42 +- .../classes/sun/jvm/hotspot/code/NMethod.java | 24 +- .../classes/sun/jvm/hotspot/code/PCDesc.java | 14 +- .../sun/jvm/hotspot/code/RicochetBlob.java | 18 +- .../sun/jvm/hotspot/code/RuntimeStub.java | 8 + .../sun/jvm/hotspot/compiler/OopMapSet.java | 2 +- .../jvm/hotspot/jdi/ReferenceTypeImpl.java | 24 + .../sun/jvm/hotspot/jdi/StackFrameImpl.java | 62 +- .../jvm/hotspot/memory/SystemDictionary.java | 6 + .../jvm/hotspot/runtime/CompiledVFrame.java | 4 + .../sun/jvm/hotspot/runtime/Frame.java | 31 +- .../sun/jvm/hotspot/runtime/JavaVFrame.java | 4 +- .../sun/jvm/hotspot/runtime/StackValue.java | 2 +- .../sun/jvm/hotspot/runtime/VFrame.java | 2 +- .../classes/sun/jvm/hotspot/runtime/VM.java | 16 + .../runtime/amd64/AMD64CurrentFrameGuess.java | 3 +- .../jvm/hotspot/runtime/amd64/AMD64Frame.java | 528 ------------------ .../LinuxAMD64JavaThreadPDAccess.java | 9 +- .../SolarisAMD64JavaThreadPDAccess.java | 11 +- .../jvm/hotspot/runtime/sparc/SPARCFrame.java | 89 +-- .../runtime/sparc/SPARCRicochetFrame.java | 77 +++ .../Win32AMD64JavaThreadPDAccess.java | 11 +- .../sun/jvm/hotspot/runtime/x86/X86Frame.java | 177 +++--- .../hotspot/runtime/x86/X86RicochetFrame.java | 81 +++ hotspot/src/cpu/x86/vm/methodHandles_x86.hpp | 1 + hotspot/src/share/vm/c1/c1_LinearScan.cpp | 6 +- hotspot/src/share/vm/c1/c1_LinearScan.hpp | 7 + hotspot/src/share/vm/code/pcDesc.cpp | 5 +- hotspot/src/share/vm/code/pcDesc.hpp | 32 +- .../src/share/vm/runtime/sharedRuntime.hpp | 2 + hotspot/src/share/vm/runtime/thread.cpp | 38 ++ hotspot/src/share/vm/runtime/thread.hpp | 1 + hotspot/src/share/vm/runtime/vmStructs.cpp | 56 +- 36 files changed, 678 insertions(+), 729 deletions(-) rename hotspot/agent/src/share/classes/sun/jvm/hotspot/{runtime/amd64/AMD64RegisterMap.java => code/MethodHandlesAdapterBlob.java} (57%) delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java index 5e7e4fb1cd5..d48c1600723 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java @@ -1740,7 +1740,7 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener { else if (f.isCompiledFrame()) { tty.print("compiled"); } else if (f.isEntryFrame()) { tty.print("entry"); } else if (f.isNativeFrame()) { tty.print("native"); } - else if (f.isGlueFrame()) { tty.print("glue"); } + else if (f.isRuntimeFrame()) { tty.print("runtime"); } else { tty.print("external"); } tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP()); if (f.isSignalHandlerFrameDbg()) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java index 7ed801eb5b8..a9bc5983bda 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java @@ -102,6 +102,11 @@ public class CodeBlob extends VMObject { /** On-Stack Replacement method */ public boolean isOSRMethod() { return false; } + public NMethod asNMethodOrNull() { + if (isNMethod()) return (NMethod)this; + return null; + } + // Boundaries public Address headerBegin() { return addr; @@ -195,7 +200,7 @@ public class CodeBlob extends VMObject { } // Returns true, if the next frame is responsible for GC'ing oops passed as arguments - public boolean callerMustGCArguments(JavaThread thread) { return false; } + public boolean callerMustGCArguments() { return false; } public String getName() { return CStringUtilities.getString(nameField.getValue(addr)); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java index bf7a12f5bb0..6d0dd0fb6d0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java @@ -59,6 +59,7 @@ public class CodeCache { virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class); virtualConstructor.addMapping("RicochetBlob", RicochetBlob.class); virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class); + virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class); virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class); virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); if (VM.getVM().isServerCompiler()) { @@ -126,6 +127,10 @@ public class CodeCache { Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)), "found wrong CodeBlob"); } + if (result.isRicochetBlob()) { + // This should probably be done for other SingletonBlobs + return VM.getVM().ricochetBlob(); + } return result; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java similarity index 57% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java index d5b99561810..3b265e1b72e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,31 +22,37 @@ * */ -package sun.jvm.hotspot.runtime.amd64; +package sun.jvm.hotspot.code; -import sun.jvm.hotspot.asm.amd64.*; +import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; -public class AMD64RegisterMap extends RegisterMap { - - /** This is the only public constructor */ - public AMD64RegisterMap(JavaThread thread, boolean updateMap) { - super(thread, updateMap); +public class MethodHandlesAdapterBlob extends AdapterBlob { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); } - protected AMD64RegisterMap(RegisterMap map) { - super(map); + private static void initialize(TypeDataBase db) { + Type type = db.lookupType("MethodHandlesAdapterBlob"); + + // FIXME: add any needed fields } - public Object clone() { - AMD64RegisterMap retval = new AMD64RegisterMap(this); - return retval; + public MethodHandlesAdapterBlob(Address addr) { + super(addr); } - // no PD state to clear or copy: - protected void clearPD() {} - protected void initializePD() {} - protected void initializeFromPD(RegisterMap map) {} - protected Address getLocationPD(VMReg reg) { return null; } + public boolean isMethodHandlesAdapterBlob() { + return true; + } + + public String getName() { + return "MethodHandlesAdapterBlob: " + super.getName(); + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java index 80da843d3ab..d33aaecebee 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -46,6 +46,7 @@ public class NMethod extends CodeBlob { /** Offsets for different nmethod parts */ private static CIntegerField exceptionOffsetField; private static CIntegerField deoptOffsetField; + private static CIntegerField deoptMhOffsetField; private static CIntegerField origPCOffsetField; private static CIntegerField stubOffsetField; private static CIntegerField oopsOffsetField; @@ -95,6 +96,7 @@ public class NMethod extends CodeBlob { exceptionOffsetField = type.getCIntegerField("_exception_offset"); deoptOffsetField = type.getCIntegerField("_deoptimize_offset"); + deoptMhOffsetField = type.getCIntegerField("_deoptimize_mh_offset"); origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); stubOffsetField = type.getCIntegerField("_stub_offset"); oopsOffsetField = type.getCIntegerField("_oops_offset"); @@ -136,10 +138,11 @@ public class NMethod extends CodeBlob { /** Boundaries for different parts */ public Address constantsBegin() { return contentBegin(); } public Address constantsEnd() { return getEntryPoint(); } - public Address instsBegin() { return codeBegin(); } + public Address instsBegin() { return codeBegin(); } public Address instsEnd() { return headerBegin().addOffsetTo(getStubOffset()); } public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); } - public Address deoptBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); } + public Address deoptHandlerBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); } + public Address deoptMhHandlerBegin() { return headerBegin().addOffsetTo(getDeoptMhOffset()); } public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); } public Address stubEnd() { return headerBegin().addOffsetTo(getOopsOffset()); } public Address oopsBegin() { return headerBegin().addOffsetTo(getOopsOffset()); } @@ -250,6 +253,22 @@ public class NMethod extends CodeBlob { return (int) scavengeRootStateField.getValue(addr); } + // MethodHandle + public boolean isMethodHandleReturn(Address returnPc) { + // Hard to read a bit fields from Java and it's only there for performance + // so just go directly to the PCDesc + // if (!hasMethodHandleInvokes()) return false; + PCDesc pd = getPCDescAt(returnPc); + if (pd == null) + return false; + return pd.isMethodHandleInvoke(); + } + + // Deopt + // Return true is the PC is one would expect if the frame is being deopted. + public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); } + public boolean isDeoptEntry (Address pc) { return pc == deoptHandlerBegin(); } + public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); } /** Tells whether frames described by this nmethod can be deoptimized. Note: native wrappers cannot be deoptimized. */ @@ -388,6 +407,7 @@ public class NMethod extends CodeBlob { private int getEntryBCI() { return (int) entryBCIField .getValue(addr); } private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); } private int getDeoptOffset() { return (int) deoptOffsetField .getValue(addr); } + private int getDeoptMhOffset() { return (int) deoptMhOffsetField .getValue(addr); } private int getStubOffset() { return (int) stubOffsetField .getValue(addr); } private int getOopsOffset() { return (int) oopsOffsetField .getValue(addr); } private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java index c6bf5d78b5e..15846108911 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java @@ -38,6 +38,9 @@ public class PCDesc extends VMObject { private static CIntegerField scopeDecodeOffsetField; private static CIntegerField objDecodeOffsetField; private static CIntegerField pcFlagsField; + private static int reexecuteMask; + private static int isMethodHandleInvokeMask; + private static int returnOopMask; static { VM.registerVMInitializedObserver(new Observer() { @@ -54,6 +57,10 @@ public class PCDesc extends VMObject { scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset"); objDecodeOffsetField = type.getCIntegerField("_obj_decode_offset"); pcFlagsField = type.getCIntegerField("_flags"); + + reexecuteMask = db.lookupIntConstant("PcDesc::PCDESC_reexecute"); + isMethodHandleInvokeMask = db.lookupIntConstant("PcDesc::PCDESC_is_method_handle_invoke"); + returnOopMask = db.lookupIntConstant("PcDesc::PCDESC_return_oop"); } public PCDesc(Address addr) { @@ -81,7 +88,12 @@ public class PCDesc extends VMObject { public boolean getReexecute() { int flags = (int)pcFlagsField.getValue(addr); - return ((flags & 0x1)== 1); //first is the reexecute bit + return (flags & reexecuteMask) != 0; + } + + public boolean isMethodHandleInvoke() { + int flags = (int)pcFlagsField.getValue(addr); + return (flags & isMethodHandleInvokeMask) != 0; } public void print(NMethod code) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java index 3f7dd765451..0fa8518c830 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java @@ -41,11 +41,15 @@ public class RicochetBlob extends SingletonBlob { } private static void initialize(TypeDataBase db) { - // Type type = db.lookupType("RicochetBlob"); + Type type = db.lookupType("RicochetBlob"); - // FIXME: add any needed fields + bounceOffsetField = type.getCIntegerField("_bounce_offset"); + exceptionOffsetField = type.getCIntegerField("_exception_offset"); } + private static CIntegerField bounceOffsetField; + private static CIntegerField exceptionOffsetField; + public RicochetBlob(Address addr) { super(addr); } @@ -53,4 +57,14 @@ public class RicochetBlob extends SingletonBlob { public boolean isRicochetBlob() { return true; } + + public Address bounceAddr() { + return codeBegin().addOffsetTo(bounceOffsetField.getValue(addr)); + } + + public boolean returnsToBounceAddr(Address pc) { + Address bouncePc = bounceAddr(); + return (pc.equals(bouncePc) || pc.addOffsetTo(Frame.pcReturnOffset()).equals(bouncePc)); + } + } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java index 86f471be7e3..fd0d72aaace 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java @@ -30,6 +30,8 @@ import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; public class RuntimeStub extends CodeBlob { + private static CIntegerField callerMustGCArgumentsField; + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -40,6 +42,7 @@ public class RuntimeStub extends CodeBlob { private static void initialize(TypeDataBase db) { Type type = db.lookupType("RuntimeStub"); + callerMustGCArgumentsField = type.getCIntegerField("_caller_must_gc_arguments"); // FIXME: add any needed fields } @@ -52,6 +55,11 @@ public class RuntimeStub extends CodeBlob { return true; } + public boolean callerMustGCArguments() { + return callerMustGCArgumentsField.getValue(addr) != 0; + } + + public String getName() { return "RuntimeStub: " + super.getName(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java index 3e8857893e1..9433cf6864d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java @@ -246,7 +246,7 @@ public class OopMapSet extends VMObject { } // Check if caller must update oop argument - regMap.setIncludeArgumentOops(cb.callerMustGCArguments(regMap.getThread())); + regMap.setIncludeArgumentOops(cb.callerMustGCArguments()); int nofCallee = 0; Address[] locs = new Address[2 * REG_COUNT + 1]; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java index 811075dc635..d28bca18d2e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java @@ -28,11 +28,13 @@ import java.io.*; import com.sun.jdi.*; +import sun.jvm.hotspot.memory.SystemDictionary; import sun.jvm.hotspot.oops.Instance; import sun.jvm.hotspot.oops.InstanceKlass; import sun.jvm.hotspot.oops.ArrayKlass; import sun.jvm.hotspot.oops.JVMDIClassStatus; import sun.jvm.hotspot.oops.Klass; +import sun.jvm.hotspot.oops.ObjArray; import sun.jvm.hotspot.oops.Oop; import sun.jvm.hotspot.oops.Symbol; import sun.jvm.hotspot.oops.DefaultHeapVisitor; @@ -53,6 +55,7 @@ implements ReferenceType { private SoftReference methodsCache; private SoftReference allMethodsCache; private SoftReference nestedTypesCache; + private SoftReference methodInvokesCache; /* to mark when no info available */ static final SDE NO_SDE_INFO_MARK = new SDE(); @@ -82,6 +85,27 @@ implements ReferenceType { return method; } } + if (ref.getMethodHolder().equals(SystemDictionary.getMethodHandleKlass())) { + // invoke methods are generated as needed, so make mirrors as needed + List mis = null; + if (methodInvokesCache == null) { + mis = new ArrayList(); + methodInvokesCache = new SoftReference(mis); + } else { + mis = (List)methodInvokesCache.get(); + } + it = mis.iterator(); + while (it.hasNext()) { + MethodImpl method = (MethodImpl)it.next(); + if (ref.equals(method.ref())) { + return method; + } + } + + MethodImpl method = MethodImpl.createMethodImpl(vm, this, ref); + mis.add(method); + return method; + } throw new IllegalArgumentException("Invalid method id: " + ref); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java index 8ef0aa1eebe..69461d3712a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java @@ -123,6 +123,9 @@ public class StackFrameImpl extends MirrorImpl Assert.that(values.size() > 0, "this is missing"); } // 'this' at index 0. + if (values.get(0).getType() == BasicType.getTConflict()) { + return null; + } OopHandle handle = values.oopHandleAt(0); ObjectHeap heap = vm.saObjectHeap(); thisObject = vm.objectMirror(heap.newOop(handle)); @@ -210,6 +213,8 @@ public class StackFrameImpl extends MirrorImpl validateStackFrame(); StackValueCollection values = saFrame.getLocals(); MethodImpl mmm = (MethodImpl)location.method(); + if (mmm.isNative()) + return null; List argSigs = mmm.argumentSignatures(); int count = argSigs.size(); List res = new ArrayList(0); @@ -231,34 +236,67 @@ public class StackFrameImpl extends MirrorImpl ValueImpl valueImpl = null; OopHandle handle = null; ObjectHeap heap = vm.saObjectHeap(); - if (variableType == BasicType.T_BOOLEAN) { + if (values.get(ss).getType() == BasicType.getTConflict()) { + // Dead locals, so just represent them as a zero of the appropriate type + if (variableType == BasicType.T_BOOLEAN) { + valueImpl = (BooleanValueImpl) vm.mirrorOf(false); + } else if (variableType == BasicType.T_CHAR) { + valueImpl = (CharValueImpl) vm.mirrorOf((char)0); + } else if (variableType == BasicType.T_FLOAT) { + valueImpl = (FloatValueImpl) vm.mirrorOf((float)0); + } else if (variableType == BasicType.T_DOUBLE) { + valueImpl = (DoubleValueImpl) vm.mirrorOf((double)0); + } else if (variableType == BasicType.T_BYTE) { + valueImpl = (ByteValueImpl) vm.mirrorOf((byte)0); + } else if (variableType == BasicType.T_SHORT) { + valueImpl = (ShortValueImpl) vm.mirrorOf((short)0); + } else if (variableType == BasicType.T_INT) { + valueImpl = (IntegerValueImpl) vm.mirrorOf((int)0); + } else if (variableType == BasicType.T_LONG) { + valueImpl = (LongValueImpl) vm.mirrorOf((long)0); + } else if (variableType == BasicType.T_OBJECT) { + // we may have an [Ljava/lang/Object; - i.e., Object[] with the + // elements themselves may be arrays because every array is an Object. + handle = null; + valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle)); + } else if (variableType == BasicType.T_ARRAY) { + handle = null; + valueImpl = vm.arrayMirror((Array)heap.newOop(handle)); + } else if (variableType == BasicType.T_VOID) { + valueImpl = new VoidValueImpl(vm); + } else { + throw new RuntimeException("Should not read here"); + } + } else { + if (variableType == BasicType.T_BOOLEAN) { valueImpl = (BooleanValueImpl) vm.mirrorOf(values.booleanAt(ss)); - } else if (variableType == BasicType.T_CHAR) { + } else if (variableType == BasicType.T_CHAR) { valueImpl = (CharValueImpl) vm.mirrorOf(values.charAt(ss)); - } else if (variableType == BasicType.T_FLOAT) { + } else if (variableType == BasicType.T_FLOAT) { valueImpl = (FloatValueImpl) vm.mirrorOf(values.floatAt(ss)); - } else if (variableType == BasicType.T_DOUBLE) { + } else if (variableType == BasicType.T_DOUBLE) { valueImpl = (DoubleValueImpl) vm.mirrorOf(values.doubleAt(ss)); - } else if (variableType == BasicType.T_BYTE) { + } else if (variableType == BasicType.T_BYTE) { valueImpl = (ByteValueImpl) vm.mirrorOf(values.byteAt(ss)); - } else if (variableType == BasicType.T_SHORT) { + } else if (variableType == BasicType.T_SHORT) { valueImpl = (ShortValueImpl) vm.mirrorOf(values.shortAt(ss)); - } else if (variableType == BasicType.T_INT) { + } else if (variableType == BasicType.T_INT) { valueImpl = (IntegerValueImpl) vm.mirrorOf(values.intAt(ss)); - } else if (variableType == BasicType.T_LONG) { + } else if (variableType == BasicType.T_LONG) { valueImpl = (LongValueImpl) vm.mirrorOf(values.longAt(ss)); - } else if (variableType == BasicType.T_OBJECT) { + } else if (variableType == BasicType.T_OBJECT) { // we may have an [Ljava/lang/Object; - i.e., Object[] with the // elements themselves may be arrays because every array is an Object. handle = values.oopHandleAt(ss); valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle)); - } else if (variableType == BasicType.T_ARRAY) { + } else if (variableType == BasicType.T_ARRAY) { handle = values.oopHandleAt(ss); valueImpl = vm.arrayMirror((Array)heap.newOop(handle)); - } else if (variableType == BasicType.T_VOID) { + } else if (variableType == BasicType.T_VOID) { valueImpl = new VoidValueImpl(vm); - } else { + } else { throw new RuntimeException("Should not read here"); + } } return valueImpl; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java index f8bb01adb96..c999ff1a80d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java @@ -44,6 +44,7 @@ public class SystemDictionary { private static sun.jvm.hotspot.types.OopField systemKlassField; private static sun.jvm.hotspot.types.OopField threadKlassField; private static sun.jvm.hotspot.types.OopField threadGroupKlassField; + private static sun.jvm.hotspot.types.OopField methodHandleKlassField; static { VM.registerVMInitializedObserver(new Observer() { @@ -69,6 +70,7 @@ public class SystemDictionary { systemKlassField = type.getOopField(WK_KLASS("System_klass")); threadKlassField = type.getOopField(WK_KLASS("Thread_klass")); threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass")); + methodHandleKlassField = type.getOopField(WK_KLASS("MethodHandle_klass")); } // This WK functions must follow the definitions in systemDictionary.hpp: @@ -127,6 +129,10 @@ public class SystemDictionary { return (InstanceKlass) newOop(systemKlassField.getValue()); } + public static InstanceKlass getMethodHandleKlass() { + return (InstanceKlass) newOop(methodHandleKlassField.getValue()); + } + public InstanceKlass getAbstractOwnableSynchronizerKlass() { return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer", null, null); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java index d0d96740080..ba42e8da19f 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @@ -93,6 +93,8 @@ public class CompiledVFrame extends JavaVFrame { } public StackValueCollection getLocals() { + if (getScope() == null) + return new StackValueCollection(); List scvList = getScope().getLocals(); if (scvList == null) return new StackValueCollection(); @@ -108,6 +110,8 @@ public class CompiledVFrame extends JavaVFrame { } public StackValueCollection getExpressions() { + if (getScope() == null) + return new StackValueCollection(); List scvList = getScope().getExpressions(); if (scvList == null) return new StackValueCollection(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java index 3b99ec29168..70eace55f33 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java @@ -33,6 +33,7 @@ import sun.jvm.hotspot.c1.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.interpreter.*; import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.runtime.sparc.SPARCFrame; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; @@ -74,11 +75,19 @@ public abstract class Frame implements Cloneable { /** Size of constMethodOopDesc for computing BCI from BCP (FIXME: hack) */ private static long constMethodOopDescSize; + private static int pcReturnOffset; + + public static int pcReturnOffset() { + return pcReturnOffset; + } + private static synchronized void initialize(TypeDataBase db) { Type constMethodOopType = db.lookupType("constMethodOopDesc"); // FIXME: not sure whether alignment here is correct or how to // force it (round up to address size?) constMethodOopDescSize = constMethodOopType.getSize(); + + pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue(); } protected int bcpToBci(Address bcp, ConstMethod cm) { @@ -106,6 +115,10 @@ public abstract class Frame implements Cloneable { public void setPC(Address newpc) { pc = newpc; } public boolean isDeoptimized() { return deoptimized; } + public CodeBlob cb() { + return VM.getVM().getCodeCache().findBlob(getPC()); + } + public abstract Address getSP(); public abstract Address getID(); public abstract Address getFP(); @@ -134,6 +147,12 @@ public abstract class Frame implements Cloneable { } } + public boolean isRicochetFrame() { + CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); + RicochetBlob rcb = VM.getVM().ricochetBlob(); + return (cb == rcb && rcb != null && rcb.returnsToBounceAddr(getPC())); + } + public boolean isCompiledFrame() { if (Assert.ASSERTS_ENABLED) { Assert.that(!VM.getVM().isCore(), "noncore builds only"); @@ -142,7 +161,7 @@ public abstract class Frame implements Cloneable { return (cb != null && cb.isJavaMethod()); } - public boolean isGlueFrame() { + public boolean isRuntimeFrame() { if (Assert.ASSERTS_ENABLED) { Assert.that(!VM.getVM().isCore(), "noncore builds only"); } @@ -197,7 +216,8 @@ public abstract class Frame implements Cloneable { public Frame realSender(RegisterMap map) { if (!VM.getVM().isCore()) { Frame result = sender(map); - while (result.isGlueFrame()) { + while (result.isRuntimeFrame() || + result.isRicochetFrame()) { result = result.sender(map); } return result; @@ -611,6 +631,9 @@ public abstract class Frame implements Cloneable { if (Assert.ASSERTS_ENABLED) { Assert.that(cb != null, "sanity check"); } + if (cb == VM.getVM().ricochetBlob()) { + oopsRicochetDo(oopVisitor, regMap); + } if (cb.getOopMaps() != null) { OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); @@ -627,6 +650,10 @@ public abstract class Frame implements Cloneable { // } } + private void oopsRicochetDo (AddressVisitor oopVisitor, RegisterMap regMap) { + // XXX Empty for now + } + // FIXME: implement the above routines, plus add // oops_interpreted_arguments_do and oops_compiled_arguments_do } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java index 63108f78dd4..a45cbc3640c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java @@ -128,14 +128,14 @@ public abstract class JavaVFrame extends VFrame { } // dynamic part - we just compare the frame pointer - if (! getFrame().getFP().equals(other.getFrame().getFP())) { + if (! getFrame().equals(other.getFrame())) { return false; } return true; } public int hashCode() { - return getMethod().hashCode() ^ getBCI() ^ getFrame().getFP().hashCode(); + return getMethod().hashCode() ^ getBCI() ^ getFrame().hashCode(); } /** Structural compare */ diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java index 78ba7384cf2..5cc5f94ec8d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java @@ -100,7 +100,7 @@ public class StackValue { public int hashCode() { if (type == BasicType.getTObject()) { - return handleValue.hashCode(); + return handleValue != null ? handleValue.hashCode() : 5; } else { // Returns 0 for conflict type return (int) integerValue; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java index 98591fda6af..ea1ec197c6e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java @@ -77,7 +77,7 @@ public class VFrame { return new CompiledVFrame(f, regMap, thread, scope, mayBeImprecise); } - if (f.isGlueFrame()) { + if (f.isRuntimeFrame()) { // This is a conversion frame. Skip this frame and try again. RegisterMap tempMap = regMap.copy(); Frame s = f.sender(tempMap); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 4d333baa9a6..b1c52a35319 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -30,6 +30,7 @@ import java.util.*; import java.util.regex.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.c1.*; +import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.interpreter.*; import sun.jvm.hotspot.memory.*; @@ -85,6 +86,9 @@ public class VM { private Interpreter interpreter; private StubRoutines stubRoutines; private Bytes bytes; + + private RicochetBlob ricochetBlob; + /** Flags indicating whether we are attached to a core, C1, or C2 build */ private boolean usingClientCompiler; private boolean usingServerCompiler; @@ -618,6 +622,18 @@ public class VM { return stubRoutines; } + public RicochetBlob ricochetBlob() { + if (ricochetBlob == null) { + Type ricochetType = db.lookupType("SharedRuntime"); + AddressField ricochetBlobAddress = ricochetType.getAddressField("_ricochet_blob"); + Address addr = ricochetBlobAddress.getValue(); + if (addr != null) { + ricochetBlob = new RicochetBlob(addr); + } + } + return ricochetBlob; + } + public VMRegImpl getVMRegImplInfo() { if (vmregImpl == null) { vmregImpl = new VMRegImpl(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java index c5e4e631237..6acf0d9605c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java @@ -29,6 +29,7 @@ import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.interpreter.*; import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.x86.*; /**

Should be able to be used on all amd64 platforms we support (Linux/amd64) to implement JavaThread's @@ -123,7 +124,7 @@ public class AMD64CurrentFrameGuess { offset += vm.getAddressSize()) { try { Address curSP = sp.addOffsetTo(offset); - Frame frame = new AMD64Frame(curSP, null, pc); + Frame frame = new X86Frame(curSP, null, pc); RegisterMap map = thread.newRegisterMap(false); while (frame != null) { if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java deleted file mode 100644 index 6a5d02c3643..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.runtime.amd64; - -import java.util.*; -import sun.jvm.hotspot.code.*; -import sun.jvm.hotspot.compiler.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.*; - -/** Specialization of and implementation of abstract methods of the - Frame class for the amd64 CPU. */ - -public class AMD64Frame extends Frame { - private static final boolean DEBUG; - static { - DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG") != null; - } - - // refer to frame_amd64.hpp - private static final int PC_RETURN_OFFSET = 0; - // All frames - private static final int LINK_OFFSET = 0; - private static final int RETURN_ADDR_OFFSET = 1; - private static final int SENDER_SP_OFFSET = 2; - - // Interpreter frames - private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only - private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1; - private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; - private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1; - private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only - private static int INTERPRETER_FRAME_CACHE_OFFSET; - private static int INTERPRETER_FRAME_LOCALS_OFFSET; - private static int INTERPRETER_FRAME_BCX_OFFSET; - private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; - private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; - private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; - - // Entry frames - private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -6; - - // Native frames - private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; - - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - if (VM.getVM().isCore()) { - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; - } else { - INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; - } - INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; - INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; - INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; - INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; - INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; - } - - // an additional field beyond sp and pc: - Address raw_fp; // frame pointer - private Address raw_unextendedSP; - - private AMD64Frame() { - } - - private void adjustForDeopt() { - if ( pc != null) { - // Look for a deopt pc and if it is deopted convert to original pc - CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); - if (cb != null && cb.isJavaMethod()) { - NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptBegin())) { - // adjust pc if frame is deoptimized. - if (Assert.ASSERTS_ENABLED) { - Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); - } - pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); - deoptimized = true; - } - } - } - } - - public AMD64Frame(Address raw_sp, Address raw_fp, Address pc) { - this.raw_sp = raw_sp; - this.raw_unextendedSP = raw_sp; - this.raw_fp = raw_fp; - this.pc = pc; - - // Frame must be fully constructed before this call - adjustForDeopt(); - - if (DEBUG) { - System.out.println("AMD64Frame(sp, fp, pc): " + this); - dumpStack(); - } - } - - public AMD64Frame(Address raw_sp, Address raw_fp) { - this.raw_sp = raw_sp; - this.raw_unextendedSP = raw_sp; - this.raw_fp = raw_fp; - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); - - // Frame must be fully constructed before this call - adjustForDeopt(); - - if (DEBUG) { - System.out.println("AMD64Frame(sp, fp): " + this); - dumpStack(); - } - } - - // This constructor should really take the unextended SP as an arg - // but then the constructor is ambiguous with constructor that takes - // a PC so take an int and convert it. - public AMD64Frame(Address raw_sp, Address raw_fp, long extension) { - this.raw_sp = raw_sp; - if ( raw_sp == null) { - this.raw_unextendedSP = null; - } else { - this.raw_unextendedSP = raw_sp.addOffsetTo(extension); - } - this.raw_fp = raw_fp; - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); - - // Frame must be fully constructed before this call - adjustForDeopt(); - - if (DEBUG) { - System.out.println("AMD64Frame(sp, fp, extension): " + this); - dumpStack(); - } - - } - - public Object clone() { - AMD64Frame frame = new AMD64Frame(); - frame.raw_sp = raw_sp; - frame.raw_unextendedSP = raw_unextendedSP; - frame.raw_fp = raw_fp; - frame.pc = pc; - frame.deoptimized = deoptimized; - return frame; - } - - public boolean equals(Object arg) { - if (arg == null) { - return false; - } - - if (!(arg instanceof AMD64Frame)) { - return false; - } - - AMD64Frame other = (AMD64Frame) arg; - - return (AddressOps.equal(getSP(), other.getSP()) && - AddressOps.equal(getFP(), other.getFP()) && - AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && - AddressOps.equal(getPC(), other.getPC())); - } - - public int hashCode() { - if (raw_sp == null) { - return 0; - } - - return raw_sp.hashCode(); - } - - public String toString() { - return "sp: " + (getSP() == null? "null" : getSP().toString()) + - ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) + - ", fp: " + (getFP() == null? "null" : getFP().toString()) + - ", pc: " + (pc == null? "null" : pc.toString()); - } - - // accessors for the instance variables - public Address getFP() { return raw_fp; } - public Address getSP() { return raw_sp; } - public Address getID() { return raw_sp; } - - // FIXME: not implemented yet (should be done for Solaris/AMD64) - public boolean isSignalHandlerFrameDbg() { return false; } - public int getSignalNumberDbg() { return 0; } - public String getSignalNameDbg() { return null; } - - public boolean isInterpretedFrameValid() { - if (Assert.ASSERTS_ENABLED) { - Assert.that(isInterpretedFrame(), "Not an interpreted frame"); - } - - // These are reasonable sanity checks - if (getFP() == null || getFP().andWithMask(0x3) != null) { - return false; - } - - if (getSP() == null || getSP().andWithMask(0x3) != null) { - return false; - } - - if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) { - return false; - } - - // These are hacks to keep us out of trouble. - // The problem with these is that they mask other problems - if (getFP().lessThanOrEqual(getSP())) { - // this attempts to deal with unsigned comparison above - return false; - } - - if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { - // stack frames shouldn't be large. - return false; - } - - return true; - } - - // FIXME: not applicable in current system - // void patch_pc(Thread* thread, address pc); - - public Frame sender(RegisterMap regMap, CodeBlob cb) { - AMD64RegisterMap map = (AMD64RegisterMap) regMap; - - if (Assert.ASSERTS_ENABLED) { - Assert.that(map != null, "map must be set"); - } - - // Default is we done have to follow them. The sender_for_xxx will - // update it accordingly - map.setIncludeArgumentOops(false); - - if (isEntryFrame()) return senderForEntryFrame(map); - if (isInterpretedFrame()) return senderForInterpreterFrame(map); - - - if (!VM.getVM().isCore()) { - if(cb == null) { - cb = VM.getVM().getCodeCache().findBlob(getPC()); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); - } - } - - if (cb != null) { - return senderForCompiledFrame(map, cb); - } - } - - // Must be native-compiled frame, i.e. the marshaling code for native - // methods that exists in the core system. - return new AMD64Frame(getSenderSP(), getLink(), getSenderPC()); - } - - private Frame senderForEntryFrame(AMD64RegisterMap map) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(map != null, "map must be set"); - } - // Java frame called from C; skip all C frames and return top C - // frame of that chunk as the sender - AMD64JavaCallWrapper jcw = (AMD64JavaCallWrapper) getEntryFrameCallWrapper(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); - Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); - } - AMD64Frame fr; - if (jcw.getLastJavaPC() != null) { - fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); - } else { - fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP()); - } - map.clear(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); - } - return fr; - } - - private Frame senderForInterpreterFrame(AMD64RegisterMap map) { - Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); - Address sp = addressOfStackSlot(SENDER_SP_OFFSET); - // We do not need to update the callee-save register mapping because above - // us is either another interpreter frame or a converter-frame, but never - // directly a compiled frame. - // 11/24/04 SFG. This is no longer true after adapter were removed. However at the moment - // C2 no longer uses callee save register for java calls so there are no callee register - // to find. - return new AMD64Frame(sp, getLink(), unextendedSP.minus(sp)); - } - - private Frame senderForCompiledFrame(AMD64RegisterMap map, CodeBlob cb) { - // - // NOTE: some of this code is (unfortunately) duplicated in AMD64CurrentFrameGuess - // - - if (Assert.ASSERTS_ENABLED) { - Assert.that(map != null, "map must be set"); - } - - // frame owned by optimizing compiler - Address sender_sp = null; - - - if (VM.getVM().isClientCompiler()) { - sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use"); - } - sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize()); - } - - // On Intel the return_address is always the word on the stack - Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); - - if (map.getUpdateMap() && cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, true); - } - - if (VM.getVM().isClientCompiler()) { - // Move this here for C1 and collecting oops in arguments (According to Rene) - map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread())); - } - - Address saved_fp = null; - if (VM.getVM().isClientCompiler()) { - saved_fp = getFP().getAddressAt(0); - } else if (VM.getVM().isServerCompiler() && - (VM.getVM().getInterpreter().contains(sender_pc) || - VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) { - // C2 prologue saves EBP in the usual place. - // however only use it if the sender had link infomration in it. - saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize()); - } - - return new AMD64Frame(sender_sp, saved_fp, sender_pc); - } - - protected boolean hasSenderPD() { - // FIXME - // Check for null ebp? Need to do some tests. - return true; - } - - public long frameSize() { - return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); - } - - public Address getLink() { - return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); - } - - // FIXME: not implementable yet - //inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } - - public Address getUnextendedSP() { return raw_unextendedSP; } - - // Return address: - public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } - public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } - - // return address of param, zero origin index. - public Address getNativeParamAddr(int idx) { - return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx); - } - - public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } - - public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) { - if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) { - throw new RuntimeException("Should not reach here"); - } - - return oopMapRegToLocation(reg, regMap); - } - - public Address addressOfInterpreterFrameLocals() { - return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); - } - - private Address addressOfInterpreterFrameBCX() { - return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); - } - - public int getInterpreterFrameBCI() { - // FIXME: this is not atomic with respect to GC and is unsuitable - // for use in a non-debugging, or reflective, system. Need to - // figure out how to express this. - Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); - OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); - Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); - return (int) bcpToBci(bcp, method); - } - - public Address addressOfInterpreterFrameMDX() { - return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); - } - - // FIXME - //inline int frame::interpreter_frame_monitor_size() { - // return BasicObjectLock::size(); - //} - - // expression stack - // (the max_stack arguments are used by the GC; see class FrameClosure) - - public Address addressOfInterpreterFrameExpressionStack() { - Address monitorEnd = interpreterFrameMonitorEnd().address(); - return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); - } - - public int getInterpreterFrameExpressionStackDirection() { return -1; } - - // top of expression stack - public Address addressOfInterpreterFrameTOS() { - return getSP(); - } - - /** Expression stack from top down */ - public Address addressOfInterpreterFrameTOSAt(int slot) { - return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); - } - - public Address getInterpreterFrameSenderSP() { - if (Assert.ASSERTS_ENABLED) { - Assert.that(isInterpretedFrame(), "interpreted frame expected"); - } - return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); - } - - // Monitors - public BasicObjectLock interpreterFrameMonitorBegin() { - return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); - } - - public BasicObjectLock interpreterFrameMonitorEnd() { - Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); - if (Assert.ASSERTS_ENABLED) { - // make sure the pointer points inside the frame - Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); - Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); - } - return new BasicObjectLock(result); - } - - public int interpreterFrameMonitorSize() { - return BasicObjectLock.size(); - } - - // Method - public Address addressOfInterpreterFrameMethod() { - return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); - } - - // Constant pool cache - public Address addressOfInterpreterFrameCPCache() { - return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); - } - - // Entry frames - public JavaCallWrapper getEntryFrameCallWrapper() { - return new AMD64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); - } - - protected Address addressOfSavedOopResult() { - // offset is 2 for compiler2 and 3 for compiler1 - return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * - VM.getVM().getAddressSize()); - } - - protected Address addressOfSavedReceiver() { - return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); - } - - private void dumpStack() { - if (getFP() != null) { - for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); - AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); - addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { - System.out.println(addr + ": " + addr.getAddressAt(0)); - } - } else { - for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); - AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); - addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { - System.out.println(addr + ": " + addr.getAddressAt(0)); - } - } - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java index ea025da0bfc..89fcb12b1a6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java @@ -30,6 +30,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.amd64.*; +import sun.jvm.hotspot.runtime.x86.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; @@ -80,11 +81,11 @@ public class LinuxAMD64JavaThreadPDAccess implements JavaThreadPDAccess { if (fp == null) { return null; // no information } - return new AMD64Frame(thread.getLastJavaSP(), fp); + return new X86Frame(thread.getLastJavaSP(), fp); } public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { - return new AMD64RegisterMap(thread, updateMap); + return new X86RegisterMap(thread, updateMap); } public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { @@ -95,9 +96,9 @@ public class LinuxAMD64JavaThreadPDAccess implements JavaThreadPDAccess { return null; } if (guesser.getPC() == null) { - return new AMD64Frame(guesser.getSP(), guesser.getFP()); + return new X86Frame(guesser.getSP(), guesser.getFP()); } else { - return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java index d3c307c5535..6891040c253 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java @@ -30,6 +30,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.amd64.*; +import sun.jvm.hotspot.runtime.x86.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; @@ -84,14 +85,14 @@ public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess { } Address pc = thread.getLastJavaPC(); if ( pc != null ) { - return new AMD64Frame(thread.getLastJavaSP(), fp, pc); + return new X86Frame(thread.getLastJavaSP(), fp, pc); } else { - return new AMD64Frame(thread.getLastJavaSP(), fp); + return new X86Frame(thread.getLastJavaSP(), fp); } } public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { - return new AMD64RegisterMap(thread, updateMap); + return new X86RegisterMap(thread, updateMap); } public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { @@ -102,9 +103,9 @@ public class SolarisAMD64JavaThreadPDAccess implements JavaThreadPDAccess { return null; } if (guesser.getPC() == null) { - return new AMD64Frame(guesser.getSP(), guesser.getFP()); + return new X86Frame(guesser.getSP(), guesser.getFP()); } else { - return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java index 5523f35005f..3d55dabd85c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java @@ -236,7 +236,7 @@ public class SPARCFrame extends Frame { CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); if (cb != null && cb.isJavaMethod()) { NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptBegin())) { + if (pc.equals(nm.deoptHandlerBegin())) { // adjust pc if frame is deoptimized. pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); deoptimized = true; @@ -559,49 +559,46 @@ public class SPARCFrame extends Frame { } } - if (!VM.getVM().isCore()) { - // Note: The version of this operation on any platform with callee-save - // registers must update the register map (if not null). - // In order to do this correctly, the various subtypes of - // of frame (interpreted, compiled, glue, native), - // must be distinguished. There is no need on SPARC for - // such distinctions, because all callee-save registers are - // preserved for all frames via SPARC-specific mechanisms. - // - // *** HOWEVER, *** if and when we make any floating-point - // registers callee-saved, then we will have to copy over - // the RegisterMap update logic from the Intel code. + // Note: The version of this operation on any platform with callee-save + // registers must update the register map (if not null). + // In order to do this correctly, the various subtypes of + // of frame (interpreted, compiled, glue, native), + // must be distinguished. There is no need on SPARC for + // such distinctions, because all callee-save registers are + // preserved for all frames via SPARC-specific mechanisms. + // + // *** HOWEVER, *** if and when we make any floating-point + // registers callee-saved, then we will have to copy over + // the RegisterMap update logic from the Intel code. + if (isRicochetFrame()) return senderForRicochetFrame(map); - // The constructor of the sender must know whether this frame is interpreted so it can set the - // sender's _interpreter_sp_adjustment field. - if (VM.getVM().getInterpreter().contains(pc)) { - isInterpreted = true; - map.makeIntegerRegsUnsaved(); + // The constructor of the sender must know whether this frame is interpreted so it can set the + // sender's _interpreter_sp_adjustment field. + if (VM.getVM().getInterpreter().contains(pc)) { + isInterpreted = true; + map.makeIntegerRegsUnsaved(); + map.shiftWindow(sp, youngerSP); + } else { + // Find a CodeBlob containing this frame's pc or elide the lookup and use the + // supplied blob which is already known to be associated with this frame. + cb = VM.getVM().getCodeCache().findBlob(pc); + if (cb != null) { + // Update the location of all implicitly saved registers + // as the address of these registers in the register save + // area (for %o registers we use the address of the %i + // register in the next younger frame) map.shiftWindow(sp, youngerSP); - } else { - // Find a CodeBlob containing this frame's pc or elide the lookup and use the - // supplied blob which is already known to be associated with this frame. - cb = VM.getVM().getCodeCache().findBlob(pc); - if (cb != null) { - - if (cb.callerMustGCArguments(map.getThread())) { + if (map.getUpdateMap()) { + if (cb.callerMustGCArguments()) { map.setIncludeArgumentOops(true); } - - // Update the location of all implicitly saved registers - // as the address of these registers in the register save - // area (for %o registers we use the address of the %i - // register in the next younger frame) - map.shiftWindow(sp, youngerSP); - if (map.getUpdateMap()) { - if (cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); - } + if (cb.getOopMaps() != null) { + OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); } } } - } // #ifndef CORE + } return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); } @@ -948,6 +945,20 @@ public class SPARCFrame extends Frame { } + private Frame senderForRicochetFrame(SPARCRegisterMap map) { + if (DEBUG) { + System.out.println("senderForRicochetFrame"); + } + //RicochetFrame* f = RicochetFrame::from_frame(fr); + // Cf. is_interpreted_frame path of frame::sender + Address youngerSP = getSP(); + Address sp = getSenderSP(); + map.makeIntegerRegsUnsaved(); + map.shiftWindow(sp, youngerSP); + boolean thisFrameAdjustedStack = true; // I5_savedSP is live in this RF + return new SPARCFrame(sp, youngerSP, thisFrameAdjustedStack); + } + private Frame senderForEntryFrame(RegisterMap regMap) { SPARCRegisterMap map = (SPARCRegisterMap) regMap; @@ -965,10 +976,8 @@ public class SPARCFrame extends Frame { Address lastJavaPC = jcw.getLastJavaPC(); map.clear(); - if (!VM.getVM().isCore()) { - map.makeIntegerRegsUnsaved(); - map.shiftWindow(lastJavaSP, null); - } + map.makeIntegerRegsUnsaved(); + map.shiftWindow(lastJavaSP, null); if (Assert.ASSERTS_ENABLED) { Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java new file mode 100644 index 00000000000..57fa927fc07 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.sparc; + +import java.util.*; +import sun.jvm.hotspot.asm.sparc.SPARCRegister; +import sun.jvm.hotspot.asm.sparc.SPARCRegisters; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; + +public class SPARCRicochetFrame { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private SPARCFrame frame; + + private static void initialize(TypeDataBase db) { + // Type type = db.lookupType("MethodHandles::RicochetFrame"); + + } + + static SPARCRicochetFrame fromFrame(SPARCFrame f) { + return new SPARCRicochetFrame(f); + } + + private SPARCRicochetFrame(SPARCFrame f) { + frame = f; + } + + private Address registerValue(SPARCRegister reg) { + return frame.getSP().addOffsetTo(reg.spOffsetInSavedWindow()).getAddressAt(0); + } + + public Address savedArgsBase() { + return registerValue(SPARCRegisters.L4); + } + public Address exactSenderSP() { + return registerValue(SPARCRegisters.I5); + } + public Address senderLink() { + return frame.getSenderSP(); + } + public Address senderPC() { + return frame.getSenderPC(); + } + public Address extendedSenderSP() { + return savedArgsBase(); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java index 76a686fae1e..64785ee8c1f 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java @@ -31,6 +31,7 @@ import sun.jvm.hotspot.debugger.win32.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.amd64.*; +import sun.jvm.hotspot.runtime.x86.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; @@ -86,14 +87,14 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { } Address pc = thread.getLastJavaPC(); if ( pc != null ) { - return new AMD64Frame(thread.getLastJavaSP(), fp, pc); + return new X86Frame(thread.getLastJavaSP(), fp, pc); } else { - return new AMD64Frame(thread.getLastJavaSP(), fp); + return new X86Frame(thread.getLastJavaSP(), fp); } } public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { - return new AMD64RegisterMap(thread, updateMap); + return new X86RegisterMap(thread, updateMap); } public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { @@ -104,9 +105,9 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { return null; } if (guesser.getPC() == null) { - return new AMD64Frame(guesser.getSP(), guesser.getFP()); + return new X86Frame(guesser.getSP(), guesser.getFP()); } else { - return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java index f824218c780..41ef83276c4 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java @@ -25,7 +25,6 @@ package sun.jvm.hotspot.runtime.x86; import java.util.*; -import sun.jvm.hotspot.asm.x86.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.compiler.*; import sun.jvm.hotspot.debugger.*; @@ -62,11 +61,13 @@ public class X86Frame extends Frame { private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; // Entry frames - private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = 2; + private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; // Native frames private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; + private static VMReg rbp; + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -76,19 +77,23 @@ public class X86Frame extends Frame { } private static synchronized void initialize(TypeDataBase db) { - if (VM.getVM().isCore()) { - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; - } else { - INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; - } + INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; + INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; + + ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset"); + if (VM.getVM().getAddressSize() == 4) { + rbp = new VMReg(5); + } else { + rbp = new VMReg(5 << 1); + } } + // an additional field beyond sp and pc: Address raw_fp; // frame pointer private Address raw_unextendedSP; @@ -102,7 +107,7 @@ public class X86Frame extends Frame { CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); if (cb != null && cb.isJavaMethod()) { NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptBegin())) { + if (pc.equals(nm.deoptHandlerBegin())) { if (Assert.ASSERTS_ENABLED) { Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); } @@ -119,6 +124,7 @@ public class X86Frame extends Frame { this.raw_unextendedSP = raw_sp; this.raw_fp = raw_fp; this.pc = pc; + adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -134,6 +140,7 @@ public class X86Frame extends Frame { this.raw_unextendedSP = raw_sp; this.raw_fp = raw_fp; this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -144,24 +151,18 @@ public class X86Frame extends Frame { } } - // This constructor should really take the unextended SP as an arg - // but then the constructor is ambiguous with constructor that takes - // a PC so take an int and convert it. - public X86Frame(Address raw_sp, Address raw_fp, long extension) { + public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { this.raw_sp = raw_sp; - if (raw_sp == null) { - this.raw_unextendedSP = null; - } else { - this.raw_unextendedSP = raw_sp.addOffsetTo(extension); - } + this.raw_unextendedSP = raw_unextendedSp; this.raw_fp = raw_fp; - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + this.pc = pc; + adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); if (DEBUG) { - System.out.println("X86Frame(sp, fp): " + this); + System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this); dumpStack(); } @@ -172,7 +173,6 @@ public class X86Frame extends Frame { frame.raw_sp = raw_sp; frame.raw_unextendedSP = raw_unextendedSP; frame.raw_fp = raw_fp; - frame.raw_fp = raw_fp; frame.pc = pc; frame.deoptimized = deoptimized; return frame; @@ -269,19 +269,18 @@ public class X86Frame extends Frame { if (isEntryFrame()) return senderForEntryFrame(map); if (isInterpretedFrame()) return senderForInterpreterFrame(map); + if (isRicochetFrame()) return senderForRicochetFrame(map); - if (!VM.getVM().isCore()) { - if(cb == null) { - cb = VM.getVM().getCodeCache().findBlob(getPC()); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); - } + if(cb == null) { + cb = VM.getVM().getCodeCache().findBlob(getPC()); + } else { + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); } + } - if (cb != null) { - return senderForCompiledFrame(map, cb); - } + if (cb != null) { + return senderForCompiledFrame(map, cb); } // Must be native-compiled frame, i.e. the marshaling code for native @@ -289,7 +288,20 @@ public class X86Frame extends Frame { return new X86Frame(getSenderSP(), getLink(), getSenderPC()); } + private Frame senderForRicochetFrame(X86RegisterMap map) { + if (DEBUG) { + System.out.println("senderForRicochetFrame"); + } + X86RicochetFrame f = X86RicochetFrame.fromFrame(this); + if (map.getUpdateMap()) + updateMapWithSavedLink(map, f.senderLinkAddress()); + return new X86Frame(f.extendedSenderSP(), f.exactSenderSP(), f.senderLink(), f.senderPC()); + } + private Frame senderForEntryFrame(X86RegisterMap map) { + if (DEBUG) { + System.out.println("senderForEntryFrame"); + } if (Assert.ASSERTS_ENABLED) { Assert.that(map != null, "map must be set"); } @@ -313,7 +325,37 @@ public class X86Frame extends Frame { return fr; } + //------------------------------------------------------------------------------ + // frame::adjust_unextended_sp + private void adjustUnextendedSP() { + // If we are returning to a compiled MethodHandle call site, the + // saved_fp will in fact be a saved value of the unextended SP. The + // simplest way to tell whether we are returning to such a call site + // is as follows: + + CodeBlob cb = cb(); + NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); + if (senderNm != null) { + // If the sender PC is a deoptimization point, get the original + // PC. For MethodHandle call site the unextended_sp is stored in + // saved_fp. + if (senderNm.isDeoptMhEntry(getPC())) { + // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP())); + raw_unextendedSP = getFP(); + } + else if (senderNm.isDeoptEntry(getPC())) { + // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp)); + } + else if (senderNm.isMethodHandleReturn(getPC())) { + raw_unextendedSP = getFP(); + } + } + } + private Frame senderForInterpreterFrame(X86RegisterMap map) { + if (DEBUG) { + System.out.println("senderForInterpreterFrame"); + } Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); Address sp = addressOfStackSlot(SENDER_SP_OFFSET); // We do not need to update the callee-save register mapping because above @@ -323,10 +365,21 @@ public class X86Frame extends Frame { // However c2 no longer uses callee save register for java calls so there // are no callee register to find. - return new X86Frame(sp, getLink(), unextendedSP.minus(sp)); + if (map.getUpdateMap()) + updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); + + return new X86Frame(sp, unextendedSP, getLink(), getSenderPC()); + } + + private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { + map.setLocation(rbp, savedFPAddr); } private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { + if (DEBUG) { + System.out.println("senderForCompiledFrame"); + } + // // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess // @@ -336,41 +389,35 @@ public class X86Frame extends Frame { } // frame owned by optimizing compiler - Address sender_sp = null; - - if (VM.getVM().isClientCompiler()) { - sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use"); - } - sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize()); + if (Assert.ASSERTS_ENABLED) { + Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); } + Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); // On Intel the return_address is always the word on the stack - Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); + Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); - if (map.getUpdateMap() && cb.getOopMaps() != null) { - OopMapSet.updateRegisterMap(this, cb, map, true); + // This is the saved value of EBP which may or may not really be an FP. + // It is only an FP if the sender is an interpreter frame (or C1?). + Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize()); + + if (map.getUpdateMap()) { + // Tell GC to use argument oopmaps for some runtime stubs that need it. + // For C1, the runtime stub might not have oop maps, so set this flag + // outside of update_register_map. + map.setIncludeArgumentOops(cb.callerMustGCArguments()); + + if (cb.getOopMaps() != null) { + OopMapSet.updateRegisterMap(this, cb, map, true); + } + + // Since the prolog does the save and restore of EBP there is no oopmap + // for it so we must fill in its location as if there was an oopmap entry + // since if our caller was compiled code there could be live jvm state in it. + updateMapWithSavedLink(map, savedFPAddr); } - if (VM.getVM().isClientCompiler()) { - // Move this here for C1 and collecting oops in arguments (According to Rene) - map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread())); - } - - Address saved_fp = null; - if (VM.getVM().isClientCompiler()) { - saved_fp = getFP().getAddressAt(0); - } else if (VM.getVM().isServerCompiler() && - (VM.getVM().getInterpreter().contains(sender_pc) || - VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) { - // C2 prologue saves EBP in the usual place. - // however only use it if the sender had link infomration in it. - saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize()); - } - - return new X86Frame(sender_sp, saved_fp, sender_pc); + return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); } protected boolean hasSenderPD() { @@ -403,14 +450,6 @@ public class X86Frame extends Frame { public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } - public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) { - if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) { - throw new RuntimeException("Should not reach here"); - } - - return oopMapRegToLocation(reg, regMap); - } - public Address addressOfInterpreterFrameLocals() { return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java new file mode 100644 index 00000000000..5d73ac96a7b --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime.x86; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; + +public class X86RicochetFrame extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static void initialize(TypeDataBase db) { + Type type = db.lookupType("MethodHandles::RicochetFrame"); + + senderLinkField = type.getAddressField("_sender_link"); + savedArgsBaseField = type.getAddressField("_saved_args_base"); + exactSenderSPField = type.getAddressField("_exact_sender_sp"); + senderPCField = type.getAddressField("_sender_pc"); + } + + private static AddressField senderLinkField; + private static AddressField savedArgsBaseField; + private static AddressField exactSenderSPField; + private static AddressField senderPCField; + + static X86RicochetFrame fromFrame(X86Frame f) { + return new X86RicochetFrame(f.getFP().addOffsetTo(- senderLinkField.getOffset())); + } + + private X86RicochetFrame(Address addr) { + super(addr); + } + + public Address senderLink() { + return senderLinkField.getValue(addr); + } + public Address senderLinkAddress() { + return addr.addOffsetTo(senderLinkField.getOffset()); + } + public Address savedArgsBase() { + return savedArgsBaseField.getValue(addr); + } + public Address extendedSenderSP() { + return savedArgsBase(); + } + public Address exactSenderSP() { + return exactSenderSPField.getValue(addr); + } + public Address senderPC() { + return senderPCField.getValue(addr); + } +} diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp index c4ed0b706c0..bf85c33c731 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.hpp @@ -110,6 +110,7 @@ public: class RicochetFrame { friend class MethodHandles; + friend class VMStructs; private: intptr_t* _continuation; // what to do when control gets back here diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp index ef41cfd3224..38ee82acdd9 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp @@ -2404,7 +2404,7 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo assert(!is_call_site || assigned_reg >= nof_regs || !is_caller_save(assigned_reg), "interval is in a caller-save register at a call -> register will be overwritten"); VMReg name = vm_reg_for_interval(interval); - map->set_oop(name); + set_oop(map, name); // Spill optimization: when the stack value is guaranteed to be always correct, // then it must be added to the oop map even if the interval is currently in a register @@ -2415,7 +2415,7 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned"); assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice"); - map->set_oop(frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs)); + set_oop(map, frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs)); } } } @@ -2424,7 +2424,7 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo assert(info->stack() != NULL, "CodeEmitInfo must always have a stack"); int locks_count = info->stack()->total_locks_size(); for (int i = 0; i < locks_count; i++) { - map->set_oop(frame_map()->monitor_object_regname(i)); + set_oop(map, frame_map()->monitor_object_regname(i)); } return map; diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.hpp b/hotspot/src/share/vm/c1/c1_LinearScan.hpp index 51789ebd85d..133cc85014c 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp @@ -352,6 +352,13 @@ class LinearScan : public CompilationResourceObj { MonitorValue* location_for_monitor_index(int monitor_index); LocationValue* location_for_name(int name, Location::Type loc_type); + void set_oop(OopMap* map, VMReg name) { + if (map->legal_vm_reg_name(name)) { + map->set_oop(name); + } else { + bailout("illegal oopMap register name"); + } + } int append_scope_value_for_constant(LIR_Opr opr, GrowableArray* scope_values); int append_scope_value_for_operand(LIR_Opr opr, GrowableArray* scope_values); diff --git a/hotspot/src/share/vm/code/pcDesc.cpp b/hotspot/src/share/vm/code/pcDesc.cpp index d6c37516301..7ba25464f7d 100644 --- a/hotspot/src/share/vm/code/pcDesc.cpp +++ b/hotspot/src/share/vm/code/pcDesc.cpp @@ -30,11 +30,10 @@ #include "memory/resourceArea.hpp" PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset) { - assert(sizeof(PcDescFlags) <= 4, "occupies more than a word"); _pc_offset = pc_offset; _scope_decode_offset = scope_decode_offset; _obj_decode_offset = obj_decode_offset; - _flags.word = 0; + _flags = 0; } address PcDesc::real_pc(const nmethod* code) const { @@ -44,7 +43,7 @@ address PcDesc::real_pc(const nmethod* code) const { void PcDesc::print(nmethod* code) { #ifndef PRODUCT ResourceMark rm; - tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags.bits); + tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags); if (scope_decode_offset() == DebugInformationRecorder::serialized_null) { return; diff --git a/hotspot/src/share/vm/code/pcDesc.hpp b/hotspot/src/share/vm/code/pcDesc.hpp index 99a6e4c8ef5..83ec92149de 100644 --- a/hotspot/src/share/vm/code/pcDesc.hpp +++ b/hotspot/src/share/vm/code/pcDesc.hpp @@ -39,15 +39,17 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { int _scope_decode_offset; // offset for scope in nmethod int _obj_decode_offset; - union PcDescFlags { - int word; - struct { - unsigned int reexecute: 1; - unsigned int is_method_handle_invoke: 1; - unsigned int return_oop: 1; - } bits; - bool operator ==(const PcDescFlags& other) { return word == other.word; } - } _flags; + enum { + PCDESC_reexecute = 1 << 0, + PCDESC_is_method_handle_invoke = 1 << 1, + PCDESC_return_oop = 1 << 2 + }; + + int _flags; + + void set_flag(int mask, bool z) { + _flags = z ? (_flags | mask) : (_flags & ~mask); + } public: int pc_offset() const { return _pc_offset; } @@ -69,8 +71,8 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { }; // Flags - bool should_reexecute() const { return _flags.bits.reexecute; } - void set_should_reexecute(bool z) { _flags.bits.reexecute = z; } + bool should_reexecute() const { return (_flags & PCDESC_reexecute) != 0; } + void set_should_reexecute(bool z) { set_flag(PCDESC_reexecute, z); } // Does pd refer to the same information as pd? bool is_same_info(const PcDesc* pd) { @@ -79,11 +81,11 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { _flags == pd->_flags; } - bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } - void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } + bool is_method_handle_invoke() const { return (_flags & PCDESC_is_method_handle_invoke) != 0; } + void set_is_method_handle_invoke(bool z) { set_flag(PCDESC_is_method_handle_invoke, z); } - bool return_oop() const { return _flags.bits.return_oop; } - void set_return_oop(bool z) { _flags.bits.return_oop = z; } + bool return_oop() const { return (_flags & PCDESC_return_oop) != 0; } + void set_return_oop(bool z) { set_flag(PCDESC_return_oop, z); } // Returns the real pc address real_pc(const nmethod* code) const; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index d42ade40a27..145dacd4b5a 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -45,6 +45,8 @@ class vframeStream; // information, etc. class SharedRuntime: AllStatic { + friend class VMStructs; + private: static methodHandle resolve_sub_helper(JavaThread *thread, bool is_virtual, diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 18465a30782..4553ea62f92 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -2859,6 +2859,44 @@ void JavaThread::trace_frames() { } } +class PrintAndVerifyOopClosure: public OopClosure { + protected: + template inline void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop(p); + if (obj == NULL) return; + tty->print(INTPTR_FORMAT ": ", p); + if (obj->is_oop_or_null()) { + if (obj->is_objArray()) { + tty->print_cr("valid objArray: " INTPTR_FORMAT, (oopDesc*) obj); + } else { + obj->print(); + } + } else { + tty->print_cr("invalid oop: " INTPTR_FORMAT, (oopDesc*) obj); + } + tty->cr(); + } + public: + virtual void do_oop(oop* p) { do_oop_work(p); } + virtual void do_oop(narrowOop* p) { do_oop_work(p); } +}; + + +static void oops_print(frame* f, const RegisterMap *map) { + PrintAndVerifyOopClosure print; + f->print_value(); + f->oops_do(&print, NULL, (RegisterMap*)map); +} + +// Print our all the locations that contain oops and whether they are +// valid or not. This useful when trying to find the oldest frame +// where an oop has gone bad since the frame walk is from youngest to +// oldest. +void JavaThread::trace_oops() { + tty->print_cr("[Trace oops]"); + frames_do(oops_print); +} + #ifdef ASSERT // Print or validate the layout of stack frames diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 532ca1a5576..4d5478bdcd1 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1375,6 +1375,7 @@ public: void trace_stack() PRODUCT_RETURN; void trace_stack_from(vframe* start_vf) PRODUCT_RETURN; void trace_frames() PRODUCT_RETURN; + void trace_oops() PRODUCT_RETURN; // Print an annotated view of the stack frames void print_frame_layout(int depth = 0, bool validate_only = false) NOT_DEBUG_RETURN; diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index d1cb2cc7dbd..540649784c6 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -652,6 +652,7 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(Properties_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), klassOop) \ static_field(SystemDictionary, _box_klasses[0], klassOop) \ static_field(SystemDictionary, _java_system_loader, oop) \ \ @@ -757,12 +758,19 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(PcDesc, _pc_offset, int) \ nonstatic_field(PcDesc, _scope_decode_offset, int) \ nonstatic_field(PcDesc, _obj_decode_offset, int) \ - nonstatic_field(PcDesc, _flags, PcDesc::PcDescFlags) \ + nonstatic_field(PcDesc, _flags, int) \ \ /***************************************************/ \ /* CodeBlobs (NOTE: incomplete, but only a little) */ \ /***************************************************/ \ \ + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_pc, address)) \ + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _exact_sender_sp, intptr_t*)) \ + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_link, intptr_t*)) \ + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _saved_args_base, intptr_t*)) \ + \ + static_field(SharedRuntime, _ricochet_blob, RicochetBlob*) \ + \ nonstatic_field(CodeBlob, _name, const char*) \ nonstatic_field(CodeBlob, _size, int) \ nonstatic_field(CodeBlob, _header_size, int) \ @@ -774,6 +782,8 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(CodeBlob, _frame_size, int) \ nonstatic_field(CodeBlob, _oop_maps, OopMapSet*) \ \ + nonstatic_field(RuntimeStub, _caller_must_gc_arguments, bool) \ + \ /**************************************************/ \ /* NMethods (NOTE: incomplete, but only a little) */ \ /**************************************************/ \ @@ -786,6 +796,7 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(nmethod, _state, unsigned char) \ nonstatic_field(nmethod, _exception_offset, int) \ nonstatic_field(nmethod, _deoptimize_offset, int) \ + nonstatic_field(nmethod, _deoptimize_mh_offset, int) \ nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _stub_offset, int) \ nonstatic_field(nmethod, _consts_offset, int) \ @@ -804,6 +815,9 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _marked_for_deoptimization, bool) \ \ + nonstatic_field(RicochetBlob, _bounce_offset, int) \ + nonstatic_field(RicochetBlob, _exception_offset, int) \ + \ /********************************/ \ /* JavaCalls (NOTE: incomplete) */ \ /********************************/ \ @@ -1310,24 +1324,27 @@ static inline uint64_t cast_uint64_t(size_t x) /* CodeBlob hierarchy (needed for run-time type information) */ \ /*************************************************************/ \ \ + declare_toplevel_type(SharedRuntime) \ + X86_ONLY(declare_toplevel_type(MethodHandles::RicochetFrame)) \ + \ declare_toplevel_type(CodeBlob) \ - declare_type(BufferBlob, CodeBlob) \ - declare_type(AdapterBlob, BufferBlob) \ - declare_type(nmethod, CodeBlob) \ - declare_type(RuntimeStub, CodeBlob) \ - declare_type(SingletonBlob, CodeBlob) \ - declare_type(SafepointBlob, SingletonBlob) \ - declare_type(DeoptimizationBlob, SingletonBlob) \ - declare_type(RicochetBlob, SingletonBlob) \ - declare_c2_type(ExceptionBlob, SingletonBlob) \ - declare_c2_type(UncommonTrapBlob, CodeBlob) \ + declare_type(BufferBlob, CodeBlob) \ + declare_type(AdapterBlob, BufferBlob) \ + declare_type(MethodHandlesAdapterBlob, BufferBlob) \ + declare_type(nmethod, CodeBlob) \ + declare_type(RuntimeStub, CodeBlob) \ + declare_type(SingletonBlob, CodeBlob) \ + declare_type(SafepointBlob, SingletonBlob) \ + declare_type(DeoptimizationBlob, SingletonBlob) \ + declare_type(RicochetBlob, SingletonBlob) \ + declare_c2_type(ExceptionBlob, SingletonBlob) \ + declare_c2_type(UncommonTrapBlob, CodeBlob) \ \ /***************************************/ \ /* PcDesc and other compiled code info */ \ /***************************************/ \ \ declare_toplevel_type(PcDesc) \ - declare_integer_type(PcDesc::PcDescFlags) \ \ /************************/ \ /* OopMap and OopMapSet */ \ @@ -1796,6 +1813,21 @@ static inline uint64_t cast_uint64_t(size_t x) \ declare_constant(ObjectSynchronizer::_BLOCKSIZE) \ \ + /**********************/ \ + /* PcDesc */ \ + /**********************/ \ + \ + declare_constant(PcDesc::PCDESC_reexecute) \ + declare_constant(PcDesc::PCDESC_is_method_handle_invoke) \ + declare_constant(PcDesc::PCDESC_return_oop) \ + \ + /**********************/ \ + /* frame */ \ + /**********************/ \ + \ + X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)) \ + declare_constant(frame::pc_return_offset) \ + \ /********************************/ \ /* Calling convention constants */ \ /********************************/ \ From a9cd50a1c8986e230455e56c79d2b48e1969f593 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 6 Sep 2011 21:03:51 -0700 Subject: [PATCH 028/214] 7087583: Hotspot fails to allocate heap with mmap(MAP_HUGETLB) Try using small pages when transparent huge pages allocation fails Reviewed-by: ysr --- hotspot/src/os/linux/vm/os_linux.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3b0996a9875..f1e6f1597cf 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2531,10 +2531,14 @@ bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, } return true; } - return false; + // Fall through and try to use small pages } - return commit_memory(addr, size, exec); + if (commit_memory(addr, size, exec)) { + realign_memory(addr, size, alignment_hint); + return true; + } + return false; } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { From 48ecf5dfe42a6fde7a772ab3db5aa144d4e1c13d Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 7 Sep 2011 09:35:52 +0200 Subject: [PATCH 029/214] 7086394: c2/arm: enable UseFPUForSpilling ARM has instructions to move data directly between the fpu and integer registers. Reviewed-by: kvn, never --- hotspot/src/share/vm/opto/matcher.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 4b16bbad286..3244a944bbd 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -501,6 +501,12 @@ void Matcher::init_first_stack_mask() { idealreg2spillmask[Op_RegP]->OR(*idealreg2regmask[Op_RegD]); #else idealreg2spillmask[Op_RegP]->OR(*idealreg2regmask[Op_RegF]); +#ifdef ARM + // ARM has support for moving 64bit values between a pair of + // integer registers and a double register + idealreg2spillmask[Op_RegL]->OR(*idealreg2regmask[Op_RegD]); + idealreg2spillmask[Op_RegD]->OR(*idealreg2regmask[Op_RegL]); +#endif #endif } From 90844ca5dc7411eb7de1ab04e5f9eda5cbe95f53 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 7 Sep 2011 14:15:07 +0200 Subject: [PATCH 030/214] 7085012: ARM: com/sun/jdi/PopSynchronousTest.java still fails InterpreterRuntime::popframe_move_outgoing_args() is required for the ARM interpreter. Reviewed-by: kvn, twisti --- hotspot/src/share/vm/interpreter/interpreterRuntime.cpp | 2 +- hotspot/src/share/vm/interpreter/interpreterRuntime.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 87bbcd3932a..dd8386e859d 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1244,7 +1244,7 @@ IRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* thread, meth // preparing the same method will be sure to see non-null entry & mirror. IRT_END -#if defined(IA32) || defined(AMD64) +#if defined(IA32) || defined(AMD64) || defined(ARM) IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address)) if (src_address == dest_address) { return; diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 961abd5a25a..d1d14b4688f 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -141,8 +141,8 @@ class InterpreterRuntime: AllStatic { methodOopDesc* method, intptr_t* from, intptr_t* to); -#if defined(IA32) || defined(AMD64) - // Popframe support (only needed on x86 and AMD64) +#if defined(IA32) || defined(AMD64) || defined(ARM) + // Popframe support (only needed on x86, AMD64 and ARM) static void popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address); #endif From 24eb07061e303278b52b44fa66ccaaab4dd90b64 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 7 Sep 2011 12:21:23 -0400 Subject: [PATCH 031/214] 7050392: G1: Introduce flag to generate a log of the G1 ergonomic decisions It introduces ergonomic decision logging in G1 for the following heuristics: heap sizing, collection set construction, concurrent cycle initiation, and partially-young GC start/end. The code has a bit of refactoring in a few places to make the decision logging possible. It also replaces alternative ad-hoc logging that we have under different parameters and switches (G1_DEBUG, G1PolicyVerbose). Reviewed-by: johnc, ysr --- .../g1/collectionSetChooser.cpp | 21 +- .../gc_implementation/g1/concurrentMark.cpp | 16 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 143 ++++---- .../g1/g1CollectorPolicy.cpp | 311 ++++++++++++------ .../g1/g1CollectorPolicy.hpp | 9 +- .../vm/gc_implementation/g1/g1ErgoVerbose.cpp | 65 ++++ .../vm/gc_implementation/g1/g1ErgoVerbose.hpp | 197 +++++++++++ .../vm/gc_implementation/g1/g1MMUTracker.cpp | 6 +- .../gc_implementation/g1/vm_operations_g1.cpp | 2 +- 9 files changed, 563 insertions(+), 207 deletions(-) create mode 100644 hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.cpp create mode 100644 hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp diff --git a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp index 7e18ec6376c..73d578d48bf 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #include "gc_implementation/g1/collectionSetChooser.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1ErgoVerbose.hpp" #include "memory/space.inline.hpp" CSetChooserCache::CSetChooserCache() { @@ -358,6 +359,9 @@ CollectionSetChooser::getNextMarkedRegion(double time_remaining, if (_cache.is_empty()) { assert(_curMarkedIndex == _numMarkedRegions, "if cache is empty, list should also be empty"); + ergo_verbose0(ErgoCSetConstruction, + "stop adding old regions to CSet", + ergo_format_reason("cache is empty")); return NULL; } @@ -368,10 +372,23 @@ CollectionSetChooser::getNextMarkedRegion(double time_remaining, if (g1p->adaptive_young_list_length()) { if (time_remaining - predicted_time < 0.0) { g1h->check_if_region_is_too_expensive(predicted_time); + ergo_verbose2(ErgoCSetConstruction, + "stop adding old regions to CSet", + ergo_format_reason("predicted old region time higher than remaining time") + ergo_format_ms("predicted old region time") + ergo_format_ms("remaining time"), + predicted_time, time_remaining); return NULL; } } else { - if (predicted_time > 2.0 * avg_prediction) { + double threshold = 2.0 * avg_prediction; + if (predicted_time > threshold) { + ergo_verbose2(ErgoCSetConstruction, + "stop adding old regions to CSet", + ergo_format_reason("predicted old region time higher than threshold") + ergo_format_ms("predicted old region time") + ergo_format_ms("threshold"), + predicted_time, threshold); return NULL; } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 1c8673f524b..3679002b92f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -28,6 +28,7 @@ #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1ErgoVerbose.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" @@ -1727,18 +1728,21 @@ void ConcurrentMark::cleanup() { size_t known_garbage_bytes = g1_par_count_task.used_bytes() - g1_par_count_task.live_bytes(); -#if 0 - gclog_or_tty->print_cr("used %1.2lf, live %1.2lf, garbage %1.2lf", - (double) g1_par_count_task.used_bytes() / (double) (1024 * 1024), - (double) g1_par_count_task.live_bytes() / (double) (1024 * 1024), - (double) known_garbage_bytes / (double) (1024 * 1024)); -#endif // 0 g1p->set_known_garbage_bytes(known_garbage_bytes); size_t start_used_bytes = g1h->used(); _at_least_one_mark_complete = true; g1h->set_marking_complete(); + ergo_verbose4(ErgoConcCycles, + "finish cleanup", + ergo_format_byte("occupancy") + ergo_format_byte("capacity") + ergo_format_byte_perc("known garbage"), + start_used_bytes, g1h->capacity(), + known_garbage_bytes, + ((double) known_garbage_bytes / (double) g1h->capacity()) * 100.0); + double count_end = os::elapsedTime(); double this_final_counting_time = (count_end - start); if (G1PrintParCleanupStats) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 52b85d011bd..58af87240cd 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -31,6 +31,7 @@ #include "gc_implementation/g1/g1AllocRegion.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1ErgoVerbose.hpp" #include "gc_implementation/g1/g1MarkSweep.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" @@ -577,6 +578,11 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool do_expand) { res = new_region_try_secondary_free_list(); } if (res == NULL && do_expand) { + ergo_verbose1(ErgoHeapSizing, + "attempt heap expansion", + ergo_format_reason("region allocation request failed") + ergo_format_byte("allocation request"), + word_size * HeapWordSize); if (expand(word_size * HeapWordSize)) { // Even though the heap was expanded, it might not have reached // the desired size. So, we cannot assume that the allocation @@ -790,6 +796,11 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) { // room available. assert(num_regions > fs, "earlier allocation should have succeeded"); + ergo_verbose1(ErgoHeapSizing, + "attempt heap expansion", + ergo_format_reason("humongous allocation request failed") + ergo_format_byte("allocation request"), + word_size * HeapWordSize); if (expand((num_regions - fs) * HeapRegion::GrainBytes)) { // Even though the heap was expanded, it might not have // reached the desired size. So, we cannot assume that the @@ -906,6 +917,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size, if (GC_locker::is_active_and_needs_gc()) { if (g1_policy()->can_expand_young_list()) { + // No need for an ergo verbose message here, + // can_expand_young_list() does this when it returns true. result = _mutator_alloc_region.attempt_allocation_force(word_size, false /* bot_updates */); if (result != NULL) { @@ -1477,63 +1490,34 @@ resize_if_necessary_after_full_collection(size_t word_size) { // we'll try to make the capacity smaller than it, not greater). maximum_desired_capacity = MAX2(maximum_desired_capacity, min_heap_size); - if (PrintGC && Verbose) { - const double free_percentage = - (double) free_after_gc / (double) capacity_after_gc; - gclog_or_tty->print_cr("Computing new size after full GC "); - gclog_or_tty->print_cr(" " - " minimum_free_percentage: %6.2f", - minimum_free_percentage); - gclog_or_tty->print_cr(" " - " maximum_free_percentage: %6.2f", - maximum_free_percentage); - gclog_or_tty->print_cr(" " - " capacity: %6.1fK" - " minimum_desired_capacity: %6.1fK" - " maximum_desired_capacity: %6.1fK", - (double) capacity_after_gc / (double) K, - (double) minimum_desired_capacity / (double) K, - (double) maximum_desired_capacity / (double) K); - gclog_or_tty->print_cr(" " - " free_after_gc: %6.1fK" - " used_after_gc: %6.1fK", - (double) free_after_gc / (double) K, - (double) used_after_gc / (double) K); - gclog_or_tty->print_cr(" " - " free_percentage: %6.2f", - free_percentage); - } if (capacity_after_gc < minimum_desired_capacity) { // Don't expand unless it's significant size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; - if (expand(expand_bytes)) { - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " expanding:" - " max_heap_size: %6.1fK" - " minimum_desired_capacity: %6.1fK" - " expand_bytes: %6.1fK", - (double) max_heap_size / (double) K, - (double) minimum_desired_capacity / (double) K, - (double) expand_bytes / (double) K); - } - } + ergo_verbose4(ErgoHeapSizing, + "attempt heap expansion", + ergo_format_reason("capacity lower than " + "min desired capacity after Full GC") + ergo_format_byte("capacity") + ergo_format_byte("occupancy") + ergo_format_byte_perc("min desired capacity"), + capacity_after_gc, used_after_gc, + minimum_desired_capacity, (double) MinHeapFreeRatio); + expand(expand_bytes); // No expansion, now see if we want to shrink } else if (capacity_after_gc > maximum_desired_capacity) { // Capacity too large, compute shrinking size size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity; + ergo_verbose4(ErgoHeapSizing, + "attempt heap shrinking", + ergo_format_reason("capacity higher than " + "max desired capacity after Full GC") + ergo_format_byte("capacity") + ergo_format_byte("occupancy") + ergo_format_byte_perc("max desired capacity"), + capacity_after_gc, used_after_gc, + maximum_desired_capacity, (double) MaxHeapFreeRatio); shrink(shrink_bytes); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " shrinking:" - " min_heap_size: %6.1fK" - " maximum_desired_capacity: %6.1fK" - " shrink_bytes: %6.1fK", - (double) min_heap_size / (double) K, - (double) maximum_desired_capacity / (double) K, - (double) shrink_bytes / (double) K); - } } } @@ -1619,6 +1603,11 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) { verify_region_sets_optional(); size_t expand_bytes = MAX2(word_size * HeapWordSize, MinHeapDeltaBytes); + ergo_verbose1(ErgoHeapSizing, + "attempt heap expansion", + ergo_format_reason("allocation request failed") + ergo_format_byte("allocation request"), + word_size * HeapWordSize); if (expand(expand_bytes)) { _hrs.verify_optional(); verify_region_sets_optional(); @@ -1646,11 +1635,11 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); aligned_expand_bytes = align_size_up(aligned_expand_bytes, HeapRegion::GrainBytes); - - if (Verbose && PrintGC) { - gclog_or_tty->print("Expanding garbage-first heap from %ldK by %ldK", - old_mem_size/K, aligned_expand_bytes/K); - } + ergo_verbose2(ErgoHeapSizing, + "expand the heap", + ergo_format_byte("requested expansion amount") + ergo_format_byte("attempted expansion amount"), + expand_bytes, aligned_expand_bytes); // First commit the memory. HeapWord* old_end = (HeapWord*) _g1_storage.high(); @@ -1694,6 +1683,9 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { assert(curr == mr.end(), "post-condition"); } } else { + ergo_verbose0(ErgoHeapSizing, + "did not expand the heap", + ergo_format_reason("heap expansion operation failed")); // The expansion of the virtual storage space was unsuccessful. // Let's see if it was because we ran out of swap. if (G1ExitOnExpansionFailure && @@ -1702,13 +1694,6 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { vm_exit_out_of_memory(aligned_expand_bytes, "G1 heap expansion"); } } - - if (Verbose && PrintGC) { - size_t new_mem_size = _g1_storage.committed_size(); - gclog_or_tty->print_cr("...%s, expanded to %ldK", - (successful ? "Successful" : "Failed"), - new_mem_size/K); - } return successful; } @@ -1722,6 +1707,13 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { MemRegion mr = _hrs.shrink_by(aligned_shrink_bytes, &num_regions_deleted); HeapWord* old_end = (HeapWord*) _g1_storage.high(); assert(mr.end() == old_end, "post-condition"); + + ergo_verbose3(ErgoHeapSizing, + "shrink the heap", + ergo_format_byte("requested shrinking amount") + ergo_format_byte("aligned shrinking amount") + ergo_format_byte("attempted shrinking amount"), + shrink_bytes, aligned_shrink_bytes, mr.byte_size()); if (mr.byte_size() > 0) { if (_hr_printer.is_active()) { HeapWord* curr = mr.end(); @@ -1740,13 +1732,10 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { _expansion_regions += num_regions_deleted; update_committed_space(old_end, new_end); HeapRegionRemSet::shrink_heap(n_regions()); - - if (Verbose && PrintGC) { - size_t new_mem_size = _g1_storage.committed_size(); - gclog_or_tty->print_cr("Shrinking garbage-first heap from %ldK by %ldK to %ldK", - old_mem_size/K, aligned_shrink_bytes/K, - new_mem_size/K); - } + } else { + ergo_verbose0(ErgoHeapSizing, + "did not shrink the heap", + ergo_format_reason("heap shrinking operation failed")); } } @@ -3579,6 +3568,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { size_t expand_bytes = g1_policy()->expansion_amount(); if (expand_bytes > 0) { size_t bytes_before = capacity(); + // No need for an ergo verbose message here, + // expansion_amount() does this when it returns a value > 0. if (!expand(expand_bytes)) { // We failed to expand the heap so let's verify that // committed/uncommitted amount match the backing store @@ -3732,13 +3723,6 @@ public: bool do_object_b(oop p) { // It is reachable if it is outside the collection set, or is inside // and forwarded. - -#ifdef G1_DEBUG - gclog_or_tty->print_cr("is alive "PTR_FORMAT" in CS %d forwarded %d overall %d", - (void*) p, _g1->obj_in_cs(p), p->is_forwarded(), - !_g1->obj_in_cs(p) || p->is_forwarded()); -#endif // G1_DEBUG - return !_g1->obj_in_cs(p) || p->is_forwarded(); } }; @@ -3750,20 +3734,9 @@ public: void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } void do_oop( oop* p) { oop obj = *p; -#ifdef G1_DEBUG - if (PrintGC && Verbose) { - gclog_or_tty->print_cr("keep alive *"PTR_FORMAT" = "PTR_FORMAT" "PTR_FORMAT, - p, (void*) obj, (void*) *p); - } -#endif // G1_DEBUG - if (_g1->obj_in_cs(obj)) { assert( obj->is_forwarded(), "invariant" ); *p = obj->forwardee(); -#ifdef G1_DEBUG - gclog_or_tty->print_cr(" in CSet: moved "PTR_FORMAT" -> "PTR_FORMAT, - (void*) obj, (void*) *p); -#endif // G1_DEBUG } } }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 557476518ce..0ebd3e821ec 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -28,6 +28,7 @@ #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1ErgoVerbose.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" #include "runtime/arguments.hpp" @@ -271,15 +272,26 @@ G1CollectorPolicy::G1CollectorPolicy() : _recorded_survivor_tail(NULL), _survivors_age_table(true), - _gc_overhead_perc(0.0) + _gc_overhead_perc(0.0) { -{ // Set up the region size and associated fields. Given that the // policy is created before the heap, we have to set this up here, // so it's done as soon as possible. HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); HeapRegionRemSet::setup_remset_size(); + G1ErgoVerbose::initialize(); + if (PrintAdaptiveSizePolicy) { + // Currently, we only use a single switch for all the heuristics. + G1ErgoVerbose::set_enabled(true); + // Given that we don't currently have a verboseness level + // parameter, we'll hardcode this to high. This can be easily + // changed in the future. + G1ErgoVerbose::set_level(ErgoHigh); + } else { + G1ErgoVerbose::set_enabled(false); + } + // Verify PLAB sizes const uint region_size = HeapRegion::GrainWords; if (YoungPLABSize > region_size || OldPLABSize > region_size) { @@ -959,11 +971,9 @@ void G1CollectorPolicy:: record_concurrent_mark_cleanup_end_work1(size_t freed_bytes, size_t max_live_bytes) { - if (_n_marks < 2) _n_marks++; - if (G1PolicyVerbose > 0) - gclog_or_tty->print_cr("At end of marking, max_live is " SIZE_FORMAT " MB " - " (of " SIZE_FORMAT " MB heap).", - max_live_bytes/M, _g1->capacity()/M); + if (_n_marks < 2) { + _n_marks++; + } } // The important thing about this is that it includes "os::elapsedTime". @@ -977,14 +987,6 @@ void G1CollectorPolicy::record_concurrent_mark_cleanup_end_work2() { _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_time_sec, true); _num_markings++; - - // We did a marking, so reset the "since_last_mark" variables. - double considerConcMarkCost = 1.0; - // If there are available processors, concurrent activity is free... - if (Threads::number_of_non_daemon_threads() * 2 < - os::active_processor_count()) { - considerConcMarkCost = 0.0; - } _n_pauses_at_mark_end = _n_pauses; _n_marks_since_last_pause++; } @@ -1148,20 +1150,37 @@ void G1CollectorPolicy::record_collection_pause_end() { if (last_pause_included_initial_mark) record_concurrent_mark_init_end(0.0); - size_t min_used_targ = + size_t marking_initiating_used_threshold = (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; - if (!_g1->mark_in_progress() && !_last_full_young_gc) { assert(!last_pause_included_initial_mark, "invariant"); - if (cur_used_bytes > min_used_targ && - cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { + if (cur_used_bytes > marking_initiating_used_threshold) { + if (cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { assert(!during_initial_mark_pause(), "we should not see this here"); + ergo_verbose3(ErgoConcCycles, + "request concurrent cycle initiation", + ergo_format_reason("occupancy higher than threshold") + ergo_format_byte("occupancy") + ergo_format_byte_perc("threshold"), + cur_used_bytes, + marking_initiating_used_threshold, + (double) InitiatingHeapOccupancyPercent); + // Note: this might have already been set, if during the last // pause we decided to start a cycle but at the beginning of // this pause we decided to postpone it. That's OK. set_initiate_conc_mark_if_possible(); + } else { + ergo_verbose2(ErgoConcCycles, + "do not request concurrent cycle initiation", + ergo_format_reason("occupancy lower than previous occupancy") + ergo_format_byte("occupancy") + ergo_format_byte("previous occupancy"), + cur_used_bytes, + _prev_collection_pause_used_at_end_bytes); + } } } @@ -1437,16 +1456,45 @@ void G1CollectorPolicy::record_collection_pause_end() { } if (_last_full_young_gc) { + ergo_verbose2(ErgoPartiallyYoungGCs, + "start partially-young GCs", + ergo_format_byte_perc("known garbage"), + _known_garbage_bytes, _known_garbage_ratio * 100.0); set_full_young_gcs(false); _last_full_young_gc = false; } if ( !_last_young_gc_full ) { - if ( _should_revert_to_full_young_gcs || - _known_garbage_ratio < 0.05 || - (adaptive_young_list_length() && - (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) ) { - set_full_young_gcs(true); + if (_should_revert_to_full_young_gcs) { + ergo_verbose2(ErgoPartiallyYoungGCs, + "end partially-young GCs", + ergo_format_reason("partially-young GCs end requested") + ergo_format_byte_perc("known garbage"), + _known_garbage_bytes, _known_garbage_ratio * 100.0); + set_full_young_gcs(true); + } else if (_known_garbage_ratio < 0.05) { + ergo_verbose3(ErgoPartiallyYoungGCs, + "end partially-young GCs", + ergo_format_reason("known garbage percent lower than threshold") + ergo_format_byte_perc("known garbage") + ergo_format_perc("threshold"), + _known_garbage_bytes, _known_garbage_ratio * 100.0, + 0.05 * 100.0); + set_full_young_gcs(true); + } else if (adaptive_young_list_length() && + (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) { + ergo_verbose5(ErgoPartiallyYoungGCs, + "end partially-young GCs", + ergo_format_reason("current GC efficiency lower than " + "predicted fully-young GC efficiency") + ergo_format_double("GC efficiency factor") + ergo_format_double("current GC efficiency") + ergo_format_double("predicted fully-young GC efficiency") + ergo_format_byte_perc("known garbage"), + get_gc_eff_factor(), cur_efficiency, + predict_young_gc_eff(), + _known_garbage_bytes, _known_garbage_ratio * 100.0); + set_full_young_gcs(true); } } _should_revert_to_full_young_gcs = false; @@ -1877,6 +1925,12 @@ void G1CollectorPolicy::check_if_region_is_too_expensive(double // I don't think we need to do this when in young GC mode since // marking will be initiated next time we hit the soft limit anyway... if (predicted_time_ms > _expensive_region_limit_ms) { + ergo_verbose2(ErgoPartiallyYoungGCs, + "request partially-young GCs end", + ergo_format_reason("predicted region time higher than threshold") + ergo_format_ms("predicted region time") + ergo_format_ms("threshold"), + predicted_time_ms, _expensive_region_limit_ms); // no point in doing another partial one _should_revert_to_full_young_gcs = true; } @@ -1986,7 +2040,9 @@ G1CollectorPolicy::conservative_avg_survival_fraction_work(double avg, } size_t G1CollectorPolicy::expansion_amount() { - if ((recent_avg_pause_time_ratio() * 100.0) > _gc_overhead_perc) { + double recent_gc_overhead = recent_avg_pause_time_ratio() * 100.0; + double threshold = _gc_overhead_perc; + if (recent_gc_overhead > threshold) { // We will double the existing space, or take // G1ExpandByPercentOfAvailable % of the available expansion // space, whichever is smaller, bounded below by a minimum @@ -2001,20 +2057,19 @@ size_t G1CollectorPolicy::expansion_amount() { expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes); expand_bytes = MAX2(expand_bytes, min_expand_bytes); expand_bytes = MIN2(expand_bytes, uncommitted_bytes); - if (G1PolicyVerbose > 1) { - gclog_or_tty->print("Decided to expand: ratio = %5.2f, " - "committed = %d%s, uncommited = %d%s, via pct = %d%s.\n" - " Answer = %d.\n", - recent_avg_pause_time_ratio(), - byte_size_in_proper_unit(committed_bytes), - proper_unit_for_byte_size(committed_bytes), - byte_size_in_proper_unit(uncommitted_bytes), - proper_unit_for_byte_size(uncommitted_bytes), - byte_size_in_proper_unit(expand_bytes_via_pct), - proper_unit_for_byte_size(expand_bytes_via_pct), - byte_size_in_proper_unit(expand_bytes), - proper_unit_for_byte_size(expand_bytes)); - } + + ergo_verbose5(ErgoHeapSizing, + "attempt heap expansion", + ergo_format_reason("recent GC overhead higher than " + "threshold after GC") + ergo_format_perc("recent GC overhead") + ergo_format_perc("threshold") + ergo_format_byte("uncommitted") + ergo_format_byte_perc("calculated expansion amount"), + recent_gc_overhead, threshold, + uncommitted_bytes, + expand_bytes_via_pct, (double) G1ExpandByPercentOfAvailable); + return expand_bytes; } else { return 0; @@ -2237,8 +2292,7 @@ void G1CollectorPolicy::print_yg_surv_rate_info() const { #endif // PRODUCT } -void -G1CollectorPolicy::update_region_num(bool young) { +void G1CollectorPolicy::update_region_num(bool young) { if (young) { ++_region_num_young; } else { @@ -2315,13 +2369,23 @@ bool G1CollectorPolicy_BestRegionsFirst::assertMarkedBytesDataOK() { } #endif -bool -G1CollectorPolicy::force_initial_mark_if_outside_cycle() { +bool G1CollectorPolicy::force_initial_mark_if_outside_cycle( + GCCause::Cause gc_cause) { bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); if (!during_cycle) { + ergo_verbose1(ErgoConcCycles, + "request concurrent cycle initiation", + ergo_format_reason("requested by GC cause") + ergo_format_str("GC cause"), + GCCause::to_string(gc_cause)); set_initiate_conc_mark_if_possible(); return true; } else { + ergo_verbose1(ErgoConcCycles, + "do not request concurrent cycle initiation", + ergo_format_reason("concurrent cycle already in progress") + ergo_format_str("GC cause"), + GCCause::to_string(gc_cause)); return false; } } @@ -2353,6 +2417,10 @@ G1CollectorPolicy::decide_on_conc_mark_initiation() { // And we can now clear initiate_conc_mark_if_possible() as // we've already acted on it. clear_initiate_conc_mark_if_possible(); + + ergo_verbose0(ErgoConcCycles, + "initiate concurrent cycle", + ergo_format_reason("concurrent cycle initiation requested")); } else { // The concurrent marking thread is still finishing up the // previous cycle. If we start one right now the two cycles @@ -2366,6 +2434,9 @@ G1CollectorPolicy::decide_on_conc_mark_initiation() { // and, if it's in a yield point, it's waiting for us to // finish. So, at this point we will not start a cycle and we'll // let the concurrent marking thread complete the last one. + ergo_verbose0(ErgoConcCycles, + "do not initiate concurrent cycle", + ergo_format_reason("concurrent cycle already in progress")); } } } @@ -2756,6 +2827,8 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( // Set this here - in case we're not doing young collections. double non_young_start_time_sec = os::elapsedTime(); + YoungList* young_list = _g1->young_list(); + start_recording_regions(); guarantee(target_pause_time_ms > 0.0, @@ -2768,61 +2841,62 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( double time_remaining_ms = target_pause_time_ms - base_time_ms; + ergo_verbose3(ErgoCSetConstruction | ErgoHigh, + "start choosing CSet", + ergo_format_ms("predicted base time") + ergo_format_ms("remaining time") + ergo_format_ms("target pause time"), + base_time_ms, time_remaining_ms, target_pause_time_ms); + // the 10% and 50% values are arbitrary... - if (time_remaining_ms < 0.10 * target_pause_time_ms) { + double threshold = 0.10 * target_pause_time_ms; + if (time_remaining_ms < threshold) { + double prev_time_remaining_ms = time_remaining_ms; time_remaining_ms = 0.50 * target_pause_time_ms; _within_target = false; + ergo_verbose3(ErgoCSetConstruction, + "adjust remaining time", + ergo_format_reason("remaining time lower than threshold") + ergo_format_ms("remaining time") + ergo_format_ms("threshold") + ergo_format_ms("adjusted remaining time"), + prev_time_remaining_ms, threshold, time_remaining_ms); } else { _within_target = true; } - // We figure out the number of bytes available for future to-space. - // For new regions without marking information, we must assume the - // worst-case of complete survival. If we have marking information for a - // region, we can bound the amount of live data. We can add a number of - // such regions, as long as the sum of the live data bounds does not - // exceed the available evacuation space. - size_t max_live_bytes = _g1->free_regions() * HeapRegion::GrainBytes; - - size_t expansion_bytes = - _g1->expansion_regions() * HeapRegion::GrainBytes; - - _collection_set_bytes_used_before = 0; - _collection_set_size = 0; - - // Adjust for expansion and slop. - max_live_bytes = max_live_bytes + expansion_bytes; + size_t expansion_bytes = _g1->expansion_regions() * HeapRegion::GrainBytes; HeapRegion* hr; double young_start_time_sec = os::elapsedTime(); - if (G1PolicyVerbose > 0) { - gclog_or_tty->print_cr("Adding %d young regions to the CSet", - _g1->young_list()->length()); - } - + _collection_set_bytes_used_before = 0; + _collection_set_size = 0; _young_cset_length = 0; _last_young_gc_full = full_young_gcs() ? true : false; - if (_last_young_gc_full) + if (_last_young_gc_full) { ++_full_young_pause_num; - else + } else { ++_partial_young_pause_num; + } // The young list is laid with the survivor regions from the previous // pause are appended to the RHS of the young list, i.e. // [Newly Young Regions ++ Survivors from last pause]. - hr = _g1->young_list()->first_survivor_region(); + size_t survivor_region_num = young_list->survivor_length(); + size_t eden_region_num = young_list->length() - survivor_region_num; + size_t old_region_num = 0; + hr = young_list->first_survivor_region(); while (hr != NULL) { assert(hr->is_survivor(), "badly formed young list"); hr->set_young(); hr = hr->get_next_young_region(); } - // Clear the fields that point to the survivor list - they are - // all young now. - _g1->young_list()->clear_survivors(); + // Clear the fields that point to the survivor list - they are all young now. + young_list->clear_survivors(); if (_g1->mark_in_progress()) _g1->concurrent_mark()->register_collection_set_finger(_inc_cset_max_finger); @@ -2831,14 +2905,17 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( _collection_set = _inc_cset_head; _collection_set_size = _inc_cset_size; _collection_set_bytes_used_before = _inc_cset_bytes_used_before; - - // For young regions in the collection set, we assume the worst - // case of complete survival - max_live_bytes -= _inc_cset_size * HeapRegion::GrainBytes; - time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms; predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms; + ergo_verbose3(ErgoCSetConstruction | ErgoHigh, + "add young regions to CSet", + ergo_format_region("eden") + ergo_format_region("survivors") + ergo_format_ms("predicted young region time"), + eden_region_num, survivor_region_num, + _inc_cset_predicted_elapsed_time_ms); + // The number of recorded young regions is the incremental // collection set's current size set_recorded_young_regions(_inc_cset_size); @@ -2848,14 +2925,7 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( set_predicted_bytes_to_copy(_inc_cset_predicted_bytes_to_copy); #endif // PREDICTIONS_VERBOSE - if (G1PolicyVerbose > 0) { - gclog_or_tty->print_cr(" Added " PTR_FORMAT " Young Regions to CS.", - _inc_cset_size); - gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)", - max_live_bytes/K); - } - - assert(_inc_cset_size == _g1->young_list()->length(), "Invariant"); + assert(_inc_cset_size == young_list->length(), "Invariant"); double young_end_time_sec = os::elapsedTime(); _recorded_young_cset_choice_time_ms = @@ -2869,6 +2939,8 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( NumberSeq seq; double avg_prediction = 100000000000000000.0; // something very large + size_t prev_collection_set_size = _collection_set_size; + double prev_predicted_pause_time_ms = predicted_pause_time_ms; do { hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms, avg_prediction); @@ -2878,23 +2950,58 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( predicted_pause_time_ms += predicted_time_ms; add_to_collection_set(hr); record_non_young_cset_region(hr); - max_live_bytes -= MIN2(hr->max_live_bytes(), max_live_bytes); - if (G1PolicyVerbose > 0) { - gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)", - max_live_bytes/K); - } seq.add(predicted_time_ms); avg_prediction = seq.avg() + seq.sd(); } - should_continue = - ( hr != NULL) && - ( (adaptive_young_list_length()) ? time_remaining_ms > 0.0 - : _collection_set_size < _young_list_fixed_length ); + + should_continue = true; + if (hr == NULL) { + // No need for an ergo verbose message here, + // getNextMarkRegion() does this when it returns NULL. + should_continue = false; + } else { + if (adaptive_young_list_length()) { + if (time_remaining_ms < 0.0) { + ergo_verbose1(ErgoCSetConstruction, + "stop adding old regions to CSet", + ergo_format_reason("remaining time is lower than 0") + ergo_format_ms("remaining time"), + time_remaining_ms); + should_continue = false; + } + } else { + if (_collection_set_size < _young_list_fixed_length) { + ergo_verbose2(ErgoCSetConstruction, + "stop adding old regions to CSet", + ergo_format_reason("CSet length lower than target") + ergo_format_region("CSet") + ergo_format_region("young target"), + _collection_set_size, _young_list_fixed_length); + should_continue = false; + } + } + } } while (should_continue); if (!adaptive_young_list_length() && - _collection_set_size < _young_list_fixed_length) + _collection_set_size < _young_list_fixed_length) { + ergo_verbose2(ErgoCSetConstruction, + "request partially-young GCs end", + ergo_format_reason("CSet length lower than target") + ergo_format_region("CSet") + ergo_format_region("young target"), + _collection_set_size, _young_list_fixed_length); _should_revert_to_full_young_gcs = true; + } + + old_region_num = _collection_set_size - prev_collection_set_size; + + ergo_verbose2(ErgoCSetConstruction | ErgoHigh, + "add old regions to CSet", + ergo_format_region("old") + ergo_format_ms("predicted old region time"), + old_region_num, + predicted_pause_time_ms - prev_predicted_pause_time_ms); } stop_incremental_cset_building(); @@ -2903,6 +3010,16 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( end_recording_regions(); + ergo_verbose5(ErgoCSetConstruction, + "finish choosing CSet", + ergo_format_region("eden") + ergo_format_region("survivors") + ergo_format_region("old") + ergo_format_ms("predicted pause time") + ergo_format_ms("target pause time"), + eden_region_num, survivor_region_num, old_region_num, + predicted_pause_time_ms, target_pause_time_ms); + double non_young_end_time_sec = os::elapsedTime(); _recorded_non_young_cset_choice_time_ms = (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; @@ -2913,12 +3030,6 @@ void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() { _collectionSetChooser->updateAfterFullCollection(); } -void G1CollectorPolicy_BestRegionsFirst:: -expand_if_possible(size_t numRegions) { - size_t expansion_bytes = numRegions * HeapRegion::GrainBytes; - _g1->expand(expansion_bytes); -} - void G1CollectorPolicy_BestRegionsFirst:: record_collection_pause_end() { G1CollectorPolicy::record_collection_pause_end(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index c30017d3d16..c29c365cb75 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -493,7 +493,6 @@ public: // -public: void cset_regions_freed() { bool propagate = _last_young_gc_full && !_in_marking_window; _short_lived_surv_rate_group->all_surviving_words_recorded(propagate); @@ -1045,7 +1044,7 @@ public: // new cycle, as long as we are not already in one. It's best if it // is called during a safepoint when the test whether a cycle is in // progress or not is stable. - bool force_initial_mark_if_outside_cycle(); + bool force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause); // This is called at the very beginning of an evacuation pause (it // has to be the first thing that the pause does). If @@ -1234,8 +1233,6 @@ public: class G1CollectorPolicy_BestRegionsFirst: public G1CollectorPolicy { CollectionSetChooser* _collectionSetChooser; - // If the estimated is less then desirable, resize if possible. - void expand_if_possible(size_t numRegions); virtual void choose_collection_set(double target_pause_time_ms); virtual void record_collection_pause_start(double start_time_sec, @@ -1269,8 +1266,4 @@ inline double variance(int n, double sum_of_squares, double sum) { return (sum_of_squares - 2.0 * avg * sum + n_d * avg * avg) / n_d; } -// Local Variables: *** -// c-indentation-style: gnu *** -// End: *** - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTORPOLICY_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.cpp new file mode 100644 index 00000000000..dc6b49cb8f4 --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/g1ErgoVerbose.hpp" +#include "utilities/ostream.hpp" + +ErgoLevel G1ErgoVerbose::_level; +bool G1ErgoVerbose::_enabled[ErgoHeuristicNum]; + +void G1ErgoVerbose::initialize() { + set_level(ErgoLow); + set_enabled(false); +} + +void G1ErgoVerbose::set_level(ErgoLevel level) { + _level = level; +} + +void G1ErgoVerbose::set_enabled(ErgoHeuristic n, bool enabled) { + assert(0 <= n && n < ErgoHeuristicNum, "pre-condition"); + _enabled[n] = enabled; +} + +void G1ErgoVerbose::set_enabled(bool enabled) { + for (int n = 0; n < ErgoHeuristicNum; n += 1) { + set_enabled((ErgoHeuristic) n, enabled); + } +} + +const char* G1ErgoVerbose::to_string(int tag) { + ErgoHeuristic n = extract_heuristic(tag); + switch (n) { + case ErgoHeapSizing: return "Heap Sizing"; + case ErgoCSetConstruction: return "CSet Construction"; + case ErgoConcCycles: return "Concurrent Cycles"; + case ErgoPartiallyYoungGCs: return "Partially-Young GCs"; + default: + ShouldNotReachHere(); + // Keep the Windows compiler happy + return NULL; + } +} + diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp new file mode 100644 index 00000000000..1fe9f9bdede --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP + +#include "memory/allocation.hpp" +#include "utilities/debug.hpp" + +// The log of G1's heuristic decisions comprises of a series of +// records which have a similar format in order to maintain +// consistency across records and ultimately easier parsing of the +// output, if we ever choose to do that. Each record consists of: +// * A time stamp to be able to easily correlate each record with +// other events. +// * A unique string to allow us to easily identify such records. +// * The name of the heuristic the record corresponds to. +// * An action string which describes the action that G1 did or is +// about to do. +// * An optional reason string which describes the reason for the +// action. +// * An optional number of name/value pairs which contributed to the +// decision to take the action described in the record. +// +// Each record is associated with a "tag" which is the combination of +// the heuristic the record corresponds to, as well as the min level +// of verboseness at which the record should be printed. The tag is +// checked against the current settings to determine whether the record +// should be printed or not. + +// The available verboseness levels. +typedef enum { + // Determine which part of the tag is occupied by the level. + ErgoLevelShift = 8, + ErgoLevelMask = ~((1 << ErgoLevelShift) - 1), + + // ErgoLow is 0 so that we don't have to explicitly or a heuristic + // id with ErgoLow to keep its use simpler. + ErgoLow = 0, + ErgoHigh = 1 << ErgoLevelShift, +} ErgoLevel; + +// The available heuristics. +typedef enum { + // Determines which part of the tag is occupied by the heuristic id. + ErgoHeuristicMask = ~ErgoLevelMask, + + ErgoHeapSizing = 0, + ErgoCSetConstruction, + ErgoConcCycles, + ErgoPartiallyYoungGCs, + + ErgoHeuristicNum +} ErgoHeuristic; + +class G1ErgoVerbose : AllStatic { +private: + // Determines the minimum verboseness level at which records will be + // printed. + static ErgoLevel _level; + // Determines which heuristics are currently enabled. + static bool _enabled[ErgoHeuristicNum]; + + static ErgoLevel extract_level(int tag) { + return (ErgoLevel) (tag & ErgoLevelMask); + } + + static ErgoHeuristic extract_heuristic(int tag) { + return (ErgoHeuristic) (tag & ErgoHeuristicMask); + } + +public: + // Needs to be explicitly called at GC initialization. + static void initialize(); + + static void set_level(ErgoLevel level); + static void set_enabled(ErgoHeuristic h, bool enabled); + // It is applied to all heuristics. + static void set_enabled(bool enabled); + + static bool enabled(int tag) { + ErgoLevel level = extract_level(tag); + ErgoHeuristic n = extract_heuristic(tag); + return level <= _level && _enabled[n]; + } + + // Extract the heuristic id from the tag and return a string with + // its name. + static const char* to_string(int tag); +}; + +// The macros below generate the format string for values of different +// types and/or metrics. + +// The reason for the action is optional and is handled specially: the +// reason string is concatenated here so it's not necessary to pass it +// as a parameter. +#define ergo_format_reason(_reason_) ", reason: " _reason_ + +// Single parameter format strings +#define ergo_format_str(_name_) ", " _name_ ": %s" +#define ergo_format_region(_name_) ", " _name_ ": "SIZE_FORMAT" regions" +#define ergo_format_byte(_name_) ", " _name_ ": "SIZE_FORMAT" bytes" +#define ergo_format_double(_name_) ", " _name_ ": %1.2f" +#define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%" +#define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms" + +// Double parameter format strings +#define ergo_format_byte_perc(_name_) \ + ", " _name_ ": "SIZE_FORMAT" bytes (%1.2f %%)" + +// Generates the format string +#define ergo_format(_action_, _extra_format_) \ + " %1.3f: [G1Ergonomics (%s) " _action_ _extra_format_ "]" + +// Conditionally, prints an ergonomic decision record. _extra_format_ +// is the format string for the optional items we'd like to print +// (i.e., the decision's reason and any associated values). This +// string should be built up using the ergo_*_format macros (see +// above) to ensure consistency. +// +// Since we cannot rely on the compiler supporting variable argument +// macros, this macro accepts a fixed number of arguments and passes +// them to the print method. For convenience, we have wrapper macros +// below which take a specific number of arguments and set the rest to +// a default value. +#define ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ + do { \ + if (G1ErgoVerbose::enabled((_tag_))) { \ + gclog_or_tty->print_cr(ergo_format(_action_, _extra_format_), \ + os::elapsedTime(), \ + G1ErgoVerbose::to_string((_tag_)), \ + (_arg0_), (_arg1_), (_arg2_), \ + (_arg3_), (_arg4_), (_arg5_)); \ + } \ + } while (0) + + +#define ergo_verbose(_tag_, _action_) \ + ergo_verbose_common(_tag_, _action_, "", 0, 0, 0, 0, 0, 0) + +#define ergo_verbose0(_tag_, _action_, _extra_format_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, 0, 0, 0, 0, 0, 0) + +#define ergo_verbose1(_tag_, _action_, _extra_format_, \ + _arg0_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, 0, 0, 0, 0, 0) + +#define ergo_verbose2(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, 0, 0, 0, 0) + +#define ergo_verbose3(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, 0, 0, 0) + +#define ergo_verbose4(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_, 0, 0) + +#define ergo_verbose5(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, 0) + +#define ergo_verbose6(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ + ergo_verbose_common(_tag_, _action_, _extra_format_, \ + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp index 2943c83151a..bd91c8fd29a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,10 +97,6 @@ void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) { // or performance (we are GC'ing most of the time anyway!), // simply overwrite the oldest entry in the tracker. - if (G1PolicyVerbose > 1) { - warning("MMU Tracker Queue overflow. Replacing earliest entry."); - } - _head_index = trim_index(_head_index + 1); assert(_head_index == _tail_index, "Because we have a full circular buffer"); _tail_index = trim_index(_tail_index + 1); diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp index d44f2634627..04d051b8443 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @@ -98,7 +98,7 @@ void VM_G1IncCollectionPause::doit() { // At this point we are supposed to start a concurrent cycle. We // will do so if one is not already in progress. - bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle(); + bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle(_gc_cause); // The above routine returns true if we were able to force the // next GC pause to be an initial mark; it returns false if a From 61068411fa72b1a995aed92cabc7be43fef3f1bf Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 7 Sep 2011 12:58:42 -0700 Subject: [PATCH 032/214] 7054211: No loop unrolling done in jdk7b144 for a test update() while loop Restore unrolling code for CaffeineMark. Reviewed-by: never --- hotspot/src/share/vm/opto/loopTransform.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 148c2e3d278..eee153a8904 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -709,10 +709,13 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const { // Adjust body_size to determine if we unroll or not uint body_size = _body.size(); + // Key test to unroll loop in CRC32 java code + int xors_in_loop = 0; // Also count ModL, DivL and MulL which expand mightly for (uint k = 0; k < _body.size(); k++) { Node* n = _body.at(k); switch (n->Opcode()) { + case Op_XorI: xors_in_loop++; break; // CRC32 java code case Op_ModL: body_size += 30; break; case Op_DivL: body_size += 30; break; case Op_MulL: body_size += 10; break; @@ -729,7 +732,8 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const { // Check for being too big if (body_size > (uint)LoopUnrollLimit) { - // Normal case: loop too big + if (xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true; + // Normal case: loop too big return false; } From ed72e31727f1fe0d46c9301747880e08f5c962a7 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Wed, 7 Sep 2011 13:55:42 -0700 Subject: [PATCH 033/214] 4965777: GC changes to support use of discovered field for pending references If and when the reference handler thread is able to use the discovered field to link reference objects in its pending list, so will GC. In that case, GC will scan through this field once a reference object has been placed on the pending list, but not scan that field before that stage, as the field is used by the concurrent GC thread to link discovered objects. When ReferenceHandleR thread does not use the discovered field for the purpose of linking the elements in the pending list, as would be the case in older JDKs, the JVM will fall back to the old behaviour of using the next field for that purpose. Reviewed-by: jcoomes, mchung, stefank --- .../share/vm/memory/referenceProcessor.cpp | 157 ++++++++++-------- .../share/vm/memory/referenceProcessor.hpp | 10 +- .../src/share/vm/oops/instanceRefKlass.cpp | 130 +++++++++++++-- hotspot/src/share/vm/prims/jvm.h | 3 +- hotspot/src/share/vm/runtime/java.cpp | 3 +- hotspot/src/share/vm/runtime/java.hpp | 14 +- 6 files changed, 229 insertions(+), 88 deletions(-) diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 022d3754576..9b593ef3f75 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -36,6 +36,7 @@ ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; const int subclasses_of_ref = REF_PHANTOM - REF_OTHER; +bool ReferenceProcessor::_pending_list_uses_discovered_field = false; // List of discovered references. class DiscoveredList { @@ -87,6 +88,7 @@ void ReferenceProcessor::init_statics() { guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || RefDiscoveryPolicy == ReferentBasedDiscovery, "Unrecongnized RefDiscoveryPolicy"); + _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field(); } ReferenceProcessor::ReferenceProcessor(MemRegion span, @@ -122,7 +124,7 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, _discoveredSoftRefs[i].set_head(NULL); _discoveredSoftRefs[i].set_length(0); } - // If we do barreirs, cache a copy of the barrier set. + // If we do barriers, cache a copy of the barrier set. if (discovered_list_needs_barrier) { _bs = Universe::heap()->barrier_set(); } @@ -307,46 +309,77 @@ bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecut void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, HeapWord* pending_list_addr) { // Given a list of refs linked through the "discovered" field - // (java.lang.ref.Reference.discovered) chain them through the - // "next" field (java.lang.ref.Reference.next) and prepend - // to the pending list. + // (java.lang.ref.Reference.discovered), self-loop their "next" field + // thus distinguishing them from active References, then + // prepend them to the pending list. + // BKWRD COMPATIBILITY NOTE: For older JDKs (prior to the fix for 4956777), + // the "next" field is used to chain the pending list, not the discovered + // field. + if (TraceReferenceGC && PrintGCDetails) { gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, (address)refs_list.head()); } oop obj = NULL; - oop next = refs_list.head(); - // Walk down the list, copying the discovered field into - // the next field and clearing it. - while (obj != next) { - obj = next; - assert(obj->is_instanceRef(), "should be reference object"); - next = java_lang_ref_Reference::discovered(obj); - if (TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, - obj, next); - } - assert(java_lang_ref_Reference::next(obj) == NULL, - "The reference should not be enqueued"); - if (next == obj) { // obj is last - // Swap refs_list into pendling_list_addr and - // set obj's next to what we read from pending_list_addr. - oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); - // Need oop_check on pending_list_addr above; - // see special oop-check code at the end of - // enqueue_discovered_reflists() further below. - if (old == NULL) { - // obj should be made to point to itself, since - // pending list was empty. - java_lang_ref_Reference::set_next(obj, obj); - } else { - java_lang_ref_Reference::set_next(obj, old); + oop next_d = refs_list.head(); + if (pending_list_uses_discovered_field()) { // New behaviour + // Walk down the list, self-looping the next field + // so that the References are not considered active. + while (obj != next_d) { + obj = next_d; + assert(obj->is_instanceRef(), "should be reference object"); + next_d = java_lang_ref_Reference::discovered(obj); + if (TraceReferenceGC && PrintGCDetails) { + gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, + obj, next_d); + } + assert(java_lang_ref_Reference::next(obj) == NULL, + "Reference not active; should not be discovered"); + // Self-loop next, so as to make Ref not active. + java_lang_ref_Reference::set_next(obj, obj); + if (next_d == obj) { // obj is last + // Swap refs_list into pendling_list_addr and + // set obj's discovered to what we read from pending_list_addr. + oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); + // Need oop_check on pending_list_addr above; + // see special oop-check code at the end of + // enqueue_discovered_reflists() further below. + java_lang_ref_Reference::set_discovered(obj, old); // old may be NULL } - } else { - java_lang_ref_Reference::set_next(obj, next); } - java_lang_ref_Reference::set_discovered(obj, (oop) NULL); + } else { // Old behaviour + // Walk down the list, copying the discovered field into + // the next field and clearing the discovered field. + while (obj != next_d) { + obj = next_d; + assert(obj->is_instanceRef(), "should be reference object"); + next_d = java_lang_ref_Reference::discovered(obj); + if (TraceReferenceGC && PrintGCDetails) { + gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, + obj, next_d); + } + assert(java_lang_ref_Reference::next(obj) == NULL, + "The reference should not be enqueued"); + if (next_d == obj) { // obj is last + // Swap refs_list into pendling_list_addr and + // set obj's next to what we read from pending_list_addr. + oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); + // Need oop_check on pending_list_addr above; + // see special oop-check code at the end of + // enqueue_discovered_reflists() further below. + if (old == NULL) { + // obj should be made to point to itself, since + // pending list was empty. + java_lang_ref_Reference::set_next(obj, obj); + } else { + java_lang_ref_Reference::set_next(obj, old); + } + } else { + java_lang_ref_Reference::set_next(obj, next_d); + } + java_lang_ref_Reference::set_discovered(obj, (oop) NULL); + } } } @@ -615,7 +648,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list, NOT_PRODUCT( if (PrintGCDetails && TraceReferenceGC) { gclog_or_tty->print_cr(" Dropped %d dead Refs out of %d " - "discovered Refs by policy list " INTPTR_FORMAT, + "discovered Refs by policy, from list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head()); } ) @@ -1115,20 +1148,16 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, // here is when *discovered_addr is NULL (see the CAS further below), // so this will expand to nothing. As a result, we have manually // elided this out for G1, but left in the test for some future - // collector that might have need for a pre-barrier here. - if (_discovered_list_needs_barrier && !UseG1GC) { - if (UseCompressedOops) { - _bs->write_ref_field_pre((narrowOop*)discovered_addr, next_discovered); - } else { - _bs->write_ref_field_pre((oop*)discovered_addr, next_discovered); - } - guarantee(false, "Need to check non-G1 collector"); - } + // collector that might have need for a pre-barrier here, e.g.:- + // _bs->write_ref_field_pre((oop* or narrowOop*)discovered_addr, next_discovered); + assert(!_discovered_list_needs_barrier || UseG1GC, + "Need to check non-G1 collector: " + "may need a pre-write-barrier for CAS from NULL below"); oop retest = oopDesc::atomic_compare_exchange_oop(next_discovered, discovered_addr, NULL); if (retest == NULL) { // This thread just won the right to enqueue the object. - // We have separate lists for enqueueing so no synchronization + // We have separate lists for enqueueing, so no synchronization // is necessary. refs_list.set_head(obj); refs_list.inc_length(1); @@ -1137,14 +1166,14 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, } if (TraceReferenceGC) { - gclog_or_tty->print_cr("Enqueued reference (mt) (" INTPTR_FORMAT ": %s)", + gclog_or_tty->print_cr("Discovered reference (mt) (" INTPTR_FORMAT ": %s)", obj, obj->blueprint()->internal_name()); } } else { // If retest was non NULL, another thread beat us to it: // The reference has already been discovered... if (TraceReferenceGC) { - gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", + gclog_or_tty->print_cr("Already discovered reference (" INTPTR_FORMAT ": %s)", obj, obj->blueprint()->internal_name()); } } @@ -1169,7 +1198,7 @@ void ReferenceProcessor::verify_referent(oop obj) { // (or part of the heap being collected, indicated by our "span" // we don't treat it specially (i.e. we scan it as we would // a normal oop, treating its references as strong references). -// This means that references can't be enqueued unless their +// This means that references can't be discovered unless their // referent is also in the same span. This is the simplest, // most "local" and most conservative approach, albeit one // that may cause weak references to be enqueued least promptly. @@ -1191,14 +1220,13 @@ void ReferenceProcessor::verify_referent(oop obj) { // and complexity in processing these references. // We call this choice the "RefeferentBasedDiscovery" policy. bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { - // We enqueue references only if we are discovering refs - // (rather than processing discovered refs). + // Make sure we are discovering refs (rather than processing discovered refs). if (!_discovering_refs || !RegisterReferences) { return false; } - // We only enqueue active references. + // We only discover active references. oop next = java_lang_ref_Reference::next(obj); - if (next != NULL) { + if (next != NULL) { // Ref is no longer active return false; } @@ -1211,8 +1239,8 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { return false; } - // We only enqueue references whose referents are not (yet) strongly - // reachable. + // We only discover references whose referents are not (yet) + // known to be strongly reachable. if (is_alive_non_header() != NULL) { verify_referent(obj); if (is_alive_non_header()->do_object_b(java_lang_ref_Reference::referent(obj))) { @@ -1238,7 +1266,7 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { if (discovered != NULL) { // The reference has already been discovered... if (TraceReferenceGC) { - gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", + gclog_or_tty->print_cr("Already discovered reference (" INTPTR_FORMAT ": %s)", obj, obj->blueprint()->internal_name()); } if (RefDiscoveryPolicy == ReferentBasedDiscovery) { @@ -1260,9 +1288,9 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { if (RefDiscoveryPolicy == ReferentBasedDiscovery) { verify_referent(obj); - // enqueue if and only if either: - // reference is in our span or - // we are an atomic collector and referent is in our span + // Discover if and only if EITHER: + // .. reference is in our span, OR + // .. we are an atomic collector and referent is in our span if (_span.contains(obj_addr) || (discovery_is_atomic() && _span.contains(java_lang_ref_Reference::referent(obj)))) { @@ -1294,15 +1322,10 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { // As in the case further above, since we are over-writing a NULL // pre-value, we can safely elide the pre-barrier here for the case of G1. + // e.g.:- _bs->write_ref_field_pre((oop* or narrowOop*)discovered_addr, next_discovered); assert(discovered == NULL, "control point invariant"); - if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1 - if (UseCompressedOops) { - _bs->write_ref_field_pre((narrowOop*)discovered_addr, next_discovered); - } else { - _bs->write_ref_field_pre((oop*)discovered_addr, next_discovered); - } - guarantee(false, "Need to check non-G1 collector"); - } + assert(!_discovered_list_needs_barrier || UseG1GC, + "For non-G1 collector, may need a pre-write-barrier for CAS from NULL below"); oop_store_raw(discovered_addr, next_discovered); if (_discovered_list_needs_barrier) { _bs->write_ref_field((void*)discovered_addr, next_discovered); @@ -1311,11 +1334,11 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { list->inc_length(1); if (TraceReferenceGC) { - gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", + gclog_or_tty->print_cr("Discovered reference (" INTPTR_FORMAT ": %s)", obj, obj->blueprint()->internal_name()); } } - assert(obj->is_oop(), "Enqueued a bad reference"); + assert(obj->is_oop(), "Discovered a bad reference"); verify_referent(obj); return true; } diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index 56f262eb47e..8178f60ea7b 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -52,6 +52,8 @@ class DiscoveredList; class ReferenceProcessor : public CHeapObj { protected: + // Compatibility with pre-4965777 JDK's + static bool _pending_list_uses_discovered_field; MemRegion _span; // (right-open) interval of heap // subject to wkref discovery bool _discovering_refs; // true when discovery enabled @@ -111,7 +113,6 @@ class ReferenceProcessor : public CHeapObj { return _current_soft_ref_policy; } - public: // Process references with a certain reachability level. void process_discovered_reflist(DiscoveredList refs_lists[], ReferencePolicy* policy, @@ -297,6 +298,13 @@ class ReferenceProcessor : public CHeapObj { bool discovery_is_atomic() const { return _discovery_is_atomic; } void set_atomic_discovery(bool atomic) { _discovery_is_atomic = atomic; } + // whether the JDK in which we are embedded is a pre-4965777 JDK, + // and thus whether or not it uses the discovered field to chain + // the entries in the pending list. + static bool pending_list_uses_discovered_field() { + return _pending_list_uses_discovered_field; + } + // whether discovery is done by multiple threads same-old-timeously bool discovery_is_mt() const { return _discovery_is_mt; } void set_mt_discovery(bool mt) { _discovery_is_mt = mt; } diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index 12c9d3385f2..b3c3d161824 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -56,9 +56,8 @@ static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { if (!oopDesc::is_null(heap_oop)) { oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); if (!referent->is_gc_marked() && - MarkSweep::ref_processor()-> - discover_reference(obj, ref->reference_type())) { - // reference already enqueued, referent will be traversed later + MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) { + // reference was discovered, referent will be traversed later ref->instanceKlass::oop_follow_contents(obj); debug_only( if(TraceReferenceGC && PrintGCDetails) { @@ -76,8 +75,34 @@ static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { MarkSweep::mark_and_push(referent_addr); } } - // treat next as normal oop. next is a link in the pending list. T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + if (ReferenceProcessor::pending_list_uses_discovered_field()) { + // Treat discovered as normal oop, if ref is not "active", + // i.e. if next is non-NULL. + T next_oop = oopDesc::load_heap_oop(next_addr); + if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + debug_only( + if(TraceReferenceGC && PrintGCDetails) { + gclog_or_tty->print_cr(" Process discovered as normal " + INTPTR_FORMAT, discovered_addr); + } + ) + MarkSweep::mark_and_push(discovered_addr); + } + } else { +#ifdef ASSERT + // In the case of older JDKs which do not use the discovered + // field for the pending list, an inactive ref (next != NULL) + // must always have a NULL discovered field. + oop next = oopDesc::load_decode_heap_oop(next_addr); + oop discovered = java_lang_ref_Reference::discovered(obj); + assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", + obj)); +#endif + } + // treat next as normal oop. next is a link in the reference queue. debug_only( if(TraceReferenceGC && PrintGCDetails) { gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); @@ -130,13 +155,33 @@ void specialized_oop_follow_contents(instanceRefKlass* ref, PSParallelCompact::mark_and_push(cm, referent_addr); } } - // treat next as normal oop. next is a link in the pending list. T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); - debug_only( - if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); + if (ReferenceProcessor::pending_list_uses_discovered_field()) { + // Treat discovered as normal oop, if ref is not "active", + // i.e. if next is non-NULL. + T next_oop = oopDesc::load_heap_oop(next_addr); + if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + debug_only( + if(TraceReferenceGC && PrintGCDetails) { + gclog_or_tty->print_cr(" Process discovered as normal " + INTPTR_FORMAT, discovered_addr); + } + ) + PSParallelCompact::mark_and_push(cm, discovered_addr); } - ) + } else { +#ifdef ASSERT + // In the case of older JDKs which do not use the discovered + // field for the pending list, an inactive ref (next != NULL) + // must always have a NULL discovered field. + T next = oopDesc::load_heap_oop(next_addr); + oop discovered = java_lang_ref_Reference::discovered(obj); + assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", + obj)); +#endif + } PSParallelCompact::mark_and_push(cm, next_addr); ref->instanceKlass::oop_follow_contents(cm, obj); } @@ -197,27 +242,53 @@ int instanceRefKlass::oop_adjust_pointers(oop obj) { } #define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \ + T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \ if (closure->apply_to_weak_ref_discovered_field()) { \ - T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \ closure->do_oop##nv_suffix(disc_addr); \ } \ \ T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \ T heap_oop = oopDesc::load_heap_oop(referent_addr); \ - if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) { \ - ReferenceProcessor* rp = closure->_ref_processor; \ + ReferenceProcessor* rp = closure->_ref_processor; \ + if (!oopDesc::is_null(heap_oop)) { \ oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \ if (!referent->is_gc_marked() && (rp != NULL) && \ rp->discover_reference(obj, reference_type())) { \ return size; \ - } else { \ + } else if (contains(referent_addr)) { \ /* treat referent as normal oop */ \ SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ closure->do_oop##nv_suffix(referent_addr); \ } \ } \ - /* treat next as normal oop */ \ T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \ + if (ReferenceProcessor::pending_list_uses_discovered_field()) { \ + T next_oop = oopDesc::load_heap_oop(next_addr); \ + /* Treat discovered as normal oop, if ref is not "active" (next non-NULL) */\ + if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { \ + /* i.e. ref is not "active" */ \ + debug_only( \ + if(TraceReferenceGC && PrintGCDetails) { \ + gclog_or_tty->print_cr(" Process discovered as normal " \ + INTPTR_FORMAT, disc_addr); \ + } \ + ) \ + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ + closure->do_oop##nv_suffix(disc_addr); \ + } \ + } else { \ + /* In the case of older JDKs which do not use the discovered field for */ \ + /* the pending list, an inactive ref (next != NULL) must always have a */ \ + /* NULL discovered field. */ \ + debug_only( \ + T next_oop = oopDesc::load_heap_oop(next_addr); \ + T disc_oop = oopDesc::load_heap_oop(disc_addr); \ + assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop), \ + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL" \ + "discovered field", obj)); \ + ) \ + } \ + /* treat next as normal oop */ \ if (contains(next_addr)) { \ SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \ closure->do_oop##nv_suffix(next_addr); \ @@ -306,8 +377,37 @@ void specialized_oop_push_contents(instanceRefKlass *ref, pm->claim_or_forward_depth(referent_addr); } } - // treat next as normal oop + // Treat discovered as normal oop, if ref is not "active", + // i.e. if next is non-NULL. T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + if (ReferenceProcessor::pending_list_uses_discovered_field()) { + T next_oop = oopDesc::load_heap_oop(next_addr); + if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + debug_only( + if(TraceReferenceGC && PrintGCDetails) { + gclog_or_tty->print_cr(" Process discovered as normal " + INTPTR_FORMAT, discovered_addr); + } + ) + if (PSScavenge::should_scavenge(discovered_addr)) { + pm->claim_or_forward_depth(discovered_addr); + } + } + } else { +#ifdef ASSERT + // In the case of older JDKs which do not use the discovered + // field for the pending list, an inactive ref (next != NULL) + // must always have a NULL discovered field. + oop next = oopDesc::load_decode_heap_oop(next_addr); + oop discovered = java_lang_ref_Reference::discovered(obj); + assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", + obj)); +#endif + } + + // Treat next as normal oop; next is a link in the reference queue. if (PSScavenge::should_scavenge(next_addr)) { pm->claim_or_forward_depth(next_addr); } diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index f37d83342f8..c3a9909750b 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -1650,7 +1650,8 @@ typedef struct { */ unsigned int thread_park_blocker : 1; unsigned int post_vm_init_hook_enabled : 1; - unsigned int : 30; + unsigned int pending_list_uses_discovered_field : 1; + unsigned int : 29; unsigned int : 32; unsigned int : 32; } jdk_version_info; diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index fa7c647af4a..7f37e073e5b 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -672,7 +672,8 @@ void JDK_Version::initialize() { _current = JDK_Version(major, minor, micro, info.update_version, info.special_update_version, build, info.thread_park_blocker == 1, - info.post_vm_init_hook_enabled == 1); + info.post_vm_init_hook_enabled == 1, + info.pending_list_uses_discovered_field == 1); } } diff --git a/hotspot/src/share/vm/runtime/java.hpp b/hotspot/src/share/vm/runtime/java.hpp index 37e29bda983..307fcc2fb36 100644 --- a/hotspot/src/share/vm/runtime/java.hpp +++ b/hotspot/src/share/vm/runtime/java.hpp @@ -92,6 +92,7 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC { bool _partially_initialized; bool _thread_park_blocker; + bool _pending_list_uses_discovered_field; bool _post_vm_init_hook_enabled; bool is_valid() const { @@ -114,15 +115,18 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC { JDK_Version() : _major(0), _minor(0), _micro(0), _update(0), _special(0), _build(0), _partially_initialized(false), - _thread_park_blocker(false), _post_vm_init_hook_enabled(false) {} + _thread_park_blocker(false), _post_vm_init_hook_enabled(false), + _pending_list_uses_discovered_field(false) {} JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0, uint8_t update = 0, uint8_t special = 0, uint8_t build = 0, - bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) : + bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false, + bool pending_list_uses_discovered_field = false) : _major(major), _minor(minor), _micro(micro), _update(update), _special(special), _build(build), _partially_initialized(false), _thread_park_blocker(thread_park_blocker), - _post_vm_init_hook_enabled(post_vm_init_hook_enabled) {} + _post_vm_init_hook_enabled(post_vm_init_hook_enabled), + _pending_list_uses_discovered_field(pending_list_uses_discovered_field) {} // Returns the current running JDK version static JDK_Version current() { return _current; } @@ -149,6 +153,10 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC { bool post_vm_init_hook_enabled() const { return _post_vm_init_hook_enabled; } + // For compatibility wrt pre-4965777 JDK's + bool pending_list_uses_discovered_field() const { + return _pending_list_uses_discovered_field; + } // Performs a full ordering comparison using all fields (update, build, etc.) int compare(const JDK_Version& other) const; From 83b6b7ace1ca61fbf6c8da176f7b1909feb19bcb Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 8 Sep 2011 09:06:09 +0800 Subject: [PATCH 034/214] 7087428: move client tests out of jdk_misc Reviewed-by: ohair, alanb --- make/jprt.properties | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/make/jprt.properties b/make/jprt.properties index ea634d129b6..4fad5364b78 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -295,6 +295,15 @@ jprt.make.rule.all.test.targets= \ windows_i586_5.1-product-c1-jdk_security3, \ windows_x64_5.2-product-c2-jdk_security3, \ \ + solaris_sparc_5.10-product-c1-jdk_sound, \ + solaris_sparcv9_5.10-product-c2-jdk_sound, \ + solaris_i586_5.10-product-c1-jdk_sound, \ + solaris_x64_5.10-product-c2-jdk_sound, \ + linux_i586_2.6-product-{c1|c2}-jdk_sound, \ + linux_x64_2.6-product-c2-jdk_sound, \ + windows_i586_5.1-product-c1-jdk_sound, \ + windows_x64_5.2-product-c2-jdk_sound, \ + \ solaris_sparc_5.10-product-c1-jdk_swing, \ solaris_sparcv9_5.10-product-c2-jdk_swing, \ solaris_i586_5.10-product-c1-jdk_swing, \ From 1940a13d3136f110a80b06cce96c073faa79b81e Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 7 Sep 2011 18:58:33 -0700 Subject: [PATCH 035/214] 7086226: UseNUMA fails on old versions of windows Return correct answers from os::numa_*() for UMA machines or if NUMA API is not supported Reviewed-by: johnc --- hotspot/src/os/windows/vm/os_windows.cpp | 33 +++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 28a464169ef..d9cfca01038 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2706,11 +2706,10 @@ static void cleanup_after_large_page_init() { static bool numa_interleaving_init() { bool success = false; - bool use_numa_specified = !FLAG_IS_DEFAULT(UseNUMA); bool use_numa_interleaving_specified = !FLAG_IS_DEFAULT(UseNUMAInterleaving); - // print a warning if UseNUMA or UseNUMAInterleaving flag is specified on command line - bool warn_on_failure = use_numa_specified || use_numa_interleaving_specified; + // print a warning if UseNUMAInterleaving flag is specified on command line + bool warn_on_failure = use_numa_interleaving_specified; # define WARN(msg) if (warn_on_failure) { warning(msg); } // NUMAInterleaveGranularity cannot be less than vm_allocation_granularity (or _large_page_size if using large pages) @@ -2720,7 +2719,7 @@ static bool numa_interleaving_init() { if (os::Kernel32Dll::NumaCallsAvailable()) { if (numa_node_list_holder.build()) { if (PrintMiscellaneous && Verbose) { - tty->print("NUMA UsedNodeCount=%d, namely ", os::numa_get_groups_num()); + tty->print("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); for (int i = 0; i < numa_node_list_holder.get_count(); i++) { tty->print("%d ", numa_node_list_holder.get_node_list_entry(i)); } @@ -2734,7 +2733,6 @@ static bool numa_interleaving_init() { WARN("NUMA Interleaving is not supported by the operating system."); } if (!success) { - if (use_numa_specified) WARN("...Ignoring UseNUMA flag."); if (use_numa_interleaving_specified) WARN("...Ignoring UseNUMAInterleaving flag."); } return success; @@ -2816,7 +2814,8 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, prot); } else { // get the next node to use from the used_node_list - DWORD node = numa_node_list_holder.get_node_list_entry(count % os::numa_get_groups_num()); + assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected"); + DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count()); p_new = (char *)os::Kernel32Dll::VirtualAllocExNuma(hProc, next_alloc_addr, bytes_to_rq, @@ -3132,15 +3131,21 @@ void os::free_memory(char *addr, size_t bytes) { } void os::numa_make_global(char *addr, size_t bytes) { } void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { } bool os::numa_topology_changed() { return false; } -size_t os::numa_get_groups_num() { return numa_node_list_holder.get_count(); } +size_t os::numa_get_groups_num() { return MAX2(numa_node_list_holder.get_count(), 1); } int os::numa_get_group_id() { return 0; } size_t os::numa_get_leaf_groups(int *ids, size_t size) { - // check for size bigger than actual groups_num - size = MIN2(size, numa_get_groups_num()); - for (int i = 0; i < (int)size; i++) { - ids[i] = numa_node_list_holder.get_node_list_entry(i); + if (numa_node_list_holder.get_count() == 0 && size > 0) { + // Provide an answer for UMA systems + ids[0] = 0; + return 1; + } else { + // check for size bigger than actual groups_num + size = MIN2(size, numa_get_groups_num()); + for (int i = 0; i < (int)size; i++) { + ids[i] = numa_node_list_holder.get_node_list_entry(i); + } + return size; } - return size; } bool os::get_page_info(char *start, page_info* info) { @@ -3768,6 +3773,10 @@ jint os::init_2(void) { // initialize thread priority policy prio_init(); + if (UseNUMA && !ForceNUMA) { + UseNUMA = false; // We don't fully support this yet + } + if (UseNUMAInterleaving) { // first check whether this Windows OS supports VirtualAllocExNuma, if not ignore this flag bool success = numa_interleaving_init(); From 50bc4343b36701ee2f6d748cf460e1dc8e90d78f Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 7 Sep 2011 21:05:24 -0700 Subject: [PATCH 036/214] 7082631: JSR 292: need profiling support in GWTs Add CountingMethodHandle Reviewed-by: twisti, jrose --- .../java/lang/invoke/AdapterMethodHandle.java | 4 +- .../lang/invoke/CountingMethodHandle.java | 50 +++++++++++++++++++ .../java/lang/invoke/MethodHandleImpl.java | 4 +- .../java/lang/invoke/MethodHandleNatives.java | 6 ++- 4 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 jdk/src/share/classes/java/lang/invoke/CountingMethodHandle.java diff --git a/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java index 0c7619d623c..7cfc7740627 100644 --- a/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java @@ -53,7 +53,7 @@ class AdapterMethodHandle extends BoundMethodHandle { // JVM might update VM-specific bits of conversion (ignore) MethodHandleNatives.init(this, target, convArgPos(conv)); } - private AdapterMethodHandle(MethodHandle target, MethodType newType, + AdapterMethodHandle(MethodHandle target, MethodType newType, long conv) { this(target, newType, conv, null); } @@ -423,7 +423,7 @@ class AdapterMethodHandle extends BoundMethodHandle { insertStackMove(stackMove) ); } - private static long makeConv(int convOp) { + static long makeConv(int convOp) { assert(convOp == OP_RETYPE_ONLY || convOp == OP_RETYPE_RAW); return ((long)-1 << 32) | (convOp << CONV_OP_SHIFT); // stackMove, src, dst all zero } diff --git a/jdk/src/share/classes/java/lang/invoke/CountingMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/CountingMethodHandle.java new file mode 100644 index 00000000000..f8a0c6e8a03 --- /dev/null +++ b/jdk/src/share/classes/java/lang/invoke/CountingMethodHandle.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import static java.lang.invoke.MethodHandleNatives.Constants.*; + +/** + * This method handle is used to optionally provide a count of how + * many times it was invoked. + * + * @author never + */ +class CountingMethodHandle extends AdapterMethodHandle { + private int vmcount; + + private CountingMethodHandle(MethodHandle target) { + super(target, target.type(), AdapterMethodHandle.makeConv(OP_RETYPE_ONLY)); + } + + /** Wrap the incoming MethodHandle in a CountingMethodHandle if they are enabled */ + static MethodHandle wrap(MethodHandle mh) { + if (MethodHandleNatives.COUNT_GWT) { + return new CountingMethodHandle(mh); + } + return mh; + } +} diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index e817c00669f..6bf80798591 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -749,8 +749,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(target.type().equals(fallback.type())); MethodHandle tailcall = MethodHandles.exactInvoker(target.type()); MethodHandle select = selectAlternative(); - select = bindArgument(select, 2, fallback); - select = bindArgument(select, 1, target); + select = bindArgument(select, 2, CountingMethodHandle.wrap(fallback)); + select = bindArgument(select, 1, CountingMethodHandle.wrap(target)); // select(z: boolean) => (z ? target : fallback) MethodHandle filter = filterArgument(tailcall, 0, select); assert(filter.type().parameterType(0) == boolean.class); diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index bd7c3865139..e01d9b1bf45 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -120,6 +120,8 @@ class MethodHandleNatives { static final int OP_ROT_ARGS_DOWN_LIMIT_BIAS; + static final boolean COUNT_GWT; + private static native void registerNatives(); static { registerNatives(); @@ -131,6 +133,7 @@ class MethodHandleNatives { k = getConstant(Constants.GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS); OP_ROT_ARGS_DOWN_LIMIT_BIAS = (k != 0) ? (byte)k : -1; HAVE_RICOCHET_FRAMES = (CONV_OP_IMPLEMENTED_MASK & (1< Date: Thu, 8 Sep 2011 10:12:25 +0200 Subject: [PATCH 037/214] 7087445: Improve platform independence of JSR292 shared code Changes necessary for some JSR292 ports Reviewed-by: jrose, dholmes --- hotspot/src/cpu/sparc/vm/frame_sparc.cpp | 6 ++++++ hotspot/src/cpu/x86/vm/frame_x86.cpp | 6 ++++++ hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 4 ++-- hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 4 ++-- hotspot/src/cpu/zero/vm/frame_zero.cpp | 6 ++++++ hotspot/src/share/vm/runtime/arguments.cpp | 3 --- hotspot/src/share/vm/runtime/deoptimization.cpp | 9 +++++---- hotspot/src/share/vm/runtime/deoptimization.hpp | 6 +++--- hotspot/src/share/vm/runtime/frame.hpp | 4 ++++ 9 files changed, 34 insertions(+), 14 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index edac2b3ca73..83fd37182ca 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -839,3 +839,9 @@ void frame::describe_pd(FrameValues& values, int frame_no) { } #endif + +intptr_t *frame::initial_deoptimization_info() { + // unused... but returns fp() to minimize changes introduced by 7087445 + return fp(); +} + diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 21705957e50..3d82d062289 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -666,3 +666,9 @@ void frame::describe_pd(FrameValues& values, int frame_no) { } #endif + +intptr_t *frame::initial_deoptimization_info() { + // used to reset the saved FP + return fp(); +} + diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index f21ed399f7c..9b43aba25dd 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -2471,7 +2471,7 @@ void SharedRuntime::generate_deopt_blob() { __ movl(counter, rbx); // Pick up the initial fp we should save - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_fp_offset_in_bytes())); + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); // Now adjust the caller's stack to make up for the extra locals // but record the original sp so that we can save it in the skeletal interpreter @@ -2691,7 +2691,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { __ movl(counter, rbx); // Pick up the initial fp we should save - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_fp_offset_in_bytes())); + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); // Now adjust the caller's stack to make up for the extra locals // but record the original sp so that we can save it in the skeletal interpreter diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 06b3d8d0c07..effb3ce365a 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -2730,7 +2730,7 @@ void SharedRuntime::generate_deopt_blob() { __ movl(rdx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); // Pick up the initial fp we should save - __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_fp_offset_in_bytes())); + __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); // Now adjust the caller's stack to make up for the extra locals // but record the original sp so that we can save it in the skeletal interpreter @@ -2922,7 +2922,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { // Pick up the initial fp we should save __ movptr(rbp, Address(rdi, - Deoptimization::UnrollBlock::initial_fp_offset_in_bytes())); + Deoptimization::UnrollBlock::initial_info_offset_in_bytes())); // Now adjust the caller's stack to make up for the extra locals but // record the original sp so that we can save it in the skeletal diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 9e3211224d4..35b6e52e41e 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -425,3 +425,9 @@ void frame::describe_pd(FrameValues& values, int frame_no) { } #endif + +intptr_t *frame::initial_deoptimization_info() { + // unused... but returns fp() to minimize changes introduced by 7087445 + return fp(); +} + diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index c159e48f0be..c802f0351d4 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3018,9 +3018,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } #ifdef JAVASE_EMBEDDED - #ifdef PPC - UNSUPPORTED_OPTION(EnableInvokeDynamic, "Invoke dynamic"); - #endif UNSUPPORTED_OPTION(UseG1GC, "G1 GC"); #endif diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index b2f172d1d70..db95badcded 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -103,7 +103,7 @@ Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame, _frame_pcs = frame_pcs; _register_block = NEW_C_HEAP_ARRAY(intptr_t, RegisterMap::reg_count * 2); _return_type = return_type; - _initial_fp = 0; + _initial_info = 0; // PD (x86 only) _counter_temp = 0; _unpack_kind = 0; @@ -486,9 +486,10 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread frame_sizes, frame_pcs, return_type); - // On some platforms, we need a way to pass fp to the unpacking code - // so the skeletal frames come out correct. - info->set_initial_fp((intptr_t) array->sender().fp()); + // On some platforms, we need a way to pass some platform dependent + // information to the unpacking code so the skeletal frames come out + // correct (initial fp value, unextended sp, ...) + info->set_initial_info((intptr_t) array->sender().initial_deoptimization_info()); if (array->frames() > 1) { if (VerifyStack && TraceDeoptimization) { diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index 853cd9a017e..161d3a31afe 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.hpp +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp @@ -137,7 +137,7 @@ class Deoptimization : AllStatic { address* _frame_pcs; // Array of frame pc's, in bytes, for unrolling the stack intptr_t* _register_block; // Block for storing callee-saved registers. BasicType _return_type; // Tells if we have to restore double or long return value - intptr_t _initial_fp; // FP of the sender frame + intptr_t _initial_info; // Platform dependent data for the sender frame (was FP on x86) int _caller_actual_parameters; // The number of actual arguments at the // interpreted caller of the deoptimized frame @@ -170,7 +170,7 @@ class Deoptimization : AllStatic { // Returns the total size of frames int size_of_frames() const; - void set_initial_fp(intptr_t fp) { _initial_fp = fp; } + void set_initial_info(intptr_t info) { _initial_info = info; } int caller_actual_parameters() const { return _caller_actual_parameters; } @@ -184,7 +184,7 @@ class Deoptimization : AllStatic { static int register_block_offset_in_bytes() { return offset_of(UnrollBlock, _register_block); } static int return_type_offset_in_bytes() { return offset_of(UnrollBlock, _return_type); } static int counter_temp_offset_in_bytes() { return offset_of(UnrollBlock, _counter_temp); } - static int initial_fp_offset_in_bytes() { return offset_of(UnrollBlock, _initial_fp); } + static int initial_info_offset_in_bytes() { return offset_of(UnrollBlock, _initial_info); } static int unpack_kind_offset_in_bytes() { return offset_of(UnrollBlock, _unpack_kind); } static int sender_sp_temp_offset_in_bytes() { return offset_of(UnrollBlock, _sender_sp_temp); } diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 0273edf928f..ec3e3e6ebe3 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -221,6 +221,10 @@ class frame VALUE_OBJ_CLASS_SPEC { // returns the stack pointer of the calling frame intptr_t* sender_sp() const; + // Deoptimization info, if needed (platform dependent). + // Stored in the initial_info field of the unroll info, to be used by + // the platform dependent deoptimization blobs. + intptr_t *initial_deoptimization_info(); // Interpreter frames: From 439b75eb12b15f271d9899da592bfb35987c3c2c Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 8 Sep 2011 05:11:31 -0700 Subject: [PATCH 038/214] 7085860: JSR 292: implement CallSite.setTargetNormal and setTargetVolatile as native methods Reviewed-by: jrose, never --- .../src/share/vm/classfile/javaClasses.cpp | 8 --- .../src/share/vm/classfile/javaClasses.hpp | 21 +++--- hotspot/src/share/vm/oops/klassOop.hpp | 4 +- hotspot/src/share/vm/oops/oop.hpp | 4 +- hotspot/src/share/vm/oops/oop.inline.hpp | 12 +++- hotspot/src/share/vm/prims/methodHandles.cpp | 69 ++++++++++++++----- 6 files changed, 82 insertions(+), 36 deletions(-) diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index b7455b81b91..3f101188f5c 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2707,14 +2707,6 @@ void java_lang_invoke_CallSite::compute_offsets() { } } -oop java_lang_invoke_CallSite::target(oop site) { - return site->obj_field(_target_offset); -} - -void java_lang_invoke_CallSite::set_target(oop site, oop target) { - site->obj_field_put(_target_offset, target); -} - // Support for java_security_AccessControlContext diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 6e144635f4d..045717718ae 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -771,7 +771,7 @@ class java_lang_ref_Reference: AllStatic { ref->obj_field_put(referent_offset, value); } static void set_referent_raw(oop ref, oop value) { - ref->obj_field_raw_put(referent_offset, value); + ref->obj_field_put_raw(referent_offset, value); } static HeapWord* referent_addr(oop ref) { return ref->obj_field_addr(referent_offset); @@ -783,7 +783,7 @@ class java_lang_ref_Reference: AllStatic { ref->obj_field_put(next_offset, value); } static void set_next_raw(oop ref, oop value) { - ref->obj_field_raw_put(next_offset, value); + ref->obj_field_put_raw(next_offset, value); } static HeapWord* next_addr(oop ref) { return ref->obj_field_addr(next_offset); @@ -795,7 +795,7 @@ class java_lang_ref_Reference: AllStatic { ref->obj_field_put(discovered_offset, value); } static void set_discovered_raw(oop ref, oop value) { - ref->obj_field_raw_put(discovered_offset, value); + ref->obj_field_put_raw(discovered_offset, value); } static HeapWord* discovered_addr(oop ref) { return ref->obj_field_addr(discovered_offset); @@ -1163,14 +1163,17 @@ private: public: // Accessors - static oop target(oop site); - static void set_target(oop site, oop target); + static oop target( oop site) { return site->obj_field( _target_offset); } + static void set_target( oop site, oop target) { site->obj_field_put( _target_offset, target); } - static oop caller_method(oop site); - static void set_caller_method(oop site, oop ref); + static volatile oop target_volatile(oop site) { return site->obj_field_volatile( _target_offset); } + static void set_target_volatile(oop site, oop target) { site->obj_field_put_volatile(_target_offset, target); } - static jint caller_bci(oop site); - static void set_caller_bci(oop site, jint bci); + static oop caller_method(oop site); + static void set_caller_method(oop site, oop ref); + + static jint caller_bci(oop site); + static void set_caller_bci(oop site, jint bci); // Testers static bool is_subclass(klassOop klass) { diff --git a/hotspot/src/share/vm/oops/klassOop.hpp b/hotspot/src/share/vm/oops/klassOop.hpp index 7617b8590d1..25dca1d6aaf 100644 --- a/hotspot/src/share/vm/oops/klassOop.hpp +++ b/hotspot/src/share/vm/oops/klassOop.hpp @@ -53,8 +53,10 @@ class klassOopDesc : public oopDesc { private: // These have no implementation since klassOop should never be accessed in this fashion oop obj_field(int offset) const; + volatile oop obj_field_volatile(int offset) const; void obj_field_put(int offset, oop value); - void obj_field_raw_put(int offset, oop value); + void obj_field_put_raw(int offset, oop value); + void obj_field_put_volatile(int offset, oop value); jbyte byte_field(int offset) const; void byte_field_put(int offset, jbyte contents); diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index c778f0d7204..4d2f4537024 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -214,8 +214,10 @@ class oopDesc { // Access to fields in a instanceOop through these methods. oop obj_field(int offset) const; + volatile oop obj_field_volatile(int offset) const; void obj_field_put(int offset, oop value); - void obj_field_raw_put(int offset, oop value); + void obj_field_put_raw(int offset, oop value); + void obj_field_put_volatile(int offset, oop value); jbyte byte_field(int offset) const; void byte_field_put(int offset, jbyte contents); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 01f001c391b..a050f960f9d 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -321,15 +321,25 @@ inline oop oopDesc::obj_field(int offset) const { load_decode_heap_oop(obj_field_addr(offset)) : load_decode_heap_oop(obj_field_addr(offset)); } +inline volatile oop oopDesc::obj_field_volatile(int offset) const { + volatile oop value = obj_field(offset); + OrderAccess::acquire(); + return value; +} inline void oopDesc::obj_field_put(int offset, oop value) { UseCompressedOops ? oop_store(obj_field_addr(offset), value) : oop_store(obj_field_addr(offset), value); } -inline void oopDesc::obj_field_raw_put(int offset, oop value) { +inline void oopDesc::obj_field_put_raw(int offset, oop value) { UseCompressedOops ? encode_store_heap_oop(obj_field_addr(offset), value) : encode_store_heap_oop(obj_field_addr(offset), value); } +inline void oopDesc::obj_field_put_volatile(int offset, oop value) { + OrderAccess::release(); + obj_field_put(offset, value); + OrderAccess::fence(); +} inline jbyte oopDesc::byte_field(int offset) const { return (jbyte) *byte_field_addr(offset); } inline void oopDesc::byte_field_put(int offset, jbyte contents) { *byte_field_addr(offset) = (jint) contents; } diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 3978f47f4ff..df0d70e64d6 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -3081,6 +3081,30 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls, } JVM_END +JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) { + oop call_site = JNIHandles::resolve_non_null(call_site_jh); + oop target = JNIHandles::resolve(target_jh); + { + // Walk all nmethods depending on this call site. + MutexLocker mu(Compile_lock, thread); + Universe::flush_dependents_on(call_site, target); + } + java_lang_invoke_CallSite::set_target(call_site, target); +} +JVM_END + +JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) { + oop call_site = JNIHandles::resolve_non_null(call_site_jh); + oop target = JNIHandles::resolve(target_jh); + { + // Walk all nmethods depending on this call site. + MutexLocker mu(Compile_lock, thread); + Universe::flush_dependents_on(call_site, target); + } + java_lang_invoke_CallSite::set_target_volatile(call_site, target); +} +JVM_END + methodOop MethodHandles::resolve_raise_exception_method(TRAPS) { if (_raise_exception_method != NULL) { // no need to do it twice @@ -3137,12 +3161,15 @@ JVM_END /// JVM_RegisterMethodHandleMethods +#undef CS // Solaris builds complain + #define LANG "Ljava/lang/" #define JLINV "Ljava/lang/invoke/" #define OBJ LANG"Object;" #define CLS LANG"Class;" #define STRG LANG"String;" +#define CS JLINV"CallSite;" #define MT JLINV"MethodType;" #define MH JLINV"MethodHandle;" #define MEM JLINV"MemberName;" @@ -3153,29 +3180,34 @@ JVM_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) -// These are the native methods on sun.invoke.MethodHandleNatives. +// These are the native methods on java.lang.invoke.MethodHandleNatives. static JNINativeMethod methods[] = { // void init(MemberName self, AccessibleObject ref) - {CC"init", CC"("AMH""MH"I)V", FN_PTR(MHN_init_AMH)}, - {CC"init", CC"("BMH""OBJ"I)V", FN_PTR(MHN_init_BMH)}, - {CC"init", CC"("DMH""OBJ"Z"CLS")V", FN_PTR(MHN_init_DMH)}, - {CC"init", CC"("MT")V", FN_PTR(MHN_init_MT)}, - {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHN_init_Mem)}, - {CC"expand", CC"("MEM")V", FN_PTR(MHN_expand_Mem)}, - {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHN_resolve_Mem)}, - {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHN_getTarget)}, - {CC"getConstant", CC"(I)I", FN_PTR(MHN_getConstant)}, + {CC"init", CC"("AMH""MH"I)V", FN_PTR(MHN_init_AMH)}, + {CC"init", CC"("BMH""OBJ"I)V", FN_PTR(MHN_init_BMH)}, + {CC"init", CC"("DMH""OBJ"Z"CLS")V", FN_PTR(MHN_init_DMH)}, + {CC"init", CC"("MT")V", FN_PTR(MHN_init_MT)}, + {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHN_init_Mem)}, + {CC"expand", CC"("MEM")V", FN_PTR(MHN_expand_Mem)}, + {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHN_resolve_Mem)}, + {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHN_getTarget)}, + {CC"getConstant", CC"(I)I", FN_PTR(MHN_getConstant)}, // static native int getNamedCon(int which, Object[] name) - {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHN_getNamedCon)}, + {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHN_getNamedCon)}, // static native int getMembers(Class defc, String matchName, String matchSig, // int matchFlags, Class caller, int skip, MemberName[] results); - {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)} + {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)} +}; + +static JNINativeMethod call_site_methods[] = { + {CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)}, + {CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)} }; static JNINativeMethod invoke_methods[] = { // void init(MemberName self, AccessibleObject ref) - {CC"invoke", CC"(["OBJ")"OBJ, FN_PTR(MH_invoke_UOE)}, - {CC"invokeExact", CC"(["OBJ")"OBJ, FN_PTR(MH_invokeExact_UOE)} + {CC"invoke", CC"(["OBJ")"OBJ, FN_PTR(MH_invoke_UOE)}, + {CC"invokeExact", CC"(["OBJ")"OBJ, FN_PTR(MH_invokeExact_UOE)} }; // This one function is exported, used by NativeLookup. @@ -3188,11 +3220,11 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) return; // bind nothing } + assert(!MethodHandles::enabled(), "must not be enabled"); bool enable_MH = true; { ThreadToNativeFromVM ttnfv(thread); - int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); if (!env->ExceptionOccurred()) { const char* L_MH_name = (JLINV "MethodHandle"); @@ -3201,11 +3233,16 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) status = env->RegisterNatives(MH_class, invoke_methods, sizeof(invoke_methods)/sizeof(JNINativeMethod)); } if (env->ExceptionOccurred()) { - MethodHandles::set_enabled(false); warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); enable_MH = false; env->ExceptionClear(); } + + status = env->RegisterNatives(MHN_class, call_site_methods, sizeof(call_site_methods)/sizeof(JNINativeMethod)); + if (env->ExceptionOccurred()) { + // Exception is okay until 7087357 + env->ExceptionClear(); + } } if (enable_MH) { From 42c3c5cb7be22043ef71b56cdf6437e1539ee508 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 8 Sep 2011 12:44:04 -0700 Subject: [PATCH 039/214] 7087947: Add regression test for 7068051 Add regression test. Reviewed-by: never --- .../test/compiler/7068051/Test7068051.java | 82 +++++++++++++++++++ hotspot/test/compiler/7068051/Test7068051.sh | 49 +++++++++++ 2 files changed, 131 insertions(+) create mode 100644 hotspot/test/compiler/7068051/Test7068051.java create mode 100644 hotspot/test/compiler/7068051/Test7068051.sh diff --git a/hotspot/test/compiler/7068051/Test7068051.java b/hotspot/test/compiler/7068051/Test7068051.java new file mode 100644 index 00000000000..e2b1927aa55 --- /dev/null +++ b/hotspot/test/compiler/7068051/Test7068051.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7068051 + * @summary SIGSEGV in PhaseIdealLoop::build_loop_late_post on T5440 + * + * @run shell/timeout=300 Test7068051.sh + */ + +import java.io.*; +import java.nio.*; +import java.util.*; +import java.util.zip.*; + +public class Test7068051 { + + public static void main (String[] args) throws Throwable { + + ZipFile zf = new ZipFile(args[0]); + + Enumeration entries = zf.entries(); + ArrayList names = new ArrayList(); + while (entries.hasMoreElements()) { + names.add(entries.nextElement().getName()); + } + + byte[] bytes = new byte[16]; + for (String name : names) { + ZipEntry e = zf.getEntry(name); + + if (e.isDirectory()) + continue; + + final InputStream is = zf.getInputStream(e); + + try { + while (is.read(bytes) >= 0) { + } + is.close(); + + } catch (IOException x) { + System.out.println(".................................."); + System.out.println(" --> is :" + is); + System.out.println(" is.hash :" + is.hashCode()); + System.out.println(); + System.out.println(" e.name :" + e.getName()); + System.out.println(" e.hash :" + e.hashCode()); + System.out.println(" e.method :" + e.getMethod()); + System.out.println(" e.size :" + e.getSize()); + System.out.println(" e.csize :" + e.getCompressedSize()); + + x.printStackTrace(); + System.out.println(".................................."); + System.exit(97); + } + } + zf.close(); + } +} diff --git a/hotspot/test/compiler/7068051/Test7068051.sh b/hotspot/test/compiler/7068051/Test7068051.sh new file mode 100644 index 00000000000..ddf3bb9a74c --- /dev/null +++ b/hotspot/test/compiler/7068051/Test7068051.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTSRC=${TESTSRC}" +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTJAVA=${TESTJAVA}" + +set -x + +${TESTJAVA}/bin/jar xf ${TESTJAVA}/jre/lib/javaws.jar +${TESTJAVA}/bin/jar cf foo.jar * +cp ${TESTSRC}/Test7068051.java ./ +${TESTJAVA}/bin/jar -uf0 foo.jar Test7068051.java + +${TESTJAVA}/bin/javac -d . Test7068051.java + +${TESTJAVA}/bin/java -showversion -Xbatch ${TESTVMOPTS} Test7068051 foo.jar + From 499732d316d29d6a0e5d05f157301b277b402282 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 8 Sep 2011 09:35:41 +0200 Subject: [PATCH 040/214] 7087453: PhaseChaitin::yank_if_dead() should handle MachTemp inputs PhaseChaitin::yank_if_dead() should be able to handle MachTemp inputs as a special case and yank them. Reviewed-by: never, kvn --- hotspot/src/share/vm/opto/chaitin.hpp | 1 + hotspot/src/share/vm/opto/postaloc.cpp | 41 ++++++++++++++++++-------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index e379c0c3ceb..af116050c11 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -482,6 +482,7 @@ private: } int yank_if_dead( Node *old, Block *current_block, Node_List *value, Node_List *regnd ); + int yank( Node *old, Block *current_block, Node_List *value, Node_List *regnd ); int elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List ®nd, bool can_change_regs ); int use_prior_register( Node *copy, uint idx, Node *def, Block *current_block, Node_List &value, Node_List ®nd ); bool may_be_copy_of_callee( Node *def ) const; diff --git a/hotspot/src/share/vm/opto/postaloc.cpp b/hotspot/src/share/vm/opto/postaloc.cpp index 897d5102c05..f2605b0cb46 100644 --- a/hotspot/src/share/vm/opto/postaloc.cpp +++ b/hotspot/src/share/vm/opto/postaloc.cpp @@ -72,7 +72,22 @@ bool PhaseChaitin::may_be_copy_of_callee( Node *def ) const { return i == limit; } - +//------------------------------yank----------------------------------- +// Helper function for yank_if_dead +int PhaseChaitin::yank( Node *old, Block *current_block, Node_List *value, Node_List *regnd ) { + int blk_adjust=0; + Block *oldb = _cfg._bbs[old->_idx]; + oldb->find_remove(old); + // Count 1 if deleting an instruction from the current block + if( oldb == current_block ) blk_adjust++; + _cfg._bbs.map(old->_idx,NULL); + OptoReg::Name old_reg = lrgs(n2lidx(old)).reg(); + if( regnd && (*regnd)[old_reg]==old ) { // Instruction is currently available? + value->map(old_reg,NULL); // Yank from value/regnd maps + regnd->map(old_reg,NULL); // This register's value is now unknown + } + return blk_adjust; +} //------------------------------yank_if_dead----------------------------------- // Removed an edge from 'old'. Yank if dead. Return adjustment counts to @@ -80,18 +95,20 @@ bool PhaseChaitin::may_be_copy_of_callee( Node *def ) const { int PhaseChaitin::yank_if_dead( Node *old, Block *current_block, Node_List *value, Node_List *regnd ) { int blk_adjust=0; while (old->outcnt() == 0 && old != C->top()) { - Block *oldb = _cfg._bbs[old->_idx]; - oldb->find_remove(old); - // Count 1 if deleting an instruction from the current block - if( oldb == current_block ) blk_adjust++; - _cfg._bbs.map(old->_idx,NULL); - OptoReg::Name old_reg = lrgs(n2lidx(old)).reg(); - if( regnd && (*regnd)[old_reg]==old ) { // Instruction is currently available? - value->map(old_reg,NULL); // Yank from value/regnd maps - regnd->map(old_reg,NULL); // This register's value is now unknown + blk_adjust += yank(old, current_block, value, regnd); + + Node *tmp = NULL; + for (uint i = 1; i < old->req(); i++) { + if (old->in(i)->is_MachTemp()) { + Node* machtmp = old->in(i); + assert(machtmp->outcnt() == 1, "expected for a MachTemp"); + blk_adjust += yank(machtmp, current_block, value, regnd); + machtmp->disconnect_inputs(NULL); + } else { + assert(tmp == NULL, "can't handle more non MachTemp inputs"); + tmp = old->in(i); + } } - assert(old->req() <= 2, "can't handle more inputs"); - Node *tmp = old->req() > 1 ? old->in(1) : NULL; old->disconnect_inputs(NULL); if( !tmp ) break; old = tmp; From d96de580b6e466feb876f3f071705a1321e22fc7 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Thu, 8 Sep 2011 05:16:49 -0400 Subject: [PATCH 041/214] 7084509: G1: fix inconsistencies and mistakes in the young list target length calculations Fixed inconsistencies and mistakes in the young list target length calculations so that a) the calculated target length is optimal (before, it was not), b) other parameters like max survivor size and max gc locker eden expansion are always consistent with the calculated target length (before, they were not always), and c) the resulting target length was always bound by desired min and max values (before, it was not). Reviewed-by: brutisso, johnc --- .../g1/concurrentG1RefineThread.cpp | 2 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 2 + .../g1/g1CollectorPolicy.cpp | 495 ++++++++++-------- .../g1/g1CollectorPolicy.hpp | 61 ++- .../vm/gc_implementation/g1/g1_globals.hpp | 2 +- 5 files changed, 316 insertions(+), 246 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp index 2e87ca700e9..ee9a1b67aae 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp @@ -91,7 +91,7 @@ void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { } } - g1p->check_prediction_validity(); + g1p->revise_young_list_target_length_if_necessary(); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 0c21f8d48cd..5f8d8aea43b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1682,6 +1682,7 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { } assert(curr == mr.end(), "post-condition"); } + g1_policy()->calculate_reserve(n_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not expand the heap", @@ -1732,6 +1733,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { _expansion_regions += num_regions_deleted; update_committed_space(old_end, new_end); HeapRegionRemSet::shrink_heap(n_regions()); + g1_policy()->calculate_reserve(n_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not shrink the heap", diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 0ebd3e821ec..e83c72c7248 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -414,7 +414,7 @@ G1CollectorPolicy::G1CollectorPolicy() : _concurrent_mark_cleanup_times_ms->add(0.20); _tenuring_threshold = MaxTenuringThreshold; // _max_survivor_regions will be calculated by - // calculate_young_list_target_length() during initialization. + // update_young_list_target_length() during initialization. _max_survivor_regions = 0; assert(GCTimeRatio > 0, @@ -422,6 +422,18 @@ G1CollectorPolicy::G1CollectorPolicy() : "if a user set it to 0"); _gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio)); + uintx reserve_perc = G1ReservePercent; + // Put an artificial ceiling on this so that it's not set to a silly value. + if (reserve_perc > 50) { + reserve_perc = 50; + warning("G1ReservePercent is set to a value that is too large, " + "it's been updated to %u", reserve_perc); + } + _reserve_factor = (double) reserve_perc / 100.0; + // This will be set in calculate_reserve() when the heap is expanded + // for the first time during initialization. + _reserve_regions = 0; + initialize_all(); } @@ -486,9 +498,7 @@ void G1CollectorPolicy::init() { _young_list_fixed_length = initial_region_num; } _free_regions_at_end_of_collection = _g1->free_regions(); - calculate_young_list_min_length(); - guarantee( _young_list_min_length == 0, "invariant, not enough info" ); - calculate_young_list_target_length(); + update_young_list_target_length(); // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info @@ -496,238 +506,254 @@ void G1CollectorPolicy::init() { } // Create the jstat counters for the policy. -void G1CollectorPolicy::initialize_gc_policy_counters() -{ +void G1CollectorPolicy::initialize_gc_policy_counters() { _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 3); } -void G1CollectorPolicy::calculate_young_list_min_length() { - _young_list_min_length = 0; - - if (!adaptive_young_list_length()) - return; - - if (_alloc_rate_ms_seq->num() > 3) { - double now_sec = os::elapsedTime(); - double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; - double alloc_rate_ms = predict_alloc_rate_ms(); - size_t min_regions = (size_t) ceil(alloc_rate_ms * when_ms); - size_t current_region_num = _g1->young_list()->length(); - _young_list_min_length = min_regions + current_region_num; - } -} - -void G1CollectorPolicy::calculate_young_list_target_length() { - if (adaptive_young_list_length()) { - size_t rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq); - calculate_young_list_target_length(rs_lengths); - } else { - if (full_young_gcs()) - _young_list_target_length = _young_list_fixed_length; - else - _young_list_target_length = _young_list_fixed_length / 2; - } - - // Make sure we allow the application to allocate at least one - // region before we need to do a collection again. - size_t min_length = _g1->young_list()->length() + 1; - _young_list_target_length = MAX2(_young_list_target_length, min_length); - calculate_max_gc_locker_expansion(); - calculate_survivors_policy(); -} - -void G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths) { - guarantee( adaptive_young_list_length(), "pre-condition" ); - guarantee( !_in_marking_window || !_last_full_young_gc, "invariant" ); - - double start_time_sec = os::elapsedTime(); - size_t min_reserve_perc = MAX2((size_t)2, (size_t)G1ReservePercent); - min_reserve_perc = MIN2((size_t) 50, min_reserve_perc); - size_t reserve_regions = - (size_t) ((double) min_reserve_perc * (double) _g1->n_regions() / 100.0); - - if (full_young_gcs() && _free_regions_at_end_of_collection > 0) { - // we are in fully-young mode and there are free regions in the heap - - double survivor_regions_evac_time = - predict_survivor_regions_evac_time(); - - double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; - size_t pending_cards = (size_t) get_new_prediction(_pending_cards_seq); - size_t adj_rs_lengths = rs_lengths + predict_rs_length_diff(); - size_t scanned_cards = predict_young_card_num(adj_rs_lengths); - double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards) - + survivor_regions_evac_time; - - // the result - size_t final_young_length = 0; - - size_t init_free_regions = - MAX2((size_t)0, _free_regions_at_end_of_collection - reserve_regions); - - // if we're still under the pause target... - if (base_time_ms <= target_pause_time_ms) { - // We make sure that the shortest young length that makes sense - // fits within the target pause time. - size_t min_young_length = 1; - - if (predict_will_fit(min_young_length, base_time_ms, - init_free_regions, target_pause_time_ms)) { - // The shortest young length will fit within the target pause time; - // we'll now check whether the absolute maximum number of young - // regions will fit in the target pause time. If not, we'll do - // a binary search between min_young_length and max_young_length - size_t abs_max_young_length = _free_regions_at_end_of_collection - 1; - size_t max_young_length = abs_max_young_length; - - if (max_young_length > min_young_length) { - // Let's check if the initial max young length will fit within the - // target pause. If so then there is no need to search for a maximal - // young length - we'll return the initial maximum - - if (predict_will_fit(max_young_length, base_time_ms, - init_free_regions, target_pause_time_ms)) { - // The maximum young length will satisfy the target pause time. - // We are done so set min young length to this maximum length. - // The code after the loop will then set final_young_length using - // the value cached in the minimum length. - min_young_length = max_young_length; - } else { - // The maximum possible number of young regions will not fit within - // the target pause time so let's search.... - - size_t diff = (max_young_length - min_young_length) / 2; - max_young_length = min_young_length + diff; - - while (max_young_length > min_young_length) { - if (predict_will_fit(max_young_length, base_time_ms, - init_free_regions, target_pause_time_ms)) { - - // The current max young length will fit within the target - // pause time. Note we do not exit the loop here. By setting - // min = max, and then increasing the max below means that - // we will continue searching for an upper bound in the - // range [max..max+diff] - min_young_length = max_young_length; - } - diff = (max_young_length - min_young_length) / 2; - max_young_length = min_young_length + diff; - } - // the above loop found a maximal young length that will fit - // within the target pause time. - } - assert(min_young_length <= abs_max_young_length, "just checking"); - } - final_young_length = min_young_length; - } - } - // and we're done! - - // we should have at least one region in the target young length - _young_list_target_length = - final_young_length + _recorded_survivor_regions; - - // let's keep an eye of how long we spend on this calculation - // right now, I assume that we'll print it when we need it; we - // should really adde it to the breakdown of a pause - double end_time_sec = os::elapsedTime(); - double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0; - -#ifdef TRACE_CALC_YOUNG_LENGTH - // leave this in for debugging, just in case - gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT ", " - "elapsed %1.2lf ms, (%s%s) " SIZE_FORMAT SIZE_FORMAT, - target_pause_time_ms, - _young_list_target_length - elapsed_time_ms, - full_young_gcs() ? "full" : "partial", - during_initial_mark_pause() ? " i-m" : "", - _in_marking_window, - _in_marking_window_im); -#endif // TRACE_CALC_YOUNG_LENGTH - - if (_young_list_target_length < _young_list_min_length) { - // bummer; this means that, if we do a pause when the maximal - // length dictates, we'll violate the pause spacing target (the - // min length was calculate based on the application's current - // alloc rate); - - // so, we have to bite the bullet, and allocate the minimum - // number. We'll violate our target, but we just can't meet it. - -#ifdef TRACE_CALC_YOUNG_LENGTH - // leave this in for debugging, just in case - gclog_or_tty->print_cr("adjusted target length from " - SIZE_FORMAT " to " SIZE_FORMAT, - _young_list_target_length, _young_list_min_length); -#endif // TRACE_CALC_YOUNG_LENGTH - - _young_list_target_length = _young_list_min_length; - } - } else { - // we are in a partially-young mode or we've run out of regions (due - // to evacuation failure) - -#ifdef TRACE_CALC_YOUNG_LENGTH - // leave this in for debugging, just in case - gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT - _young_list_min_length); -#endif // TRACE_CALC_YOUNG_LENGTH - // we'll do the pause as soon as possible by choosing the minimum - _young_list_target_length = _young_list_min_length; - } - - _rs_lengths_prediction = rs_lengths; -} - -// This is used by: calculate_young_list_target_length(rs_length). It -// returns true iff: -// the predicted pause time for the given young list will not overflow -// the target pause time -// and: -// the predicted amount of surviving data will not overflow the -// the amount of free space available for survivor regions. -// -bool -G1CollectorPolicy::predict_will_fit(size_t young_length, - double base_time_ms, - size_t init_free_regions, - double target_pause_time_ms) { - - if (young_length >= init_free_regions) +bool G1CollectorPolicy::predict_will_fit(size_t young_length, + double base_time_ms, + size_t base_free_regions, + double target_pause_time_ms) { + if (young_length >= base_free_regions) { // end condition 1: not enough space for the young regions return false; + } - double accum_surv_rate_adj = 0.0; - double accum_surv_rate = - accum_yg_surv_rate_pred((int)(young_length - 1)) - accum_surv_rate_adj; - + double accum_surv_rate = accum_yg_surv_rate_pred((int)(young_length - 1)); size_t bytes_to_copy = - (size_t) (accum_surv_rate * (double) HeapRegion::GrainBytes); - + (size_t) (accum_surv_rate * (double) HeapRegion::GrainBytes); double copy_time_ms = predict_object_copy_time_ms(bytes_to_copy); - - double young_other_time_ms = - predict_young_other_time_ms(young_length); - - double pause_time_ms = - base_time_ms + copy_time_ms + young_other_time_ms; - - if (pause_time_ms > target_pause_time_ms) - // end condition 2: over the target pause time + double young_other_time_ms = predict_young_other_time_ms(young_length); + double pause_time_ms = base_time_ms + copy_time_ms + young_other_time_ms; + if (pause_time_ms > target_pause_time_ms) { + // end condition 2: prediction is over the target pause time return false; + } size_t free_bytes = - (init_free_regions - young_length) * HeapRegion::GrainBytes; - - if ((2.0 + sigma()) * (double) bytes_to_copy > (double) free_bytes) - // end condition 3: out of to-space (conservatively) + (base_free_regions - young_length) * HeapRegion::GrainBytes; + if ((2.0 * sigma()) * (double) bytes_to_copy > (double) free_bytes) { + // end condition 3: out-of-space (conservatively!) return false; + } // success! return true; } +void G1CollectorPolicy::calculate_reserve(size_t all_regions) { + double reserve_regions_d = (double) all_regions * _reserve_factor; + // We use ceiling so that if reserve_regions_d is > 0.0 (but + // smaller than 1.0) we'll get 1. + _reserve_regions = (size_t) ceil(reserve_regions_d); +} + +size_t G1CollectorPolicy::calculate_young_list_desired_min_length( + size_t base_min_length) { + size_t desired_min_length = 0; + if (adaptive_young_list_length()) { + if (_alloc_rate_ms_seq->num() > 3) { + double now_sec = os::elapsedTime(); + double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; + double alloc_rate_ms = predict_alloc_rate_ms(); + desired_min_length = (size_t) ceil(alloc_rate_ms * when_ms); + } else { + // otherwise we don't have enough info to make the prediction + } + } + // Here, we might want to also take into account any additional + // constraints (i.e., user-defined minimum bound). Currently, we don't. + return base_min_length + desired_min_length; +} + +size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { + // Here, we might want to also take into account any additional + // constraints (i.e., user-defined minimum bound). Currently, we + // effectively don't set this bound. + return _g1->n_regions(); +} + +void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { + if (rs_lengths == (size_t) -1) { + // if it's set to the default value (-1), we should predict it; + // otherwise, use the given value. + rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq); + } + + // Calculate the absolute and desired min bounds. + + // This is how many young regions we already have (currently: the survivors). + size_t base_min_length = recorded_survivor_regions(); + // This is the absolute minimum young length, which ensures that we + // can allocate one eden region in the worst-case. + size_t absolute_min_length = base_min_length + 1; + size_t desired_min_length = + calculate_young_list_desired_min_length(base_min_length); + if (desired_min_length < absolute_min_length) { + desired_min_length = absolute_min_length; + } + + // Calculate the absolute and desired max bounds. + + // We will try our best not to "eat" into the reserve. + size_t absolute_max_length = 0; + if (_free_regions_at_end_of_collection > _reserve_regions) { + absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions; + } + size_t desired_max_length = calculate_young_list_desired_max_length(); + if (desired_max_length > absolute_max_length) { + desired_max_length = absolute_max_length; + } + + size_t young_list_target_length = 0; + if (adaptive_young_list_length()) { + if (full_young_gcs()) { + young_list_target_length = + calculate_young_list_target_length(rs_lengths, + base_min_length, + desired_min_length, + desired_max_length); + _rs_lengths_prediction = rs_lengths; + } else { + // Don't calculate anything and let the code below bound it to + // the desired_min_length, i.e., do the next GC as soon as + // possible to maximize how many old regions we can add to it. + } + } else { + if (full_young_gcs()) { + young_list_target_length = _young_list_fixed_length; + } else { + // A bit arbitrary: during partially-young GCs we allocate half + // the young regions to try to add old regions to the CSet. + young_list_target_length = _young_list_fixed_length / 2; + // We choose to accept that we might go under the desired min + // length given that we intentionally ask for a smaller young gen. + desired_min_length = absolute_min_length; + } + } + + // Make sure we don't go over the desired max length, nor under the + // desired min length. In case they clash, desired_min_length wins + // which is why that test is second. + if (young_list_target_length > desired_max_length) { + young_list_target_length = desired_max_length; + } + if (young_list_target_length < desired_min_length) { + young_list_target_length = desired_min_length; + } + + assert(young_list_target_length > recorded_survivor_regions(), + "we should be able to allocate at least one eden region"); + assert(young_list_target_length >= absolute_min_length, "post-condition"); + _young_list_target_length = young_list_target_length; + + update_max_gc_locker_expansion(); +} + +size_t +G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths, + size_t base_min_length, + size_t desired_min_length, + size_t desired_max_length) { + assert(adaptive_young_list_length(), "pre-condition"); + assert(full_young_gcs(), "only call this for fully-young GCs"); + + // In case some edge-condition makes the desired max length too small... + if (desired_max_length <= desired_min_length) { + return desired_min_length; + } + + // We'll adjust min_young_length and max_young_length not to include + // the already allocated young regions (i.e., so they reflect the + // min and max eden regions we'll allocate). The base_min_length + // will be reflected in the predictions by the + // survivor_regions_evac_time prediction. + assert(desired_min_length > base_min_length, "invariant"); + size_t min_young_length = desired_min_length - base_min_length; + assert(desired_max_length > base_min_length, "invariant"); + size_t max_young_length = desired_max_length - base_min_length; + + double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; + double survivor_regions_evac_time = predict_survivor_regions_evac_time(); + size_t pending_cards = (size_t) get_new_prediction(_pending_cards_seq); + size_t adj_rs_lengths = rs_lengths + predict_rs_length_diff(); + size_t scanned_cards = predict_young_card_num(adj_rs_lengths); + double base_time_ms = + predict_base_elapsed_time_ms(pending_cards, scanned_cards) + + survivor_regions_evac_time; + size_t available_free_regions = _free_regions_at_end_of_collection; + size_t base_free_regions = 0; + if (available_free_regions > _reserve_regions) { + base_free_regions = available_free_regions - _reserve_regions; + } + + // Here, we will make sure that the shortest young length that + // makes sense fits within the target pause time. + + if (predict_will_fit(min_young_length, base_time_ms, + base_free_regions, target_pause_time_ms)) { + // The shortest young length will fit into the target pause time; + // we'll now check whether the absolute maximum number of young + // regions will fit in the target pause time. If not, we'll do + // a binary search between min_young_length and max_young_length. + if (predict_will_fit(max_young_length, base_time_ms, + base_free_regions, target_pause_time_ms)) { + // The maximum young length will fit into the target pause time. + // We are done so set min young length to the maximum length (as + // the result is assumed to be returned in min_young_length). + min_young_length = max_young_length; + } else { + // The maximum possible number of young regions will not fit within + // the target pause time so we'll search for the optimal + // length. The loop invariants are: + // + // min_young_length < max_young_length + // min_young_length is known to fit into the target pause time + // max_young_length is known not to fit into the target pause time + // + // Going into the loop we know the above hold as we've just + // checked them. Every time around the loop we check whether + // the middle value between min_young_length and + // max_young_length fits into the target pause time. If it + // does, it becomes the new min. If it doesn't, it becomes + // the new max. This way we maintain the loop invariants. + + assert(min_young_length < max_young_length, "invariant"); + size_t diff = (max_young_length - min_young_length) / 2; + while (diff > 0) { + size_t young_length = min_young_length + diff; + if (predict_will_fit(young_length, base_time_ms, + base_free_regions, target_pause_time_ms)) { + min_young_length = young_length; + } else { + max_young_length = young_length; + } + assert(min_young_length < max_young_length, "invariant"); + diff = (max_young_length - min_young_length) / 2; + } + // The results is min_young_length which, according to the + // loop invariants, should fit within the target pause time. + + // These are the post-conditions of the binary search above: + assert(min_young_length < max_young_length, + "otherwise we should have discovered that max_young_length " + "fits into the pause target and not done the binary search"); + assert(predict_will_fit(min_young_length, base_time_ms, + base_free_regions, target_pause_time_ms), + "min_young_length, the result of the binary search, should " + "fit into the pause target"); + assert(!predict_will_fit(min_young_length + 1, base_time_ms, + base_free_regions, target_pause_time_ms), + "min_young_length, the result of the binary search, should be " + "optimal, so no larger length should fit into the pause target"); + } + } else { + // Even the minimum length doesn't fit into the pause time + // target, return it as the result nevertheless. + } + return base_min_length + min_young_length; +} + double G1CollectorPolicy::predict_survivor_regions_evac_time() { double survivor_regions_evac_time = 0.0; for (HeapRegion * r = _recorded_survivor_head; @@ -738,17 +764,19 @@ double G1CollectorPolicy::predict_survivor_regions_evac_time() { return survivor_regions_evac_time; } -void G1CollectorPolicy::check_prediction_validity() { +void G1CollectorPolicy::revise_young_list_target_length_if_necessary() { guarantee( adaptive_young_list_length(), "should not call this otherwise" ); size_t rs_lengths = _g1->young_list()->sampled_rs_lengths(); if (rs_lengths > _rs_lengths_prediction) { // add 10% to avoid having to recalculate often size_t rs_lengths_prediction = rs_lengths * 1100 / 1000; - calculate_young_list_target_length(rs_lengths_prediction); + update_young_list_target_length(rs_lengths_prediction); } } + + HeapWord* G1CollectorPolicy::mem_allocate_work(size_t size, bool is_tlab, bool* gc_overhead_limit_was_exceeded) { @@ -855,8 +883,7 @@ void G1CollectorPolicy::record_full_collection_end() { _free_regions_at_end_of_collection = _g1->free_regions(); // Reset survivors SurvRateGroup. _survivor_surv_rate_group->reset(); - calculate_young_list_min_length(); - calculate_young_list_target_length(); + update_young_list_target_length(); } void G1CollectorPolicy::record_stop_world_start() { @@ -871,6 +898,11 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial"); } + // We only need to do this here as the policy will only be applied + // to the GC we're about to start. so, no point is calculating this + // every time we calculate / recalculate the target young length. + update_survivors_policy(); + assert(_g1->used() == _g1->recalculate_used(), err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT, _g1->used(), _g1->recalculate_used())); @@ -996,8 +1028,6 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { _should_revert_to_full_young_gcs = false; _last_full_young_gc = true; _in_marking_window = false; - if (adaptive_young_list_length()) - calculate_young_list_target_length(); } void G1CollectorPolicy::record_concurrent_pause() { @@ -1648,8 +1678,7 @@ void G1CollectorPolicy::record_collection_pause_end() { _in_marking_window = new_in_marking_window; _in_marking_window_im = new_in_marking_window_im; _free_regions_at_end_of_collection = _g1->free_regions(); - calculate_young_list_min_length(); - calculate_young_list_target_length(); + update_young_list_target_length(); // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; @@ -2324,7 +2353,7 @@ size_t G1CollectorPolicy::max_regions(int purpose) { }; } -void G1CollectorPolicy::calculate_max_gc_locker_expansion() { +void G1CollectorPolicy::update_max_gc_locker_expansion() { size_t expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { double perc = (double) GCLockerEdenExpansionPercent / 100.0; @@ -2340,9 +2369,13 @@ void G1CollectorPolicy::calculate_max_gc_locker_expansion() { } // Calculates survivor space parameters. -void G1CollectorPolicy::calculate_survivors_policy() -{ - _max_survivor_regions = _young_list_target_length / SurvivorRatio; +void G1CollectorPolicy::update_survivors_policy() { + double max_survivor_regions_d = + (double) _young_list_target_length / (double) SurvivorRatio; + // We use ceiling so that if max_survivor_regions_d is > 0.0 (but + // smaller than 1.0) we'll get 1. + _max_survivor_regions = (size_t) ceil(max_survivor_regions_d); + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( HeapRegion::GrainWords * _max_survivor_regions); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index c29c365cb75..c07e6edc067 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -183,7 +183,6 @@ protected: // if true, then it tries to dynamically adjust the length of the // young list bool _adaptive_young_list_length; - size_t _young_list_min_length; size_t _young_list_target_length; size_t _young_list_fixed_length; @@ -207,6 +206,9 @@ protected: double _gc_overhead_perc; + double _reserve_factor; + size_t _reserve_regions; + bool during_marking() { return _during_marking; } @@ -456,12 +458,6 @@ public: size_t predict_bytes_to_copy(HeapRegion* hr); double predict_region_elapsed_time_ms(HeapRegion* hr, bool young); - // for use by: calculate_young_list_target_length(rs_length) - bool predict_will_fit(size_t young_region_num, - double base_time_ms, - size_t init_free_regions, - double target_pause_time_ms); - void start_recording_regions(); void record_cset_region_info(HeapRegion* hr, bool young); void record_non_young_cset_region(HeapRegion* hr); @@ -771,9 +767,41 @@ protected: double _mark_cleanup_start_sec; double _mark_closure_time_ms; - void calculate_young_list_min_length(); - void calculate_young_list_target_length(); - void calculate_young_list_target_length(size_t rs_lengths); + // Update the young list target length either by setting it to the + // desired fixed value or by calculating it using G1's pause + // prediction model. If no rs_lengths parameter is passed, predict + // the RS lengths using the prediction model, otherwise use the + // given rs_lengths as the prediction. + void update_young_list_target_length(size_t rs_lengths = (size_t) -1); + + // Calculate and return the minimum desired young list target + // length. This is the minimum desired young list length according + // to the user's inputs. + size_t calculate_young_list_desired_min_length(size_t base_min_length); + + // Calculate and return the maximum desired young list target + // length. This is the maximum desired young list length according + // to the user's inputs. + size_t calculate_young_list_desired_max_length(); + + // Calculate and return the maximum young list target length that + // can fit into the pause time goal. The parameters are: rs_lengths + // represent the prediction of how large the young RSet lengths will + // be, base_min_length is the alreay existing number of regions in + // the young list, min_length and max_length are the desired min and + // max young list length according to the user's inputs. + size_t calculate_young_list_target_length(size_t rs_lengths, + size_t base_min_length, + size_t desired_min_length, + size_t desired_max_length); + + // Check whether a given young length (young_length) fits into the + // given target pause time and whether the prediction for the amount + // of objects to be copied for the given length will fit into the + // given free space (expressed by base_free_regions). It is used by + // calculate_young_list_target_length(). + bool predict_will_fit(size_t young_length, double base_time_ms, + size_t base_free_regions, double target_pause_time_ms); public: @@ -785,7 +813,10 @@ public: return CollectorPolicy::G1CollectorPolicyKind; } - void check_prediction_validity(); + // Check the current value of the young list RSet lengths and + // compare it against the last prediction. If the current value is + // higher, recalculate the young list target length prediction. + void revise_young_list_target_length_if_necessary(); size_t bytes_in_collection_set() { return _bytes_in_collection_set_before_gc; @@ -795,6 +826,10 @@ public: return _all_pause_times_ms->num() + 1; } + // Recalculate the reserve region number. This should be called + // after the heap is resized. + void calculate_reserve(size_t all_regions); + protected: // Count the number of bytes used in the CS. @@ -1203,10 +1238,10 @@ public: _survivors_age_table.merge_par(age_table); } - void calculate_max_gc_locker_expansion(); + void update_max_gc_locker_expansion(); // Calculates survivor space parameters. - void calculate_survivors_policy(); + void update_survivors_policy(); }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 94f0ada6920..0e71a85b1c5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -228,7 +228,7 @@ "the number of regions for which we'll print a surv rate " \ "summary.") \ \ - product(intx, G1ReservePercent, 10, \ + product(uintx, G1ReservePercent, 10, \ "It determines the minimum reserve we should have in the heap " \ "to minimize the probability of promotion failure.") \ \ From 0be11c915cb69eabce348cc67a283a4e99f653f4 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Thu, 8 Sep 2011 16:29:41 +0200 Subject: [PATCH 042/214] 6929868: G1: introduce min / max young gen size bounds Make G1 handle young gen size command line flags more consistently Reviewed-by: tonyp, jwilhelm --- .../gc_implementation/g1/g1CollectedHeap.cpp | 17 +++- .../g1/g1CollectorPolicy.cpp | 91 +++++++++++++------ .../g1/g1CollectorPolicy.hpp | 12 ++- 3 files changed, 89 insertions(+), 31 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 5f8d8aea43b..9d628451002 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1682,7 +1682,7 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { } assert(curr == mr.end(), "post-condition"); } - g1_policy()->calculate_reserve(n_regions()); + g1_policy()->record_new_heap_size(n_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not expand the heap", @@ -1733,7 +1733,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { _expansion_regions += num_regions_deleted; update_committed_space(old_end, new_end); HeapRegionRemSet::shrink_heap(n_regions()); - g1_policy()->calculate_reserve(n_regions()); + g1_policy()->record_new_heap_size(n_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not shrink the heap", @@ -3525,6 +3525,19 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { init_mutator_alloc_region(); + { + size_t expand_bytes = g1_policy()->expansion_amount(); + if (expand_bytes > 0) { + size_t bytes_before = capacity(); + if (!expand(expand_bytes)) { + // We failed to expand the heap so let's verify that + // committed/uncommitted amount match the backing store + assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); + assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + } + } + } + double end_time_sec = os::elapsedTime(); double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; g1_policy()->record_pause_time_ms(pause_time_ms); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index e83c72c7248..306eec115c8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -146,6 +146,7 @@ G1CollectorPolicy::G1CollectorPolicy() : _stop_world_start(0.0), _all_stop_world_times_ms(new NumberSeq()), _all_yield_times_ms(new NumberSeq()), + _using_new_ratio_calculations(false), _all_mod_union_times_ms(new NumberSeq()), @@ -430,7 +431,7 @@ G1CollectorPolicy::G1CollectorPolicy() : "it's been updated to %u", reserve_perc); } _reserve_factor = (double) reserve_perc / 100.0; - // This will be set in calculate_reserve() when the heap is expanded + // This will be set when the heap is expanded // for the first time during initialization. _reserve_regions = 0; @@ -458,16 +459,15 @@ void G1CollectorPolicy::initialize_flags() { // ParallelScavengeHeap::initialize()). We might change this in the // future, but it's a good start. class G1YoungGenSizer : public TwoGenerationCollectorPolicy { - size_t size_to_region_num(size_t byte_size) { - return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); - } public: G1YoungGenSizer() { initialize_flags(); initialize_size_info(); } - + size_t size_to_region_num(size_t byte_size) { + return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); + } size_t min_young_region_num() { return size_to_region_num(_min_gen0_size); } @@ -479,6 +479,13 @@ public: } }; +void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) { + assert(number_of_heap_regions > 0, "Heap must be initialized"); + size_t young_size = number_of_heap_regions / (NewRatio + 1); + _min_desired_young_length = young_size; + _max_desired_young_length = young_size; +} + void G1CollectorPolicy::init() { // Set aside an initial future to_space. _g1 = G1CollectedHeap::heap(); @@ -489,16 +496,35 @@ void G1CollectorPolicy::init() { G1YoungGenSizer sizer; size_t initial_region_num = sizer.initial_young_region_num(); + _min_desired_young_length = sizer.min_young_region_num(); + _max_desired_young_length = sizer.max_young_region_num(); - if (UseAdaptiveSizePolicy) { - set_adaptive_young_list_length(true); + if (FLAG_IS_CMDLINE(NewRatio)) { + if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { + gclog_or_tty->print_cr("-XX:NewSize and -XX:MaxNewSize overrides -XX:NewRatio"); + } else { + // Treat NewRatio as a fixed size that is only recalculated when the heap size changes + size_t heap_regions = sizer.size_to_region_num(_g1->n_regions()); + update_young_list_size_using_newratio(heap_regions); + _using_new_ratio_calculations = true; + } + } + + // GenCollectorPolicy guarantees that min <= initial <= max. + // Asserting here just to state that we rely on this property. + assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); + assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large"); + assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small"); + + set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length); + if (adaptive_young_list_length()) { _young_list_fixed_length = 0; } else { - set_adaptive_young_list_length(false); _young_list_fixed_length = initial_region_num; } _free_regions_at_end_of_collection = _g1->free_regions(); update_young_list_target_length(); + _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes; // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info @@ -541,11 +567,18 @@ bool G1CollectorPolicy::predict_will_fit(size_t young_length, return true; } -void G1CollectorPolicy::calculate_reserve(size_t all_regions) { - double reserve_regions_d = (double) all_regions * _reserve_factor; +void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) { + // re-calculate the necessary reserve + double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; // We use ceiling so that if reserve_regions_d is > 0.0 (but // smaller than 1.0) we'll get 1. _reserve_regions = (size_t) ceil(reserve_regions_d); + + if (_using_new_ratio_calculations) { + // -XX:NewRatio was specified so we need to update the + // young gen length when the heap size has changed. + update_young_list_size_using_newratio(new_number_of_regions); + } } size_t G1CollectorPolicy::calculate_young_list_desired_min_length( @@ -561,16 +594,16 @@ size_t G1CollectorPolicy::calculate_young_list_desired_min_length( // otherwise we don't have enough info to make the prediction } } - // Here, we might want to also take into account any additional - // constraints (i.e., user-defined minimum bound). Currently, we don't. - return base_min_length + desired_min_length; + desired_min_length += base_min_length; + // make sure we don't go below any user-defined minimum bound + return MAX2(_min_desired_young_length, desired_min_length); } size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { // Here, we might want to also take into account any additional // constraints (i.e., user-defined minimum bound). Currently, we // effectively don't set this bound. - return _g1->n_regions(); + return _max_desired_young_length; } void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { @@ -1699,20 +1732,26 @@ void G1CollectorPolicy::print_heap_transition() { size_t used_before_gc = _cur_collection_pause_used_at_start_bytes; size_t used = _g1->used(); size_t capacity = _g1->capacity(); + size_t eden_capacity = + (_young_list_target_length * HeapRegion::GrainBytes) - survivor_bytes; gclog_or_tty->print_cr( - " [Eden: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " - "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " - "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" - EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", - EXT_SIZE_PARAMS(_eden_bytes_before_gc), - EXT_SIZE_PARAMS(eden_bytes), - EXT_SIZE_PARAMS(_survivor_bytes_before_gc), - EXT_SIZE_PARAMS(survivor_bytes), - EXT_SIZE_PARAMS(used_before_gc), - EXT_SIZE_PARAMS(_capacity_before_gc), - EXT_SIZE_PARAMS(used), - EXT_SIZE_PARAMS(capacity)); + " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") " + "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " + "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" + EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", + EXT_SIZE_PARAMS(_eden_bytes_before_gc), + EXT_SIZE_PARAMS(_prev_eden_capacity), + EXT_SIZE_PARAMS(eden_bytes), + EXT_SIZE_PARAMS(eden_capacity), + EXT_SIZE_PARAMS(_survivor_bytes_before_gc), + EXT_SIZE_PARAMS(survivor_bytes), + EXT_SIZE_PARAMS(used_before_gc), + EXT_SIZE_PARAMS(_capacity_before_gc), + EXT_SIZE_PARAMS(used), + EXT_SIZE_PARAMS(capacity)); + + _prev_eden_capacity = eden_capacity; } else if (PrintGC) { _g1->print_size_transition(gclog_or_tty, _cur_collection_pause_used_at_start_bytes, diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index c07e6edc067..9dc7349fa47 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -185,6 +185,7 @@ protected: bool _adaptive_young_list_length; size_t _young_list_target_length; size_t _young_list_fixed_length; + size_t _prev_eden_capacity; // used for logging // The max number of regions we can extend the eden by while the GC // locker is active. This should be >= _young_list_target_length; @@ -245,6 +246,10 @@ private: TruncatedSeq* _max_conc_overhead_seq; + bool _using_new_ratio_calculations; + size_t _min_desired_young_length; // as set on the command line or default calculations + size_t _max_desired_young_length; // as set on the command line or default calculations + size_t _recorded_young_regions; size_t _recorded_non_young_regions; size_t _recorded_region_num; @@ -826,9 +831,8 @@ public: return _all_pause_times_ms->num() + 1; } - // Recalculate the reserve region number. This should be called - // after the heap is resized. - void calculate_reserve(size_t all_regions); + // This should be called after the heap is resized. + void record_new_heap_size(size_t new_number_of_regions); protected: @@ -841,6 +845,8 @@ protected: size_t max_live_bytes); void record_concurrent_mark_cleanup_end_work2(); + void update_young_list_size_using_newratio(size_t number_of_heap_regions); + public: virtual void init(); From 1a9d9b84f833f068a73ac0050eba9f1c4d1259ce Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Fri, 9 Sep 2011 05:20:58 -0400 Subject: [PATCH 043/214] 7087717: G1: make the G1PrintRegionLivenessInfo parameter diagnostic Reviewed-by: brutisso, ysr --- hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 0e71a85b1c5..1e2ab289363 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -134,9 +134,9 @@ develop(bool, G1RSCountHisto, false, \ "If true, print a histogram of RS occupancies after each pause") \ \ - product(bool, G1PrintRegionLivenessInfo, false, \ - "Prints the liveness information for all regions in the heap " \ - "at the end of a marking cycle.") \ + diagnostic(bool, G1PrintRegionLivenessInfo, false, \ + "Prints the liveness information for all regions in the heap " \ + "at the end of a marking cycle.") \ \ develop(bool, G1PrintParCleanupStats, false, \ "When true, print extra stats about parallel cleanup.") \ From 92b2b44b1825ce28eb34192e7903097c09209f52 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 9 Sep 2011 13:47:11 -0700 Subject: [PATCH 044/214] 7035946: Up to 15% regression on JDK 7 b136 vs b135 on specjvm2008.crypto.rsa on x64 Revert changes which caused regression. Reviewed-by: never --- hotspot/src/share/vm/opto/loopnode.cpp | 55 +++++++++++++++----------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp index 688c5c0b03c..2243c39e553 100644 --- a/hotspot/src/share/vm/opto/loopnode.cpp +++ b/hotspot/src/share/vm/opto/loopnode.cpp @@ -582,20 +582,25 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { // Build a canonical trip test. // Clone code, as old values may be in use. - Node* nphi = PhiNode::make(x, init_trip, TypeInt::INT); - nphi = _igvn.register_new_node_with_optimizer(nphi); - set_ctrl(nphi, get_ctrl(phi)); - incr = incr->clone(); - incr->set_req(1,nphi); + incr->set_req(1,phi); incr->set_req(2,stride); incr = _igvn.register_new_node_with_optimizer(incr); set_early_ctrl( incr ); + _igvn.hash_delete(phi); + phi->set_req_X( LoopNode::LoopBackControl, incr, &_igvn ); - nphi->set_req(LoopNode::LoopBackControl, incr); - _igvn.replace_node(phi, nphi); - phi = nphi->as_Phi(); - + // If phi type is more restrictive than Int, raise to + // Int to prevent (almost) infinite recursion in igvn + // which can only handle integer types for constants or minint..maxint. + if (!TypeInt::INT->higher_equal(phi->bottom_type())) { + Node* nphi = PhiNode::make(phi->in(0), phi->in(LoopNode::EntryControl), TypeInt::INT); + nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl)); + nphi = _igvn.register_new_node_with_optimizer(nphi); + set_ctrl(nphi, get_ctrl(phi)); + _igvn.replace_node(phi, nphi); + phi = nphi->as_Phi(); + } cmp = cmp->clone(); cmp->set_req(1,incr); cmp->set_req(2,limit); @@ -1618,8 +1623,6 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { Node *phi = cl->phi(); int stride_con = cl->stride_con(); - PhaseGVN *gvn = &_igvn; - // Visit all children, looking for Phis for (DUIterator i = cl->outs(); cl->has_out(i); i++) { Node *out = cl->out(i); @@ -1655,25 +1658,31 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { int ratio_con = stride_con2/stride_con; if ((ratio_con * stride_con) == stride_con2) { // Check for exact +#ifndef PRODUCT + if (TraceLoopOpts) { + tty->print("Parallel IV: %d ", phi2->_idx); + loop->dump_head(); + } +#endif // Convert to using the trip counter. The parallel induction // variable differs from the trip counter by a loop-invariant // amount, the difference between their respective initial values. // It is scaled by the 'ratio_con'. - // Perform local Ideal transformation since in most cases ratio == 1. Node* ratio = _igvn.intcon(ratio_con); set_ctrl(ratio, C->root()); - Node* hook = new (C, 3) Node(3); - Node* ratio_init = gvn->transform(new (C, 3) MulINode(init, ratio)); - hook->init_req(0, ratio_init); - Node* diff = gvn->transform(new (C, 3) SubINode(init2, ratio_init)); - hook->init_req(1, diff); - Node* ratio_idx = gvn->transform(new (C, 3) MulINode(phi, ratio)); - hook->init_req(2, ratio_idx); - Node* add = gvn->transform(new (C, 3) AddINode(ratio_idx, diff)); - set_subtree_ctrl(add); + Node* ratio_init = new (C, 3) MulINode(init, ratio); + _igvn.register_new_node_with_optimizer(ratio_init, init); + set_early_ctrl(ratio_init); + Node* diff = new (C, 3) SubINode(init2, ratio_init); + _igvn.register_new_node_with_optimizer(diff, init2); + set_early_ctrl(diff); + Node* ratio_idx = new (C, 3) MulINode(phi, ratio); + _igvn.register_new_node_with_optimizer(ratio_idx, phi); + set_ctrl(ratio_idx, cl); + Node* add = new (C, 3) AddINode(ratio_idx, diff); + _igvn.register_new_node_with_optimizer(add); + set_ctrl(add, cl); _igvn.replace_node( phi2, add ); - // Free up intermediate goo - _igvn.remove_dead_node(hook); // Sometimes an induction variable is unused if (add->outcnt() == 0) { _igvn.remove_dead_node(add); From 8ad902f1ed45a8f64457a570d69fe2c653efaa6e Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 9 Sep 2011 16:24:12 -0700 Subject: [PATCH 045/214] 7088991: Bump ths hs22 build number to 05 Reviewed-by: johnc --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 0be8bcd1946..ce2f28e8564 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=22 HS_MINOR_VER=0 -HS_BUILD_NUMBER=04 +HS_BUILD_NUMBER=05 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From d6fd9c2339e67a9677af48da0778c39f7e60b9ea Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 9 Sep 2011 16:33:13 -0700 Subject: [PATCH 046/214] Added tag hs22-b05 for changeset 2787676b53cf --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 672698e1093..e091968ba0b 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -182,3 +182,4 @@ c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143 7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03 ce9bde819dcba4a5d2822229d9183e69c74326ca hs22-b04 +513a84dd0f8b56dc0836b4e0bdd5dd0a778fc634 hs22-b05 From 1ebca30d2686cbce9e2d233556359bdf2a8f1729 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sat, 10 Sep 2011 00:11:04 -0700 Subject: [PATCH 047/214] 7088020: SEGV in JNIHandleBlock::release_block Reviewed-by: kvn, twisti --- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 19 ++--- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 5 ++ .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 18 ++--- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 37 ++------- .../src/cpu/zero/vm/stubGenerator_zero.cpp | 6 -- hotspot/src/share/vm/runtime/stubRoutines.cpp | 2 - hotspot/src/share/vm/runtime/stubRoutines.hpp | 4 - .../test/compiler/7088020/Test7088020.java | 80 +++++++++++++++++++ 8 files changed, 104 insertions(+), 67 deletions(-) create mode 100644 hotspot/test/compiler/7088020/Test7088020.java diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index a7fe854e069..cf403040dfa 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -436,7 +436,7 @@ class StubGenerator: public StubCodeGenerator { #undef __ #define __ masm-> - address generate_throw_exception(const char* name, address runtime_entry, bool restore_saved_exception_pc, + address generate_throw_exception(const char* name, address runtime_entry, Register arg1 = noreg, Register arg2 = noreg) { #ifdef ASSERT int insts_size = VerifyThread ? 1 * K : 600; @@ -462,11 +462,6 @@ class StubGenerator: public StubCodeGenerator { int frame_complete = __ offset(); - if (restore_saved_exception_pc) { - __ ld_ptr(G2_thread, JavaThread::saved_exception_pc_offset(), I7); - __ sub(I7, frame::pc_return_offset, I7); - } - // Note that we always have a runtime stub frame on the top of stack by this point Register last_java_sp = SP; // 64-bit last_java_sp is biased! @@ -3418,7 +3413,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_WrongMethodTypeException_entry = generate_throw_exception("WrongMethodTypeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException), - false, G5_method_type, G3_method_handle); + G5_method_type, G3_method_handle); } @@ -3429,12 +3424,10 @@ class StubGenerator: public StubCodeGenerator { // UseZeroBaseCompressedOops which is defined after heap initialization. StubRoutines::Sparc::_partial_subtype_check = generate_partial_subtype_check(); // These entry points require SharedInfo::stack0 to be set up in non-core builds - StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false); - StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); - StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException), true); - StubRoutines::_throw_NullPointerException_entry = generate_throw_exception("NullPointerException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true); - StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); - StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false); + StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError)); + StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError)); + StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call)); + StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError)); StubRoutines::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access(); diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 0e5d1599e5e..dd741fda0d8 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -624,6 +624,11 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* // error path for invokeExact (only) __ bind(invoke_exact_error_path); + // ensure that the top of stack is properly aligned. + __ mov(rdi, rsp); + __ andptr(rsp, -StackAlignmentInBytes); // Align the stack for the ABI + __ pushptr(Address(rdi, 0)); // Pick up the return address + // Stub wants expected type in rax and the actual type in rcx __ jump(ExternalAddress(StubRoutines::throw_WrongMethodTypeException_entry())); diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index c0a6ec358ea..e8a85336149 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -2187,7 +2187,7 @@ class StubGenerator: public StubCodeGenerator { // either at call sites or otherwise assume that stack unwinding will be initiated, // so caller saved registers were assumed volatile in the compiler. address generate_throw_exception(const char* name, address runtime_entry, - bool restore_saved_exception_pc, Register arg1 = noreg, Register arg2 = noreg) { + Register arg1 = noreg, Register arg2 = noreg) { int insts_size = 256; int locs_size = 32; @@ -2204,10 +2204,6 @@ class StubGenerator: public StubCodeGenerator { // differently than the real call_VM Register java_thread = rbx; __ get_thread(java_thread); - if (restore_saved_exception_pc) { - __ movptr(rax, Address(java_thread, in_bytes(JavaThread::saved_exception_pc_offset()))); - __ push(rax); - } __ enter(); // required for proper stackwalking of RuntimeStub frame @@ -2323,7 +2319,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_WrongMethodTypeException_entry = generate_throw_exception("WrongMethodTypeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException), - false, rax, rcx); + rax, rcx); } @@ -2332,12 +2328,10 @@ class StubGenerator: public StubCodeGenerator { // These entry points require SharedInfo::stack0 to be set up in non-core builds // and need to be relocatable, so they each fabricate a RuntimeStub internally. - StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false); - StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); - StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException), true); - StubRoutines::_throw_NullPointerException_entry = generate_throw_exception("NullPointerException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true); - StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); - StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false); + StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError)); + StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError)); + StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call)); + StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError)); //------------------------------------------------------------------------------------------------------------------------ // entry points that are platform specific diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 095412b0332..a58b8d9eb9e 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -935,6 +935,8 @@ class StubGenerator: public StubCodeGenerator { __ pusha(); // push registers Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord); + // FIXME: this probably needs alignment logic + __ subptr(rsp, frame::arg_reg_save_area_bytes); BLOCK_COMMENT("call handle_unsafe_access"); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access))); @@ -2934,7 +2936,6 @@ class StubGenerator: public StubCodeGenerator { // caller saved registers were assumed volatile in the compiler. address generate_throw_exception(const char* name, address runtime_entry, - bool restore_saved_exception_pc, Register arg1 = noreg, Register arg2 = noreg) { // Information about frame layout at time of blocking runtime call. @@ -2962,12 +2963,6 @@ class StubGenerator: public StubCodeGenerator { // which has the ability to fetch the return PC out of // thread-local storage and also sets up last_Java_sp slightly // differently than the real call_VM - if (restore_saved_exception_pc) { - __ movptr(rax, - Address(r15_thread, - in_bytes(JavaThread::saved_exception_pc_offset()))); - __ push(rax); - } __ enter(); // required for proper stackwalking of RuntimeStub frame @@ -3068,7 +3063,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_WrongMethodTypeException_entry = generate_throw_exception("WrongMethodTypeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException), - false, rax, rcx); + rax, rcx); } void generate_all() { @@ -3081,43 +3076,25 @@ class StubGenerator: public StubCodeGenerator { generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime:: - throw_AbstractMethodError), - false); + throw_AbstractMethodError)); StubRoutines::_throw_IncompatibleClassChangeError_entry = generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime:: - throw_IncompatibleClassChangeError), - false); - - StubRoutines::_throw_ArithmeticException_entry = - generate_throw_exception("ArithmeticException throw_exception", - CAST_FROM_FN_PTR(address, - SharedRuntime:: - throw_ArithmeticException), - true); - - StubRoutines::_throw_NullPointerException_entry = - generate_throw_exception("NullPointerException throw_exception", - CAST_FROM_FN_PTR(address, - SharedRuntime:: - throw_NullPointerException), - true); + throw_IncompatibleClassChangeError)); StubRoutines::_throw_NullPointerException_at_call_entry = generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime:: - throw_NullPointerException_at_call), - false); + throw_NullPointerException_at_call)); StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime:: - throw_StackOverflowError), - false); + throw_StackOverflowError)); // entry points that are platform specific StubRoutines::x86::_f2i_fixup = generate_f2i_fixup(); diff --git a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp index 77d23a4ffb7..b13c0f3ef8f 100644 --- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp @@ -215,12 +215,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_AbstractMethodError_entry = ShouldNotCallThisStub(); - StubRoutines::_throw_ArithmeticException_entry = - ShouldNotCallThisStub(); - - StubRoutines::_throw_NullPointerException_entry = - ShouldNotCallThisStub(); - StubRoutines::_throw_NullPointerException_at_call_entry = ShouldNotCallThisStub(); diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index 5f77761a249..f38173f0f1d 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -51,8 +51,6 @@ address StubRoutines::_catch_exception_entry = NULL; address StubRoutines::_forward_exception_entry = NULL; address StubRoutines::_throw_AbstractMethodError_entry = NULL; address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL; -address StubRoutines::_throw_ArithmeticException_entry = NULL; -address StubRoutines::_throw_NullPointerException_entry = NULL; address StubRoutines::_throw_NullPointerException_at_call_entry = NULL; address StubRoutines::_throw_StackOverflowError_entry = NULL; address StubRoutines::_throw_WrongMethodTypeException_entry = NULL; diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index e2ca75c812a..8481dce6dca 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -128,8 +128,6 @@ class StubRoutines: AllStatic { static address _catch_exception_entry; static address _throw_AbstractMethodError_entry; static address _throw_IncompatibleClassChangeError_entry; - static address _throw_ArithmeticException_entry; - static address _throw_NullPointerException_entry; static address _throw_NullPointerException_at_call_entry; static address _throw_StackOverflowError_entry; static address _throw_WrongMethodTypeException_entry; @@ -254,8 +252,6 @@ class StubRoutines: AllStatic { // Implicit exceptions static address throw_AbstractMethodError_entry() { return _throw_AbstractMethodError_entry; } static address throw_IncompatibleClassChangeError_entry(){ return _throw_IncompatibleClassChangeError_entry; } - static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; } - static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; } static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; } static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; } static address throw_WrongMethodTypeException_entry() { return _throw_WrongMethodTypeException_entry; } diff --git a/hotspot/test/compiler/7088020/Test7088020.java b/hotspot/test/compiler/7088020/Test7088020.java new file mode 100644 index 00000000000..4ea991340bd --- /dev/null +++ b/hotspot/test/compiler/7088020/Test7088020.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7088020 + * @summary SEGV in JNIHandleBlock::release_block + * + * @run main Test7088020 + */ + +import java.lang.invoke.*; + + +public class Test7088020 { + public static boolean test() { + return false; + } + + public static void main(String... args) throws Throwable { + MethodHandle test = MethodHandles.lookup().findStatic(Test7088020.class, "test", MethodType.methodType(Boolean.TYPE)); + + // Exercise WMT with different argument alignments + int thrown = 0; + try { + test.invokeExact(0); + } catch (WrongMethodTypeException wmt) { + thrown++; + if (wmt.getStackTrace().length < 1) throw new InternalError("missing stack frames"); + } + try { + test.invokeExact(0, 1); + } catch (WrongMethodTypeException wmt) { + thrown++; + if (wmt.getStackTrace().length < 1) throw new InternalError("missing stack frames"); + } + try { + test.invokeExact(0, 1, 2); + } catch (WrongMethodTypeException wmt) { + thrown++; + if (wmt.getStackTrace().length < 1) throw new InternalError("missing stack frames"); + } + try { + test.invokeExact(0, 1, 2, 3); + } catch (WrongMethodTypeException wmt) { + thrown++; + if (wmt.getStackTrace().length < 1) throw new InternalError("missing stack frames"); + } + try { + thrown++; + test.invokeExact(0, 1, 2, 3, 4); + } catch (WrongMethodTypeException wmt) { + if (wmt.getStackTrace().length < 1) throw new InternalError("missing stack frames"); + } + if (thrown != 5) { + throw new InternalError("not enough throws"); + } + } +} From e39ba1a5fefed1d24ea0d93f28f05362fc7aa201 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sat, 10 Sep 2011 17:29:02 -0700 Subject: [PATCH 048/214] 7086585: make Java field injection more flexible Reviewed-by: jrose, twisti, kvn, coleenp --- .../classes/sun/jvm/hotspot/oops/Field.java | 32 +- .../sun/jvm/hotspot/oops/InstanceKlass.java | 68 ++- .../sun/jvm/hotspot/oops/java_lang_Class.java | 4 +- .../jvm/hotspot/tools/jcore/ClassWriter.java | 8 +- .../sun/jvm/hotspot/tools/soql/SOQL.java | 11 +- .../ui/classbrowser/HTMLGenerator.java | 19 +- hotspot/agent/test/jdi/sasanity.sh | 2 +- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 14 +- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 13 +- hotspot/src/share/vm/ci/ciInstanceKlass.cpp | 68 +-- .../share/vm/classfile/classFileParser.cpp | 552 ++++++------------ .../share/vm/classfile/classFileParser.hpp | 30 +- .../src/share/vm/classfile/javaClasses.cpp | 260 +++++---- .../src/share/vm/classfile/javaClasses.hpp | 134 +++-- .../share/vm/classfile/systemDictionary.cpp | 12 +- .../share/vm/classfile/systemDictionary.hpp | 35 +- hotspot/src/share/vm/classfile/vmSymbols.hpp | 9 +- .../vm/interpreter/interpreterRuntime.cpp | 9 +- hotspot/src/share/vm/oops/cpCacheOop.cpp | 8 +- hotspot/src/share/vm/oops/fieldInfo.hpp | 132 +++++ hotspot/src/share/vm/oops/fieldStreams.hpp | 174 ++++++ hotspot/src/share/vm/oops/instanceKlass.cpp | 89 +-- hotspot/src/share/vm/oops/instanceKlass.hpp | 43 +- .../src/share/vm/oops/instanceKlassKlass.cpp | 2 +- hotspot/src/share/vm/prims/jni.cpp | 4 +- hotspot/src/share/vm/prims/jvm.cpp | 38 +- .../vm/prims/jvmtiClassFileReconstituter.cpp | 30 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 4 - hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 9 - hotspot/src/share/vm/prims/jvmtiEnvBase.hpp | 2 - .../share/vm/prims/jvmtiRedefineClasses.cpp | 61 +- hotspot/src/share/vm/prims/methodHandles.cpp | 7 +- hotspot/src/share/vm/prims/unsafe.cpp | 2 +- .../src/share/vm/runtime/fieldDescriptor.cpp | 36 +- .../src/share/vm/runtime/fieldDescriptor.hpp | 67 ++- .../src/share/vm/runtime/reflectionUtils.hpp | 23 +- hotspot/src/share/vm/runtime/thread.cpp | 2 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 34 +- .../src/share/vm/utilities/accessFlags.hpp | 17 +- 39 files changed, 1073 insertions(+), 991 deletions(-) create mode 100644 hotspot/src/share/vm/oops/fieldInfo.hpp create mode 100644 hotspot/src/share/vm/oops/fieldStreams.hpp diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java index fc29a3949a2..e130e9edf8e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java @@ -39,28 +39,20 @@ public class Field { /** Constructor for fields that are named in an InstanceKlass's fields array (i.e., named, non-VM fields) */ - Field(InstanceKlass holder, int fieldArrayIndex) { + Field(InstanceKlass holder, int fieldIndex) { this.holder = holder; - this.fieldArrayIndex = fieldArrayIndex; + this.fieldIndex = fieldIndex; - ConstantPool cp = holder.getConstants(); - TypeArray fields = holder.getFields(); - short access = fields.getShortAt(fieldArrayIndex + InstanceKlass.ACCESS_FLAGS_OFFSET); - short nameIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.NAME_INDEX_OFFSET); - short signatureIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.SIGNATURE_INDEX_OFFSET); - offset = VM.getVM().buildIntFromShorts(fields.getShortAt(fieldArrayIndex + InstanceKlass.LOW_OFFSET), - fields.getShortAt(fieldArrayIndex + InstanceKlass.HIGH_OFFSET)); - short genericSignatureIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET); - Symbol name = cp.getSymbolAt(nameIndex); + offset = holder.getFieldOffset(fieldIndex); + genericSignature = holder.getFieldGenericSignature(fieldIndex); + + Symbol name = holder.getFieldName(fieldIndex); id = new NamedFieldIdentifier(name.asString()); - signature = cp.getSymbolAt(signatureIndex); - if (genericSignatureIndex != 0) { - genericSignature = cp.getSymbolAt(genericSignatureIndex); - } else { - genericSignature = null; - } + signature = holder.getFieldSignature(fieldIndex); fieldType = new FieldType(signature); + + short access = holder.getFieldAccessFlags(fieldIndex); accessFlags = new AccessFlags(access); } @@ -73,7 +65,7 @@ public class Field { private Symbol signature; private Symbol genericSignature; private AccessFlags accessFlags; - private int fieldArrayIndex; + private int fieldIndex; /** Returns the byte offset of the field within the object or klass */ public long getOffset() { return offset; } @@ -101,8 +93,8 @@ public class Field { /** (Named, non-VM fields only) Returns the index in the fields TypeArray for this field. Equivalent to the "index" in the VM's fieldDescriptors. */ - public int getFieldArrayIndex() { - return fieldArrayIndex; + public int getFieldIndex() { + return fieldIndex; } /** (Named, non-VM fields only) Retrieves the access flags. */ diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index b1d6741ce63..bf49cc3f152 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -51,7 +51,7 @@ public class InstanceKlass extends Klass { public static int LOW_OFFSET; public static int HIGH_OFFSET; public static int GENERIC_SIGNATURE_INDEX_OFFSET; - public static int NEXT_OFFSET; + public static int FIELD_SLOTS; public static int IMPLEMENTORS_LIMIT; // ClassState constants @@ -78,6 +78,7 @@ public class InstanceKlass extends Klass { implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset); } fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize()); + javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize()); constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize()); classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize()); protectionDomain = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize()); @@ -100,14 +101,14 @@ public class InstanceKlass extends Klass { headerSize = alignObjectOffset(Oop.getHeaderSize() + type.getSize()); // read field offset constants - ACCESS_FLAGS_OFFSET = db.lookupIntConstant("instanceKlass::access_flags_offset").intValue(); - NAME_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::name_index_offset").intValue(); - SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::signature_index_offset").intValue(); - INITVAL_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::initval_index_offset").intValue(); - LOW_OFFSET = db.lookupIntConstant("instanceKlass::low_offset").intValue(); - HIGH_OFFSET = db.lookupIntConstant("instanceKlass::high_offset").intValue(); - GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::generic_signature_offset").intValue(); - NEXT_OFFSET = db.lookupIntConstant("instanceKlass::next_offset").intValue(); + ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue(); + NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue(); + SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue(); + INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue(); + LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue(); + HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue(); + GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::generic_signature_offset").intValue(); + FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); // read ClassState constants CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue(); CLASS_STATE_ALLOCATED = db.lookupIntConstant("instanceKlass::allocated").intValue(); @@ -131,6 +132,7 @@ public class InstanceKlass extends Klass { private static CIntField nofImplementors; private static OopField[] implementors; private static OopField fields; + private static CIntField javaFieldsCount; private static OopField constants; private static OopField classLoader; private static OopField protectionDomain; @@ -247,6 +249,34 @@ public class InstanceKlass extends Klass { public static long getHeaderSize() { return headerSize; } + public short getFieldAccessFlags(int index) { + return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET); + } + + public Symbol getFieldName(int index) { + int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET); + return getConstants().getSymbolAt(nameIndex); + } + + public Symbol getFieldSignature(int index) { + int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); + return getConstants().getSymbolAt(signatureIndex); + } + + public Symbol getFieldGenericSignature(int index) { + short genericSignatureIndex = getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET); + if (genericSignatureIndex != 0) { + return getConstants().getSymbolAt(genericSignatureIndex); + } + return null; + } + + public int getFieldOffset(int index) { + TypeArray fields = getFields(); + return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET), + fields.getShortAt(index * FIELD_SLOTS + HIGH_OFFSET)); + } + // Accessors for declared fields public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); } public ObjArray getMethods() { return (ObjArray) methods.getValue(this); } @@ -257,6 +287,8 @@ public class InstanceKlass extends Klass { public Klass getImplementor() { return (Klass) implementors[0].getValue(this); } public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); } public TypeArray getFields() { return (TypeArray) fields.getValue(this); } + public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } + public int getAllFieldsCount() { return (int)getFields().getLength(); } public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } public Oop getClassLoader() { return classLoader.getValue(this); } public Oop getProtectionDomain() { return protectionDomain.getValue(this); } @@ -480,8 +512,8 @@ public class InstanceKlass extends Klass { void iterateStaticFieldsInternal(OopVisitor visitor) { TypeArray fields = getFields(); - int length = (int) fields.getLength(); - for (int index = 0; index < length; index += NEXT_OFFSET) { + int length = getJavaFieldsCount(); + for (int index = 0; index < length; index += FIELD_SLOTS) { short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); @@ -502,8 +534,8 @@ public class InstanceKlass extends Klass { } TypeArray fields = getFields(); - int length = (int) fields.getLength(); - for (int index = 0; index < length; index += NEXT_OFFSET) { + int length = getJavaFieldsCount(); + for (int index = 0; index < length; index += FIELD_SLOTS) { short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); @@ -518,9 +550,9 @@ public class InstanceKlass extends Klass { /** Field access by name. */ public Field findLocalField(Symbol name, Symbol sig) { TypeArray fields = getFields(); - int n = (int) fields.getLength(); + int length = (int) fields.getLength(); ConstantPool cp = getConstants(); - for (int i = 0; i < n; i += NEXT_OFFSET) { + for (int i = 0; i < length; i += FIELD_SLOTS) { int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET); int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET); Symbol f_name = cp.getSymbolAt(nameIndex); @@ -613,9 +645,9 @@ public class InstanceKlass extends Klass { // not including inherited fields. TypeArray fields = getFields(); - int length = (int) fields.getLength(); - List immediateFields = new ArrayList(length / NEXT_OFFSET); - for (int index = 0; index < length; index += NEXT_OFFSET) { + int length = getJavaFieldsCount(); + List immediateFields = new ArrayList(length); + for (int index = 0; index < length; index += FIELD_SLOTS) { immediateFields.add(getFieldByIndex(index)); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java index b91eab3655a..9f2dbb3faa8 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java @@ -55,13 +55,13 @@ public class java_lang_Class { // klass and oop_size are HotSpot magic fields and hence we can't // find them from InstanceKlass for java.lang.Class. Type jlc = db.lookupType("java_lang_Class"); - int klassOffset = (int) jlc.getCIntegerField("klass_offset").getValue(); + int klassOffset = (int) jlc.getCIntegerField("_klass_offset").getValue(); if (VM.getVM().isCompressedOopsEnabled()) { klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true); } else { klassField = new OopField(new NamedFieldIdentifier("klass"), klassOffset, true); } - int oopSizeOffset = (int) jlc.getCIntegerField("oop_size_offset").getValue(); + int oopSizeOffset = (int) jlc.getCIntegerField("_oop_size_offset").getValue(); oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java index 91739eff523..f5e5837e1a9 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java @@ -380,15 +380,15 @@ public class ClassWriter implements /* imports */ ClassConstants protected void writeFields() throws IOException { TypeArray fields = klass.getFields(); - final int length = (int) fields.getLength(); + final int length = klass.getJavaFieldsCount(); // write number of fields - dos.writeShort((short) (length / InstanceKlass.NEXT_OFFSET) ); + dos.writeShort((short) (length / InstanceKlass.FIELD_SLOTS) ); if (DEBUG) debugMessage("number of fields = " - + length/InstanceKlass.NEXT_OFFSET); + + length/InstanceKlass.FIELD_SLOTS); - for (int index = 0; index < length; index += InstanceKlass.NEXT_OFFSET) { + for (int index = 0; index < length; index += InstanceKlass.FIELD_SLOTS) { short accessFlags = fields.getShortAt(index + InstanceKlass.ACCESS_FLAGS_OFFSET); dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java index e19763589b1..77537dd6f52 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java @@ -150,16 +150,13 @@ public class SOQL extends Tool { } // list immediate fields only - TypeArray fields = klass.getFields(); - int numFields = (int) fields.getLength(); + int numFields = klass.getJavaFieldsCount(); ConstantPool cp = klass.getConstants(); out.println("fields"); if (numFields != 0) { - for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { - int nameIndex = fields.getShortAt(f + InstanceKlass.NAME_INDEX_OFFSET); - int sigIndex = fields.getShortAt(f + InstanceKlass.SIGNATURE_INDEX_OFFSET); - Symbol f_name = cp.getSymbolAt(nameIndex); - Symbol f_sig = cp.getSymbolAt(sigIndex); + for (int f = 0; f < numFields; f++){ + Symbol f_name = klass.getFieldName(f); + Symbol f_sig = klass.getFieldSignature(f); StringBuffer sigBuf = new StringBuffer(); new SignatureConverter(f_sig, sigBuf).dispatchField(); out.print('\t'); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java index 8e3cbb7f8dd..210bed768f6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java @@ -1116,20 +1116,15 @@ public class HTMLGenerator implements /* imports */ ClassConstants { InstanceKlass kls = (InstanceKlass) obj; buf.append(" " + kls.getName().asString() + "={"); int flen = ov.fieldsSize(); - - TypeArray klfields = kls.getFields(); - int klen = (int) klfields.getLength(); - - ConstantPool cp = kls.getConstants(); + int klen = kls.getJavaFieldsCount(); int findex = 0; - for (int index = 0; index < klen; index += kls.NEXT_OFFSET) { - int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET); - int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET); + for (int index = 0; index < klen; index++) { + int accsFlags = kls.getFieldAccessFlags(index); + Symbol f_name = kls.getFieldName(index); AccessFlags access = new AccessFlags(accsFlags); if (!access.isStatic()) { ScopeValue svf = ov.getFieldAt(findex++); String fstr = scopeValueAsString(sd, svf); - Symbol f_name = cp.getSymbolAt(nameIndex); buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")"); } } @@ -1819,13 +1814,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants { protected String genHTMLListForFields(InstanceKlass klass) { Formatter buf = new Formatter(genHTML); - TypeArray fields = klass.getFields(); - int numFields = (int) fields.getLength(); - ConstantPool cp = klass.getConstants(); + int numFields = klass.getJavaFieldsCount(); if (numFields != 0) { buf.h3("Fields"); buf.beginList(); - for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { + for (int f = 0; f < numFields; f++) { sun.jvm.hotspot.oops.Field field = klass.getFieldByIndex(f); String f_name = ((NamedFieldIdentifier)field.getID()).getName(); Symbol f_sig = field.getSignature(); diff --git a/hotspot/agent/test/jdi/sasanity.sh b/hotspot/agent/test/jdi/sasanity.sh index 4b033fa703e..19580aa2049 100644 --- a/hotspot/agent/test/jdi/sasanity.sh +++ b/hotspot/agent/test/jdi/sasanity.sh @@ -76,5 +76,5 @@ while [ ! -s $tmp ] ; do sleep 2 done -$jdk/bin/java -showversion ${OPTIONS} -classpath $javacp SASanityChecker $pid +$jdk/bin/java -showversion ${OPTIONS} -classpath $javacp $* SASanityChecker $pid kill -9 $pid diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 309f34da80f..8fe11550f28 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -3257,15 +3257,10 @@ void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register m Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { - // hoist vmslots into every mh to avoid dependent load chain - ld( Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); - } else { - Register temp2_reg = vmslots_reg; - load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); - load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); - ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); - } + Register temp2_reg = vmslots_reg; + load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); + load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); + ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); } @@ -4966,4 +4961,3 @@ void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Lab cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); nop(); // Separate short branches } - diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index a16bacf022c..d57a55f6b07 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -8004,15 +8004,10 @@ void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register m Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { - // hoist vmslots into every mh to avoid dependent load chain - movl(vmslots_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg))); - } else { - Register temp2_reg = vmslots_reg; - load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg))); - load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg))); - movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); - } + Register temp2_reg = vmslots_reg; + load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg))); + load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg))); + movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); } diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index 35ee2b89e00..f10b92fa33d 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -31,6 +31,7 @@ #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/fieldStreams.hpp" #include "runtime/fieldDescriptor.hpp" // ciInstanceKlass @@ -412,7 +413,7 @@ GrowableArray* ciInstanceKlass::non_static_fields() { VM_ENTRY_MARK; ciEnv* curEnv = ciEnv::current(); instanceKlass* ik = get_instanceKlass(); - int max_n_fields = ik->fields()->length()/instanceKlass::next_offset; + int max_n_fields = ik->java_fields_count(); Arena* arena = curEnv->arena(); _non_static_fields = @@ -476,23 +477,6 @@ int ciInstanceKlass::compute_nonstatic_fields() { // Now sort them by offset, ascending. // (In principle, they could mix with superclass fields.) fields->sort(sort_field_by_offset); -#ifdef ASSERT - int last_offset = instanceOopDesc::base_offset_in_bytes(); - for (int i = 0; i < fields->length(); i++) { - ciField* field = fields->at(i); - int offset = field->offset_in_bytes(); - int size = (field->_type == NULL) ? heapOopSize : field->size_in_bytes(); - assert(last_offset <= offset, err_msg("no field overlap: %d <= %d", last_offset, offset)); - if (last_offset > (int)sizeof(oopDesc)) - assert((offset - last_offset) < BytesPerLong, "no big holes"); - // Note: Two consecutive T_BYTE fields will be separated by wordSize-1 - // padding bytes if one of them is declared by a superclass. - // This is a minor inefficiency classFileParser.cpp. - last_offset = offset + size; - } - assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow"); -#endif - _nonstatic_fields = fields; return flen; } @@ -505,33 +489,29 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray* int flen = 0; GrowableArray* fields = NULL; instanceKlass* k = get_instanceKlass(); - typeArrayOop fields_array = k->fields(); - for (int pass = 0; pass <= 1; pass++) { - for (int i = 0, alen = fields_array->length(); i < alen; i += instanceKlass::next_offset) { - fieldDescriptor fd; - fd.initialize(k->as_klassOop(), i); - if (fd.is_static()) continue; - if (pass == 0) { - flen += 1; - } else { - ciField* field = new (arena) ciField(&fd); - fields->append(field); - } - } + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) continue; + flen += 1; + } - // Between passes, allocate the array: - if (pass == 0) { - if (flen == 0) { - return NULL; // return nothing if none are locally declared - } - if (super_fields != NULL) { - flen += super_fields->length(); - } - fields = new (arena) GrowableArray(arena, flen, 0, NULL); - if (super_fields != NULL) { - fields->appendAll(super_fields); - } - } + // allocate the array: + if (flen == 0) { + return NULL; // return nothing if none are locally declared + } + if (super_fields != NULL) { + flen += super_fields->length(); + } + fields = new (arena) GrowableArray(arena, flen, 0, NULL); + if (super_fields != NULL) { + fields->appendAll(super_fields); + } + + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) continue; + fieldDescriptor fd; + fd.initialize(k->as_klassOop(), fs.index()); + ciField* field = new (arena) ciField(&fd); + fields->append(field); } assert(fields->length() == flen, "sanity"); return fields; diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 4c664bdf9e3..b28b8ad7e19 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -36,6 +36,7 @@ #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" #include "oops/constantPoolOop.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/klass.inline.hpp" @@ -991,42 +992,98 @@ enum FieldAllocationType { STATIC_BYTE, // Boolean, Byte, char STATIC_SHORT, // shorts STATIC_WORD, // ints - STATIC_DOUBLE, // long or double - STATIC_ALIGNED_DOUBLE,// aligned long or double + STATIC_DOUBLE, // aligned long or double NONSTATIC_OOP, NONSTATIC_BYTE, NONSTATIC_SHORT, NONSTATIC_WORD, NONSTATIC_DOUBLE, - NONSTATIC_ALIGNED_DOUBLE + MAX_FIELD_ALLOCATION_TYPE, + BAD_ALLOCATION_TYPE = -1 +}; + +static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = { + BAD_ALLOCATION_TYPE, // 0 + BAD_ALLOCATION_TYPE, // 1 + BAD_ALLOCATION_TYPE, // 2 + BAD_ALLOCATION_TYPE, // 3 + NONSTATIC_BYTE , // T_BOOLEAN = 4, + NONSTATIC_SHORT, // T_CHAR = 5, + NONSTATIC_WORD, // T_FLOAT = 6, + NONSTATIC_DOUBLE, // T_DOUBLE = 7, + NONSTATIC_BYTE, // T_BYTE = 8, + NONSTATIC_SHORT, // T_SHORT = 9, + NONSTATIC_WORD, // T_INT = 10, + NONSTATIC_DOUBLE, // T_LONG = 11, + NONSTATIC_OOP, // T_OBJECT = 12, + NONSTATIC_OOP, // T_ARRAY = 13, + BAD_ALLOCATION_TYPE, // T_VOID = 14, + BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, + BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16, + BAD_ALLOCATION_TYPE, // T_CONFLICT = 17, + BAD_ALLOCATION_TYPE, // 0 + BAD_ALLOCATION_TYPE, // 1 + BAD_ALLOCATION_TYPE, // 2 + BAD_ALLOCATION_TYPE, // 3 + STATIC_BYTE , // T_BOOLEAN = 4, + STATIC_SHORT, // T_CHAR = 5, + STATIC_WORD, // T_FLOAT = 6, + STATIC_DOUBLE, // T_DOUBLE = 7, + STATIC_BYTE, // T_BYTE = 8, + STATIC_SHORT, // T_SHORT = 9, + STATIC_WORD, // T_INT = 10, + STATIC_DOUBLE, // T_LONG = 11, + STATIC_OOP, // T_OBJECT = 12, + STATIC_OOP, // T_ARRAY = 13, + BAD_ALLOCATION_TYPE, // T_VOID = 14, + BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, + BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16, + BAD_ALLOCATION_TYPE, // T_CONFLICT = 17, +}; + +static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) { + assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values"); + FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)]; + assert(result != BAD_ALLOCATION_TYPE, "bad type"); + return result; +} + +class FieldAllocationCount: public ResourceObj { + public: + unsigned int count[MAX_FIELD_ALLOCATION_TYPE]; + + FieldAllocationCount() { + for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) { + count[i] = 0; + } + } + + FieldAllocationType update(bool is_static, BasicType type) { + FieldAllocationType atype = basic_type_to_atype(is_static, type); + count[atype]++; + return atype; + } }; -struct FieldAllocationCount { - unsigned int static_oop_count; - unsigned int static_byte_count; - unsigned int static_short_count; - unsigned int static_word_count; - unsigned int static_double_count; - unsigned int nonstatic_oop_count; - unsigned int nonstatic_byte_count; - unsigned int nonstatic_short_count; - unsigned int nonstatic_word_count; - unsigned int nonstatic_double_count; -}; - -typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface, - struct FieldAllocationCount *fac, - objArrayHandle* fields_annotations, TRAPS) { +typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, + constantPoolHandle cp, bool is_interface, + FieldAllocationCount *fac, + objArrayHandle* fields_annotations, + int* java_fields_count_ptr, TRAPS) { ClassFileStream* cfs = stream(); typeArrayHandle nullHandle; cfs->guarantee_more(2, CHECK_(nullHandle)); // length u2 length = cfs->get_u2_fast(); + *java_fields_count_ptr = length; + + int num_injected = 0; + InjectedField* injected = JavaClasses::get_injected(class_name, &num_injected); + // Tuples of shorts [access, name index, sig index, initial value index, byte offset, generic signature index] - typeArrayOop new_fields = oopFactory::new_permanent_shortArray(length*instanceKlass::next_offset, CHECK_(nullHandle)); + typeArrayOop new_fields = oopFactory::new_permanent_shortArray((length + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle)); typeArrayHandle fields(THREAD, new_fields); - int index = 0; typeArrayHandle field_annotations; for (int n = 0; n < length; n++) { cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count @@ -1077,93 +1134,77 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int } } - fields->short_at_put(index++, access_flags.as_short()); - fields->short_at_put(index++, name_index); - fields->short_at_put(index++, signature_index); - fields->short_at_put(index++, constantvalue_index); + FieldInfo* field = FieldInfo::from_field_array(fields(), n); + field->initialize(access_flags.as_short(), + name_index, + signature_index, + constantvalue_index, + generic_signature_index, + 0); + + BasicType type = cp->basic_type_for_signature_at(signature_index); // Remember how many oops we encountered and compute allocation type - BasicType type = cp->basic_type_for_signature_at(signature_index); - FieldAllocationType atype; - if ( is_static ) { - switch ( type ) { - case T_BOOLEAN: - case T_BYTE: - fac->static_byte_count++; - atype = STATIC_BYTE; - break; - case T_LONG: - case T_DOUBLE: - if (Universe::field_type_should_be_aligned(type)) { - atype = STATIC_ALIGNED_DOUBLE; - } else { - atype = STATIC_DOUBLE; - } - fac->static_double_count++; - break; - case T_CHAR: - case T_SHORT: - fac->static_short_count++; - atype = STATIC_SHORT; - break; - case T_FLOAT: - case T_INT: - fac->static_word_count++; - atype = STATIC_WORD; - break; - case T_ARRAY: - case T_OBJECT: - fac->static_oop_count++; - atype = STATIC_OOP; - break; - case T_ADDRESS: - case T_VOID: - default: - assert(0, "bad field type"); - } - } else { - switch ( type ) { - case T_BOOLEAN: - case T_BYTE: - fac->nonstatic_byte_count++; - atype = NONSTATIC_BYTE; - break; - case T_LONG: - case T_DOUBLE: - if (Universe::field_type_should_be_aligned(type)) { - atype = NONSTATIC_ALIGNED_DOUBLE; - } else { - atype = NONSTATIC_DOUBLE; - } - fac->nonstatic_double_count++; - break; - case T_CHAR: - case T_SHORT: - fac->nonstatic_short_count++; - atype = NONSTATIC_SHORT; - break; - case T_FLOAT: - case T_INT: - fac->nonstatic_word_count++; - atype = NONSTATIC_WORD; - break; - case T_ARRAY: - case T_OBJECT: - fac->nonstatic_oop_count++; - atype = NONSTATIC_OOP; - break; - case T_ADDRESS: - case T_VOID: - default: - assert(0, "bad field type"); - } - } + FieldAllocationType atype = fac->update(is_static, type); // The correct offset is computed later (all oop fields will be located together) // We temporarily store the allocation type in the offset field - fields->short_at_put(index++, atype); - fields->short_at_put(index++, 0); // Clear out high word of byte offset - fields->short_at_put(index++, generic_signature_index); + field->set_offset(atype); + } + + if (num_injected != 0) { + int index = length; + for (int n = 0; n < num_injected; n++) { + // Check for duplicates + if (injected[n].may_be_java) { + Symbol* name = injected[n].name(); + Symbol* signature = injected[n].signature(); + bool duplicate = false; + for (int i = 0; i < length; i++) { + FieldInfo* f = FieldInfo::from_field_array(fields(), i); + if (name == cp->symbol_at(f->name_index()) && + signature == cp->symbol_at(f->signature_index())) { + // Symbol is desclared in Java so skip this one + duplicate = true; + break; + } + } + if (duplicate) { + // These will be removed from the field array at the end + continue; + } + } + + // Injected field + FieldInfo* field = FieldInfo::from_field_array(fields(), index); + field->initialize(JVM_ACC_FIELD_INTERNAL, + injected[n].name_index, + injected[n].signature_index, + 0, + 0, + 0); + + BasicType type = FieldType::basic_type(injected[n].signature()); + + // Remember how many oops we encountered and compute allocation type + FieldAllocationType atype = fac->update(false, type); + + // The correct offset is computed later (all oop fields will be located together) + // We temporarily store the allocation type in the offset field + field->set_offset(atype); + index++; + } + + if (index < length + num_injected) { + // sometimes injected fields already exist in the Java source so + // the fields array could be too long. In that case trim the + // fields array. + new_fields = oopFactory::new_permanent_shortArray(index * FieldInfo::field_slots, CHECK_(nullHandle)); + for (int i = 0; i < index * FieldInfo::field_slots; i++) { + new_fields->short_at_put(i, fields->short_at(i)); + } + fields = new_fields; + } } if (_need_verify && length > 1) { @@ -1175,11 +1216,9 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int bool dup = false; { debug_only(No_Safepoint_Verifier nsv;) - for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) { - int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); - Symbol* name = cp->symbol_at(name_index); - int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); - Symbol* sig = cp->symbol_at(sig_index); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + Symbol* name = fs.name(); + Symbol* sig = fs.signature(); // If no duplicates, add name/signature in hashtable names_and_sigs. if (!put_after_lookup(name, sig, names_and_sigs)) { dup = true; @@ -2592,227 +2631,6 @@ typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annota } -void ClassFileParser::java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr, - constantPoolHandle cp, FieldAllocationCount *fac_ptr, TRAPS) { - // This code is for compatibility with earlier jdk's that do not - // have the "discovered" field in java.lang.ref.Reference. For 1.5 - // the check for the "discovered" field should issue a warning if - // the field is not found. For 1.6 this code should be issue a - // fatal error if the "discovered" field is not found. - // - // Increment fac.nonstatic_oop_count so that the start of the - // next type of non-static oops leaves room for the fake oop. - // Do not increment next_nonstatic_oop_offset so that the - // fake oop is place after the java.lang.ref.Reference oop - // fields. - // - // Check the fields in java.lang.ref.Reference for the "discovered" - // field. If it is not present, artifically create a field for it. - // This allows this VM to run on early JDK where the field is not - // present. - int reference_sig_index = 0; - int reference_name_index = 0; - int reference_index = 0; - int extra = java_lang_ref_Reference::number_of_fake_oop_fields; - const int n = (*fields_ptr)()->length(); - for (int i = 0; i < n; i += instanceKlass::next_offset ) { - int name_index = - (*fields_ptr)()->ushort_at(i + instanceKlass::name_index_offset); - int sig_index = - (*fields_ptr)()->ushort_at(i + instanceKlass::signature_index_offset); - Symbol* f_name = cp->symbol_at(name_index); - Symbol* f_sig = cp->symbol_at(sig_index); - if (f_sig == vmSymbols::reference_signature() && reference_index == 0) { - // Save the index for reference signature for later use. - // The fake discovered field does not entries in the - // constant pool so the index for its signature cannot - // be extracted from the constant pool. It will need - // later, however. It's signature is vmSymbols::reference_signature() - // so same an index for that signature. - reference_sig_index = sig_index; - reference_name_index = name_index; - reference_index = i; - } - if (f_name == vmSymbols::reference_discovered_name() && - f_sig == vmSymbols::reference_signature()) { - // The values below are fake but will force extra - // non-static oop fields and a corresponding non-static - // oop map block to be allocated. - extra = 0; - break; - } - } - if (extra != 0) { - fac_ptr->nonstatic_oop_count += extra; - // Add the additional entry to "fields" so that the klass - // contains the "discoverd" field and the field will be initialized - // in instances of the object. - int fields_with_fix_length = (*fields_ptr)()->length() + - instanceKlass::next_offset; - typeArrayOop ff = oopFactory::new_permanent_shortArray( - fields_with_fix_length, CHECK); - typeArrayHandle fields_with_fix(THREAD, ff); - - // Take everything from the original but the length. - for (int idx = 0; idx < (*fields_ptr)->length(); idx++) { - fields_with_fix->ushort_at_put(idx, (*fields_ptr)->ushort_at(idx)); - } - - // Add the fake field at the end. - int i = (*fields_ptr)->length(); - // There is no name index for the fake "discovered" field nor - // signature but a signature is needed so that the field will - // be properly initialized. Use one found for - // one of the other reference fields. Be sure the index for the - // name is 0. In fieldDescriptor::initialize() the index of the - // name is checked. That check is by passed for the last nonstatic - // oop field in a java.lang.ref.Reference which is assumed to be - // this artificial "discovered" field. An assertion checks that - // the name index is 0. - assert(reference_index != 0, "Missing signature for reference"); - - int j; - for (j = 0; j < instanceKlass::next_offset; j++) { - fields_with_fix->ushort_at_put(i + j, - (*fields_ptr)->ushort_at(reference_index +j)); - } - // Clear the public access flag and set the private access flag. - short flags; - flags = - fields_with_fix->ushort_at(i + instanceKlass::access_flags_offset); - assert(!(flags & JVM_RECOGNIZED_FIELD_MODIFIERS), "Unexpected access flags set"); - flags = flags & (~JVM_ACC_PUBLIC); - flags = flags | JVM_ACC_PRIVATE; - AccessFlags access_flags; - access_flags.set_flags(flags); - assert(!access_flags.is_public(), "Failed to clear public flag"); - assert(access_flags.is_private(), "Failed to set private flag"); - fields_with_fix->ushort_at_put(i + instanceKlass::access_flags_offset, - flags); - - assert(fields_with_fix->ushort_at(i + instanceKlass::name_index_offset) - == reference_name_index, "The fake reference name is incorrect"); - assert(fields_with_fix->ushort_at(i + instanceKlass::signature_index_offset) - == reference_sig_index, "The fake reference signature is incorrect"); - // The type of the field is stored in the low_offset entry during - // parsing. - assert(fields_with_fix->ushort_at(i + instanceKlass::low_offset) == - NONSTATIC_OOP, "The fake reference type is incorrect"); - - // "fields" is allocated in the permanent generation. Disgard - // it and let it be collected. - (*fields_ptr) = fields_with_fix; - } - return; -} - - -void ClassFileParser::java_lang_Class_fix_pre(int* nonstatic_field_size, - FieldAllocationCount *fac_ptr) { - // Add fake fields for java.lang.Class instances - // - // This is not particularly nice. We should consider adding a - // private transient object field at the Java level to - // java.lang.Class. Alternatively we could add a subclass of - // instanceKlass which provides an accessor and size computer for - // this field, but that appears to be more code than this hack. - // - // NOTE that we wedge these in at the beginning rather than the - // end of the object because the Class layout changed between JDK - // 1.3 and JDK 1.4 with the new reflection implementation; some - // nonstatic oop fields were added at the Java level. The offsets - // of these fake fields can't change between these two JDK - // versions because when the offsets are computed at bootstrap - // time we don't know yet which version of the JDK we're running in. - - // The values below are fake but will force three non-static oop fields and - // a corresponding non-static oop map block to be allocated. - const int extra = java_lang_Class::number_of_fake_oop_fields; - fac_ptr->nonstatic_oop_count += extra; - - // Reserve some leading space for fake ints - *nonstatic_field_size += align_size_up(java_lang_Class::hc_number_of_fake_int_fields * BytesPerInt, heapOopSize) / heapOopSize; -} - - -void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_ptr) { - // Cause the extra fake fields in java.lang.Class to show up before - // the Java fields for layout compatibility between 1.3 and 1.4 - // Incrementing next_nonstatic_oop_offset here advances the - // location where the real java fields are placed. - const int extra = java_lang_Class::number_of_fake_oop_fields; - (*next_nonstatic_oop_offset_ptr) += (extra * heapOopSize); -} - - -// Force MethodHandle.vmentry to be an unmanaged pointer. -// There is no way for a classfile to express this, so we must help it. -void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, - typeArrayHandle fields, - FieldAllocationCount *fac_ptr, - TRAPS) { - // Add fake fields for java.lang.invoke.MethodHandle instances - // - // This is not particularly nice, but since there is no way to express - // a native wordSize field in Java, we must do it at this level. - - if (!EnableInvokeDynamic) return; - - int word_sig_index = 0; - const int cp_size = cp->length(); - for (int index = 1; index < cp_size; index++) { - if (cp->tag_at(index).is_utf8() && - cp->symbol_at(index) == vmSymbols::machine_word_signature()) { - word_sig_index = index; - break; - } - } - - if (word_sig_index == 0) - THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing I or J signature (for vmentry) in java.lang.invoke.MethodHandle"); - - // Find vmentry field and change the signature. - bool found_vmentry = false; - for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) { - int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); - int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); - int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset); - Symbol* f_name = cp->symbol_at(name_index); - Symbol* f_sig = cp->symbol_at(sig_index); - if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) { - if (f_sig == vmSymbols::machine_word_signature()) { - // If the signature of vmentry is already changed, we're done. - found_vmentry = true; - break; - } - else if (f_sig == vmSymbols::byte_signature()) { - // Adjust the field type from byte to an unmanaged pointer. - assert(fac_ptr->nonstatic_byte_count > 0, ""); - fac_ptr->nonstatic_byte_count -= 1; - - fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); - assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); - if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; - else fac_ptr->nonstatic_word_count += 1; - - FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); - assert(atype == NONSTATIC_BYTE, ""); - FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; - fields->ushort_at_put(i + instanceKlass::low_offset, new_atype); - - found_vmentry = true; - break; - } - } - } - - if (!found_vmentry) - THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing vmentry byte field in java.lang.invoke.MethodHandle"); -} - - instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, Handle class_loader, Handle protection_domain, @@ -3025,10 +2843,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle)); } + int java_fields_count = 0; // Fields (offsets are filled in later) - struct FieldAllocationCount fac = {0,0,0,0,0,0,0,0,0,0}; + FieldAllocationCount fac; objArrayHandle fields_annotations; - typeArrayHandle fields = parse_fields(cp, access_flags.is_interface(), &fac, &fields_annotations, CHECK_(nullHandle)); + typeArrayHandle fields = parse_fields(class_name, cp, access_flags.is_interface(), &fac, &fields_annotations, + &java_fields_count, + CHECK_(nullHandle)); // Methods bool has_final_method = false; AccessFlags promoted_flags; @@ -3146,51 +2967,33 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Calculate the starting byte offsets next_static_oop_offset = instanceMirrorKlass::offset_of_static_fields(); next_static_double_offset = next_static_oop_offset + - (fac.static_oop_count * heapOopSize); - if ( fac.static_double_count && + (fac.count[STATIC_OOP] * heapOopSize); + if ( fac.count[STATIC_DOUBLE] && (Universe::field_type_should_be_aligned(T_DOUBLE) || Universe::field_type_should_be_aligned(T_LONG)) ) { next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong); } next_static_word_offset = next_static_double_offset + - (fac.static_double_count * BytesPerLong); + (fac.count[STATIC_DOUBLE] * BytesPerLong); next_static_short_offset = next_static_word_offset + - (fac.static_word_count * BytesPerInt); + (fac.count[STATIC_WORD] * BytesPerInt); next_static_byte_offset = next_static_short_offset + - (fac.static_short_count * BytesPerShort); + (fac.count[STATIC_SHORT] * BytesPerShort); next_static_type_offset = align_size_up((next_static_byte_offset + - fac.static_byte_count ), wordSize ); + fac.count[STATIC_BYTE] ), wordSize ); static_field_size = (next_static_type_offset - next_static_oop_offset) / wordSize; - // Add fake fields for java.lang.Class instances (also see below) - if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { - java_lang_Class_fix_pre(&nonstatic_field_size, &fac); - } - first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size * heapOopSize; next_nonstatic_field_offset = first_nonstatic_field_offset; - // adjust the vmentry field declaration in java.lang.invoke.MethodHandle - if (EnableInvokeDynamic && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) { - java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); - } - - // Add a fake "discovered" field if it is not present - // for compatibility with earlier jdk's. - if (class_name == vmSymbols::java_lang_ref_Reference() - && class_loader.is_null()) { - java_lang_ref_Reference_fix_pre(&fields, cp, &fac, CHECK_(nullHandle)); - } - // end of "discovered" field compactibility fix - - unsigned int nonstatic_double_count = fac.nonstatic_double_count; - unsigned int nonstatic_word_count = fac.nonstatic_word_count; - unsigned int nonstatic_short_count = fac.nonstatic_short_count; - unsigned int nonstatic_byte_count = fac.nonstatic_byte_count; - unsigned int nonstatic_oop_count = fac.nonstatic_oop_count; + unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE]; + unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD]; + unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT]; + unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE]; + unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP]; bool super_has_nonstatic_fields = (super_klass() != NULL && super_klass->has_nonstatic_fields()); @@ -3210,20 +3013,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD( THREAD, unsigned int, nonstatic_oop_count + 1); - // Add fake fields for java.lang.Class instances (also see above). - // FieldsAllocationStyle and CompactFields values will be reset to default. - if(class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { - java_lang_Class_fix_post(&next_nonstatic_field_offset); - nonstatic_oop_offsets[0] = first_nonstatic_field_offset; - const uint fake_oop_count = (next_nonstatic_field_offset - - first_nonstatic_field_offset) / heapOopSize; - nonstatic_oop_counts[0] = fake_oop_count; - nonstatic_oop_map_count = 1; - nonstatic_oop_count -= fake_oop_count; - first_nonstatic_oop_offset = first_nonstatic_field_offset; - } else { - first_nonstatic_oop_offset = 0; // will be set for first oop field - } + first_nonstatic_oop_offset = 0; // will be set for first oop field #ifndef PRODUCT if( PrintCompactFieldsSavings ) { @@ -3378,10 +3168,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Iterate over fields again and compute correct offsets. // The field allocation type was temporarily stored in the offset slot. // oop fields are located before non-oop fields (static and non-static). - int len = fields->length(); - for (int i = 0; i < len; i += instanceKlass::next_offset) { + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { int real_offset; - FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); + FieldAllocationType atype = (FieldAllocationType) fs.offset(); switch (atype) { case STATIC_OOP: real_offset = next_static_oop_offset; @@ -3399,7 +3188,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, real_offset = next_static_word_offset; next_static_word_offset += BytesPerInt; break; - case STATIC_ALIGNED_DOUBLE: case STATIC_DOUBLE: real_offset = next_static_double_offset; next_static_double_offset += BytesPerLong; @@ -3461,7 +3249,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, next_nonstatic_word_offset += BytesPerInt; } break; - case NONSTATIC_ALIGNED_DOUBLE: case NONSTATIC_DOUBLE: real_offset = next_nonstatic_double_offset; next_nonstatic_double_offset += BytesPerLong; @@ -3469,8 +3256,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, default: ShouldNotReachHere(); } - fields->short_at_put(i + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); - fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset)); + fs.set_offset(real_offset); } // Size of instances @@ -3517,12 +3303,12 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, this_klass->set_class_loader(class_loader()); this_klass->set_nonstatic_field_size(nonstatic_field_size); this_klass->set_has_nonstatic_fields(has_nonstatic_fields); - this_klass->set_static_oop_field_count(fac.static_oop_count); + this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]); cp->set_pool_holder(this_klass()); error_handler.set_in_error(false); // turn off error handler for cp this_klass->set_constants(cp()); this_klass->set_local_interfaces(local_interfaces()); - this_klass->set_fields(fields()); + this_klass->set_fields(fields(), java_fields_count); this_klass->set_methods(methods()); if (has_final_method) { this_klass->set_has_final_method(); diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 97ae755165f..8e0db5651c1 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -33,6 +33,9 @@ #include "utilities/accessFlags.hpp" class TempNewSymbol; +class FieldAllocationCount; + + // Parser for for .class files // // The bytes describing the class file structure is read from a Stream object @@ -84,9 +87,11 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { bool* is_synthetic_addr, u2* generic_signature_index_addr, typeArrayHandle* field_annotations, TRAPS); - typeArrayHandle parse_fields(constantPoolHandle cp, bool is_interface, - struct FieldAllocationCount *fac, - objArrayHandle* fields_annotations, TRAPS); + typeArrayHandle parse_fields(Symbol* class_name, + constantPoolHandle cp, bool is_interface, + FieldAllocationCount *fac, + objArrayHandle* fields_annotations, + int* java_fields_count_ptr, TRAPS); // Method parsing methodHandle parse_method(constantPoolHandle cp, bool is_interface, @@ -150,25 +155,6 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { objArrayHandle compute_transitive_interfaces(instanceKlassHandle super, objArrayHandle local_ifs, TRAPS); - // Special handling for certain classes. - // Add the "discovered" field to java.lang.ref.Reference if - // it does not exist. - void java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr, - constantPoolHandle cp, - FieldAllocationCount *fac_ptr, TRAPS); - // Adjust the field allocation counts for java.lang.Class to add - // fake fields. - void java_lang_Class_fix_pre(int* nonstatic_field_size, - FieldAllocationCount *fac_ptr); - // Adjust the next_nonstatic_oop_offset to place the fake fields - // before any Java fields. - void java_lang_Class_fix_post(int* next_nonstatic_oop_offset); - // Adjust the field allocation counts for java.lang.invoke.MethodHandle to add - // a fake address (void*) field. - void java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, - typeArrayHandle fields, - FieldAllocationCount *fac_ptr, TRAPS); - // Format checker methods void classfile_parse_error(const char* msg, TRAPS); void classfile_parse_error(const char* msg, int index, TRAPS); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 3f101188f5c..5b2131c478a 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -33,6 +33,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/klass.hpp" @@ -58,6 +59,49 @@ # include "thread_windows.inline.hpp" #endif +#define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \ + klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum); + +#define DECLARE_INJECTED_FIELD(klass, name, signature, may_be_java) \ + { SystemDictionary::WK_KLASS_ENUM_NAME(klass), vmSymbols::VM_SYMBOL_ENUM_NAME(name##_name), vmSymbols::VM_SYMBOL_ENUM_NAME(signature), may_be_java }, + +InjectedField JavaClasses::_injected_fields[] = { + ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD) +}; + +int JavaClasses::compute_injected_offset(InjectedFieldID id) { + return _injected_fields[id].compute_offset(); +} + + +InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) { + *field_count = 0; + + vmSymbols::SID sid = vmSymbols::find_sid(class_name); + if (sid == vmSymbols::NO_SID) { + // Only well known classes can inject fields + return NULL; + } + + int count = 0; + int start = -1; + +#define LOOKUP_INJECTED_FIELD(klass, name, signature, may_be_java) \ + if (sid == vmSymbols::VM_SYMBOL_ENUM_NAME(klass)) { \ + count++; \ + if (start == -1) start = klass##_##name##_enum; \ + } + ALL_INJECTED_FIELDS(LOOKUP_INJECTED_FIELD); +#undef LOOKUP_INJECTED_FIELD + + if (start != -1) { + *field_count = count; + return _injected_fields + start; + } + return NULL; +} + + static bool find_field(instanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol, fieldDescriptor* fd, @@ -428,24 +472,19 @@ static void initialize_static_field(fieldDescriptor* fd, TRAPS) { } -// During bootstrap, java.lang.Class wasn't loaded so static field -// offsets were computed without the size added it. Go back and -// update all the static field offsets to included the size. -static void fixup_static_field(fieldDescriptor* fd, TRAPS) { - if (fd->is_static()) { - int real_offset = fd->offset() + instanceMirrorKlass::offset_of_static_fields(); - typeArrayOop fields = instanceKlass::cast(fd->field_holder())->fields(); - fields->short_at_put(fd->index() + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); - fields->short_at_put(fd->index() + instanceKlass::high_offset, extract_high_short_from_int(real_offset)); - } -} - void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { assert(instanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already"); if (k->oop_is_instance()) { - // Fixup the offsets - instanceKlass::cast(k())->do_local_static_fields(&fixup_static_field, CHECK); + // During bootstrap, java.lang.Class wasn't loaded so static field + // offsets were computed without the size added it. Go back and + // update all the static field offsets to included the size. + for (JavaFieldStream fs(instanceKlass::cast(k())); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + int real_offset = fs.offset() + instanceMirrorKlass::offset_of_static_fields(); + fs.set_offset(real_offset); + } + } } create_mirror(k, CHECK); } @@ -462,7 +501,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) { // Allocate mirror (java.lang.Class instance) Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); // Setup indirections - mirror->obj_field_put(klass_offset, k()); + mirror->obj_field_put(_klass_offset, k()); k->set_java_mirror(mirror()); instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass()); @@ -504,25 +543,22 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) { int java_lang_Class::oop_size(oop java_class) { - assert(oop_size_offset != 0, "must be set"); - return java_class->int_field(oop_size_offset); + assert(_oop_size_offset != 0, "must be set"); + return java_class->int_field(_oop_size_offset); } void java_lang_Class::set_oop_size(oop java_class, int size) { - assert(oop_size_offset != 0, "must be set"); - java_class->int_field_put(oop_size_offset, size); + assert(_oop_size_offset != 0, "must be set"); + java_class->int_field_put(_oop_size_offset, size); } int java_lang_Class::static_oop_field_count(oop java_class) { - assert(static_oop_field_count_offset != 0, "must be set"); - return java_class->int_field(static_oop_field_count_offset); + assert(_static_oop_field_count_offset != 0, "must be set"); + return java_class->int_field(_static_oop_field_count_offset); } void java_lang_Class::set_static_oop_field_count(oop java_class, int size) { - assert(static_oop_field_count_offset != 0, "must be set"); - java_class->int_field_put(static_oop_field_count_offset, size); + assert(_static_oop_field_count_offset != 0, "must be set"); + java_class->int_field_put(_static_oop_field_count_offset, size); } - - - oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { // This should be improved by adding a field at the Java level or by // introducing a new VM klass (see comment in ClassFileParser) @@ -542,7 +578,7 @@ oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, Basic klassOop java_lang_Class::as_klassOop(oop java_class) { //%note memory_2 assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - klassOop k = klassOop(java_class->obj_field(klass_offset)); + klassOop k = klassOop(java_class->obj_field(_klass_offset)); assert(k == NULL || k->is_klass(), "type check"); return k; } @@ -598,7 +634,7 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, klassOop java_lang_Class::array_klass(oop java_class) { - klassOop k = klassOop(java_class->obj_field(array_klass_offset)); + klassOop k = klassOop(java_class->obj_field(_array_klass_offset)); assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass"); return k; } @@ -606,12 +642,12 @@ klassOop java_lang_Class::array_klass(oop java_class) { void java_lang_Class::set_array_klass(oop java_class, klassOop klass) { assert(klass->is_klass() && Klass::cast(klass)->oop_is_javaArray(), "should be array klass"); - java_class->obj_field_put(array_klass_offset, klass); + java_class->obj_field_put(_array_klass_offset, klass); } methodOop java_lang_Class::resolved_constructor(oop java_class) { - oop constructor = java_class->obj_field(resolved_constructor_offset); + oop constructor = java_class->obj_field(_resolved_constructor_offset); assert(constructor == NULL || constructor->is_method(), "should be method"); return methodOop(constructor); } @@ -619,21 +655,21 @@ methodOop java_lang_Class::resolved_constructor(oop java_class) { void java_lang_Class::set_resolved_constructor(oop java_class, methodOop constructor) { assert(constructor->is_method(), "should be method"); - java_class->obj_field_put(resolved_constructor_offset, constructor); + java_class->obj_field_put(_resolved_constructor_offset, constructor); } bool java_lang_Class::is_primitive(oop java_class) { // should assert: //assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - klassOop k = klassOop(java_class->obj_field(klass_offset)); + klassOop k = klassOop(java_class->obj_field(_klass_offset)); return k == NULL; } BasicType java_lang_Class::primitive_type(oop java_class) { assert(java_lang_Class::is_primitive(java_class), "just checking"); - klassOop ak = klassOop(java_class->obj_field(array_klass_offset)); + klassOop ak = klassOop(java_class->obj_field(_array_klass_offset)); BasicType type = T_VOID; if (ak != NULL) { // Note: create_basic_type_mirror above initializes ak to a non-null value. @@ -668,34 +704,18 @@ oop java_lang_Class::primitive_mirror(BasicType t) { bool java_lang_Class::offsets_computed = false; int java_lang_Class::classRedefinedCount_offset = -1; -int java_lang_Class::parallelCapable_offset = -1; void java_lang_Class::compute_offsets() { assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; - klassOop k = SystemDictionary::Class_klass(); + klassOop klass_oop = SystemDictionary::Class_klass(); // The classRedefinedCount field is only present starting in 1.5, // so don't go fatal. compute_optional_offset(classRedefinedCount_offset, - k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); + klass_oop, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); - // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, - klassOop k1 = SystemDictionary::ClassLoader_klass(); - compute_optional_offset(parallelCapable_offset, - k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); -} - -// For class loader classes, parallelCapable defined -// based on non-null field -// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it -bool java_lang_Class::parallelCapable(oop class_loader) { - if (!JDK_Version::is_gte_jdk17x_version() - || parallelCapable_offset == -1) { - // Default for backward compatibility is false - return false; - } - return (class_loader->obj_field(parallelCapable_offset) != NULL); + CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } int java_lang_Class::classRedefinedCount(oop the_class_mirror) { @@ -2308,7 +2328,6 @@ void java_lang_ref_SoftReference::set_clock(jlong value) { int java_lang_invoke_MethodHandle::_type_offset; int java_lang_invoke_MethodHandle::_vmtarget_offset; int java_lang_invoke_MethodHandle::_vmentry_offset; -int java_lang_invoke_MethodHandle::_vmslots_offset; int java_lang_invoke_MemberName::_clazz_offset; int java_lang_invoke_MemberName::_name_offset; @@ -2327,35 +2346,30 @@ int java_lang_invoke_AdapterMethodHandle::_conversion_offset; int java_lang_invoke_CountingMethodHandle::_vmcount_offset; void java_lang_invoke_MethodHandle::compute_offsets() { - klassOop k = SystemDictionary::MethodHandle_klass(); - if (k != NULL && EnableInvokeDynamic) { + klassOop klass_oop = SystemDictionary::MethodHandle_klass(); + if (klass_oop != NULL && EnableInvokeDynamic) { bool allow_super = false; - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); - compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), allow_super); - compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), allow_super); - - // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots. - // It is optional pending experiments to keep or toss. - compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), allow_super); + compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); + METHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } void java_lang_invoke_MemberName::compute_offsets() { - klassOop k = SystemDictionary::MemberName_klass(); - if (k != NULL && EnableInvokeDynamic) { - compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); - compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); - compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature()); - compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature()); - compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + klassOop klass_oop = SystemDictionary::MemberName_klass(); + if (klass_oop != NULL && EnableInvokeDynamic) { + compute_offset(_clazz_offset, klass_oop, vmSymbols::clazz_name(), vmSymbols::class_signature()); + compute_offset(_name_offset, klass_oop, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::object_signature()); + compute_offset(_flags_offset, klass_oop, vmSymbols::flags_name(), vmSymbols::int_signature()); + compute_offset(_vmindex_offset, klass_oop, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } void java_lang_invoke_DirectMethodHandle::compute_offsets() { klassOop k = SystemDictionary::DirectMethodHandle_klass(); if (k != NULL && EnableInvokeDynamic) { - compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); + DIRECTMETHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } @@ -2399,31 +2413,9 @@ void java_lang_invoke_MethodHandle::set_type(oop mh, oop mtype) { mh->obj_field_put(_type_offset, mtype); } -int java_lang_invoke_MethodHandle::vmslots(oop mh) { - int vmslots_offset = _vmslots_offset; - if (vmslots_offset != 0) { -#ifdef ASSERT - int x = mh->int_field(vmslots_offset); - int y = compute_vmslots(mh); - assert(x == y, "correct hoisted value"); -#endif - return mh->int_field(vmslots_offset); - } else { - return compute_vmslots(mh); - } -} - -// if MH.vmslots exists, hoist into it the value of type.form.vmslots -void java_lang_invoke_MethodHandle::init_vmslots(oop mh) { - int vmslots_offset = _vmslots_offset; - if (vmslots_offset != 0) { - mh->int_field_put(vmslots_offset, compute_vmslots(mh)); - } -} - // fetch type.form.vmslots, which is the number of JVM stack slots // required to carry the arguments of this MH -int java_lang_invoke_MethodHandle::compute_vmslots(oop mh) { +int java_lang_invoke_MethodHandle::vmslots(oop mh) { oop mtype = type(mh); if (mtype == NULL) return 0; // Java code would get NPE oop form = java_lang_invoke_MethodType::form(mtype); @@ -2643,6 +2635,7 @@ void java_lang_invoke_MethodTypeForm::compute_offsets() { compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_lang_invoke_MethodType_signature(), true); compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_lang_invoke_MethodHandle_signature(), true); if (_genericInvoker_offset == 0) _genericInvoker_offset = -1; // set to explicit "empty" value + METHODTYPEFORM_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } @@ -2751,6 +2744,18 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr // Support for java_lang_ClassLoader +bool java_lang_ClassLoader::offsets_computed = false; +int java_lang_ClassLoader::parallelCapable_offset = -1; + +void java_lang_ClassLoader::compute_offsets() { + assert(!offsets_computed, "offsets should be initialized only once"); + offsets_computed = true; + + // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, + klassOop k1 = SystemDictionary::ClassLoader_klass(); + compute_optional_offset(parallelCapable_offset, + k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); +} oop java_lang_ClassLoader::parent(oop loader) { assert(loader->is_oop(), "loader must be oop"); @@ -2758,6 +2763,18 @@ oop java_lang_ClassLoader::parent(oop loader) { } +// For class loader classes, parallelCapable defined +// based on non-null field +// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it +bool java_lang_ClassLoader::parallelCapable(oop class_loader) { + if (!JDK_Version::is_gte_jdk17x_version() + || parallelCapable_offset == -1) { + // Default for backward compatibility is false + return false; + } + return (class_loader->obj_field(parallelCapable_offset) != NULL); +} + bool java_lang_ClassLoader::is_trusted_loader(oop loader) { // Fix for 4474172; see evaluation for more details loader = non_reflection_class_loader(loader); @@ -2807,12 +2824,11 @@ int java_lang_String::value_offset; int java_lang_String::offset_offset; int java_lang_String::count_offset; int java_lang_String::hash_offset; -int java_lang_Class::klass_offset; -int java_lang_Class::array_klass_offset; -int java_lang_Class::resolved_constructor_offset; -int java_lang_Class::number_of_fake_oop_fields; -int java_lang_Class::oop_size_offset; -int java_lang_Class::static_oop_field_count_offset; +int java_lang_Class::_klass_offset; +int java_lang_Class::_array_klass_offset; +int java_lang_Class::_resolved_constructor_offset; +int java_lang_Class::_oop_size_offset; +int java_lang_Class::_static_oop_field_count_offset; int java_lang_Throwable::backtrace_offset; int java_lang_Throwable::detailMessage_offset; int java_lang_Throwable::cause_offset; @@ -2925,20 +2941,20 @@ int java_nio_Buffer::limit_offset() { void java_nio_Buffer::compute_offsets() { - klassOop k = SystemDictionary::java_nio_Buffer_klass(); + klassOop k = SystemDictionary::nio_Buffer_klass(); assert(k != NULL, "must be loaded in 1.4+"); compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature()); } // Support for intrinsification of sun.misc.AtomicLongCSImpl.attemptUpdate int sun_misc_AtomicLongCSImpl::value_offset() { - assert(SystemDictionary::sun_misc_AtomicLongCSImpl_klass() != NULL, "can't call this"); + assert(SystemDictionary::AtomicLongCSImpl_klass() != NULL, "can't call this"); return _value_offset; } void sun_misc_AtomicLongCSImpl::compute_offsets() { - klassOop k = SystemDictionary::sun_misc_AtomicLongCSImpl_klass(); + klassOop k = SystemDictionary::AtomicLongCSImpl_klass(); // If this class is not present, its value field offset won't be referenced. if (k != NULL) { compute_offset(_value_offset, k, vmSymbols::value_name(), vmSymbols::long_signature()); @@ -2973,23 +2989,6 @@ void JavaClasses::compute_hard_coded_offsets() { java_lang_String::count_offset = java_lang_String::offset_offset + sizeof (jint); java_lang_String::hash_offset = java_lang_String::count_offset + sizeof (jint); - { - // Do the Class Class - int offset = header; - java_lang_Class::oop_size_offset = header; - offset += BytesPerInt; - java_lang_Class::static_oop_field_count_offset = offset; - offset = align_size_up(offset + BytesPerInt, x); - java_lang_Class::klass_offset = offset; - offset += x; - java_lang_Class::array_klass_offset = offset; - offset += x; - java_lang_Class::resolved_constructor_offset = offset; - } - - // This is NOT an offset - java_lang_Class::number_of_fake_oop_fields = java_lang_Class::hc_number_of_fake_oop_fields; - // Throwable Class java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header; java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header; @@ -3041,8 +3040,8 @@ void JavaClasses::compute_hard_coded_offsets() { // Compute non-hard-coded field offsets of all the classes in this file void JavaClasses::compute_offsets() { - - java_lang_Class::compute_offsets(); + // java_lang_Class::compute_offsets was called earlier in bootstrap + java_lang_ClassLoader::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); if (EnableInvokeDynamic) { @@ -3267,6 +3266,23 @@ void JavaClasses::check_offsets() { #endif // PRODUCT +int InjectedField::compute_offset() { + klassOop klass_oop = klass(); + for (AllFieldStream fs(instanceKlass::cast(klass_oop)); !fs.done(); fs.next()) { + if (!may_be_java && !fs.access_flags().is_internal()) { + // Only look at injected fields + continue; + } + if (fs.name() == name() && fs.signature() == signature()) { + return fs.offset(); + } + } + ResourceMark rm; + tty->print_cr("Invalid layout of %s at %s", instanceKlass::cast(klass_oop)->external_name(), name()->as_C_string()); + fatal("Invalid layout of preloaded class"); + return -1; +} + void javaClasses_init() { JavaClasses::compute_offsets(); JavaClasses::check_offsets(); diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 045717718ae..fca98970de0 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -156,30 +156,32 @@ class java_lang_String : AllStatic { // Interface to java.lang.Class objects +#define CLASS_INJECTED_FIELDS(macro) \ + macro(java_lang_Class, klass, object_signature, false) \ + macro(java_lang_Class, resolved_constructor, object_signature, false) \ + macro(java_lang_Class, array_klass, object_signature, false) \ + macro(java_lang_Class, oop_size, int_signature, false) \ + macro(java_lang_Class, static_oop_field_count, int_signature, false) + class java_lang_Class : AllStatic { - friend class VMStructs; + friend class VMStructs; + private: // The fake offsets are added by the class loader when java.lang.Class is loaded - enum { - hc_number_of_fake_oop_fields = 3, - hc_number_of_fake_int_fields = 2 - }; + static int _klass_offset; + static int _resolved_constructor_offset; + static int _array_klass_offset; - static int klass_offset; - static int resolved_constructor_offset; - static int array_klass_offset; - static int number_of_fake_oop_fields; + static int _oop_size_offset; + static int _static_oop_field_count_offset; - static int oop_size_offset; - static int static_oop_field_count_offset; - - static void compute_offsets(); static bool offsets_computed; static int classRedefinedCount_offset; - static int parallelCapable_offset; public: + static void compute_offsets(); + // Instance creation static oop create_mirror(KlassHandle k, TRAPS); static void fixup_mirror(KlassHandle k, TRAPS); @@ -209,14 +211,12 @@ class java_lang_Class : AllStatic { static klassOop array_klass(oop java_class); static void set_array_klass(oop java_class, klassOop klass); // compiler support for class operations - static int klass_offset_in_bytes() { return klass_offset; } - static int resolved_constructor_offset_in_bytes() { return resolved_constructor_offset; } - static int array_klass_offset_in_bytes() { return array_klass_offset; } + static int klass_offset_in_bytes() { return _klass_offset; } + static int resolved_constructor_offset_in_bytes() { return _resolved_constructor_offset; } + static int array_klass_offset_in_bytes() { return _array_klass_offset; } // Support for classRedefinedCount field static int classRedefinedCount(oop the_class_mirror); static void set_classRedefinedCount(oop the_class_mirror, int value); - // Support for parallelCapable field - static bool parallelCapable(oop the_class_mirror); static int oop_size(oop java_class); static void set_oop_size(oop java_class, int size); @@ -834,16 +834,19 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference { // Interface to java.lang.invoke.MethodHandle objects +#define METHODHANDLE_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MethodHandle, vmentry, intptr_signature, false) \ + macro(java_lang_invoke_MethodHandle, vmtarget, object_signature, true) + class MethodHandleEntry; class java_lang_invoke_MethodHandle: AllStatic { friend class JavaClasses; private: - static int _vmentry_offset; // assembly code trampoline for MH - static int _vmtarget_offset; // class-specific target reference + static int _vmentry_offset; // assembly code trampoline for MH + static int _vmtarget_offset; // class-specific target reference static int _type_offset; // the MethodType of this MH - static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots static void compute_offsets(); @@ -859,8 +862,6 @@ class java_lang_invoke_MethodHandle: AllStatic { static void set_vmentry(oop mh, MethodHandleEntry* data); static int vmslots(oop mh); - static void init_vmslots(oop mh); - static int compute_vmslots(oop mh); // Testers static bool is_subclass(klassOop klass) { @@ -874,14 +875,15 @@ class java_lang_invoke_MethodHandle: AllStatic { static int type_offset_in_bytes() { return _type_offset; } static int vmtarget_offset_in_bytes() { return _vmtarget_offset; } static int vmentry_offset_in_bytes() { return _vmentry_offset; } - static int vmslots_offset_in_bytes() { return _vmslots_offset; } }; +#define DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_DirectMethodHandle, vmindex, int_signature, true) + class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle { friend class JavaClasses; private: - // _vmtarget_offset; // method or class or interface static int _vmindex_offset; // negative or vtable idx or itable idx static void compute_offsets(); @@ -1012,6 +1014,9 @@ class java_lang_invoke_CountingMethodHandle: public java_lang_invoke_MethodHandl // Interface to java.lang.invoke.MemberName objects // (These are a private interface for Java code to query the class hierarchy.) +#define MEMBERNAME_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MemberName, vmtarget, object_signature, true) + class java_lang_invoke_MemberName: AllStatic { friend class JavaClasses; @@ -1121,6 +1126,10 @@ class java_lang_invoke_MethodType: AllStatic { static int form_offset_in_bytes() { return _form_offset; } }; +#define METHODTYPEFORM_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MethodTypeForm, vmslots, int_signature, true) \ + macro(java_lang_invoke_MethodTypeForm, vmlayout, object_signature, true) + class java_lang_invoke_MethodTypeForm: AllStatic { friend class JavaClasses; @@ -1135,6 +1144,8 @@ class java_lang_invoke_MethodTypeForm: AllStatic { public: // Accessors static int vmslots(oop mtform); + static void set_vmslots(oop mtform, int vmslots); + static oop erasedType(oop mtform); static oop genericInvoker(oop mtform); @@ -1156,8 +1167,6 @@ class java_lang_invoke_CallSite: AllStatic { private: static int _target_offset; - static int _caller_method_offset; - static int _caller_bci_offset; static void compute_offsets(); @@ -1169,12 +1178,6 @@ public: static volatile oop target_volatile(oop site) { return site->obj_field_volatile( _target_offset); } static void set_target_volatile(oop site, oop target) { site->obj_field_put_volatile(_target_offset, target); } - static oop caller_method(oop site); - static void set_caller_method(oop site, oop ref); - - static jint caller_bci(oop site); - static void set_caller_bci(oop site, jint bci); - // Testers static bool is_subclass(klassOop klass) { return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass()); @@ -1185,8 +1188,6 @@ public: // Accessors for code generation: static int target_offset_in_bytes() { return _target_offset; } - static int caller_method_offset_in_bytes() { return _caller_method_offset; } - static int caller_bci_offset_in_bytes() { return _caller_bci_offset; } }; @@ -1217,11 +1218,18 @@ class java_lang_ClassLoader : AllStatic { hc_parent_offset = 0 }; + static bool offsets_computed; static int parent_offset; + static int parallelCapable_offset; + + static void compute_offsets(); public: static oop parent(oop loader); + // Support for parallelCapable field + static bool parallelCapable(oop the_class_mirror); + static bool is_trusted_loader(oop loader); // Fix for 4474172 @@ -1343,17 +1351,71 @@ class java_util_concurrent_locks_AbstractOwnableSynchronizer : AllStatic { static oop get_owner_threadObj(oop obj); }; +// Use to declare fields that need to be injected into Java classes +// for the JVM to use. The name_index and signature_index are +// declared in vmSymbols. The may_be_java flag is used to declare +// fields that might already exist in Java but should be injected if +// they don't. Otherwise the field is unconditionally injected and +// the JVM uses the injected one. This is to ensure that name +// collisions don't occur. In general may_be_java should be false +// unless there's a good reason. + +class InjectedField { + public: + const SystemDictionary::WKID klass_id; + const vmSymbols::SID name_index; + const vmSymbols::SID signature_index; + const bool may_be_java; + + + klassOop klass() const { return SystemDictionary::well_known_klass(klass_id); } + Symbol* name() const { return lookup_symbol(name_index); } + Symbol* signature() const { return lookup_symbol(signature_index); } + + int compute_offset(); + + // Find the Symbol for this index + static Symbol* lookup_symbol(int symbol_index) { + return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); + } +}; + +#define DECLARE_INJECTED_FIELD_ENUM(klass, name, signature, may_be_java) \ + klass##_##name##_enum, + +#define ALL_INJECTED_FIELDS(macro) \ + CLASS_INJECTED_FIELDS(macro) \ + METHODHANDLE_INJECTED_FIELDS(macro) \ + DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \ + MEMBERNAME_INJECTED_FIELDS(macro) \ + METHODTYPEFORM_INJECTED_FIELDS(macro) + // Interface to hard-coded offset checking class JavaClasses : AllStatic { private: + + static InjectedField _injected_fields[]; + static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0; static bool check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0; static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0; + public: + enum InjectedFieldID { + ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM) + MAX_enum + }; + + static int compute_injected_offset(InjectedFieldID id); + static void compute_hard_coded_offsets(); static void compute_offsets(); static void check_offsets() PRODUCT_RETURN; + + static InjectedField* get_injected(Symbol* class_name, int* field_count); }; +#undef DECLARE_INJECTED_FIELD_ENUM + #endif // SHARE_VM_CLASSFILE_JAVACLASSES_HPP diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 76ebb989872..1591b795fde 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -125,13 +125,13 @@ bool SystemDictionary::is_internal_format(Symbol* class_name) { bool SystemDictionary::is_parallelCapable(Handle class_loader) { if (UnsyncloadClass || class_loader.is_null()) return true; if (AlwaysLockClassLoader) return false; - return java_lang_Class::parallelCapable(class_loader()); + return java_lang_ClassLoader::parallelCapable(class_loader()); } // ---------------------------------------------------------------------------- // ParallelDefineClass flag does not apply to bootclass loader bool SystemDictionary::is_parallelDefine(Handle class_loader) { if (class_loader.is_null()) return false; - if (AllowParallelDefineClass && java_lang_Class::parallelCapable(class_loader())) { + if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) { return true; } return false; @@ -1290,7 +1290,7 @@ static instanceKlassHandle download_and_retry_class_load( Symbol* class_name, TRAPS) { - klassOop dlm = SystemDictionary::sun_jkernel_DownloadManager_klass(); + klassOop dlm = SystemDictionary::DownloadManager_klass(); instanceKlassHandle nk; // If download manager class isn't loaded just return. @@ -1953,7 +1953,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { // first do Object, String, Class initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); - debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass))); + java_lang_Class::compute_offsets(); // Fixup mirrors for classes loaded before java.lang.Class. // These calls iterate over the objects currently in the perm gen @@ -2001,7 +2001,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); #ifdef KERNEL - if (sun_jkernel_DownloadManager_klass() == NULL) { + if (DownloadManager_klass() == NULL) { warning("Cannot find sun/jkernel/DownloadManager"); } #endif // KERNEL @@ -2736,7 +2736,7 @@ class ClassStatistics: AllStatic { class_size += ik->local_interfaces()->size(); class_size += ik->transitive_interfaces()->size(); // We do not have to count implementors, since we only store one! - class_size += ik->fields()->size(); + class_size += ik->all_fields_count() * FieldInfo::field_slots; } } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index f6538dda2fc..528ecafbcde 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -133,15 +133,15 @@ class SymbolPropertyTable; template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ \ - /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ - /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ - /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ - template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ - template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ - template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ + /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ + /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ + /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ + template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ + template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ + template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ + template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \ @@ -168,14 +168,14 @@ class SymbolPropertyTable; template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \ + template(nio_Buffer_klass, java_nio_Buffer, Opt) \ \ /* If this class isn't present, it won't be referenced. */ \ - template(sun_misc_AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \ + template(AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \ \ - template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ + template(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ \ - template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \ + template(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \ \ /* Preload boxing klasses */ \ template(Boolean_klass, java_lang_Boolean, Pre) \ @@ -199,7 +199,7 @@ class SystemDictionary : AllStatic { enum WKID { NO_WKID = 0, - #define WK_KLASS_ENUM(name, ignore_s, ignore_o) WK_KLASS_ENUM_NAME(name), + #define WK_KLASS_ENUM(name, symbol, ignore_o) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name), WK_KLASSES_DO(WK_KLASS_ENUM) #undef WK_KLASS_ENUM @@ -426,11 +426,16 @@ public: } public: - #define WK_KLASS_DECLARE(name, ignore_symbol, option) \ + #define WK_KLASS_DECLARE(name, symbol, option) \ static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } WK_KLASSES_DO(WK_KLASS_DECLARE); #undef WK_KLASS_DECLARE + static klassOop well_known_klass(WKID id) { + assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); + return _well_known_klasses[id]; + } + // Local definition for direct access to the private array: #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index c621da24092..a5c5781fe2e 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -264,8 +264,8 @@ template(setTargetNormal_name, "setTargetNormal") \ template(setTargetVolatile_name, "setTargetVolatile") \ template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ - NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ - LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ + NOT_LP64( do_alias(intptr_signature, int_signature) ) \ + LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ \ /* common method and field names */ \ @@ -365,6 +365,11 @@ template(erasedType_name, "erasedType") \ template(genericInvoker_name, "genericInvoker") \ template(append_name, "append") \ + template(klass_name, "klass") \ + template(resolved_constructor_name, "resolved_constructor") \ + template(array_klass_name, "array_klass") \ + template(oop_size_name, "oop_size") \ + template(static_oop_field_count_name, "static_oop_field_count") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 296c1039035..7b7b49d368c 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -984,11 +984,8 @@ ConstantPoolCacheEntry *cp_entry)) // check the access_flags for the field in the klass instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1())); - typeArrayOop fields = ik->fields(); int index = cp_entry->field_index(); - assert(index < fields->length(), "holders field index is out of range"); - // bail out if field accesses are not watched - if ((fields->ushort_at(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; + if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; switch(cp_entry->flag_state()) { case btos: // fall through @@ -1021,11 +1018,9 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, // check the access_flags for the field in the klass instanceKlass* ik = instanceKlass::cast(k); - typeArrayOop fields = ik->fields(); int index = cp_entry->field_index(); - assert(index < fields->length(), "holders field index is out of range"); // bail out if field modifications are not watched - if ((fields->ushort_at(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return; + if ((ik->field_access_flags(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return; char sig_type = '\0'; diff --git a/hotspot/src/share/vm/oops/cpCacheOop.cpp b/hotspot/src/share/vm/oops/cpCacheOop.cpp index 087c8a1f9c5..678bc13272e 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp @@ -128,17 +128,13 @@ bool ConstantPoolCacheEntry::same_methodOop(oop cur_f1, oop f1) { void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code, Bytecodes::Code put_code, KlassHandle field_holder, - int orig_field_index, + int field_index, int field_offset, TosState field_type, bool is_final, bool is_volatile) { set_f1(field_holder()->java_mirror()); set_f2(field_offset); - // The field index is used by jvm/ti and is the index into fields() array - // in holder instanceKlass. This is scaled by instanceKlass::next_offset. - assert((orig_field_index % instanceKlass::next_offset) == 0, "wierd index"); - const int field_index = orig_field_index / instanceKlass::next_offset; assert(field_index <= field_index_mask, "field index does not fit in low flag bits"); set_flags(as_flags(field_type, is_final, false, is_volatile, false, false) | @@ -149,7 +145,7 @@ void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code, } int ConstantPoolCacheEntry::field_index() const { - return (_flags & field_index_mask) * instanceKlass::next_offset; + return (_flags & field_index_mask); } void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, diff --git a/hotspot/src/share/vm/oops/fieldInfo.hpp b/hotspot/src/share/vm/oops/fieldInfo.hpp new file mode 100644 index 00000000000..69de3aef110 --- /dev/null +++ b/hotspot/src/share/vm/oops/fieldInfo.hpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_FIELDINFO_HPP +#define SHARE_VM_OOPS_FIELDINFO_HPP + +#include "oops/typeArrayOop.hpp" +#include "classfile/vmSymbols.hpp" + +// This class represents the field information contained in the fields +// array of an instanceKlass. Currently it's laid on top an array of +// Java shorts but in the future it could simply be used as a real +// array type. FieldInfo generally shouldn't be used directly. +// Fields should be queried either through instanceKlass or through +// the various FieldStreams. +class FieldInfo VALUE_OBJ_CLASS_SPEC { + friend class fieldDescriptor; + friend class JavaFieldStream; + friend class ClassFileParser; + + public: + // fields + // Field info extracted from the class file and stored + // as an array of 7 shorts + enum FieldOffset { + access_flags_offset = 0, + name_index_offset = 1, + signature_index_offset = 2, + initval_index_offset = 3, + low_offset = 4, + high_offset = 5, + generic_signature_offset = 6, + field_slots = 7 + }; + + private: + u2 _shorts[field_slots]; + + void set_name_index(u2 val) { _shorts[name_index_offset] = val; } + void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; } + void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; } + void set_generic_signature_index(u2 val) { _shorts[generic_signature_offset] = val; } + + u2 name_index() const { return _shorts[name_index_offset]; } + u2 signature_index() const { return _shorts[signature_index_offset]; } + u2 initval_index() const { return _shorts[initval_index_offset]; } + u2 generic_signature_index() const { return _shorts[generic_signature_offset]; } + + public: + static FieldInfo* from_field_array(typeArrayOop fields, int index) { + return ((FieldInfo*)fields->short_at_addr(index * field_slots)); + } + + void initialize(u2 access_flags, + u2 name_index, + u2 signature_index, + u2 initval_index, + u2 generic_signature_index, + u4 offset) { + _shorts[access_flags_offset] = access_flags; + _shorts[name_index_offset] = name_index; + _shorts[signature_index_offset] = signature_index; + _shorts[initval_index_offset] = initval_index; + _shorts[generic_signature_offset] = generic_signature_index; + set_offset(offset); + } + + u2 access_flags() const { return _shorts[access_flags_offset]; } + u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); } + + Symbol* name(constantPoolHandle cp) const { + int index = name_index(); + if (is_internal()) { + return lookup_symbol(index); + } + return cp->symbol_at(index); + } + + Symbol* signature(constantPoolHandle cp) const { + int index = signature_index(); + if (is_internal()) { + return lookup_symbol(index); + } + return cp->symbol_at(index); + } + + Symbol* generic_signature(constantPoolHandle cp) const { + int index = generic_signature_index(); + if (index == 0) { + return NULL; + } + return cp->symbol_at(index); + } + + void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } + void set_offset(u4 val) { + _shorts[low_offset] = extract_low_short_from_int(val); + _shorts[high_offset] = extract_high_short_from_int(val); + } + + bool is_internal() const { + return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0; + } + + Symbol* lookup_symbol(int symbol_index) const { + assert(is_internal(), "only internal fields"); + return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); + } +}; + +#endif // SHARE_VM_OOPS_FIELDINFO_HPP diff --git a/hotspot/src/share/vm/oops/fieldStreams.hpp b/hotspot/src/share/vm/oops/fieldStreams.hpp new file mode 100644 index 00000000000..07c28f32eee --- /dev/null +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_FIELDSTREAMS_HPP +#define SHARE_VM_OOPS_FIELDSTREAMS_HPP + +#include "oops/instanceKlass.hpp" +#include "oops/fieldInfo.hpp" + +// The is the base class for iteration over the fields array +// describing the declared fields in the class. Several subclasses +// are provided depending on the kind of iteration required. The +// JavaFieldStream is for iterating over regular Java fields and it +// generally the preferred iterator. InternalFieldStream only +// iterates over fields that have been injected by the JVM. +// AllFieldStream exposes all fields and should only be used in rare +// cases. +class FieldStreamBase : public StackObj { + protected: + typeArrayHandle _fields; + constantPoolHandle _constants; + int _index; + int _limit; + + FieldInfo* field() const { return FieldInfo::from_field_array(_fields(), _index); } + + FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants, int start, int limit) { + _fields = fields; + _constants = constants; + _index = start; + _limit = limit; + } + + FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants) { + _fields = fields; + _constants = constants; + _index = 0; + _limit = fields->length() / FieldInfo::field_slots; + } + + public: + FieldStreamBase(instanceKlass* klass) { + _fields = klass->fields(); + _constants = klass->constants(); + _index = 0; + _limit = klass->java_fields_count(); + } + FieldStreamBase(instanceKlassHandle klass) { + _fields = klass->fields(); + _constants = klass->constants(); + _index = 0; + _limit = klass->java_fields_count(); + } + + // accessors + int index() const { return _index; } + + void next() { _index += 1; } + bool done() const { return _index >= _limit; } + + // Accessors for current field + AccessFlags access_flags() const { + AccessFlags flags; + flags.set_flags(field()->access_flags()); + return flags; + } + + void set_access_flags(u2 flags) const { + field()->set_access_flags(flags); + } + + void set_access_flags(AccessFlags flags) const { + set_access_flags(flags.as_short()); + } + + Symbol* name() const { + return field()->name(_constants); + } + + Symbol* signature() const { + return field()->signature(_constants); + } + + Symbol* generic_signature() const { + return field()->generic_signature(_constants); + } + + int offset() const { + return field()->offset(); + } + + void set_offset(int offset) { + field()->set_offset(offset); + } +}; + +// Iterate over only the internal fields +class JavaFieldStream : public FieldStreamBase { + public: + JavaFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {} + JavaFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {} + + int name_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->name_index(); + } + void set_name_index(int index) { + assert(!field()->is_internal(), "regular only"); + field()->set_name_index(index); + } + int signature_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->signature_index(); + } + void set_signature_index(int index) { + assert(!field()->is_internal(), "regular only"); + field()->set_signature_index(index); + } + int generic_signature_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->generic_signature_index(); + } + void set_generic_signature_index(int index) { + assert(!field()->is_internal(), "regular only"); + field()->set_generic_signature_index(index); + } + int initval_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->initval_index(); + } + void set_initval_index(int index) { + assert(!field()->is_internal(), "regular only"); + return field()->set_initval_index(index); + } +}; + + +// Iterate over only the internal fields +class InternalFieldStream : public FieldStreamBase { + public: + InternalFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), k->all_fields_count()) {} + InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), k->all_fields_count()) {} +}; + + +class AllFieldStream : public FieldStreamBase { + public: + AllFieldStream(typeArrayHandle fields, constantPoolHandle constants): FieldStreamBase(fields, constants) {} + AllFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants()) {} + AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {} +}; + +#endif // SHARE_VM_OOPS_FIELDSTREAMS_HPP diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 841b807d1e4..8a3c247b216 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -36,6 +36,7 @@ #include "memory/genOopClosures.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/permGen.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/instanceOop.hpp" @@ -782,14 +783,11 @@ void instanceKlass::mask_for(methodHandle method, int bci, bool instanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { - const int n = fields()->length(); - for (int i = 0; i < n; i += next_offset ) { - int name_index = fields()->ushort_at(i + name_index_offset); - int sig_index = fields()->ushort_at(i + signature_index_offset); - Symbol* f_name = constants()->symbol_at(name_index); - Symbol* f_sig = constants()->symbol_at(sig_index); + for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) { + Symbol* f_name = fs.name(); + Symbol* f_sig = fs.signature(); if (f_name == name && f_sig == sig) { - fd->initialize(as_klassOop(), i); + fd->initialize(as_klassOop(), fs.index()); return true; } } @@ -803,11 +801,10 @@ void instanceKlass::shared_symbols_iterate(SymbolClosure* closure) { closure->do_symbol(&_source_file_name); closure->do_symbol(&_source_debug_extension); - const int n = fields()->length(); - for (int i = 0; i < n; i += next_offset ) { - int name_index = fields()->ushort_at(i + name_index_offset); + for (JavaFieldStream fs(this); !fs.done(); fs.next()) { + int name_index = fs.name_index(); closure->do_symbol(constants()->symbol_at_addr(name_index)); - int sig_index = fields()->ushort_at(i + signature_index_offset); + int sig_index = fs.signature_index(); closure->do_symbol(constants()->symbol_at_addr(sig_index)); } } @@ -872,10 +869,9 @@ klassOop instanceKlass::find_field(Symbol* name, Symbol* sig, bool is_static, fi bool instanceKlass::find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const { - int length = fields()->length(); - for (int i = 0; i < length; i += next_offset) { - if (offset_from_fields( i ) == offset) { - fd->initialize(as_klassOop(), i); + for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) { + if (fs.offset() == offset) { + fd->initialize(as_klassOop(), fs.index()); if (fd->is_static() == is_static) return true; } } @@ -906,11 +902,12 @@ void instanceKlass::methods_do(void f(methodOop method)) { void instanceKlass::do_local_static_fields(FieldClosure* cl) { - fieldDescriptor fd; - int length = fields()->length(); - for (int i = 0; i < length; i += next_offset) { - fd.initialize(as_klassOop(), i); - if (fd.is_static()) cl->do_field(&fd); + for (JavaFieldStream fs(this); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor fd; + fd.initialize(as_klassOop(), fs.index()); + cl->do_field(&fd); + } } } @@ -922,11 +919,12 @@ void instanceKlass::do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAP void instanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) { - fieldDescriptor fd; - int length = this_oop->fields()->length(); - for (int i = 0; i < length; i += next_offset) { - fd.initialize(this_oop(), i); - if (fd.is_static()) { f(&fd, CHECK); } // Do NOT remove {}! (CHECK macro expands into several statements) + for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor fd; + fd.initialize(this_oop(), fs.index()); + f(&fd, CHECK); + } } } @@ -941,11 +939,11 @@ void instanceKlass::do_nonstatic_fields(FieldClosure* cl) { super->do_nonstatic_fields(cl); } fieldDescriptor fd; - int length = fields()->length(); + int length = java_fields_count(); // In DebugInfo nonstatic fields are sorted by offset. int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1)); int j = 0; - for (int i = 0; i < length; i += next_offset) { + for (int i = 0; i < length; i += 1) { fd.initialize(as_klassOop(), i); if (!fd.is_static()) { fields_sorted[j + 0] = fd.offset(); @@ -2411,43 +2409,6 @@ void instanceKlass::oop_verify_on(oop obj, outputStream* st) { oop_oop_iterate(obj, &blk); } -#ifndef PRODUCT - -void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) { - // This verification code is disabled. JDK_Version::is_gte_jdk14x_version() - // cannot be called since this function is called before the VM is - // able to determine what JDK version is running with. - // The check below always is false since 1.4. - return; - - // This verification code temporarily disabled for the 1.4 - // reflection implementation since java.lang.Class now has - // Java-level instance fields. Should rewrite this to handle this - // case. - if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) { - // Verify that java.lang.Class instances have a fake oop field added. - instanceKlass* ik = instanceKlass::cast(k); - - // Check that we have the right class - static bool first_time = true; - guarantee(k == SystemDictionary::Class_klass() && first_time, "Invalid verify of maps"); - first_time = false; - const int extra = java_lang_Class::number_of_fake_oop_fields; - guarantee(ik->nonstatic_field_size() == extra, "just checking"); - guarantee(ik->nonstatic_oop_map_count() == 1, "just checking"); - guarantee(ik->size_helper() == align_object_size(instanceOopDesc::header_size() + extra), "just checking"); - - // Check that the map is (2,extra) - int offset = java_lang_Class::klass_offset; - - OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); - guarantee(map->offset() == offset && map->count() == (unsigned int) extra, - "sanity"); - } -} - -#endif // ndef PRODUCT - // JNIid class for jfieldIDs only // Note to reviewers: // These JNI functions are just moved over to column 1 and not changed diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 1aa663c6806..8fb55ada382 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -27,6 +27,7 @@ #include "oops/constMethodOop.hpp" #include "oops/constantPoolOop.hpp" +#include "oops/fieldInfo.hpp" #include "oops/instanceOop.hpp" #include "oops/klassOop.hpp" #include "oops/klassVtable.hpp" @@ -228,6 +229,7 @@ class instanceKlass: public Klass { int _static_field_size; // number words used by static fields (oop and non-oop) in this klass int _static_oop_field_count;// number of static oop fields in this klass int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks + int _java_fields_count; // The number of declared Java fields bool _is_marked_dependent; // used for marking during flushing and deoptimization bool _rewritten; // methods rewritten. bool _has_nonstatic_fields; // for sizing with UseCompressedOops @@ -307,27 +309,28 @@ class instanceKlass: public Klass { objArrayOop transitive_interfaces() const { return _transitive_interfaces; } void set_transitive_interfaces(objArrayOop a) { oop_store_without_check((oop*) &_transitive_interfaces, (oop) a); } - // fields - // Field info extracted from the class file and stored - // as an array of 7 shorts - enum FieldOffset { - access_flags_offset = 0, - name_index_offset = 1, - signature_index_offset = 2, - initval_index_offset = 3, - low_offset = 4, - high_offset = 5, - generic_signature_offset = 6, - next_offset = 7 - }; + private: + friend class fieldDescriptor; + FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); } + + public: + int field_offset (int index) const { return field(index)->offset(); } + int field_access_flags(int index) const { return field(index)->access_flags(); } + Symbol* field_name (int index) const { return field(index)->name(constants()); } + Symbol* field_signature (int index) const { return field(index)->signature(constants()); } + + // Number of Java declared fields + int java_fields_count() const { return _java_fields_count; } + + // Number of fields including any injected fields + int all_fields_count() const { return _fields->length() / sizeof(FieldInfo::field_slots); } typeArrayOop fields() const { return _fields; } - int offset_from_fields( int index ) const { - return build_int_from_shorts( fields()->ushort_at(index + low_offset), - fields()->ushort_at(index + high_offset) ); - } - void set_fields(typeArrayOop f) { oop_store_without_check((oop*) &_fields, (oop) f); } + void set_fields(typeArrayOop f, int java_fields_count) { + oop_store_without_check((oop*) &_fields, (oop) f); + _java_fields_count = java_fields_count; + } // inner classes typeArrayOop inner_classes() const { return _inner_classes; } @@ -842,10 +845,6 @@ public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); - -#ifndef PRODUCT - static void verify_class_klass_nonstatic_oop_maps(klassOop k) PRODUCT_RETURN; -#endif }; inline methodOop instanceKlass::method_at_vtable(int index) { diff --git a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp index dc2cd6cdf45..fa13f17ede4 100644 --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp @@ -386,7 +386,7 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int it ik->set_local_interfaces(NULL); ik->set_transitive_interfaces(NULL); ik->init_implementor(); - ik->set_fields(NULL); + ik->set_fields(NULL, 0); ik->set_constants(NULL); ik->set_class_loader(NULL); ik->set_protection_domain(NULL); diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index b8e61c1f8ef..2134b3e7708 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -492,7 +492,7 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) // First check if this is a static field if (modifiers & JVM_ACC_STATIC) { - intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot ); + intptr_t offset = instanceKlass::cast(k1())->field_offset( slot ); JNIid* id = instanceKlass::cast(k1())->jni_id_for(offset); assert(id != NULL, "corrupt Field object"); debug_only(id->set_is_static_field_id();) @@ -504,7 +504,7 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) // The slot is the index of the field description in the field-array // The jfieldID is the offset of the field within the object // It may also have hash bits for k, if VerifyJNIFields is turned on. - intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot ); + intptr_t offset = instanceKlass::cast(k1())->field_offset( slot ); assert(instanceKlass::cast(k1())->contains_field_offset(offset), "stay within object"); ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset); return ret; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 6a28179c3cc..1e998e32ff5 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -32,6 +32,7 @@ #include "gc_interface/collectedHeap.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" #include "prims/jvm.h" @@ -1493,7 +1494,7 @@ JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field)) fieldDescriptor fd; KlassHandle kh(THREAD, k); - intptr_t offset = instanceKlass::cast(kh())->offset_from_fields(slot); + intptr_t offset = instanceKlass::cast(kh())->field_offset(slot); if (modifiers & JVM_ACC_STATIC) { // for static fields we only look in the current class @@ -1593,9 +1594,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, // Ensure class is linked k->link_class(CHECK_NULL); - typeArrayHandle fields(THREAD, k->fields()); - int fields_len = fields->length(); - // 4496456 We need to filter out java.lang.Throwable.backtrace bool skip_backtrace = false; @@ -1604,12 +1602,11 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, if (publicOnly) { num_fields = 0; - for (int i = 0, j = 0; i < fields_len; i += instanceKlass::next_offset, j++) { - int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; - if (mods & JVM_ACC_PUBLIC) ++num_fields; + for (JavaFieldStream fs(k()); !fs.done(); fs.next()) { + if (fs.access_flags().is_public()) ++num_fields; } } else { - num_fields = fields_len / instanceKlass::next_offset; + num_fields = k->java_fields_count(); if (k() == SystemDictionary::Throwable_klass()) { num_fields--; @@ -1622,16 +1619,15 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, int out_idx = 0; fieldDescriptor fd; - for (int i = 0; i < fields_len; i += instanceKlass::next_offset) { + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (skip_backtrace) { // 4496456 skip java.lang.Throwable.backtrace - int offset = k->offset_from_fields(i); + int offset = fs.offset(); if (offset == java_lang_Throwable::get_backtrace_offset()) continue; } - int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; - if (!publicOnly || (mods & JVM_ACC_PUBLIC)) { - fd.initialize(k(), i); + if (!publicOnly || fs.access_flags().is_public()) { + fd.initialize(k(), fs.index()); oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL); result->obj_at_put(out_idx, field); ++out_idx; @@ -2119,7 +2115,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)) k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); if (!Klass::cast(k)->oop_is_instance()) return 0; - return instanceKlass::cast(k)->fields()->length() / instanceKlass::next_offset; + return instanceKlass::cast(k)->java_fields_count(); JVM_END @@ -2215,8 +2211,7 @@ JVM_QUICK_ENTRY(jint, JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field JVMWrapper("JVM_GetFieldIxModifiers"); klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - typeArrayOop fields = instanceKlass::cast(k)->fields(); - return fields->ushort_at(field_index * instanceKlass::next_offset + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; + return instanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS; JVM_END @@ -2399,7 +2394,7 @@ JVM_ENTRY(const char*, JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint JVM_END -JVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) +JVM_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) JVMWrapper("JVM_GetCPFieldModifiers"); klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls)); @@ -2411,12 +2406,9 @@ JVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_in case JVM_CONSTANT_Fieldref: { Symbol* name = cp->uncached_name_ref_at(cp_index); Symbol* signature = cp->uncached_signature_ref_at(cp_index); - typeArrayOop fields = instanceKlass::cast(k_called)->fields(); - int fields_count = fields->length(); - for (int i = 0; i < fields_count; i += instanceKlass::next_offset) { - if (cp_called->symbol_at(fields->ushort_at(i + instanceKlass::name_index_offset)) == name && - cp_called->symbol_at(fields->ushort_at(i + instanceKlass::signature_index_offset)) == signature) { - return fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; + for (JavaFieldStream fs(k_called); !fs.done(); fs.next()) { + if (fs.name() == name && fs.signature() == signature) { + return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS; } } return -1; diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp index d12d69cee71..8502ef26212 100644 --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/symbolTable.hpp" #include "interpreter/bytecodeStream.hpp" +#include "oops/fieldStreams.hpp" #include "prims/jvmtiClassFileReconstituter.hpp" #include "runtime/signature.hpp" #ifdef TARGET_ARCH_x86 @@ -52,25 +53,22 @@ // JVMSpec| field_info fields[fields_count]; void JvmtiClassFileReconstituter::write_field_infos() { HandleMark hm(thread()); - typeArrayHandle fields(thread(), ikh()->fields()); - int fields_length = fields->length(); - int num_fields = fields_length / instanceKlass::next_offset; objArrayHandle fields_anno(thread(), ikh()->fields_annotations()); - write_u2(num_fields); - for (int index = 0; index < fields_length; index += instanceKlass::next_offset) { - AccessFlags access_flags; - int flags = fields->ushort_at(index + instanceKlass::access_flags_offset); - access_flags.set_flags(flags); - int name_index = fields->ushort_at(index + instanceKlass::name_index_offset); - int signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset); - int initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset); + // Compute the real number of Java fields + int java_fields = ikh()->java_fields_count(); + + write_u2(java_fields * FieldInfo::field_slots); + for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) { + AccessFlags access_flags = fs.access_flags(); + int name_index = fs.name_index(); + int signature_index = fs.signature_index(); + int initial_value_index = fs.initval_index(); guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field"); - int offset = ikh()->offset_from_fields( index ); - int generic_signature_index = - fields->ushort_at(index + instanceKlass::generic_signature_offset); + // int offset = ikh()->field_offset( index ); + int generic_signature_index = fs.generic_signature_index(); typeArrayHandle anno(thread(), fields_anno.not_null() ? - (typeArrayOop)(fields_anno->obj_at(index / instanceKlass::next_offset)) : + (typeArrayOop)(fields_anno->obj_at(fs.index())) : (typeArrayOop)NULL); // JVMSpec| field_info { @@ -81,7 +79,7 @@ void JvmtiClassFileReconstituter::write_field_infos() { // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } - write_u2(flags & JVM_RECOGNIZED_FIELD_MODIFIERS); + write_u2(access_flags.as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); write_u2(name_index); write_u2(signature_index); int attr_count = 0; diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 61a8a2319ae..f93fdf1bd43 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -2044,7 +2044,6 @@ JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) { // make sure we haven't set this watch before if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; fdesc_ptr->set_is_field_access_watched(true); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true); @@ -2057,7 +2056,6 @@ JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) { // make sure we have a watch to clear if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; fdesc_ptr->set_is_field_access_watched(false); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false); @@ -2070,7 +2068,6 @@ JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) { // make sure we haven't set this watch before if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; fdesc_ptr->set_is_field_modification_watched(true); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true); @@ -2083,7 +2080,6 @@ JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) { // make sure we have a watch to clear if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; fdesc_ptr->set_is_field_modification_watched(false); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false); diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index 30903a63226..fd426422b13 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -565,15 +565,6 @@ JvmtiEnvBase::get_JavaThread(jthread jni_thread) { } -// update the access_flags for the field in the klass -void -JvmtiEnvBase::update_klass_field_access_flag(fieldDescriptor *fd) { - instanceKlass* ik = instanceKlass::cast(fd->field_holder()); - typeArrayOop fields = ik->fields(); - fields->ushort_at_put(fd->index(), (jushort)fd->access_flags().as_short()); -} - - // return the vframe on the specified thread and depth, NULL if no such frame vframe* JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) { diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp index 0ad1b925bc4..ba0374648e5 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp @@ -267,8 +267,6 @@ class JvmtiEnvBase : public CHeapObj { // convert to a jni jclass from a non-null klassOop jclass get_jni_class_non_null(klassOop k); - void update_klass_field_access_flag(fieldDescriptor *fd); - jint count_locked_objects(JavaThread *java_thread, Handle hobj); jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread, JavaThread* java_thread, diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 62f8ba830fe..10a478bd5eb 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -30,6 +30,7 @@ #include "interpreter/rewriter.hpp" #include "memory/gcLocker.hpp" #include "memory/universe.inline.hpp" +#include "oops/fieldStreams.hpp" #include "oops/klassVtable.hpp" #include "prims/jvmtiImpl.hpp" #include "prims/jvmtiRedefineClasses.hpp" @@ -551,41 +552,35 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( // Check if the number, names, types and order of fields declared in these classes // are the same. - typeArrayOop k_old_fields = the_class->fields(); - typeArrayOop k_new_fields = scratch_class->fields(); - int n_fields = k_old_fields->length(); - if (n_fields != k_new_fields->length()) { - return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; - } - - for (i = 0; i < n_fields; i += instanceKlass::next_offset) { + JavaFieldStream old_fs(the_class); + JavaFieldStream new_fs(scratch_class); + for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) { // access - old_flags = k_old_fields->ushort_at(i + instanceKlass::access_flags_offset); - new_flags = k_new_fields->ushort_at(i + instanceKlass::access_flags_offset); + old_flags = old_fs.access_flags().as_short(); + new_flags = new_fs.access_flags().as_short(); if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // offset - if (k_old_fields->short_at(i + instanceKlass::low_offset) != - k_new_fields->short_at(i + instanceKlass::low_offset) || - k_old_fields->short_at(i + instanceKlass::high_offset) != - k_new_fields->short_at(i + instanceKlass::high_offset)) { + if (old_fs.offset() != new_fs.offset()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // name and signature - jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset); - jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset); - Symbol* name_sym1 = the_class->constants()->symbol_at(name_index); - Symbol* sig_sym1 = the_class->constants()->symbol_at(sig_index); - name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset); - sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset); - Symbol* name_sym2 = scratch_class->constants()->symbol_at(name_index); - Symbol* sig_sym2 = scratch_class->constants()->symbol_at(sig_index); + Symbol* name_sym1 = the_class->constants()->symbol_at(old_fs.name_index()); + Symbol* sig_sym1 = the_class->constants()->symbol_at(old_fs.signature_index()); + Symbol* name_sym2 = scratch_class->constants()->symbol_at(new_fs.name_index()); + Symbol* sig_sym2 = scratch_class->constants()->symbol_at(new_fs.signature_index()); if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } } + // If both streams aren't done then we have a differing number of + // fields. + if (!old_fs.done() || !new_fs.done()) { + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; + } + // Do a parallel walk through the old and new methods. Detect // cases where they match (exist in both), have been added in // the new methods, or have been deleted (exist only in the @@ -2369,38 +2364,34 @@ void VM_RedefineClasses::set_new_constant_pool( int i; // for portability // update each field in klass to use new constant pool indices as needed - typeArrayHandle fields(THREAD, scratch_class->fields()); - int n_fields = fields->length(); - for (i = 0; i < n_fields; i += instanceKlass::next_offset) { - jshort cur_index = fields->short_at(i + instanceKlass::name_index_offset); + for (JavaFieldStream fs(scratch_class); !fs.done(); fs.next()) { + jshort cur_index = fs.name_index(); jshort new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-name_index change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::name_index_offset, new_index); + fs.set_name_index(new_index); } - cur_index = fields->short_at(i + instanceKlass::signature_index_offset); + cur_index = fs.signature_index(); new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-signature_index change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::signature_index_offset, - new_index); + fs.set_signature_index(new_index); } - cur_index = fields->short_at(i + instanceKlass::initval_index_offset); + cur_index = fs.initval_index(); new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-initval_index change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::initval_index_offset, new_index); + fs.set_initval_index(new_index); } - cur_index = fields->short_at(i + instanceKlass::generic_signature_offset); + cur_index = fs.generic_signature_index(); new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-generic_signature change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::generic_signature_offset, - new_index); + fs.set_generic_signature_index(new_index); } } // end for each field diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index df0d70e64d6..c5d5c888402 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -520,7 +520,7 @@ void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() int mods = java_lang_reflect_Field::modifiers(target_oop); klassOop k = java_lang_Class::as_klassOop(clazz); - int offset = instanceKlass::cast(k)->offset_from_fields(slot); + int offset = instanceKlass::cast(k)->field_offset(slot); init_MemberName(mname_oop, k, accessFlags_from(mods), offset); } else { KlassHandle receiver_limit; int decode_flags = 0; @@ -1632,8 +1632,6 @@ void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_d THROW(vmSymbols::java_lang_InternalError()); } - java_lang_invoke_MethodHandle::init_vmslots(mh()); - if (VerifyMethodHandles) { // The privileged code which invokes this routine should not make // a mistake about types, but it's better to verify. @@ -1756,7 +1754,6 @@ void MethodHandles::init_BoundMethodHandle_with_receiver(Handle mh, if (m.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); } - java_lang_invoke_MethodHandle::init_vmslots(mh()); int vmargslot = m->size_of_parameters() - 1; assert(java_lang_invoke_BoundMethodHandle::vmargslot(mh()) == vmargslot, ""); @@ -1862,7 +1859,6 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, THROW(vmSymbols::java_lang_InternalError()); } - java_lang_invoke_MethodHandle::init_vmslots(mh()); int argslot = java_lang_invoke_BoundMethodHandle::vmargslot(mh()); if (VerifyMethodHandles) { @@ -2686,6 +2682,7 @@ void MethodHandles::ensure_vmlayout_field(Handle target, TRAPS) { java_lang_invoke_MethodTypeForm::init_vmlayout(mtform(), cookie); } } + assert(java_lang_invoke_MethodTypeForm::vmslots(mtform()) == argument_slot_count(mtype()), "must agree"); } #ifdef ASSERT diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index fbb723b77b2..48d13dba7ea 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -719,7 +719,7 @@ jint find_field_offset(jobject field, int must_be_static, TRAPS) { } } - int offset = instanceKlass::cast(k)->offset_from_fields(slot); + int offset = instanceKlass::cast(k)->field_offset(slot); return field_offset_from_byte_offset(offset); } diff --git a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp index 0832d31d1bd..1fb0ce0c5e8 100644 --- a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp @@ -42,59 +42,51 @@ typeArrayOop fieldDescriptor::annotations() const { objArrayOop md = ik->fields_annotations(); if (md == NULL) return NULL; - assert((index() % instanceKlass::next_offset) == 0, ""); - return typeArrayOop(md->obj_at(index() / instanceKlass::next_offset)); + return typeArrayOop(md->obj_at(index())); } constantTag fieldDescriptor::initial_value_tag() const { - return constants()->tag_at(_initial_value_index); + return constants()->tag_at(initial_value_index()); } jint fieldDescriptor::int_initial_value() const { - return constants()->int_at(_initial_value_index); + return constants()->int_at(initial_value_index()); } jlong fieldDescriptor::long_initial_value() const { - return constants()->long_at(_initial_value_index); + return constants()->long_at(initial_value_index()); } jfloat fieldDescriptor::float_initial_value() const { - return constants()->float_at(_initial_value_index); + return constants()->float_at(initial_value_index()); } jdouble fieldDescriptor::double_initial_value() const { - return constants()->double_at(_initial_value_index); + return constants()->double_at(initial_value_index()); } oop fieldDescriptor::string_initial_value(TRAPS) const { - return constants()->string_at(_initial_value_index, CHECK_0); + return constants()->string_at(initial_value_index(), CHECK_0); } void fieldDescriptor::initialize(klassOop k, int index) { instanceKlass* ik = instanceKlass::cast(k); _cp = ik->constants(); - typeArrayOop fields = ik->fields(); + FieldInfo* f = ik->field(index); + assert(!f->is_internal(), "regular Java fields only"); - assert(fields->length() % instanceKlass::next_offset == 0, "Illegal size of field array"); - assert(fields->length() >= index + instanceKlass::next_offset, "Illegal size of field array"); - - _access_flags.set_field_flags(fields->ushort_at(index + instanceKlass::access_flags_offset)); - _name_index = fields->ushort_at(index + instanceKlass::name_index_offset); - _signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset); - _initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset); - guarantee(_name_index != 0 && _signature_index != 0, "bad constant pool index for fieldDescriptor"); - _offset = ik->offset_from_fields( index ); - _generic_signature_index = fields->ushort_at(index + instanceKlass::generic_signature_offset); + _access_flags = accessFlags_from(f->access_flags()); + guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor"); _index = index; } #ifndef PRODUCT void fieldDescriptor::print_on(outputStream* st) const { - _access_flags.print_on(st); - constants()->symbol_at(_name_index)->print_value_on(st); + access_flags().print_on(st); + name()->print_value_on(st); st->print(" "); - constants()->symbol_at(_signature_index)->print_value_on(st); + signature()->print_value_on(st); st->print(" @%d ", offset()); if (WizardMode && has_initial_value()) { st->print("(initval "); diff --git a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp index 00f8864a807..e68b5c5f005 100644 --- a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp @@ -40,29 +40,40 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { private: AccessFlags _access_flags; - int _name_index; - int _signature_index; - int _initial_value_index; - int _offset; - int _generic_signature_index; - int _index; // index into fields() array + int _index; // the field index constantPoolHandle _cp; + // update the access_flags for the field in the klass + void update_klass_field_access_flag() { + instanceKlass* ik = instanceKlass::cast(field_holder()); + ik->field(index())->set_access_flags(_access_flags.as_short()); + } + + FieldInfo* field() const { + instanceKlass* ik = instanceKlass::cast(field_holder()); + return ik->field(_index); + } + public: - Symbol* name() const { return _cp->symbol_at(_name_index); } - Symbol* signature() const { return _cp->symbol_at(_signature_index); } + Symbol* name() const { + return field()->name(_cp); + } + Symbol* signature() const { + return field()->signature(_cp); + } klassOop field_holder() const { return _cp->pool_holder(); } constantPoolOop constants() const { return _cp(); } AccessFlags access_flags() const { return _access_flags; } oop loader() const; // Offset (in words) of field from start of instanceOop / klassOop - int offset() const { return _offset; } - Symbol* generic_signature() const { return (_generic_signature_index > 0 ? _cp->symbol_at(_generic_signature_index) : (Symbol*)NULL); } + int offset() const { return field()->offset(); } + Symbol* generic_signature() const { return field()->generic_signature(_cp); } int index() const { return _index; } typeArrayOop annotations() const; // Initial field value - bool has_initial_value() const { return _initial_value_index != 0; } + bool has_initial_value() const { return field()->initval_index() != 0; } + int initial_value_index() const { return field()->initval_index(); } constantTag initial_value_tag() const; // The tag will return true on one of is_int(), is_long(), is_single(), is_double() jint int_initial_value() const; jlong long_initial_value() const; @@ -74,25 +85,31 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { BasicType field_type() const { return FieldType::basic_type(signature()); } // Access flags - bool is_public() const { return _access_flags.is_public(); } - bool is_private() const { return _access_flags.is_private(); } - bool is_protected() const { return _access_flags.is_protected(); } + bool is_public() const { return access_flags().is_public(); } + bool is_private() const { return access_flags().is_private(); } + bool is_protected() const { return access_flags().is_protected(); } bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); } - bool is_static() const { return _access_flags.is_static(); } - bool is_final() const { return _access_flags.is_final(); } - bool is_volatile() const { return _access_flags.is_volatile(); } - bool is_transient() const { return _access_flags.is_transient(); } + bool is_static() const { return access_flags().is_static(); } + bool is_final() const { return access_flags().is_final(); } + bool is_volatile() const { return access_flags().is_volatile(); } + bool is_transient() const { return access_flags().is_transient(); } - bool is_synthetic() const { return _access_flags.is_synthetic(); } + bool is_synthetic() const { return access_flags().is_synthetic(); } - bool is_field_access_watched() const { return _access_flags.is_field_access_watched(); } + bool is_field_access_watched() const { return access_flags().is_field_access_watched(); } bool is_field_modification_watched() const - { return _access_flags.is_field_modification_watched(); } - void set_is_field_access_watched(const bool value) - { _access_flags.set_is_field_access_watched(value); } - void set_is_field_modification_watched(const bool value) - { _access_flags.set_is_field_modification_watched(value); } + { return access_flags().is_field_modification_watched(); } + + void set_is_field_access_watched(const bool value) { + _access_flags.set_is_field_access_watched(value); + update_klass_field_access_flag(); + } + + void set_is_field_modification_watched(const bool value) { + _access_flags.set_is_field_modification_watched(value); + update_klass_field_access_flag(); + } // Initialization void initialize(klassOop k, int index); diff --git a/hotspot/src/share/vm/runtime/reflectionUtils.hpp b/hotspot/src/share/vm/runtime/reflectionUtils.hpp index c9eecaa2324..5d4ba501876 100644 --- a/hotspot/src/share/vm/runtime/reflectionUtils.hpp +++ b/hotspot/src/share/vm/runtime/reflectionUtils.hpp @@ -107,10 +107,8 @@ class MethodStream : public KlassStream { class FieldStream : public KlassStream { private: - int length() const { return fields()->length(); } - constantPoolOop constants() const { return _klass->constants(); } - protected: - typeArrayOop fields() const { return _klass->fields(); } + int length() const { return _klass->java_fields_count(); } + public: FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) : KlassStream(klass, local_only, classes_only) { @@ -118,26 +116,23 @@ class FieldStream : public KlassStream { next(); } - void next() { _index -= instanceKlass::next_offset; } + void next() { _index -= 1; } // Accessors for current field AccessFlags access_flags() const { AccessFlags flags; - flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset)); + flags.set_flags(_klass->field_access_flags(_index)); return flags; } Symbol* name() const { - int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset); - return constants()->symbol_at(name_index); + return _klass->field_name(_index); } Symbol* signature() const { - int signature_index = fields()->ushort_at(index() + - instanceKlass::signature_index_offset); - return constants()->symbol_at(signature_index); + return _klass->field_signature(_index); } // missing: initval() int offset() const { - return _klass->offset_from_fields( index() ); + return _klass->field_offset( index() ); } }; @@ -213,10 +208,10 @@ class FilteredFieldStream : public FieldStream { } int field_count(); void next() { - _index -= instanceKlass::next_offset; + _index -= 1; if (has_filtered_field()) { while (_index >=0 && FilteredFieldsMap::is_filtered_field((klassOop)_klass(), offset())) { - _index -= instanceKlass::next_offset; + _index -= 1; } } } diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 4553ea62f92..5b5138e8350 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -966,7 +966,7 @@ static void call_initializeSystemClass(TRAPS) { // General purpose hook into Java code, run once when the VM is initialized. // The Java library method itself may be changed independently from the VM. static void call_postVMInitHook(TRAPS) { - klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass(); + klassOop k = SystemDictionary::PostVMInitHook_klass(); instanceKlassHandle klass (THREAD, k); if (klass.not_null()) { JavaValue result(T_VOID); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 540649784c6..40b703f15a6 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -261,6 +261,7 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(instanceKlass, _nof_implementors, int) \ nonstatic_field(instanceKlass, _implementors[0], klassOop) \ nonstatic_field(instanceKlass, _fields, typeArrayOop) \ + nonstatic_field(instanceKlass, _java_fields_count, int) \ nonstatic_field(instanceKlass, _constants, constantPoolOop) \ nonstatic_field(instanceKlass, _class_loader, oop) \ nonstatic_field(instanceKlass, _protection_domain, oop) \ @@ -967,11 +968,11 @@ static inline uint64_t cast_uint64_t(size_t x) /* java_lang_Class fields */ \ /*********************************/ \ \ - static_field(java_lang_Class, klass_offset, int) \ - static_field(java_lang_Class, resolved_constructor_offset, int) \ - static_field(java_lang_Class, array_klass_offset, int) \ - static_field(java_lang_Class, oop_size_offset, int) \ - static_field(java_lang_Class, static_oop_field_count_offset, int) \ + static_field(java_lang_Class, _klass_offset, int) \ + static_field(java_lang_Class, _resolved_constructor_offset, int) \ + static_field(java_lang_Class, _array_klass_offset, int) \ + static_field(java_lang_Class, _oop_size_offset, int) \ + static_field(java_lang_Class, _static_oop_field_count_offset, int) \ \ /************************/ \ /* Miscellaneous fields */ \ @@ -1662,19 +1663,24 @@ static inline uint64_t cast_uint64_t(size_t x) declare_constant(constMethodOopDesc::_has_localvariable_table) \ \ /*************************************/ \ - /* instanceKlass FieldOffset enum */ \ + /* instanceKlass enum */ \ /*************************************/ \ \ - declare_constant(instanceKlass::access_flags_offset) \ - declare_constant(instanceKlass::name_index_offset) \ - declare_constant(instanceKlass::signature_index_offset) \ - declare_constant(instanceKlass::initval_index_offset) \ - declare_constant(instanceKlass::low_offset) \ - declare_constant(instanceKlass::high_offset) \ - declare_constant(instanceKlass::generic_signature_offset) \ - declare_constant(instanceKlass::next_offset) \ declare_constant(instanceKlass::implementors_limit) \ \ + /*************************************/ \ + /* FieldInfo FieldOffset enum */ \ + /*************************************/ \ + \ + declare_constant(FieldInfo::access_flags_offset) \ + declare_constant(FieldInfo::name_index_offset) \ + declare_constant(FieldInfo::signature_index_offset) \ + declare_constant(FieldInfo::initval_index_offset) \ + declare_constant(FieldInfo::low_offset) \ + declare_constant(FieldInfo::high_offset) \ + declare_constant(FieldInfo::generic_signature_offset) \ + declare_constant(FieldInfo::field_slots) \ + \ /************************************************/ \ /* instanceKlass InnerClassAttributeOffset enum */ \ /************************************************/ \ diff --git a/hotspot/src/share/vm/utilities/accessFlags.hpp b/hotspot/src/share/vm/utilities/accessFlags.hpp index 663cec30f44..484ce4f3f8d 100644 --- a/hotspot/src/share/vm/utilities/accessFlags.hpp +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp @@ -79,9 +79,14 @@ enum { // Note that the class-related ACC_ANNOTATION bit conflicts with these flags. JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification is watched by JVMTI + JVM_ACC_FIELD_INTERNAL = 0x00000400, // internal field, same as JVM_ACC_ABSTRACT + + JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED | + JVM_ACC_FIELD_MODIFICATION_WATCHED | + JVM_ACC_FIELD_INTERNAL, // flags accepted by set_field_flags() - JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS + JVM_ACC_FIELD_FLAGS = JVM_RECOGNIZED_FIELD_MODIFIERS | JVM_ACC_FIELD_INTERNAL_FLAGS }; @@ -150,13 +155,17 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC { bool is_field_access_watched() const { return (_flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; } bool is_field_modification_watched() const { return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; } + bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; } // get .class file flags jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); } // Initialization void add_promoted_flags(jint flags) { _flags |= (flags & JVM_ACC_PROMOTED_FLAGS); } - void set_field_flags(jint flags) { _flags = (flags & JVM_ACC_FIELD_FLAGS); } + void set_field_flags(jint flags) { + assert((flags & JVM_ACC_FIELD_FLAGS) == flags, "only recognized flags"); + _flags = (flags & JVM_ACC_FIELD_FLAGS); + } void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); } void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); } @@ -218,8 +227,8 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC { } // Conversion - jshort as_short() { return (jshort)_flags; } - jint as_int() { return _flags; } + jshort as_short() const { return (jshort)_flags; } + jint as_int() const { return _flags; } inline friend AccessFlags accessFlags_from(jint flags); From e3afdf10adbc31266951d5d8d3a6350cbaa28211 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sun, 11 Sep 2011 14:48:24 -0700 Subject: [PATCH 049/214] 7088955: add C2 IR support to the SA Reviewed-by: kvn --- hotspot/agent/make/Makefile | 14 +- hotspot/agent/make/saenv.sh | 8 + hotspot/agent/make/saenv64.sh | 8 + hotspot/agent/src/os/solaris/Makefile | 2 - hotspot/agent/src/os/solaris/dbx/Makefile | 91 -- hotspot/agent/src/os/solaris/dbx/README | 9 - .../src/os/solaris/dbx/README-commands.txt | 82 -- .../agent/src/os/solaris/dbx/helloWorld.cpp | 59 - .../agent/src/os/solaris/dbx/proc_service_2.h | 172 --- hotspot/agent/src/os/solaris/dbx/shell_imp.h | 164 --- .../src/os/solaris/dbx/svc_agent_dbx.cpp | 1068 -------------- .../src/os/solaris/dbx/svc_agent_dbx.hpp | 188 --- hotspot/agent/src/os/win32/BasicList.hpp | 66 - hotspot/agent/src/os/win32/Buffer.cpp | 110 -- hotspot/agent/src/os/win32/Buffer.hpp | 68 - hotspot/agent/src/os/win32/Dispatcher.cpp | 115 -- hotspot/agent/src/os/win32/Dispatcher.hpp | 38 - hotspot/agent/src/os/win32/Handler.hpp | 53 - hotspot/agent/src/os/win32/IOBuf.cpp | 490 ------- hotspot/agent/src/os/win32/IOBuf.hpp | 222 --- hotspot/agent/src/os/win32/LockableList.hpp | 54 - hotspot/agent/src/os/win32/Makefile | 80 -- hotspot/agent/src/os/win32/Message.hpp | 123 -- hotspot/agent/src/os/win32/Monitor.cpp | 176 --- hotspot/agent/src/os/win32/Monitor.hpp | 58 - .../agent/src/os/win32/README-commands.txt | 246 ---- hotspot/agent/src/os/win32/README.txt | 64 - hotspot/agent/src/os/win32/Reaper.cpp | 159 --- hotspot/agent/src/os/win32/Reaper.hpp | 90 -- hotspot/agent/src/os/win32/SwDbgSrv.cpp | 1266 ----------------- hotspot/agent/src/os/win32/SwDbgSrv.dsp | 146 -- hotspot/agent/src/os/win32/SwDbgSrv.dsw | 41 - hotspot/agent/src/os/win32/SwDbgSub.cpp | 883 ------------ hotspot/agent/src/os/win32/SwDbgSub.dsp | 130 -- hotspot/agent/src/os/win32/initWinsock.cpp | 71 - hotspot/agent/src/os/win32/initWinsock.hpp | 30 - hotspot/agent/src/os/win32/ioUtils.cpp | 156 -- hotspot/agent/src/os/win32/ioUtils.hpp | 36 - hotspot/agent/src/os/win32/isNT4.cpp | 39 - hotspot/agent/src/os/win32/isNT4.hpp | 34 - hotspot/agent/src/os/win32/libInfo.cpp | 186 --- hotspot/agent/src/os/win32/libInfo.hpp | 44 - hotspot/agent/src/os/win32/nt4internals.cpp | 75 - hotspot/agent/src/os/win32/nt4internals.hpp | 273 ---- hotspot/agent/src/os/win32/ports.h | 32 - hotspot/agent/src/os/win32/procList.cpp | 190 --- hotspot/agent/src/os/win32/procList.hpp | 55 - hotspot/agent/src/os/win32/serverLists.cpp | 270 ---- hotspot/agent/src/os/win32/serverLists.hpp | 204 --- hotspot/agent/src/os/win32/toolHelp.cpp | 48 - hotspot/agent/src/os/win32/toolHelp.hpp | 75 - .../share/classes/sun/jvm/hotspot/CLHSDB.java | 5 +- .../sun/jvm/hotspot/CommandProcessor.java | 246 +++- .../classes/sun/jvm/hotspot/DebugServer.java | 3 +- .../classes/sun/jvm/hotspot/HotSpotAgent.java | 136 +- .../sun/jvm/hotspot/HotSpotTypeDataBase.java | 187 ++- .../classes/sun/jvm/hotspot/TestDebugger.java | 13 +- .../sun/jvm/hotspot/bugspot/BugSpot.java | 6 +- .../sun/jvm/hotspot/bugspot/BugSpotAgent.java | 125 +- .../sun/jvm/hotspot/ci/ciArrayKlass.java | 53 + .../sun/jvm/hotspot/ci/ciArrayKlassKlass.java | 51 + .../sun/jvm/hotspot/ci/ciConstant.java | 63 + .../classes/sun/jvm/hotspot/ci/ciEnv.java | 77 + .../classes/sun/jvm/hotspot/ci/ciField.java | 62 + .../sun/jvm/hotspot/ci/ciInstance.java | 51 + .../sun/jvm/hotspot/ci/ciInstanceKlass.java | 83 ++ .../ciInstanceKlassKlass.java} | 36 +- .../classes/sun/jvm/hotspot/ci/ciKlass.java | 58 + .../sun/jvm/hotspot/ci/ciKlassKlass.java | 51 + .../classes/sun/jvm/hotspot/ci/ciMethod.java | 91 ++ .../sun/jvm/hotspot/ci/ciMethodData.java | 177 +++ .../sun/jvm/hotspot/ci/ciMethodKlass.java | 50 + .../sun/jvm/hotspot/ci/ciObjArrayKlass.java | 55 + .../jvm/hotspot/ci/ciObjArrayKlassKlass.java | 51 + .../classes/sun/jvm/hotspot/ci/ciObject.java | 71 + .../sun/jvm/hotspot/ci/ciObjectFactory.java | 78 + .../jvm/hotspot/ci/ciReceiverTypeData.java | 53 + .../classes/sun/jvm/hotspot/ci/ciSymbol.java | 60 + .../classes/sun/jvm/hotspot/ci/ciType.java | 52 + .../sun/jvm/hotspot/ci/ciTypeArrayKlass.java | 50 + .../jvm/hotspot/ci/ciTypeArrayKlassKlass.java | 51 + .../sun/jvm/hotspot/ci/ciVirtualCallData.java | 52 + .../classes/sun/jvm/hotspot/code/NMethod.java | 6 +- .../sun/jvm/hotspot/compiler/CompileTask.java | 66 + .../hotspot/debugger/AddressException.java | 6 +- .../jvm/hotspot/debugger/dbx/DbxAddress.java | 395 ----- .../jvm/hotspot/debugger/dbx/DbxDebugger.java | 76 - .../debugger/dbx/DbxDebuggerLocal.java | 744 ---------- .../hotspot/debugger/dbx/DbxOopHandle.java | 49 - .../debugger/dbx/DbxThreadFactory.java | 35 - .../debugger/dbx/sparc/DbxSPARCThread.java | 86 -- .../debugger/dbx/x86/DbxX86Thread.java | 86 -- .../debugger/win32/AddressDataSource.java | 99 -- .../sun/jvm/hotspot/debugger/win32/DLL.java | 209 --- .../hotspot/debugger/win32/TestDebugger.java | 70 - .../debugger/win32/TestHelloWorld.java | 70 - .../hotspot/debugger/win32/Win32Address.java | 403 ------ .../win32/Win32CDebugInfoBuilder.java | 824 ----------- .../debugger/win32/Win32CDebugger.java | 123 -- .../hotspot/debugger/win32/Win32Debugger.java | 135 -- .../debugger/win32/Win32DebuggerLocal.java | 1083 -------------- .../hotspot/debugger/win32/Win32LDTEntry.java | 100 -- .../win32/Win32LDTEntryConstants.java | 39 - .../debugger/win32/Win32OopHandle.java | 61 - .../hotspot/debugger/win32/Win32Thread.java | 129 -- .../sun/jvm/hotspot/jdi/SADebugServer.java | 10 +- .../jvm/hotspot/jdi/VirtualMachineImpl.java | 8 - .../sun/jvm/hotspot/oops/ArrayData.java | 86 ++ .../classes/sun/jvm/hotspot/oops/BitData.java | 74 + .../sun/jvm/hotspot/oops/BranchData.java | 76 + .../sun/jvm/hotspot/oops/CIntField.java | 5 +- .../sun/jvm/hotspot/oops/CounterData.java | 71 + .../sun/jvm/hotspot/oops/DataLayout.java | 206 +++ .../classes/sun/jvm/hotspot/oops/Field.java | 2 +- .../sun/jvm/hotspot/oops/FieldType.java | 4 +- .../sun/jvm/hotspot/oops/InstanceKlass.java | 12 +- .../sun/jvm/hotspot/oops/JumpData.java | 81 ++ .../classes/sun/jvm/hotspot/oops/Method.java | 24 + .../sun/jvm/hotspot/oops/MethodData.java | 261 +++- .../sun/jvm/hotspot/oops/MultiBranchData.java | 113 ++ .../sun/jvm/hotspot/oops/OopUtilities.java | 30 + .../sun/jvm/hotspot/oops/ProfileData.java | 127 ++ .../jvm/hotspot/oops/ReceiverTypeData.java | 123 ++ .../classes/sun/jvm/hotspot/oops/RetData.java | 113 ++ .../sun/jvm/hotspot/oops/VirtualCallData.java | 63 + .../classes/sun/jvm/hotspot/opto/Block.java | 88 ++ .../sun/jvm/hotspot/opto/Block_Array.java | 64 + .../sun/jvm/hotspot/opto/Block_List.java | 56 + .../jvm/hotspot/opto/CallDynamicJavaNode.java | 50 + .../sun/jvm/hotspot/opto/CallJavaNode.java | 66 + .../sun/jvm/hotspot/opto/CallNode.java | 65 + .../sun/jvm/hotspot/opto/CallRuntimeNode.java | 64 + .../jvm/hotspot/opto/CallStaticJavaNode.java | 75 + .../classes/sun/jvm/hotspot/opto/Compile.java | 95 ++ .../HaltNode.java} | 38 +- .../sun/jvm/hotspot/opto/InlineTree.java | 104 ++ .../sun/jvm/hotspot/opto/JVMState.java | 106 ++ .../sun/jvm/hotspot/opto/LoopNode.java | 50 + .../jvm/hotspot/opto/MachCallJavaNode.java | 70 + .../sun/jvm/hotspot/opto/MachCallNode.java | 57 + .../jvm/hotspot/opto/MachCallRuntimeNode.java | 63 + .../hotspot/opto/MachCallStaticJavaNode.java | 69 + .../sun/jvm/hotspot/opto/MachIfNode.java | 67 + .../sun/jvm/hotspot/opto/MachNode.java | 49 + .../sun/jvm/hotspot/opto/MachReturnNode.java | 49 + .../jvm/hotspot/opto/MachSafePointNode.java | 75 + .../sun/jvm/hotspot/opto/MultiNode.java | 50 + .../classes/sun/jvm/hotspot/opto/Node.java | 269 ++++ .../sun/jvm/hotspot/opto/Node_Array.java | 64 + .../sun/jvm/hotspot/opto/Node_List.java | 56 + .../Phase.java} | 36 +- .../sun/jvm/hotspot/opto/PhaseCFG.java | 69 + .../sun/jvm/hotspot/opto/PhaseRegAlloc.java | 58 + .../classes/sun/jvm/hotspot/opto/PhiNode.java | 50 + .../ProjNode.java} | 38 +- .../sun/jvm/hotspot/opto/RegionNode.java | 50 + .../sun/jvm/hotspot/opto/RootNode.java | 50 + .../sun/jvm/hotspot/opto/SafePointNode.java | 68 + .../sun/jvm/hotspot/opto/TypeNode.java | 50 + .../sun/jvm/hotspot/prims/JvmtiExport.java | 66 + .../jvm/hotspot/runtime/CompilerThread.java | 32 +- .../hotspot/runtime/InstanceConstructor.java | 64 + .../StaticBaseConstructor.java} | 33 +- .../classes/sun/jvm/hotspot/runtime/VM.java | 68 +- .../runtime/VirtualBaseConstructor.java | 96 ++ .../hotspot/runtime/VirtualConstructor.java | 21 +- .../Win32AMD64JavaThreadPDAccess.java | 3 +- .../win32_x86/Win32X86JavaThreadPDAccess.java | 3 +- .../jvm/hotspot/tools/jcore/ClassDump.java | 107 +- .../sun/jvm/hotspot/types/TypeDataBase.java | 7 +- .../types/basic/BasicTypeDataBase.java | 89 +- .../jvm/hotspot/ui/CommandProcessorPanel.java | 6 +- .../utilities/GenericGrowableArray.java | 64 + .../jvm/hotspot/utilities/GrowableArray.java | 68 + hotspot/make/sa.files | 12 +- hotspot/src/share/vm/ci/ciArrayKlass.hpp | 3 +- hotspot/src/share/vm/ci/ciClassList.hpp | 4 +- hotspot/src/share/vm/ci/ciConstant.hpp | 3 +- hotspot/src/share/vm/ci/ciObjectFactory.hpp | 3 + .../src/share/vm/compiler/compileBroker.hpp | 2 + hotspot/src/share/vm/memory/allocation.hpp | 4 + hotspot/src/share/vm/memory/resourceArea.hpp | 3 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 31 - hotspot/src/share/vm/oops/instanceKlass.hpp | 32 + hotspot/src/share/vm/opto/block.hpp | 10 +- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 19 + hotspot/src/share/vm/opto/callnode.hpp | 5 +- hotspot/src/share/vm/opto/chaitin.hpp | 6 +- hotspot/src/share/vm/opto/compile.hpp | 2 + hotspot/src/share/vm/opto/node.hpp | 9 +- hotspot/src/share/vm/opto/optoreg.hpp | 3 +- hotspot/src/share/vm/opto/parse.hpp | 7 +- hotspot/src/share/vm/opto/regalloc.hpp | 3 +- hotspot/src/share/vm/opto/type.hpp | 2 + hotspot/src/share/vm/prims/jvmtiExport.hpp | 1 + .../src/share/vm/runtime/deoptimization.hpp | 2 + hotspot/src/share/vm/runtime/vframeArray.hpp | 6 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 730 +++++++++- hotspot/src/share/vm/utilities/exceptions.hpp | 2 + .../src/share/vm/utilities/growableArray.hpp | 6 +- 200 files changed, 7232 insertions(+), 13674 deletions(-) delete mode 100644 hotspot/agent/src/os/solaris/dbx/Makefile delete mode 100644 hotspot/agent/src/os/solaris/dbx/README delete mode 100644 hotspot/agent/src/os/solaris/dbx/README-commands.txt delete mode 100644 hotspot/agent/src/os/solaris/dbx/helloWorld.cpp delete mode 100644 hotspot/agent/src/os/solaris/dbx/proc_service_2.h delete mode 100644 hotspot/agent/src/os/solaris/dbx/shell_imp.h delete mode 100644 hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.cpp delete mode 100644 hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.hpp delete mode 100644 hotspot/agent/src/os/win32/BasicList.hpp delete mode 100644 hotspot/agent/src/os/win32/Buffer.cpp delete mode 100644 hotspot/agent/src/os/win32/Buffer.hpp delete mode 100644 hotspot/agent/src/os/win32/Dispatcher.cpp delete mode 100644 hotspot/agent/src/os/win32/Dispatcher.hpp delete mode 100644 hotspot/agent/src/os/win32/Handler.hpp delete mode 100644 hotspot/agent/src/os/win32/IOBuf.cpp delete mode 100644 hotspot/agent/src/os/win32/IOBuf.hpp delete mode 100644 hotspot/agent/src/os/win32/LockableList.hpp delete mode 100644 hotspot/agent/src/os/win32/Makefile delete mode 100644 hotspot/agent/src/os/win32/Message.hpp delete mode 100644 hotspot/agent/src/os/win32/Monitor.cpp delete mode 100644 hotspot/agent/src/os/win32/Monitor.hpp delete mode 100644 hotspot/agent/src/os/win32/README-commands.txt delete mode 100644 hotspot/agent/src/os/win32/README.txt delete mode 100644 hotspot/agent/src/os/win32/Reaper.cpp delete mode 100644 hotspot/agent/src/os/win32/Reaper.hpp delete mode 100644 hotspot/agent/src/os/win32/SwDbgSrv.cpp delete mode 100644 hotspot/agent/src/os/win32/SwDbgSrv.dsp delete mode 100644 hotspot/agent/src/os/win32/SwDbgSrv.dsw delete mode 100644 hotspot/agent/src/os/win32/SwDbgSub.cpp delete mode 100644 hotspot/agent/src/os/win32/SwDbgSub.dsp delete mode 100644 hotspot/agent/src/os/win32/initWinsock.cpp delete mode 100644 hotspot/agent/src/os/win32/initWinsock.hpp delete mode 100644 hotspot/agent/src/os/win32/ioUtils.cpp delete mode 100644 hotspot/agent/src/os/win32/ioUtils.hpp delete mode 100644 hotspot/agent/src/os/win32/isNT4.cpp delete mode 100644 hotspot/agent/src/os/win32/isNT4.hpp delete mode 100644 hotspot/agent/src/os/win32/libInfo.cpp delete mode 100644 hotspot/agent/src/os/win32/libInfo.hpp delete mode 100644 hotspot/agent/src/os/win32/nt4internals.cpp delete mode 100644 hotspot/agent/src/os/win32/nt4internals.hpp delete mode 100644 hotspot/agent/src/os/win32/ports.h delete mode 100644 hotspot/agent/src/os/win32/procList.cpp delete mode 100644 hotspot/agent/src/os/win32/procList.hpp delete mode 100644 hotspot/agent/src/os/win32/serverLists.cpp delete mode 100644 hotspot/agent/src/os/win32/serverLists.hpp delete mode 100644 hotspot/agent/src/os/win32/toolHelp.cpp delete mode 100644 hotspot/agent/src/os/win32/toolHelp.hpp create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlassKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciField.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstance.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java rename hotspot/agent/src/share/classes/sun/jvm/hotspot/{debugger/dbx/sparc/DbxSPARCThreadFactory.java => ci/ciInstanceKlassKlass.java} (50%) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlassKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlassKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObject.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciReceiverTypeData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciSymbol.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciType.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlassKlass.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciVirtualCallData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxOopHandle.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxThreadFactory.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThread.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86Thread.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/AddressDataSource.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/DLL.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestDebugger.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestHelloWorld.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugInfoBuilder.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugger.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntry.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntryConstants.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32OopHandle.java delete mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Thread.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BitData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BranchData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CounterData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DataLayout.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/JumpData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MultiBranchData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ProfileData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/RetData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block_Array.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block_List.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallDynamicJavaNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallJavaNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Compile.java rename hotspot/agent/src/share/classes/sun/jvm/hotspot/{debugger/dbx/sparc/DbxSPARCThreadContext.java => opto/HaltNode.java} (51%) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/InlineTree.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/JVMState.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/LoopNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachIfNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MultiNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_Array.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_List.java rename hotspot/agent/src/share/classes/sun/jvm/hotspot/{debugger/dbx/x86/DbxX86ThreadFactory.java => opto/Phase.java} (51%) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhiNode.java rename hotspot/agent/src/share/classes/sun/jvm/hotspot/{debugger/dbx/x86/DbxX86ThreadContext.java => opto/ProjNode.java} (51%) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RegionNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RootNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/SafePointNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/TypeNode.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/prims/JvmtiExport.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InstanceConstructor.java rename hotspot/agent/src/share/classes/sun/jvm/hotspot/{debugger/win32/Win32ThreadContext.java => runtime/StaticBaseConstructor.java} (56%) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualBaseConstructor.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GenericGrowableArray.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GrowableArray.java diff --git a/hotspot/agent/make/Makefile b/hotspot/agent/make/Makefile index c1c8ddabc3b..fc845ffd09a 100644 --- a/hotspot/agent/make/Makefile +++ b/hotspot/agent/make/Makefile @@ -48,6 +48,7 @@ sun.jvm.hotspot.asm.x86 \ sun.jvm.hotspot.bugspot \ sun.jvm.hotspot.bugspot.tree \ sun.jvm.hotspot.c1 \ +sun.jvm.hotspot.ci \ sun.jvm.hotspot.code \ sun.jvm.hotspot.compiler \ sun.jvm.hotspot.debugger \ @@ -56,9 +57,6 @@ sun.jvm.hotspot.debugger.cdbg \ sun.jvm.hotspot.debugger.cdbg.basic \ sun.jvm.hotspot.debugger.cdbg.basic.amd64 \ sun.jvm.hotspot.debugger.cdbg.basic.x86 \ -sun.jvm.hotspot.debugger.dbx \ -sun.jvm.hotspot.debugger.dbx.sparc \ -sun.jvm.hotspot.debugger.dbx.x86 \ sun.jvm.hotspot.debugger.dummy \ sun.jvm.hotspot.debugger.ia64 \ sun.jvm.hotspot.debugger.linux \ @@ -76,7 +74,6 @@ sun.jvm.hotspot.debugger.remote.amd64 \ sun.jvm.hotspot.debugger.remote.sparc \ sun.jvm.hotspot.debugger.remote.x86 \ sun.jvm.hotspot.debugger.sparc \ -sun.jvm.hotspot.debugger.win32 \ sun.jvm.hotspot.debugger.win32.coff \ sun.jvm.hotspot.debugger.windbg \ sun.jvm.hotspot.debugger.windbg.amd64 \ @@ -91,7 +88,9 @@ sun.jvm.hotspot.interpreter \ sun.jvm.hotspot.jdi \ sun.jvm.hotspot.livejvm \ sun.jvm.hotspot.memory \ +sun.jvm.hotspot.opto \ sun.jvm.hotspot.oops \ +sun.jvm.hotspot.prims \ sun.jvm.hotspot.runtime \ sun.jvm.hotspot.runtime.amd64 \ sun.jvm.hotspot.runtime.ia64 \ @@ -139,6 +138,7 @@ sun/jvm/hotspot/asm/x86/*.java \ sun/jvm/hotspot/bugspot/*.java \ sun/jvm/hotspot/bugspot/tree/*.java \ sun/jvm/hotspot/c1/*.java \ +sun/jvm/hotspot/ci/*.java \ sun/jvm/hotspot/code/*.java \ sun/jvm/hotspot/compiler/*.java \ sun/jvm/hotspot/debugger/*.java \ @@ -147,9 +147,6 @@ sun/jvm/hotspot/debugger/cdbg/*.java \ sun/jvm/hotspot/debugger/cdbg/basic/*.java \ sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \ sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \ -sun/jvm/hotspot/debugger/dbx/*.java \ -sun/jvm/hotspot/debugger/dbx/sparc/*.java \ -sun/jvm/hotspot/debugger/dbx/x86/*.java \ sun/jvm/hotspot/debugger/dummy/*.java \ sun/jvm/hotspot/debugger/ia64/*.java \ sun/jvm/hotspot/debugger/linux/*.java \ @@ -165,7 +162,6 @@ sun/jvm/hotspot/debugger/remote/amd64/*.java \ sun/jvm/hotspot/debugger/remote/sparc/*.java \ sun/jvm/hotspot/debugger/remote/x86/*.java \ sun/jvm/hotspot/debugger/sparc/*.java \ -sun/jvm/hotspot/debugger/win32/*.java \ sun/jvm/hotspot/debugger/win32/coff/*.java \ sun/jvm/hotspot/debugger/windbg/*.java \ sun/jvm/hotspot/debugger/windbg/ia64/*.java \ @@ -176,6 +172,8 @@ sun/jvm/hotspot/jdi/*.java \ sun/jvm/hotspot/livejvm/*.java \ sun/jvm/hotspot/memory/*.java \ sun/jvm/hotspot/oops/*.java \ +sun/jvm/hotspot/opto/*.java \ +sun/jvm/hotspot/prims/*.java \ sun/jvm/hotspot/runtime/*.java \ sun/jvm/hotspot/runtime/amd64/*.java \ sun/jvm/hotspot/runtime/ia64/*.java \ diff --git a/hotspot/agent/make/saenv.sh b/hotspot/agent/make/saenv.sh index b41a3113cfe..81c2d152c67 100644 --- a/hotspot/agent/make/saenv.sh +++ b/hotspot/agent/make/saenv.sh @@ -70,6 +70,14 @@ fi SA_CLASSPATH=$STARTDIR/../build/classes:$STARTDIR/../src/share/lib/js.jar:$STARTDIR/sa.jar:$STARTDIR/lib/js.jar +if [ ! -z "$SA_TYPEDB" ]; then + if [ ! -f $SA_TYPEDB ]; then + echo "$SA_TYPEDB is unreadable" + exit 1 + fi + OPTIONS="-Dsun.jvm.hotspot.typedb=$SA_TYPEDB ${OPTIONS}" +fi + OPTIONS="-Djava.system.class.loader=sun.jvm.hotspot.SALauncherLoader ${OPTIONS}" SA_JAVA_CMD="$SA_PREFIX_CMD $SA_JAVA -showversion ${OPTIONS} -cp $SA_CLASSPATH $SA_OPTIONS" diff --git a/hotspot/agent/make/saenv64.sh b/hotspot/agent/make/saenv64.sh index 98d5885b3d5..c00dc0d17c0 100644 --- a/hotspot/agent/make/saenv64.sh +++ b/hotspot/agent/make/saenv64.sh @@ -67,6 +67,14 @@ fi SA_CLASSPATH=$STARTDIR/../build/classes:$STARTDIR/../src/share/lib/js.jar:$STARTDIR/sa.jar::$STARTDIR/lib/js.jar +if [ ! -z "$SA_TYPEDB" ]; then + if [ ! -f $SA_TYPEDB ]; then + echo "$SA_TYPEDB is unreadable" + exit 1 + fi + OPTIONS="-Dsun.jvm.hotspot.typedb=$SA_TYPEDB ${OPTIONS}" +fi + OPTIONS="-Djava.system.class.loader=sun.jvm.hotspot.SALauncherLoader ${OPTIONS}" SA_JAVA_CMD="$SA_PREFIX_CMD $SA_JAVA -d64 -showversion ${OPTIONS} -cp $SA_CLASSPATH $SA_OPTIONS" diff --git a/hotspot/agent/src/os/solaris/Makefile b/hotspot/agent/src/os/solaris/Makefile index f1bb0b3df00..0e964bf2c60 100644 --- a/hotspot/agent/src/os/solaris/Makefile +++ b/hotspot/agent/src/os/solaris/Makefile @@ -24,9 +24,7 @@ all: - cd dbx; $(MAKE) all cd proc; $(MAKE) all clean: - cd dbx; $(MAKE) clean cd proc; $(MAKE) clean diff --git a/hotspot/agent/src/os/solaris/dbx/Makefile b/hotspot/agent/src/os/solaris/dbx/Makefile deleted file mode 100644 index 4b1760d9795..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -# -# Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - - -# Targets are: -# 32bit: Build the 32 bit version in ./32bit -# 64bit: Build the 64 bit version in ./64bit -# helloWorld: Build the helloWorld test program -# all: Build all of the above. This is the default. -# -# NOTE: This makefile uses IOBuf.cpp, IOBuf.hpp, Buffer.cpp, and -# Buffer.hpp from the src/os/win32/agent directory. - -.PHONY: 32bit 64bit - -ARCH_ORIG = $(shell uname -p) - -# C++ := /java/devtools/$(ARCH_ORIG)/SUNWspro/SC6.1/bin/CC - -C++ := CC -RM := /usr/bin/rm -MKDIRS := /usr/bin/mkdir -p - - -WIN32_DIR := ../../win32 -ARCH := $(subst i386,i486,$(ARCH_ORIG)) -# INCLUDES := -I/net/sparcworks.eng/export/set/sparcworks5/dbx_62_intg/dev/src/dbx -I$(WIN32_DIR) -INCLUDES := -I. -I$(WIN32_DIR) -CFLAGS_32bit := -xarch=v8 -CFLAGS_64bit := -xarch=v9 -CFLAGS := -PIC -xO3 $(INCLUDES) -LIBS := -lsocket -lnsl -lrtld_db -LDFLAGS := -G - -ifneq "$(ARCH)" "i486" - CFLAGS += $(CFLAGS_$(VERSION)) - LDFLAGS += $(CFLAGS_$(VERSION)) -endif - -# We use IOBuf.hpp, IOBuf.cpp, Buffer.hpp, and Buffer.cpp from the win32 dir. -vpath %.cpp .:$(WIN32_DIR) -vpath %.hpp .:$(WIN32_DIR) - -OBJS = $(VERSION)/svc_agent_dbx.o $(VERSION)/IOBuf.o $(VERSION)/Buffer.o - - - -# The default is to make both 32 bit and 64 bit versions. -all:: 32bit 64bit - -32bit 64bit:: - $(MKDIRS) $@ - $(MAKE) $@/libsvc_agent_dbx.so helloWorld VERSION=$@ - -$(VERSION)/IOBuf.o: IOBuf.hpp -$(VERSION)/Buffer.o: Buffer.hpp -$(VERSION)/svc_agent_dbx.o: svc_agent_dbx.hpp - -$(VERSION)/%.o: %.cpp - $(C++) $(CFLAGS) -c $< -o $@ - -$(VERSION)/libsvc_agent_dbx.so:: $(OBJS) - $(C++) $(LDFLAGS) -o $(VERSION)/libsvc_agent_dbx.so $(OBJS) $(LIBS) - -# Would be nice to move this into a shared directory -helloWorld:: helloWorld.cpp - $(C++) -g $< -o $@ - -clean:: - $(RM) -rf 32bit 64bit *.o helloWorld diff --git a/hotspot/agent/src/os/solaris/dbx/README b/hotspot/agent/src/os/solaris/dbx/README deleted file mode 100644 index e043f7e1642..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/README +++ /dev/null @@ -1,9 +0,0 @@ -shell_impl.h -proc_service_2.h - -The above files are captured from the dbx build environment. -Rather then use a -I that points to stuff in .eng domain that -may not be accessible in other domains these files are just -copied here so local builds in other domains will work. -These files rarely change so the fact that we might have to -strobe in new ones on rare occasions is no big deal. diff --git a/hotspot/agent/src/os/solaris/dbx/README-commands.txt b/hotspot/agent/src/os/solaris/dbx/README-commands.txt deleted file mode 100644 index 4bc22d20d93..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/README-commands.txt +++ /dev/null @@ -1,82 +0,0 @@ -This import module uses a largely text-based protocol, except for -certain bulk data transfer operations. All text is in single-byte -US-ASCII. - -Commands understood: - -address_size ::= - - Returns 32 if attached to 32-bit process, 64 if 64-bit. - -peek_fail_fast ::= - - Indicates whether "peek" requests should "fail fast"; that is, if - any of the addresses in the requested range are unmapped, report - the entire range as unmapped. This is substantially faster than - the alternative, which is to read the entire range byte-by-byte. - However, it should only be used when it is guaranteed by the - client application that peeks come from at most one page. The - default is that peek_fast_fail is not enabled. - -peek

::= - B - [ []...]... - - NOTE that the binary portion of this message is prefixed by the - uppercase US-ASCII letter 'B', allowing easier synchronization by - clients. There is no data between the 'B' and the rest of the - message. - - May only be called once attached. Reads the address space of the - target process starting at the given address (see below for format - specifications) and extending the given number of bytes. Whether - the read succeeded is indicated by a single byte containing a 1 or - 0 (success or failure). If successful, the return result is given - in a sequence of ranges. _len_, the length of each range, is - indicated by a 32-bit unsigned integer transmitted with big-endian - byte ordering (i.e., most significant byte first). _isMapped_ - indicates whether the range is mapped or unmapped in the target - process's address space, and will contain the value 1 or 0 for - mapped or unmapped, respectively. If the range is mapped, - _isMapped_ is followed by _data_, containing the raw binary data - for the range. The sum of all ranges' lengths is guaranteed to be - equivalent to the number of bytes requested. - -poke
B[]... ::= - - NOTE that the binary portion of this message is prefixed by the - uppercase US-ASCII letter 'B', allowing easier synchronization by - clients. There is no data between the 'B' and the rest of the - message. - - Writes the given data to the target process starting at the given - address. Returns 1 on success, 0 on failure (i.e., one or more of - target addresses were unmapped). - -mapped
::= - - Returns 1 if entire address range [address...address + int arg) is - mapped in target process's address space, 0 if not - -lookup ::=
- - First symbol is object name; second is symbol to be looked up. - Looks up symbol in target process's symbol table and returns - address. Returns NULL (0x0) if symbol is not found. - -thr_gregs ::= - - Fetch the "general" (integer) register set for the given thread. - Returned as a series of hexidecimal values. NOTE: the meaning of - the return value is architecture-dependent. In general it is the - contents of the prgregset_t. - -exit ::= - - Exits the serviceability agent dbx module, returning control to - the dbx prompt. - -// Data formats and example values: -
::= 0x12345678[9ABCDEF0] /* up to 64-bit hex value */ - ::= 5 /* up to 32-bit integer number; no leading sign */ - ::= 1 /* ASCII '0' or '1' */ diff --git a/hotspot/agent/src/os/solaris/dbx/helloWorld.cpp b/hotspot/agent/src/os/solaris/dbx/helloWorld.cpp deleted file mode 100644 index 7fd4ea47466..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/helloWorld.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include - -extern "C" { - const char* helloWorldString = "Hello, world!"; - // Do not change these values without changing TestDebugger.java as well - // FIXME: should make these jbyte, jshort, etc... - volatile int8_t testByte = 132; - volatile int16_t testShort = 27890; - volatile int32_t testInt = 1020304050; - volatile int64_t testLong = 102030405060708090LL; - volatile float testFloat = 35.4F; - volatile double testDouble = 1.23456789; - - volatile int helloWorldTrigger = 0; -} - -int -main(int, char**) { - while (1) { - while (helloWorldTrigger == 0) { - } - - fprintf(stderr, "%s\n", helloWorldString); - fprintf(stderr, "testByte=%d\n", testByte); - fprintf(stderr, "testShort=%d\n", testShort); - fprintf(stderr, "testInt=%d\n", testInt); - fprintf(stderr, "testLong=%d\n", testLong); - fprintf(stderr, "testFloat=%d\n", testFloat); - fprintf(stderr, "testDouble=%d\n", testDouble); - - while (helloWorldTrigger != 0) { - } - } -} diff --git a/hotspot/agent/src/os/solaris/dbx/proc_service_2.h b/hotspot/agent/src/os/solaris/dbx/proc_service_2.h deleted file mode 100644 index 93163cbc7c0..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/proc_service_2.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _PROC_SERVICE_2_H -#define _PROC_SERVICE_2_H - -/* - * Types, function definitions for the provider of services beyond - * proc_service. This interface will be used by import modules like - * BAT/prex, NEO debugger etc. - */ - -/* - CCR info - - Version history: - - 1.0 - Initial CCR release - - 1.1 - Changes for GLUE/neo. - New entry points ps_svnt_generic() and ps_svc_generic() - - New entry point ps_getpid() - - Release information for automatic CCR updates: - BEGIN RELEASE NOTES: (signifies what gets put into CCR release notes) - 1.2 - Changes to support Solaris 2.7 - - END RELEASE NOTES: (signifies what gets put into CCR release notes) - - Following is used for CCR version number: - -#define CCR_PROC_SERVICE_2_VERSION 1.2 - -*/ - - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct ps_loadobj { - int objfd; /* fd of the load object or executable - * -1 implies its not available. - * This file decriptor is live only during the - * particular call to ps_iter_f(). If you - * need it beyond that you need to dup() it. - */ - psaddr_t - text_base; /* address where text of loadobj was mapped */ - psaddr_t - data_base; /* address where data of loadobj was mapped */ - const char *objname; /* loadobj name */ -}; - -typedef int ps_iter_f(const struct ps_prochandle *, const struct ps_loadobj *, - void *cd); - -/* - * Returns the ps_prochandle for the current process under focus. Returns - * NULL if there is none. - */ - -const struct ps_prochandle * -ps_get_prochandle(void); - -/* - * Returns the ps_prochandle for the current process(allows core files to - * be specified) under focus. Returns NULL if there is none. - */ -const struct ps_prochandle * -ps_get_prochandle2(int cores_too); - -/* - * Returns the pid of the process referred to by the ps_prochandle. - * - * 0 is returned in case the ps_prochandle is not valid or refers to dead - * process. - * - */ -pid_t -ps_getpid(const struct ps_prochandle *); - -/* - * Iteration function that iterates over all load objects *and the - * executable* - * - * If the callback routine returns: - * 0 - continue processing link objects - * non zero - stop calling the callback function - * - */ - -ps_err_e -ps_loadobj_iter(const struct ps_prochandle *, ps_iter_f *, void *clnt_data); - -/* - * Address => function name mapping - * - * Given an address, returns a pointer to the function's - * linker name (null terminated). - */ - -ps_err_e -ps_find_fun_name(const struct ps_prochandle *, psaddr_t addr, - const char **name); - -/* - * Interface to LD_PRELOAD. LD_PRELOAD given library across the - * program 'exec'. - * - */ - -/* - * Append/Prepend the 'lib' (has to be library name as understood by LD_PRELOAD) - * to the LD_PRELOAD variable setting to be used by the debugee - * Returns a cookie (in id). - */ -ps_err_e -ps_ld_preload_append(const char *lib, int *id); -ps_err_e -ps_ld_preload_prepend(const char *lib, int *id); - -/* - * Remove the library associated with 'id' from the LD_PRELOAD setting. - * - */ -ps_err_e -ps_ld_preload_remove(int id); - -#ifdef __cplusplus -} -#endif - -/* - * The following are C++ only interfaces - */ -#ifdef __cplusplus - -/* - * classes ServiceDbx and ServantDbx and defined in "gp_dbx_svc.h" which is - * accessed via CCR - */ -extern class ServantDbx *ps_svnt_generic(); -extern class ServiceDbx *ps_svc_generic(); - -#endif - -#endif /* _PROC_SERVICE_2_H */ diff --git a/hotspot/agent/src/os/solaris/dbx/shell_imp.h b/hotspot/agent/src/os/solaris/dbx/shell_imp.h deleted file mode 100644 index 65de0ce7b8f..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/shell_imp.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHELL_IMP_H -#define SHELL_IMP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - CCR info - - Vesrion history: - - 1.0 - Initial CCR release - - Release information for automatic CCR updates: - - BEGIN RELEASE NOTES: (signifies what gets put into CCR release notes) - 1.1 - - Entry points for va_list style msgs; new shell_imp_vmsg() - and shell_imp_verrmsg() - - shell_imp_env_checker() is now shell_imp_var_checker(). - Also the var_checker callback gets passed interp. - 1.2 - interposition framework (used by jdbx) - - access to input FILE pointer. - - END RELEASE NOTES: (signifies what gets put into CCR release notes) - -Following is used as a CCR version number: -#define CCR_SHELL_IMP_VERSION 1.1 -*/ - -#include - -#define SHELL_IMP_MAJOR 1 -#define SHELL_IMP_MINOR 2 -#define SHELL_IMP_FLAG_GLOB 0x1 -#define SHELL_IMP_FLAG_ARGQ 0x2 - -typedef void *shell_imp_interp_t; -typedef void *shell_imp_command_t; -typedef int shell_imp_fun_t(shell_imp_interp_t, int, char **, void *); - -int -shell_imp_init( - int, /* major version number */ - int, /* minor version number */ - shell_imp_interp_t, /* interpreter */ - int, /* argc */ - char *[] /* argv */ -); - -int -shell_imp_fini(shell_imp_interp_t); - -shell_imp_command_t -shell_imp_define_command(char *, /* command name e.g. "tnf" */ - shell_imp_fun_t *, /* callback function */ - int, /* SHELL_IMP_FLAG_* bit vector */ - void *, /* client_data Passed as last arg to - /* callback function */ - char * /* help message, e.g. */ - /* "enable the specified tnf probes" */ - ); - -int -shell_imp_undefine_command(shell_imp_command_t); - -int -shell_imp_var_checker(shell_imp_interp_t, - const char *, /* var name */ - int (*)(shell_imp_interp_t, const char*) /* env checker */ - ); - -int -shell_imp_execute(shell_imp_interp_t, const char *); - -const char * -shell_imp_get_var(shell_imp_interp_t, const char *); - -void -shell_imp_msg(shell_imp_interp_t, const char *, ...); - -void -shell_imp_errmsg(shell_imp_interp_t, const char *, ...); - -void -shell_imp_vmsg(shell_imp_interp_t, const char *, va_list); - -void -shell_imp_verrmsg(shell_imp_interp_t, const char *, va_list); - - - -/* - * Stuff added for 1.2 - */ - -struct shell_imp_interposition_info_t { - shell_imp_fun_t * - new_func; - void * new_client_data; - shell_imp_fun_t * - original_func; - void * original_client_data; - int original_flags; -}; - -typedef int shell_imp_dispatcher_t(shell_imp_interp_t, int, char **, - shell_imp_interposition_info_t *); - -shell_imp_command_t -shell_imp_interpose(char *name, - shell_imp_fun_t *new_func, - int flags, - void *client_data, - char * description, - shell_imp_dispatcher_t *); - -int shell_imp_uninterpose(shell_imp_command_t); - -int -shell_imp_dispatch_interposition(shell_imp_interp_t, - shell_imp_interposition_info_t *, - int argc, char *argv[]); - -int -shell_imp_dispatch_original(shell_imp_interp_t, - shell_imp_interposition_info_t *, - int argc, char *argv[]); - -FILE * -shell_imp_cur_input(shell_imp_interp_t); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.cpp b/hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.cpp deleted file mode 100644 index 5547fdc161d..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.cpp +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -// This is the implementation of a very simple dbx import module which -// handles requests from the VM which come in over a socket. The -// higher-level Java wrapper for dbx starts the debugger, attaches to -// the process, imports this command, and runs it. After that, the SA -// writes commands to this agent via its own private communications -// channel. The intent is to move away from the text-based front-end -// completely in the near future (no more calling "debug" by printing -// text to dbx's stdin). - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "proc_service_2.h" -#include "svc_agent_dbx.hpp" - -static ServiceabilityAgentDbxModule* module = NULL; -#define NEEDS_CLEANUP - -// Useful for debugging -#define VERBOSE_DEBUGGING - -#ifdef VERBOSE_DEBUGGING -# define debug_only(x) x -#else -# define debug_only(x) -#endif - -// For profiling -//#define PROFILING - -#ifdef PROFILING -#define PROFILE_COUNT 200 -static Timer scanTimer; -static Timer workTimer; -static Timer writeTimer; -static int numRequests = 0; -#endif /* PROFILING */ - -const char* ServiceabilityAgentDbxModule::CMD_ADDRESS_SIZE = "address_size"; -const char* ServiceabilityAgentDbxModule::CMD_PEEK_FAIL_FAST = "peek_fail_fast"; -const char* ServiceabilityAgentDbxModule::CMD_PEEK = "peek"; -const char* ServiceabilityAgentDbxModule::CMD_POKE = "poke"; -const char* ServiceabilityAgentDbxModule::CMD_MAPPED = "mapped"; -const char* ServiceabilityAgentDbxModule::CMD_LOOKUP = "lookup"; -const char* ServiceabilityAgentDbxModule::CMD_THR_GREGS = "thr_gregs"; -const char* ServiceabilityAgentDbxModule::CMD_EXIT = "exit"; - -// The initialization routines must not have C++ name mangling -extern "C" { - -/** This is the initialization routine called by dbx upon importing of - this module. Returns 0 upon successful initialization, -1 upon - failure. */ -int shell_imp_init(int major, int minor, - shell_imp_interp_t interp, int argc, char *argv[]) -{ - // Ensure shell interpreter data structure is laid out the way we - // expect - if (major != SHELL_IMP_MAJOR) { - debug_only(fprintf(stderr, "Serviceability agent: unexpected value for SHELL_IMP_MAJOR (got %d, expected %d)\n", major, SHELL_IMP_MAJOR);) - return -1; - } - if (minor < SHELL_IMP_MINOR) { - debug_only(fprintf(stderr, "Serviceability agent: unexpected value for SHELL_IMP_MINOR (got %d, expected >= %d)\n", minor, SHELL_IMP_MINOR);) - return -1; - } - - if (module != NULL) { - debug_only(fprintf(stderr, "Serviceability agent: module appears to already be initialized (should not happen)\n");) - // Already initialized. Should not happen. - return -1; - } - - module = new ServiceabilityAgentDbxModule(major, minor, interp, argc, argv); - if (!module->install()) { - debug_only(fprintf(stderr, "Serviceability agent: error installing import module\n");) - delete module; - module = NULL; - return -1; - } - - // Installation was successful. Next step will be for the user to - // enter the appropriate command on the command line, which will - // make the SA's dbx module wait for commands to come in over the - // socket. - return 0; -} - -/** This is the routine called by dbx upon unloading of this module. - Returns 0 upon success, -1 upon failure. */ -int -shell_imp_fini(shell_imp_interp_t) -{ - if (module == NULL) { - return -1; - } - - bool res = module->uninstall(); - delete module; - module = NULL; - if (!res) { - return -1; - } - return 0; -} - -} // extern "C" - -/** This is the routine which is called by the dbx shell when the user - requests the serviceability agent module to run. This delegates to - ServiceabilityAgentDbxModule::run. This routine's signature must - match that of shell_imp_fun_t. */ -extern "C" { -static int -svc_agent_run(shell_imp_interp_t, int, char **, void *) { - if (module == NULL) { - return -1; - } - - module->run(); - return 0; -} -} - -/* - * Implementation of ServiceabilityAgentDbxModule class - */ - -// NOTE: we need to forward declare the special "ps_get_prochandle2" -// function which allows examination of core files as well. It isn't -// currently in proc_service_2.h. Note also that it has name mangling -// because it isn't declared extern "C". -//const struct ps_prochandle *ps_get_prochandle2(int cores_too); - -ServiceabilityAgentDbxModule::ServiceabilityAgentDbxModule(int, int, shell_imp_interp_t interp, - int argc, char *argv[]) - :myComm(32768, 131072) -{ - _interp = interp; - _argc = argc; - _argv = argv; - _tdb_agent = NULL; - peek_fail_fast = false; - libThreadName = NULL; -} - -ServiceabilityAgentDbxModule::~ServiceabilityAgentDbxModule() { - if (_command != NULL) { - uninstall(); - } -} - -char* -readCStringFromProcess(psaddr_t addr) { - char c; - int num = 0; - ps_prochandle* cur_proc = (ps_prochandle*) ps_get_prochandle2(1); - - // Search for null terminator - do { - if (ps_pread(cur_proc, addr + num, &c, 1) != PS_OK) { - return NULL; - } - ++num; - } while (c != 0); - - // Allocate string - char* res = new char[num]; - if (ps_pread(cur_proc, addr, res, num) != PS_OK) { - delete[] res; - return NULL; - } - return res; -} - -int -findLibThreadCB(const rd_loadobj_t* lo, void* data) { - ServiceabilityAgentDbxModule* module = (ServiceabilityAgentDbxModule*) data; - char* name = readCStringFromProcess(lo->rl_nameaddr); - if (strstr(name, "libthread.so") != NULL) { - module->libThreadName = name; - return 0; - } else { - delete[] name; - return 1; - } -} - -bool -ServiceabilityAgentDbxModule::install() { - // NOTE interdependency between here and Java side wrapper - // FIXME: casts of string literal to char * to match prototype - _command = shell_imp_define_command((char *) "svc_agent_run", - &svc_agent_run, - 0, - NULL, - (char *) "Run the serviceability agent's dbx module.\n" - "This routine causes the module to listen on a socket for requests.\n" - "It does not return until the Java-side code tells it to exit, at\n" - "which point control is returned to the dbx shell."); - if (_command == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to install svc_agent_run command\n")); - return false; - } - - // This is fairly painful. Since dbx doesn't currently load - // libthread_db with RTLD_GLOBAL, we can't just use RTLD_DEFAULT for - // the argument to dlsym. Instead, we have to use rtld_db to search - // through the loaded objects in the target process for libthread.so and - - // Try rtld_db - if (rd_init(RD_VERSION) != RD_OK) { - debug_only(fprintf(stderr, "Serviceability agent: Unable to init rtld_db\n")); - return false; - } - - rd_agent_t* rda = rd_new((struct ps_prochandle*) ps_get_prochandle2(1)); - if (rda == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: Unable to allocate rtld_db agent\n")); - return false; - } - - if (rd_loadobj_iter(rda, (rl_iter_f*) findLibThreadCB, this) != RD_OK) { - debug_only(fprintf(stderr, "Serviceability agent: Loadobject iteration failed\n")); - return false; - } - - if (libThreadName == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to find pathname to libthread.so in target process\n")); - return false; - } - - // Find and open libthread_db.so - char* slash = strrchr(libThreadName, '/'); - if (slash == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: can't parse path to libthread.so \"%s\"\n")); - return false; - } - - int slashPos = slash - libThreadName; - char* buf = new char[slashPos + strlen("libthread_db.so") + 20]; // slop - if (buf == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: error allocating libthread_db.so pathname\n")); - return false; - } - strncpy(buf, libThreadName, slashPos + 1); - - // Check dbx's data model; use sparcv9/ subdirectory if 64-bit and - // if target process is 32-bit - if ((sizeof(void*) == 8) && - (strstr(libThreadName, "sparcv9") == NULL)) { - strcpy(buf + slashPos + 1, "sparcv9/"); - slashPos += strlen("sparcv9/"); - } - - strcpy(buf + slashPos + 1, "libthread_db.so"); - - libThreadDB = dlopen(buf, RTLD_LAZY); - void* tmpDB = libThreadDB; - if (libThreadDB == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: Warning: unable to find libthread_db.so at \"%s\"\n", buf)); - // Would like to handle this case as well. Maybe dbx has a better - // idea of where libthread_db.so lies. If the problem with dbx - // loading libthread_db without RTLD_GLOBAL specified ever gets - // fixed, we could run this code all the time. - tmpDB = RTLD_DEFAULT; - } - - delete[] buf; - - // Initialize access to libthread_db - td_init_fn = (td_init_fn_t*) dlsym(tmpDB, "td_init"); - td_ta_new_fn = (td_ta_new_fn_t*) dlsym(tmpDB, "td_ta_new"); - td_ta_delete_fn = (td_ta_delete_fn_t*) dlsym(tmpDB, "td_ta_delete"); - td_ta_map_id2thr_fn = (td_ta_map_id2thr_fn_t*) dlsym(tmpDB, "td_ta_map_id2thr"); - td_thr_getgregs_fn = (td_thr_getgregs_fn_t*) dlsym(tmpDB, "td_thr_getgregs"); - - if (td_init_fn == NULL || - td_ta_new_fn == NULL || - td_ta_delete_fn == NULL || - td_ta_map_id2thr_fn == NULL || - td_thr_getgregs_fn == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to find one or more libthread_db symbols:\n")); - debug_only(if (td_init_fn == NULL) fprintf(stderr, " td_init\n")); - debug_only(if (td_ta_new_fn == NULL) fprintf(stderr, " td_ta_new\n")); - debug_only(if (td_ta_delete_fn == NULL) fprintf(stderr, " td_ta_delete\n")); - debug_only(if (td_ta_map_id2thr_fn == NULL) fprintf(stderr, " td_ta_map_id2thr\n")); - debug_only(if (td_thr_getgregs_fn == NULL) fprintf(stderr, " td_thr_getgregs\n")); - return false; - } - - if ((*td_init_fn)() != TD_OK) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to initialize libthread_db\n")); - return false; - } - - return true; -} - -bool -ServiceabilityAgentDbxModule::uninstall() { - if (_command == NULL) { - return false; - } - - if (libThreadDB != NULL) { - dlclose(libThreadDB); - libThreadDB = NULL; - } - - int res = shell_imp_undefine_command(_command); - - if (res != 0) { - return false; - } - - return true; -} - -bool -ServiceabilityAgentDbxModule::run() { - // This is where most of the work gets done. - // The command processor loop looks like the following: - // - create listening socket - // - accept a connection (only one for now) - // - while that connection is open and the "exit" command has not - // been received: - // - read command - // - if it's the exit command, cleanup and return - // - otherwise, process command and write result - - int listening_socket = socket(AF_INET, SOCK_STREAM, 0); - if (listening_socket < 0) { - return false; - } - - // Set the SO_REUSEADDR property on the listening socket. This - // prevents problems with calls to bind() to the same port failing - // after this process exits. This seems to work on all platforms. - int reuse_address = 1; - if (setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, - (char *)&reuse_address, sizeof(reuse_address)) < 0) { - close(listening_socket); - return false; - } - - sockaddr_in server_address; - // Build the server address. We can bind the listening socket to the - // INADDR_ANY internet address. - memset((char*)&server_address, 0, sizeof(server_address)); - server_address.sin_family = AF_INET; - server_address.sin_addr.s_addr = (unsigned long)htonl(INADDR_ANY); - server_address.sin_port = htons((short)PORT); - - // Bind socket to port - if (bind(listening_socket, (sockaddr*) &server_address, - sizeof(server_address)) < 0) { - close(listening_socket); - return false; - } - - // Arbitrarily chosen backlog of 5 (shouldn't matter since we expect - // at most one connection) - if (listen(listening_socket, 5) < 0) { - close(listening_socket); - return false; - } - - // OK, now ready to wait for a data connection. This call to - // accept() will block. - struct sockaddr_in client_address; - int address_len = sizeof(client_address); - int client_socket = accept(listening_socket, (sockaddr*) &client_address, - &address_len); - // Close listening socket regardless of whether accept() succeeded. - // (FIXME: this may be annoying, especially during debugging, but I - // really feel that robustness and multiple connections should be - // handled higher up, e.g., at the Java level -- multiple clients - // could conceivably connect to the SA via RMI, and that would be a - // more robust solution than implementing multiple connections at - // this level) - NEEDS_CLEANUP; - - // NOTE: the call to shutdown() usually fails, so don't panic if this happens - shutdown(listening_socket, 2); - - if (close(listening_socket) < 0) { - debug_only(fprintf(stderr, "Serviceability agent: Error closing listening socket\n")); - return false; - } - - if (client_socket < 0) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to open client socket\n")); - // No more cleanup necessary - return false; - } - - // Attempt to disable TCP buffering on this socket. We send small - // amounts of data back and forth and don't want buffering. - int buffer_val = 1; - if (setsockopt(client_socket, IPPROTO_IP, TCP_NODELAY, (char *) &buffer_val, sizeof(buffer_val)) < 0) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to set TCP_NODELAY option on client socket\n")); - cleanup(client_socket); - return false; - } - - // OK, we have the data socket through which we will communicate - // with the Java side. Wait for commands or until reading or writing - // caused an error. - - bool should_continue = true; - - myComm.setSocket(client_socket); - -#ifdef PROFILING - scanTimer.reset(); - workTimer.reset(); - writeTimer.reset(); -#endif - - // Allocate a new thread agent for libthread_db - if ((*td_ta_new_fn)((ps_prochandle*) ps_get_prochandle2(1), &_tdb_agent) != - TD_OK) { - debug_only(fprintf(stderr, "Serviceability agent: Failed to allocate thread agent\n")); - cleanup(client_socket); - return false; - } - - do { - // Decided to use text to communicate between these processes. - // Probably will make debugging easier -- could telnet in if - // necessary. Will make scanning harder, but probably doesn't - // matter. - - // Why not just do what workshop does and parse dbx's console? - // Probably could do that, but at least this way we are in control - // of the text format on both ends. - - // FIXME: should have some way of synchronizing these commands - // between the C and Java sources. - - NEEDS_CLEANUP; - - // Do a blocking read of a line from the socket. - char *input_buffer = myComm.readLine(); - if (input_buffer == NULL) { - debug_only(fprintf(stderr, "Serviceability agent: error during read: errno = %d\n", errno)); - debug_only(perror("Serviceability agent")); - // Error occurred during read. - // FIXME: should guard against SIGPIPE - cleanup(client_socket); - return false; - } - - // OK, now ready to scan. See README-commands.txt for syntax - // descriptions. - - bool res = false; - if (!strncmp(input_buffer, CMD_ADDRESS_SIZE, strlen(CMD_ADDRESS_SIZE))) { - res = handleAddressSize(input_buffer + strlen(CMD_ADDRESS_SIZE)); - } else if (!strncmp(input_buffer, CMD_PEEK_FAIL_FAST, strlen(CMD_PEEK_FAIL_FAST))) { - res = handlePeekFailFast(input_buffer + strlen(CMD_PEEK_FAIL_FAST)); - } else if (!strncmp(input_buffer, CMD_PEEK, strlen(CMD_PEEK))) { - res = handlePeek(input_buffer + strlen(CMD_PEEK)); - } else if (!strncmp(input_buffer, CMD_POKE, strlen(CMD_POKE))) { - res = handlePoke(input_buffer + strlen(CMD_POKE)); - } else if (!strncmp(input_buffer, CMD_MAPPED, strlen(CMD_MAPPED))) { - res = handleMapped(input_buffer + strlen(CMD_MAPPED)); - } else if (!strncmp(input_buffer, CMD_LOOKUP, strlen(CMD_LOOKUP))) { - res = handleLookup(input_buffer + strlen(CMD_LOOKUP)); - } else if (!strncmp(input_buffer, CMD_THR_GREGS, strlen(CMD_THR_GREGS))) { - res = handleThrGRegs(input_buffer + strlen(CMD_THR_GREGS)); - } else if (!strncmp(input_buffer, CMD_EXIT, strlen(CMD_EXIT))) { - should_continue = false; - } - - if (should_continue) { - if (!res) { - cleanup(client_socket); - return false; - } - } - -#ifdef PROFILING - if (++numRequests == PROFILE_COUNT) { - fprintf(stderr, "%d requests: %d ms scanning, %d ms work, %d ms writing\n", - PROFILE_COUNT, scanTimer.total(), workTimer.total(), writeTimer.total()); - fflush(stderr); - scanTimer.reset(); - workTimer.reset(); - writeTimer.reset(); - numRequests = 0; - } -#endif - - } while (should_continue); - - // Successful exit - cleanup(client_socket); - return true; -} - -void -ServiceabilityAgentDbxModule::cleanup(int client_socket) { - shutdown(client_socket, 2); - close(client_socket); - if (_tdb_agent != NULL) { - (*td_ta_delete_fn)(_tdb_agent); - } -} - -bool -ServiceabilityAgentDbxModule::handleAddressSize(char* data) { - int data_model; - ps_err_e result = ps_pdmodel((ps_prochandle*) ps_get_prochandle2(1), - &data_model); - if (result != PS_OK) { - myComm.writeString("0"); - myComm.flush(); - return false; - } - - int val; - switch (data_model) { - case PR_MODEL_ILP32: - val = 32; - break; - case PR_MODEL_LP64: - val = 64; - break; - default: - val = 0; - break; - } - - if (!myComm.writeInt(val)) { - return false; - } - if (!myComm.writeEOL()) { - return false; - } - return myComm.flush(); -} - -bool -ServiceabilityAgentDbxModule::handlePeekFailFast(char* data) { - unsigned int val; - if (!scanUnsignedInt(&data, &val)) { - return false; - } - peek_fail_fast = (val ? true : false); - return true; -} - -bool -ServiceabilityAgentDbxModule::handlePeek(char* data) { - // Scan hex address, return false if failed - psaddr_t addr; -#ifdef PROFILING - scanTimer.start(); -#endif /* PROFILING */ - if (!scanAddress(&data, &addr)) { - return false; - } - unsigned int num; - if (!scanUnsignedInt(&data, &num)) { - return false; - } - if (num == 0) { -#ifdef PROFILING - writeTimer.start(); -#endif /* PROFILING */ - myComm.writeBinChar('B'); - myComm.writeBinChar(1); - myComm.writeBinUnsignedInt(0); - myComm.writeBinChar(0); -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - return true; - } -#ifdef PROFILING - scanTimer.stop(); - workTimer.start(); -#endif /* PROFILING */ - char* buf = new char[num]; - ps_prochandle* cur_proc = (ps_prochandle*) ps_get_prochandle2(1); - ps_err_e result = ps_pread(cur_proc, addr, buf, num); - if (result == PS_OK) { - // Fast case; entire read succeeded. -#ifdef PROFILING - workTimer.stop(); - writeTimer.start(); -#endif /* PROFILING */ - myComm.writeBinChar('B'); - myComm.writeBinChar(1); - myComm.writeBinUnsignedInt(num); - myComm.writeBinChar(1); - myComm.writeBinBuf(buf, num); -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - } else { -#ifdef PROFILING - workTimer.stop(); -#endif /* PROFILING */ - - if (peek_fail_fast) { -#ifdef PROFILING - writeTimer.start(); -#endif /* PROFILING */ - // Fail fast - myComm.writeBinChar('B'); - myComm.writeBinChar(1); - myComm.writeBinUnsignedInt(num); - myComm.writeBinChar(0); -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - } else { - // Slow case: try to read one byte at a time - // FIXME: need better way of handling this, a la VirtualQuery - - unsigned int strideLen = 0; - int bufIdx = 0; - bool lastByteMapped = (ps_pread(cur_proc, addr, buf, 1) == PS_OK ? true : false); - -#ifdef PROFILING - writeTimer.start(); -#endif /* PROFILING */ - myComm.writeBinChar('B'); - myComm.writeBinChar(1); -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - - for (int i = 0; i < num; ++i, ++addr) { -#ifdef PROFILING - workTimer.start(); -#endif /* PROFILING */ - result = ps_pread(cur_proc, addr, &buf[bufIdx], 1); -#ifdef PROFILING - workTimer.stop(); -#endif /* PROFILING */ - bool tmpMapped = (result == PS_OK ? true : false); -#ifdef PROFILING - writeTimer.start(); -#endif /* PROFILING */ - if (tmpMapped != lastByteMapped) { - // State change. Write the length of the last stride. - myComm.writeBinUnsignedInt(strideLen); - if (lastByteMapped) { - // Stop gathering data. Write the data of the last stride. - myComm.writeBinChar(1); - myComm.writeBinBuf(buf, strideLen); - bufIdx = 0; - } else { - // Start gathering data to write. - myComm.writeBinChar(0); - } - strideLen = 0; - lastByteMapped = tmpMapped; - } -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - if (lastByteMapped) { - ++bufIdx; - } - ++strideLen; - } - - // Write last stride (must be at least one byte long by definition) -#ifdef PROFILING - writeTimer.start(); -#endif /* PROFILING */ - myComm.writeBinUnsignedInt(strideLen); - if (lastByteMapped) { - myComm.writeBinChar(1); - myComm.writeBinBuf(buf, strideLen); - } else { - myComm.writeBinChar(0); - } -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - } - } - delete[] buf; - myComm.flush(); - return true; -} - -bool -ServiceabilityAgentDbxModule::handlePoke(char* data) { - // FIXME: not yet implemented - NEEDS_CLEANUP; - bool res = myComm.writeBoolAsInt(false); - myComm.flush(); - return res; -} - -bool -ServiceabilityAgentDbxModule::handleMapped(char* data) { - // Scan address - psaddr_t addr; - if (!scanAddress(&data, &addr)) { - return false; - } - unsigned int num; - if (!scanUnsignedInt(&data, &num)) { - return false; - } - unsigned char val; - ps_prochandle* cur_proc = (ps_prochandle*) ps_get_prochandle2(1); - char* buf = new char[num]; - if (ps_pread(cur_proc, addr, buf, num) == PS_OK) { - myComm.writeBoolAsInt(true); - } else { - myComm.writeBoolAsInt(false); - } - delete[] buf; - myComm.writeEOL(); - myComm.flush(); - return true; -} - -extern "C" -int loadobj_iterator(const rd_loadobj_t* loadobj, void *) { - if (loadobj != NULL) { - fprintf(stderr, "loadobj_iterator: visited loadobj \"%p\"\n", (void*) loadobj->rl_nameaddr); - return 1; - } - - fprintf(stderr, "loadobj_iterator: NULL loadobj\n"); - return 0; -} - -bool -ServiceabilityAgentDbxModule::handleLookup(char* data) { - // Debugging: iterate over loadobjs - /* - rd_agent_t* rld_agent = rd_new((ps_prochandle*) ps_get_prochandle2(1)); - rd_loadobj_iter(rld_agent, &loadobj_iterator, NULL); - rd_delete(rld_agent); - */ - -#ifdef PROFILING - scanTimer.start(); -#endif /* PROFILING */ - - char* object_name = scanSymbol(&data); - if (object_name == NULL) { - return false; - } - char* symbol_name = scanSymbol(&data); - if (symbol_name == NULL) { - delete[] object_name; - return false; - } - -#ifdef PROFILING - scanTimer.stop(); - workTimer.start(); -#endif /* PROFILING */ - - ps_sym_t sym; - // FIXME: check return values from write routines - ps_prochandle* process = (ps_prochandle*) ps_get_prochandle2(1); - ps_err_e lookup_res = ps_pglobal_sym(process, - object_name, symbol_name, &sym); -#ifdef PROFILING - workTimer.stop(); - writeTimer.start(); -#endif /* PROFILING */ - - delete[] object_name; - delete[] symbol_name; - if (lookup_res != PS_OK) { - // This is too noisy - // debug_only(fprintf(stderr, "ServiceabilityAgentDbxModule::handleLookup: error %d\n", lookup_res)); - myComm.writeString("0x0"); - } else { - myComm.writeAddress((void *)sym.st_value); - } - myComm.writeEOL(); - myComm.flush(); - -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - - return true; -} - -bool -ServiceabilityAgentDbxModule::handleThrGRegs(char* data) { -#ifdef PROFILING - scanTimer.start(); -#endif /* PROFILING */ - - unsigned int num; - // Get the thread ID - if (!scanUnsignedInt(&data, &num)) { - return false; - } - -#ifdef PROFILING - scanTimer.stop(); - workTimer.start(); -#endif /* PROFILING */ - - // Map tid to thread handle - td_thrhandle_t thread_handle; - if ((*td_ta_map_id2thr_fn)(_tdb_agent, num, &thread_handle) != TD_OK) { - // fprintf(stderr, "Error mapping thread ID %d to thread handle\n", num); - return false; - } - - // Fetch register set - prgregset_t reg_set; - memset(reg_set, 0, sizeof(reg_set)); - td_err_e result = (*td_thr_getgregs_fn)(&thread_handle, reg_set); - if ((result != TD_OK) && (result != TD_PARTIALREG)) { - // fprintf(stderr, "Error fetching registers for thread handle %d: error = %d\n", num, result); - return false; - } - -#ifdef PROFILING - workTimer.stop(); - writeTimer.start(); -#endif /* PROFILING */ - -#if (defined(__sparc) || defined(__i386)) - myComm.writeInt(NPRGREG); - myComm.writeSpace(); - for (int i = 0; i < NPRGREG; i++) { - myComm.writeAddress((void *)reg_set[i]); - if (i == NPRGREG - 1) { - myComm.writeEOL(); - } else { - myComm.writeSpace(); - } - } -#else -#error Please port ServiceabilityAgentDbxModule::handleThrGRegs to your current platform -#endif - - myComm.flush(); - -#ifdef PROFILING - writeTimer.stop(); -#endif /* PROFILING */ - - return true; -} - -// -// Input routines -// - -bool -ServiceabilityAgentDbxModule::scanAddress(char** data, psaddr_t* addr) { - *addr = 0; - - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (**data == 0) { - return false; - } - - if (strncmp(*data, "0x", 2) != 0) { - return false; - } - - *data += 2; - - while ((**data != 0) && (!isspace(**data))) { - int val; - bool res = charToNibble(**data, &val); - if (!res) { - return false; - } - *addr <<= 4; - *addr |= val; - ++*data; - } - - return true; -} - -bool -ServiceabilityAgentDbxModule::scanUnsignedInt(char** data, unsigned int* num) { - *num = 0; - - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (**data == 0) { - return false; - } - - while ((**data != 0) && (!isspace(**data))) { - char cur = **data; - if ((cur < '0') || (cur > '9')) { - return false; - } - *num *= 10; - *num += cur - '0'; - ++*data; - } - - return true; -} - -char* -ServiceabilityAgentDbxModule::scanSymbol(char** data) { - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (**data == 0) { - return NULL; - } - - // First count length - int len = 1; // Null terminator - char* tmpData = *data; - while ((*tmpData != 0) && (!isspace(*tmpData))) { - ++tmpData; - ++len; - } - char* buf = new char[len]; - strncpy(buf, *data, len - 1); - buf[len - 1] = 0; - *data += len - 1; - return buf; -} - -bool -ServiceabilityAgentDbxModule::charToNibble(char ascii, int* value) { - if (ascii >= '0' && ascii <= '9') { - *value = ascii - '0'; - return true; - } else if (ascii >= 'A' && ascii <= 'F') { - *value = 10 + ascii - 'A'; - return true; - } else if (ascii >= 'a' && ascii <= 'f') { - *value = 10 + ascii - 'a'; - return true; - } - - return false; -} - - -char* -ServiceabilityAgentDbxModule::readCStringFromProcess(psaddr_t addr) { - char c; - int num = 0; - ps_prochandle* cur_proc = (ps_prochandle*) ps_get_prochandle2(1); - - // Search for null terminator - do { - if (ps_pread(cur_proc, addr + num, &c, 1) != PS_OK) { - return NULL; - } - ++num; - } while (c != 0); - - // Allocate string - char* res = new char[num]; - if (ps_pread(cur_proc, addr, res, num) != PS_OK) { - delete[] res; - return NULL; - } - return res; -} - - -//-------------------------------------------------------------------------------- -// Class Timer -// - -Timer::Timer() { - reset(); -} - -Timer::~Timer() { -} - -void -Timer::start() { - gettimeofday(&startTime, NULL); -} - -void -Timer::stop() { - struct timeval endTime; - gettimeofday(&endTime, NULL); - totalMicroseconds += timevalDiff(&startTime, &endTime); - ++counter; -} - -long -Timer::total() { - return (totalMicroseconds / 1000); -} - -long -Timer::average() { - return (long) ((double) total() / (double) counter); -} - -void -Timer::reset() { - totalMicroseconds = 0; - counter = 0; -} - -long long -Timer::timevalDiff(struct timeval* start, struct timeval* end) { - long long secs = end->tv_sec - start->tv_sec; - secs *= 1000000; - long long usecs = end->tv_usec - start->tv_usec; - return (secs + usecs); -} diff --git a/hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.hpp b/hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.hpp deleted file mode 100644 index 0fbe8d0624e..00000000000 --- a/hotspot/agent/src/os/solaris/dbx/svc_agent_dbx.hpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "shell_imp.h" -#include "IOBuf.hpp" -#include -#include - -typedef td_err_e td_init_fn_t(); -typedef td_err_e td_ta_new_fn_t(struct ps_prochandle *, td_thragent_t **); -typedef td_err_e td_ta_delete_fn_t(td_thragent_t *); -typedef td_err_e td_ta_map_id2thr_fn_t(const td_thragent_t *, thread_t, td_thrhandle_t *); -typedef td_err_e td_thr_getgregs_fn_t(const td_thrhandle_t *, prgregset_t); - -class ServiceabilityAgentDbxModule { -public: - ServiceabilityAgentDbxModule(int major, int minor, - shell_imp_interp_t interp, int argc, char *argv[]); - ~ServiceabilityAgentDbxModule(); - - bool install(); - bool uninstall(); - - /* This is invoked through the dbx command interpreter. It listens - on a socket for commands and does not return until it receives an - "exit" command. At that point control is returned to dbx's main - loop, at which point if the user sends an exit command to dbx's - shell the dbx process will exit. Returns true if completed - successfully, false if an error occurred while running (for - example, unable to bind listening socket). */ - bool run(); - -private: - - // This must be shared between the Java and C layers - static const int PORT = 21928; - - // Command handlers - bool handleAddressSize(char* data); - bool handlePeekFailFast(char* data); - bool handlePeek(char* data); - bool handlePoke(char* data); - bool handleMapped(char* data); - bool handleLookup(char* data); - bool handleThrGRegs(char* data); - - // Input routines - - // May mutate addr argument even if result is false - bool scanAddress(char** data, psaddr_t* addr); - // May mutate num argument even if result is false - bool scanUnsignedInt(char** data, unsigned int* num); - // Returns NULL if error occurred while scanning. Otherwise, returns - // newly-allocated character array which must be freed with delete[]. - char* scanSymbol(char** data); - // Helper routine: converts ASCII to 4-bit integer. Returns true if - // character is in range, false otherwise. - bool charToNibble(char ascii, int* value); - - // Output routines - - // Writes an int with no leading or trailing spaces - bool writeInt(int val, int fd); - // Writes an address in hex format with no leading or trailing - // spaces - bool writeAddress(psaddr_t addr, int fd); - // Writes a register in hex format with no leading or trailing - // spaces (addresses and registers might be of different size) - bool writeRegister(prgreg_t reg, int fd); - // Writes a space to given file descriptor - bool writeSpace(int fd); - // Writes carriage return to given file descriptor - bool writeCR(int fd); - // Writes a bool as [0|1] - bool writeBoolAsInt(bool val, int fd); - // Helper routine: converts low 4 bits to ASCII [0..9][A..F] - char nibbleToChar(unsigned char nibble); - - // Base routine called by most of the above - bool writeString(const char* str, int fd); - - // Writes a binary character - bool writeBinChar(char val, int fd); - // Writes a binary unsigned int in network (big-endian) byte order - bool writeBinUnsignedInt(unsigned int val, int fd); - // Writes a binary buffer - bool writeBinBuf(char* buf, int size, int fd); - - // Routine to flush the socket - bool flush(int client_socket); - - void cleanup(int client_socket); - - // The shell interpreter on which we can invoke commands (?) - shell_imp_interp_t _interp; - - // The "command line" arguments passed to us by dbx (?) - int _argc; - char **_argv; - - // The installed command in the dbx shell - shell_imp_command_t _command; - - // Access to libthread_db (dlsym'ed to be able to pick up the - // version loaded by dbx) - td_init_fn_t* td_init_fn; - td_ta_new_fn_t* td_ta_new_fn; - td_ta_delete_fn_t* td_ta_delete_fn; - td_ta_map_id2thr_fn_t* td_ta_map_id2thr_fn; - td_thr_getgregs_fn_t* td_thr_getgregs_fn; - - // Our "thread agent" -- access to libthread_db - td_thragent_t* _tdb_agent; - - // Path to libthread.so in target process; free with delete[] - char* libThreadName; - - // Handle to dlopen'ed libthread_db.so - void* libThreadDB; - - // Helper callback for finding libthread_db.so - friend int findLibThreadCB(const rd_loadobj_t* lo, void* data); - - // Support for reading C strings out of the target process (so we - // can find the correct libthread_db). Returns newly-allocated char* - // which must be freed with delete[], or null if the read failed. - char* readCStringFromProcess(psaddr_t addr); - - IOBuf myComm; - - // Output buffer support (used by writeString, writeChar, flush) - char* output_buffer; - int output_buffer_size; - int output_buffer_pos; - - // "Fail fast" flag - bool peek_fail_fast; - - // Commands - static const char* CMD_ADDRESS_SIZE; - static const char* CMD_PEEK_FAIL_FAST; - static const char* CMD_PEEK; - static const char* CMD_POKE; - static const char* CMD_MAPPED; - static const char* CMD_LOOKUP; - static const char* CMD_THR_GREGS; - static const char* CMD_EXIT; -}; - -// For profiling. Times reported are in milliseconds. -class Timer { -public: - Timer(); - ~Timer(); - - void start(); - void stop(); - long total(); - long average(); - void reset(); - -private: - struct timeval startTime; - long long totalMicroseconds; // stored internally in microseconds - int counter; - long long timevalDiff(struct timeval* startTime, struct timeval* endTime); -}; diff --git a/hotspot/agent/src/os/win32/BasicList.hpp b/hotspot/agent/src/os/win32/BasicList.hpp deleted file mode 100644 index 5b9164f94cb..00000000000 --- a/hotspot/agent/src/os/win32/BasicList.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _BASIC_LIST_ -#define _BASIC_LIST_ - -#include - -template -class BasicList { -protected: - typedef std::vector InternalListType; - InternalListType internalList; - -public: - BasicList() { - } - virtual ~BasicList() { - } - - void add(T arg) { - internalList.push_back(arg); - } - - bool remove(T arg) { - for (InternalListType::iterator iter = internalList.begin(); - iter != internalList.end(); iter++) { - if (*iter == arg) { - internalList.erase(iter); - return true; - } - } - return false; - } - - int size() { - return internalList.size(); - } - - T get(int index) { - return internalList[index]; - } -}; - -#endif // #defined _BASIC_LIST_ diff --git a/hotspot/agent/src/os/win32/Buffer.cpp b/hotspot/agent/src/os/win32/Buffer.cpp deleted file mode 100644 index 6c14b6a17dc..00000000000 --- a/hotspot/agent/src/os/win32/Buffer.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "Buffer.hpp" - -#include - -Buffer::Buffer(int bufSize) { - buf = new char[bufSize]; - sz = bufSize; - fill = 0; - drain = 0; -} - -Buffer::~Buffer() { - delete[] buf; -} - -char* -Buffer::fillPos() { - return buf + fill; -} - -int -Buffer::remaining() { - return sz - fill; -} - -int -Buffer::size() { - return sz; -} - -bool -Buffer::incrFillPos(int amt) { - if (fill + amt >= sz) { - return false; - } - fill += amt; - return true; -} - -int -Buffer::readByte() { - if (drain < fill) { - return buf[drain++] & 0xFF; - } else { - return -1; - } -} - -int -Buffer::readBytes(char* data, int len) { - int numRead = 0; - while (numRead < len) { - int c = readByte(); - if (c < 0) break; - data[numRead++] = (char) c; - } - return numRead; -} - -char* -Buffer::drainPos() { - return buf + drain; -} - -int -Buffer::drainRemaining() { - return fill - drain; -} - -bool -Buffer::incrDrainPos(int amt) { - if (drainRemaining() < amt) { - return false; - } - drain += amt; - return true; -} - -void -Buffer::compact() { - // Copy down data - memmove(buf, buf + drain, fill - drain); - // Adjust positions - fill -= drain; - drain = 0; -} diff --git a/hotspot/agent/src/os/win32/Buffer.hpp b/hotspot/agent/src/os/win32/Buffer.hpp deleted file mode 100644 index c775a7ad6d7..00000000000 --- a/hotspot/agent/src/os/win32/Buffer.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _BUFFER_ -#define _BUFFER_ - -// A Buffer is the backing store for the IOBuf abstraction and -// supports producer-consumer filling and draining. - -class Buffer { -public: - Buffer(int bufSize); - ~Buffer(); - - char* fillPos(); // Position of the place where buffer should be filled - int remaining(); // Number of bytes that can be placed starting at fillPos - int size(); // Size of the buffer - // Move up fill position by amount (decreases remaining()); returns - // false if not enough space - bool incrFillPos(int amt); - - // Read single byte (0..255); returns -1 if no data available. - int readByte(); - // Read multiple bytes, non-blocking (this buffer does not define a - // fill mechanism), into provided buffer. Returns number of bytes read. - int readBytes(char* buf, int len); - - // Access to drain position. Be very careful using this. - char* drainPos(); - int drainRemaining(); - bool incrDrainPos(int amt); - - // Compact buffer, removing already-consumed input. This must be - // called periodically to yield the illusion of an infinite buffer. - void compact(); - -private: - Buffer(const Buffer&); - Buffer& operator=(const Buffer&); - - char* buf; - int sz; - int fill; - int drain; -}; - -#endif // #defined _BUFFER_ diff --git a/hotspot/agent/src/os/win32/Dispatcher.cpp b/hotspot/agent/src/os/win32/Dispatcher.cpp deleted file mode 100644 index ebb85e83a7d..00000000000 --- a/hotspot/agent/src/os/win32/Dispatcher.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include -#include "dispatcher.hpp" - -const char* CMD_ASCII = "ascii"; -const char* CMD_UNICODE = "unicode"; -const char* CMD_PROCLIST = "proclist"; -const char* CMD_ATTACH = "attach"; -const char* CMD_DETACH = "detach"; -const char* CMD_LIBINFO = "libinfo"; -const char* CMD_PEEK = "peek"; -const char* CMD_POKE = "poke"; -const char* CMD_THREADLIST = "threadlist"; -const char* CMD_DUPHANDLE = "duphandle"; -const char* CMD_CLOSEHANDLE = "closehandle"; -const char* CMD_GETCONTEXT = "getcontext"; -const char* CMD_SETCONTEXT = "setcontext"; -const char* CMD_SELECTORENTRY = "selectorentry"; -const char* CMD_SUSPEND = "suspend"; -const char* CMD_RESUME = "resume"; -const char* CMD_POLLEVENT = "pollevent"; -const char* CMD_CONTINUEEVENT = "continueevent"; -const char* CMD_EXIT = "exit"; - -// Uncomment the #define below to get messages on stderr -// #define DEBUGGING - -void -Dispatcher::dispatch(char* cmd, Handler* handler) { - if (!strncmp(cmd, CMD_ASCII, strlen(CMD_ASCII))) { - handler->ascii(cmd + strlen(CMD_ASCII)); - - } else if (!strncmp(cmd, CMD_UNICODE, strlen(CMD_UNICODE))) { - handler->unicode(cmd + strlen(CMD_UNICODE)); - - } else if (!strncmp(cmd, CMD_PROCLIST, strlen(CMD_PROCLIST))) { - handler->procList(cmd + strlen(CMD_PROCLIST)); - - } else if (!strncmp(cmd, CMD_ATTACH, strlen(CMD_ATTACH))) { - handler->attach(cmd + strlen(CMD_ATTACH)); - - } else if (!strncmp(cmd, CMD_DETACH, strlen(CMD_DETACH))) { - handler->detach(cmd + strlen(CMD_DETACH)); - - } else if (!strncmp(cmd, CMD_LIBINFO, strlen(CMD_LIBINFO))) { - handler->libInfo(cmd + strlen(CMD_LIBINFO)); - - } else if (!strncmp(cmd, CMD_PEEK, strlen(CMD_PEEK))) { - handler->peek(cmd + strlen(CMD_PEEK)); - - } else if (!strncmp(cmd, CMD_POKE, strlen(CMD_POKE))) { - handler->poke(cmd + strlen(CMD_POKE)); - - } else if (!strncmp(cmd, CMD_THREADLIST, strlen(CMD_THREADLIST))) { - handler->threadList(cmd + strlen(CMD_THREADLIST)); - - } else if (!strncmp(cmd, CMD_DUPHANDLE, strlen(CMD_DUPHANDLE))) { - handler->dupHandle(cmd + strlen(CMD_DUPHANDLE)); - - } else if (!strncmp(cmd, CMD_CLOSEHANDLE, strlen(CMD_CLOSEHANDLE))) { - handler->closeHandle(cmd + strlen(CMD_CLOSEHANDLE)); - - } else if (!strncmp(cmd, CMD_GETCONTEXT, strlen(CMD_GETCONTEXT))) { - handler->getContext(cmd + strlen(CMD_GETCONTEXT)); - - } else if (!strncmp(cmd, CMD_SETCONTEXT, strlen(CMD_SETCONTEXT))) { - handler->setContext(cmd + strlen(CMD_SETCONTEXT)); - - } else if (!strncmp(cmd, CMD_SELECTORENTRY, strlen(CMD_SELECTORENTRY))) { - handler->selectorEntry(cmd + strlen(CMD_SELECTORENTRY)); - - } else if (!strncmp(cmd, CMD_SUSPEND, strlen(CMD_SUSPEND))) { - handler->suspend(cmd + strlen(CMD_SUSPEND)); - - } else if (!strncmp(cmd, CMD_RESUME, strlen(CMD_RESUME))) { - handler->resume(cmd + strlen(CMD_RESUME)); - - } else if (!strncmp(cmd, CMD_POLLEVENT, strlen(CMD_POLLEVENT))) { - handler->pollEvent(cmd + strlen(CMD_POLLEVENT)); - - } else if (!strncmp(cmd, CMD_CONTINUEEVENT, strlen(CMD_CONTINUEEVENT))) { - handler->continueEvent(cmd + strlen(CMD_CONTINUEEVENT)); - - } else if (!strcmp(cmd, CMD_EXIT)) { - handler->exit(cmd + strlen(CMD_EXIT)); - } - -#ifdef DEBUGGING - else fprintf(stderr, "Ignoring illegal command \"%s\"\n", cmd); -#endif -} diff --git a/hotspot/agent/src/os/win32/Dispatcher.hpp b/hotspot/agent/src/os/win32/Dispatcher.hpp deleted file mode 100644 index 72f9dd78727..00000000000 --- a/hotspot/agent/src/os/win32/Dispatcher.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _DISPATCHER_ -#define _DISPATCHER_ - -#include "Handler.hpp" - -/** This class understands the commands supported by the system and - calls the appropriate handler routines. */ - -class Dispatcher { -public: - static void dispatch(char* cmd, Handler* handler); -}; - -#endif // #defined _DISPATCHER_ diff --git a/hotspot/agent/src/os/win32/Handler.hpp b/hotspot/agent/src/os/win32/Handler.hpp deleted file mode 100644 index 0aa32c4a785..00000000000 --- a/hotspot/agent/src/os/win32/Handler.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _HANDLER_ -#define _HANDLER_ - -/** An abstract base class encapsulating the handlers for all commands - understood by the system. */ -class Handler { -public: - virtual void ascii(char* arg) = 0; - virtual void unicode(char* arg) = 0; - virtual void procList(char* arg) = 0; - virtual void attach(char* arg) = 0; - virtual void detach(char* arg) = 0; - virtual void libInfo(char* arg) = 0; - virtual void peek(char* arg) = 0; - virtual void poke(char* arg) = 0; - virtual void threadList(char* arg) = 0; - virtual void dupHandle(char* arg) = 0; - virtual void closeHandle(char* arg) = 0; - virtual void getContext(char* arg) = 0; - virtual void setContext(char* arg) = 0; - virtual void selectorEntry(char* arg) = 0; - virtual void suspend(char* arg) = 0; - virtual void resume(char* arg) = 0; - virtual void pollEvent(char* arg) = 0; - virtual void continueEvent(char* arg) = 0; - virtual void exit(char* arg) = 0; -}; - -#endif // #defined _HANDLER_ diff --git a/hotspot/agent/src/os/win32/IOBuf.cpp b/hotspot/agent/src/os/win32/IOBuf.cpp deleted file mode 100644 index 08d29b1fada..00000000000 --- a/hotspot/agent/src/os/win32/IOBuf.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include - -// This file is currently used for os/solaris/agent too. At some point in time -// the source will be reorganized to avoid these ifdefs. - -#ifdef __sun - #include - #include - #include -#endif - -#include "IOBuf.hpp" - -// Formats for printing pointers -#ifdef _LP64 -# define INTPTR_FORMAT "0x%016lx" -#else /* ! _LP64 */ -# define INTPTR_FORMAT "0x%08lx" -#endif /* _LP64 */ - -// Uncomment the #define below to get messages on stderr -// #define DEBUGGING - -IOBuf::IOBuf(int inLen, int outLen) { - inBuf = new Buffer(inLen); - outBuf = new Buffer(outLen); - fd = INVALID_SOCKET; - outHandle = NULL; - usingSocket = true; - reset(); -} - -IOBuf::~IOBuf() { - delete inBuf; - delete outBuf; -} - -void -IOBuf::setSocket(SOCKET sock) { - fd = sock; - usingSocket = true; -} - -// Reading/writing files is only needed and used on windows. -#ifdef WIN32 -void -IOBuf::setOutputFileHandle(HANDLE handle) { - outHandle = handle; - usingSocket = false; -} -#endif - -void -IOBuf::reset() { - gotDataLastTime = false; - state = TEXT_STATE; - binPos = 0; - binLength = 0; -} - -IOBuf::ReadLineResult -IOBuf::tryReadLine() { - return doReadLine(false); -} - -char* -IOBuf::readLine() { - ReadLineResult rr = doReadLine(true); - if (rr != RL_GOT_DATA) { - return NULL; - } - return getLine(); -} - -IOBuf::ReadLineResult -IOBuf::doReadLine(bool shouldWait) { - - if (!usingSocket) { - return IOBuf::RL_ERROR; - } - - if (gotDataLastTime) { - curLine.clear(); - } - - int c; - do { - c = readChar(shouldWait); - if (c >= 0) { - Action act = processChar((char) c); - if (act == GOT_LINE) { - curLine.push_back('\0'); - gotDataLastTime = true; - return IOBuf::RL_GOT_DATA; - } else if (act == SKIP_EOL_CHAR) { - // Do nothing - } else { - curLine.push_back((char) c); - } - } - } while (shouldWait || c >= 0); - - gotDataLastTime = false; - return IOBuf::RL_NO_DATA; -} - -bool -IOBuf::flushImpl(bool moreDataToCome) { - int numWritten = 0; - -#ifdef WIN32 - // When running on Windows and using IOBufs for inter-process - // communication, we need to write metadata into the stream - // indicating how many bytes are coming down. Five bytes are written - // per flush() call, four containing the integer number of bytes - // coming (not including the five-byte header) and one (a 0 or 1) - // indicating whether there is more data coming. - if (!usingSocket) { - int numToWrite = outBuf->drainRemaining(); - char moreToCome = (moreDataToCome ? 1 : 0); - DWORD numBytesWritten; - if (!WriteFile(outHandle, &numToWrite, sizeof(int), &numBytesWritten, NULL)) { - return false; - } - if (numBytesWritten != sizeof(int)) { - return false; - } - if (!WriteFile(outHandle, &moreToCome, 1, &numBytesWritten, NULL)) { - return false; - } - if (numBytesWritten != 1) { - return false; - } - } -#endif - - while (outBuf->drainRemaining() != 0) { -#ifdef DEBUGGING - fprintf(stderr, "Flushing %d bytes\n", outBuf->drainRemaining()); -#endif - if (usingSocket) { - numWritten = send(fd, outBuf->drainPos(), outBuf->drainRemaining(), 0); - } else { -#ifdef WIN32 - DWORD numBytesWritten; - if (!WriteFile(outHandle, outBuf->drainPos(), outBuf->drainRemaining(), &numBytesWritten, NULL)) { - numWritten = -1; - } else { - numWritten = numBytesWritten; - } -#endif - } - if (numWritten != -1) { -#ifdef DEBUGGING - fprintf(stderr, "Flushed %d bytes\n", numWritten); -#endif - outBuf->incrDrainPos(numWritten); - } else { - return false; - } - } - - outBuf->compact(); - - return true; -} - -int -IOBuf::readChar(bool block) { - do { - int c = inBuf->readByte(); - if (c >= 0) { - return c; - } - // See whether we need to compact the input buffer - if (inBuf->remaining() < inBuf->size() / 2) { - inBuf->compact(); - } - // See whether socket is ready - fd_set fds; - FD_ZERO(&fds); - FD_SET(fd, &fds); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - if (block || select(1 + fd, &fds, NULL, NULL, &timeout) > 0) { - if (block || FD_ISSET(fd, &fds)) { -#ifdef DEBUGGING - int b = (block ? 1 : 0); - fprintf(stderr, "calling recv: block = %d\n", b); -#endif - // Read data from socket - int numRead = recv(fd, inBuf->fillPos(), inBuf->remaining(), 0); - if (numRead < 0) { -#ifdef DEBUGGING - fprintf(stderr, "recv failed\n"); -#endif - return -1; - } - inBuf->incrFillPos(numRead); - } - } - } while (block); - - return inBuf->readByte(); -} - -char* -IOBuf::getLine() { -#ifdef DEBUGGING - fprintf(stderr, "Returning (first 10 chars) \"%.10s\"\n", curLine.begin()); -#endif - return curLine.begin(); -} - -bool -IOBuf::flush() { - return flushImpl(false); -} - -bool -IOBuf::writeString(const char* str) { - int len = strlen(str); - - if (len > outBuf->size()) { - return false; - } - - if (len > outBuf->remaining()) { - if (!flushImpl(true)) { - return false; - } - } - - // NOTE we do not copy the null terminator of the string. - - strncpy(outBuf->fillPos(), str, len); - outBuf->incrFillPos(len); - return true; -} - -bool -IOBuf::writeInt(int val) { - char buf[128]; - sprintf(buf, "%d", val); - return writeString(buf); -} - -bool -IOBuf::writeUnsignedInt(unsigned int val) { - char buf[128]; - sprintf(buf, "%u", val); - return writeString(buf); -} - -bool -IOBuf::writeBoolAsInt(bool val) { - if (val) { - return writeString("1"); - } else { - return writeString("0"); - } -} - -bool -IOBuf::writeAddress(void* val) { - char buf[128]; - sprintf(buf, INTPTR_FORMAT, val); - return writeString(buf); -} - -bool -IOBuf::writeSpace() { - return writeString(" "); -} - -bool -IOBuf::writeEOL() { - return writeString("\n\r"); -} - -bool -IOBuf::writeBinChar(char c) { - return writeBinBuf((char*) &c, sizeof(c)); -} - -bool -IOBuf::writeBinUnsignedShort(unsigned short i) { - i = htons(i); - return writeBinBuf((char*) &i, sizeof(i)); -} - -bool -IOBuf::writeBinUnsignedInt(unsigned int i) { - i = htonl(i); - return writeBinBuf((char*) &i, sizeof(i)); -} - -bool -IOBuf::writeBinBuf(char* buf, int size) { - while (size > 0) { - int spaceRemaining = outBuf->remaining(); - if (spaceRemaining == 0) { - if (!flushImpl(true)) { - return false; - } - spaceRemaining = outBuf->remaining(); - } - int toCopy = (size > spaceRemaining) ? spaceRemaining : size; - memcpy(outBuf->fillPos(), buf, toCopy); - outBuf->incrFillPos(toCopy); - buf += toCopy; - size -= toCopy; - if (size > 0) { - if (!flushImpl(true)) { - return false; - } - } - } - return true; -} - -#ifdef WIN32 -IOBuf::FillState -IOBuf::fillFromFileHandle(HANDLE fh, DWORD* numBytesRead) { - int totalToRead; - char moreToCome; - - outBuf->compact(); - - DWORD numRead; - if (!ReadFile(fh, &totalToRead, sizeof(int), &numRead, NULL)) { - return FAILED; - } - if (numRead != sizeof(int)) { - return FAILED; - } - if (!ReadFile(fh, &moreToCome, 1, &numRead, NULL)) { - return FAILED; - } - if (numRead != 1) { - return FAILED; - } - if (outBuf->remaining() < totalToRead) { - return FAILED; - } - - int tmp = totalToRead; - - while (totalToRead > 0) { - if (!ReadFile(fh, outBuf->fillPos(), totalToRead, &numRead, NULL)) { - return FAILED; - } - outBuf->incrFillPos((int) numRead); - totalToRead -= numRead; - } - - *numBytesRead = tmp; - return ((moreToCome == 0) ? DONE : MORE_DATA_PENDING); -} -#endif - -bool -IOBuf::isBinEscapeChar(char c) { - return (c == '|'); -} - -IOBuf::Action -IOBuf::processChar(char c) { - Action action = NO_ACTION; - switch (state) { - case TEXT_STATE: { - // Looking for text char, bin escape char, or EOL - if (isBinEscapeChar(c)) { -#ifdef DEBUGGING - fprintf(stderr, "[a: '%c'] ", inBuf[0]); -#endif - binPos = 0; -#ifdef DEBUGGING - fprintf(stderr, "[b: '%c'] ", inBuf[0]); -#endif - binLength = 0; -#ifdef DEBUGGING - fprintf(stderr, "[c: '%c'] ", inBuf[0]); -#endif - state = BIN_STATE; -#ifdef DEBUGGING - fprintf(stderr, "[d: '%c'] ", inBuf[0]); -#endif -#ifdef DEBUGGING - fprintf(stderr, "\nSwitching to BIN_STATE\n"); -#endif - } else if (isEOL(c)) { - state = EOL_STATE; - action = GOT_LINE; -#ifdef DEBUGGING - fprintf(stderr, "\nSwitching to EOL_STATE (GOT_LINE)\n"); -#endif - } -#ifdef DEBUGGING - else { - fprintf(stderr, "'%c' ", c); - fflush(stderr); - } -#endif - break; - } - - case BIN_STATE: { - // Seeking to finish read of input - if (binPos < 4) { - int cur = c & 0xFF; - binLength <<= 8; - binLength |= cur; - ++binPos; - } else { -#ifdef DEBUGGING - fprintf(stderr, "Reading binary byte %d of %d\n", - binPos - 4, binLength); -#endif - ++binPos; - if (binPos == 4 + binLength) { - state = TEXT_STATE; -#ifdef DEBUGGING - fprintf(stderr, "Switching to TEXT_STATE\n"); -#endif - } - } - break; - } - - case EOL_STATE: { - // More EOL characters just cause us to re-enter this state - if (isEOL(c)) { - action = SKIP_EOL_CHAR; - } else if (isBinEscapeChar(c)) { - binPos = 0; - binLength = 0; - state = BIN_STATE; - } else { - state = TEXT_STATE; -#ifdef DEBUGGING - fprintf(stderr, "'%c' ", c); - fflush(stderr); -#endif - } - break; - } - - } // switch - - return action; -} - - -bool -IOBuf::isEOL(char c) { -#ifdef WIN32 - return ((c == '\n') || (c == '\r')); -#elif defined(__sun) - return c == '\n'; -#else - #error Please port isEOL() to your platform - return false; -#endif -} diff --git a/hotspot/agent/src/os/win32/IOBuf.hpp b/hotspot/agent/src/os/win32/IOBuf.hpp deleted file mode 100644 index 31ed391119e..00000000000 --- a/hotspot/agent/src/os/win32/IOBuf.hpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _IO_BUF_ -#define _IO_BUF_ - -// This file is currently used for os/solaris/agent/ too. At some point in time -// the source will be reorganized to avoid these ifdefs. -// Note that this class can read/write from a file as well as a socket. This -// file capability is only implemented on win32. - -#ifdef WIN32 - #include -#else - #include - #include - // These are from win32 winsock2.h - typedef unsigned int SOCKET; - typedef void * HANDLE; - typedef unsigned long DWORD; - #define INVALID_SOCKET (SOCKET)(~0) -#endif - -#include -#include "Buffer.hpp" - -/** Manages an input/output buffer pair for a socket or file handle. */ -class IOBuf { -public: - IOBuf(int inBufLen, int outBufLen); - ~IOBuf(); - - enum ReadLineResult { - RL_GOT_DATA, - RL_NO_DATA, - RL_ERROR - }; - - /** Change the socket with which this buffer is associated */ - void setSocket(SOCKET sock); - - // Reading/writing files is only supported on windows. -#ifdef WIN32 - /** Change the output file handle with which this buffer is - associated. Currently IOBufs can not be used to read from a file - handle. */ - void setOutputFileHandle(HANDLE handle); -#endif - - /** Reset the input and output buffers, without flushing the output - data to the socket */ - void reset(); - - /** Try to read a line of data from the given socket without - blocking. If was able to read a complete line of data, returns a - character pointer to the beginning of the (null-terminated) - string. If not, returns NULL, but maintains enough state that - subsequent calls to tryReadLine() will not ignore the data - already read. NOTE: this skips end-of-line characters (typically - CR/LF) as defined by "isEOL()". When switching back and forth - between binary and text modes, to be sure no data is lost, pad - the beginning and end of the binary transmission with bytes - which can not be confused with these characters. */ - ReadLineResult tryReadLine(); - - /** Read a line of data from the given socket, blocking until a - line, including EOL, appears. Return the line, or NULL if - something goes wrong. */ - char *readLine(); - - /** Get the pointer to the beginning of the (null-terminated) line. - This should only be called if tryReadLine() has returned - RL_GOT_DATA. This sets the "parsing cursor" to the beginning of - the line. */ - char* getLine(); - - // NOTE: any further data-acquisition routines must ALWAYS call - // fixupData() at the beginning! - - //---------------------------------------------------------------------- - // Output routines - // - - /** Flush the output buffer to the socket. Returns true if - succeeded, false if write error occurred. */ - bool flush(); - - /** Write the given string to the output buffer. May flush if output - buffer becomes too full to store the data. Not guaranteed to - work if string is longer than the size of the output buffer. - Does not include the null terminator of the string. Returns true - if succeeded, false if write error occurred. */ - bool writeString(const char* str); - - /** Write the given int to the output buffer. May flush if output - buffer becomes too full to store the data. Returns true if - succeeded, false if write error occurred. */ - bool writeInt(int val); - - /** Write the given unsigned int to the output buffer. May flush if - output buffer becomes too full to store the data. Returns true - if succeeded, false if write error occurred. */ - bool writeUnsignedInt(unsigned int val); - - /** Write the given boolean to the output buffer. May flush if - output buffer becomes too full to store the data. Returns true - if succeeded, false if write error occurred. */ - bool writeBoolAsInt(bool val); - - /** Write the given address to the output buffer. May flush if - output buffer becomes too full to store the data. Returns true - if succeeded, false if write error occurred. */ - bool writeAddress(void* val); - - /** Writes a space to the output buffer. May flush if output buffer - becomes too full to store the data. Returns true if succeeded, - false if write error occurred. */ - bool writeSpace(); - - /** Writes an end-of-line sequence to the output buffer. May flush - if output buffer becomes too full to store the data. Returns - true if succeeded, false if write error occurred. */ - bool writeEOL(); - - /** Writes a binary character to the output buffer. */ - bool writeBinChar(char c); - - /** Writes a binary unsigned short in network (big-endian) byte - order to the output buffer. */ - bool writeBinUnsignedShort(unsigned short i); - - /** Writes a binary unsigned int in network (big-endian) byte order - to the output buffer. */ - bool writeBinUnsignedInt(unsigned int i); - - /** Writes a binary buffer to the output buffer. */ - bool writeBinBuf(char* buf, int size); - -#ifdef WIN32 - enum FillState { - DONE = 1, - MORE_DATA_PENDING = 2, - FAILED = 3 - }; - - /** Very specialized routine; fill the output buffer from the given - file handle. Caller is responsible for ensuring that there is - data to be read on the file handle. */ - FillState fillFromFileHandle(HANDLE fh, DWORD* numRead); -#endif - - /** Binary utility routine (for poke) */ - static bool isBinEscapeChar(char c); - -private: - IOBuf(const IOBuf&); - IOBuf& operator=(const IOBuf&); - - // Returns -1 if non-blocking and no data available - int readChar(bool block); - // Line-oriented reading - std::vector curLine; - bool gotDataLastTime; - - ReadLineResult doReadLine(bool); - - bool flushImpl(bool moreDataToCome); - - SOCKET fd; - HANDLE outHandle; - bool usingSocket; - - // Buffers - Buffer* inBuf; - Buffer* outBuf; - - // Simple finite-state machine to handle binary data - enum State { - TEXT_STATE, - BIN_STATE, - EOL_STATE - }; - enum Action { - NO_ACTION, - GOT_LINE, // TEXT_STATE -> EOL_STATE transition - SKIP_EOL_CHAR // EOL_STATE -> EOL_STATE transition - }; - - State state; - Action processChar(char c); - - // Handling incoming binary buffers (poke command) - int binPos; // Number of binary characters read so far; - // total number to read is binLength + 4 - int binLength; // Number of binary characters in message; - // not valid until binPos >= 4 - - bool isEOL(char c); -}; - -#endif // #defined _IO_BUF_ diff --git a/hotspot/agent/src/os/win32/LockableList.hpp b/hotspot/agent/src/os/win32/LockableList.hpp deleted file mode 100644 index 91fc072f6a0..00000000000 --- a/hotspot/agent/src/os/win32/LockableList.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _LOCKABLE_LIST_ -#define _LOCKABLE_LIST_ - -#include -#include "BasicList.hpp" - -template -class LockableList : public BasicList { -private: - CRITICAL_SECTION crit; - -public: - LockableList() { - InitializeCriticalSection(&crit); - } - - ~LockableList() { - DeleteCriticalSection(&crit); - } - - void lock() { - EnterCriticalSection(&crit); - } - - void unlock() { - LeaveCriticalSection(&crit); - } -}; - -#endif // #defined _LOCKABLE_LIST_ diff --git a/hotspot/agent/src/os/win32/Makefile b/hotspot/agent/src/os/win32/Makefile deleted file mode 100644 index 43d45072357..00000000000 --- a/hotspot/agent/src/os/win32/Makefile +++ /dev/null @@ -1,80 +0,0 @@ -# -# Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# - -SERVER=SwDbgSrv.exe -SUBPROCESS=SwDbgSub.exe - -SERVER_SOURCES = \ - Buffer.cpp \ - Dispatcher.cpp \ - initWinsock.cpp \ - IOBuf.cpp \ - ioUtils.cpp \ - isNT4.cpp \ - nt4internals.cpp \ - procList.cpp \ - Reaper.cpp \ - SwDbgSrv.cpp \ - serverLists.cpp \ - toolHelp.cpp - -SUBPROCESS_SOURCES = \ - SwDbgSub.cpp \ - Buffer.cpp \ - IOBuf.cpp \ - isNT4.cpp \ - libInfo.cpp \ - Monitor.cpp \ - nt4internals.cpp \ - toolHelp.cpp - -SERVER_OBJS = $(SERVER_SOURCES:.cpp=.obj) -SUBPROCESS_OBJS = $(SUBPROCESS_SOURCES:.cpp=.obj) - -CPP=cl.exe -LINK32=link.exe - -# These do not need to be optimized (don't run a lot of code) and it -# will be useful to have the assertion checks in place - -CFLAGS=/nologo /MD /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c - -LIBS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib \ - ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib \ - winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib \ - odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 - -default: $(SERVER) $(SUBPROCESS) - -$(SERVER): $(SERVER_OBJS) - $(LINK32) /out:$@ $(SERVER_OBJS) $(LIBS) - -$(SUBPROCESS): $(SUBPROCESS_OBJS) - $(LINK32) /out:$@ $(SUBPROCESS_OBJS) $(LIBS) - -clean: - rm -f *.obj *.idb *.pch *.pdb *.ncb *.opt *.plg *.exe *.ilk - -.cpp.obj: - @ $(CPP) $(CFLAGS) /o $@ $< diff --git a/hotspot/agent/src/os/win32/Message.hpp b/hotspot/agent/src/os/win32/Message.hpp deleted file mode 100644 index 61c6bd0fd70..00000000000 --- a/hotspot/agent/src/os/win32/Message.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _MESSAGE_ -#define _MESSAGE_ - -// These are the commands sent from the server to the child processes -// over the child processes' stdin pipes. A subset of the commands -// understood by the overall system, these require responses from the -// child process. Having a data structure rather than sending text -// simplifies parsing on the child side. The child replies by sending -// back fully-formatted replies which are copied by the server process -// to the clients' sockets. - -struct PeekArg { - DWORD address; - DWORD numBytes; -}; - -// NOTE: when sending a PokeArg to the child process, we handle the -// buffer specially -struct PokeArg { - DWORD address; - DWORD numBytes; - void* data; -}; - -// Used for continueevent -struct BoolArg { - bool val; -}; - -// Used for duphandle, closehandle, and getcontext -struct HandleArg { - HANDLE handle; -}; - -// Used for setcontext -const int NUM_REGS_IN_CONTEXT = 22; -struct SetContextArg { - HANDLE handle; - DWORD Eax; - DWORD Ebx; - DWORD Ecx; - DWORD Edx; - DWORD Esi; - DWORD Edi; - DWORD Ebp; - DWORD Esp; - DWORD Eip; - DWORD Ds; - DWORD Es; - DWORD Fs; - DWORD Gs; - DWORD Cs; - DWORD Ss; - DWORD EFlags; - DWORD Dr0; - DWORD Dr1; - DWORD Dr2; - DWORD Dr3; - DWORD Dr6; - DWORD Dr7; -}; - -// Used for selectorentry -struct SelectorEntryArg { - HANDLE handle; - DWORD selector; -}; - -struct Message { - typedef enum { - ATTACH, - DETACH, - LIBINFO, - PEEK, - POKE, - THREADLIST, - DUPHANDLE, - CLOSEHANDLE, - GETCONTEXT, - SETCONTEXT, - SELECTORENTRY, - SUSPEND, - RESUME, - POLLEVENT, - CONTINUEEVENT - } Type; - - Type type; - union { - PeekArg peekArg; - PokeArg pokeArg; - BoolArg boolArg; - HandleArg handleArg; - SetContextArg setContextArg; - SelectorEntryArg selectorArg; - }; -}; - -#endif // #defined _MESSAGE_ diff --git a/hotspot/agent/src/os/win32/Monitor.cpp b/hotspot/agent/src/os/win32/Monitor.cpp deleted file mode 100644 index 181c173bbb8..00000000000 --- a/hotspot/agent/src/os/win32/Monitor.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include -#include "Monitor.hpp" - -Monitor::Monitor() { - _lock_count = -1; // No threads have entered the critical section - _owner = NULL; - _lock_event = CreateEvent(NULL, false, false, NULL); - _wait_event = CreateEvent(NULL, true, false, NULL); - _counter = 0; - _tickets = 0; - _waiters = 0; -} - -Monitor::~Monitor() { - assert(_owner == NULL); // Otherwise, owned monitor being deleted - assert(_lock_count == -1); // Otherwise, monitor being deleted with non -1 lock count - CloseHandle(_lock_event); - CloseHandle(_wait_event); -} - -void -Monitor::lock() { - if (InterlockedIncrement(&_lock_count) == 0) { - // Success, we now own the lock - } else { - DWORD dwRet = WaitForSingleObject((HANDLE)_lock_event, INFINITE); - assert(dwRet == WAIT_OBJECT_0); // Unexpected return value from WaitForSingleObject - } - assert(owner() == NULL); // Otherwise, lock count and owner are inconsistent - setOwner(GetCurrentThread()); -} - -void -Monitor::unlock() { - setOwner(NULL); - if (InterlockedDecrement(&_lock_count) >= 0) { - // Wake a waiting thread up - DWORD dwRet = SetEvent(_lock_event); - assert(dwRet != 0); // Unexpected return value from SetEvent - } -} - -bool -Monitor::wait(long timeout) { - assert(owner() != NULL); - assert(owner() == GetCurrentThread()); - - // 0 means forever. Convert to Windows specific code. - DWORD timeout_value = (timeout == 0) ? INFINITE : timeout; - DWORD which; - - long c = _counter; - bool retry = false; - - _waiters++; - // Loop until condition variable is signaled. The event object is - // set whenever the condition variable is signaled, and tickets will - // reflect the number of threads which have been notified. The counter - // field is used to make sure we don't respond to notifications that - // have occurred *before* we started waiting, and is incremented each - // time the condition variable is signaled. - - while (true) { - - // Leave critical region - unlock(); - - // If this is a retry, let other low-priority threads have a chance - // to run. Make sure that we sleep outside of the critical section. - if (retry) { - Sleep(1); - } else { - retry = true; - } - - which = WaitForSingleObject(_wait_event, timeout_value); - // Enter critical section - lock(); - - if (_tickets != 0 && _counter != c) break; - - if (which == WAIT_TIMEOUT) { - --_waiters; - return true; - } - } - _waiters--; - - // If this was the last thread to be notified, then we need to reset - // the event object. - if (--_tickets == 0) { - ResetEvent(_wait_event); - } - - return false; -} - -// Notify a single thread waiting on this monitor -bool -Monitor::notify() { - assert(ownedBySelf()); // Otherwise, notify on unknown thread - - if (_waiters > _tickets) { - if (!SetEvent(_wait_event)) { - return false; - } - _tickets++; - _counter++; - } - - return true; -} - -// Notify all threads waiting on this monitor -bool -Monitor::notifyAll() { - assert(ownedBySelf()); // Otherwise, notifyAll on unknown thread - - if (_waiters > 0) { - if (!SetEvent(_wait_event)) { - return false; - } - _tickets = _waiters; - _counter++; - } - - return true; -} - -HANDLE -Monitor::owner() { - return _owner; -} - -void -Monitor::setOwner(HANDLE owner) { - if (owner != NULL) { - assert(_owner == NULL); // Setting owner thread of already owned monitor - assert(owner == GetCurrentThread()); // Else should not be doing this - } else { - HANDLE oldOwner = _owner; - assert(oldOwner != NULL); // Removing the owner thread of an unowned mutex - assert(oldOwner == GetCurrentThread()); - } - _owner = owner; -} - -bool -Monitor::ownedBySelf() { - return (_owner == GetCurrentThread()); -} diff --git a/hotspot/agent/src/os/win32/Monitor.hpp b/hotspot/agent/src/os/win32/Monitor.hpp deleted file mode 100644 index 1475f21ba0f..00000000000 --- a/hotspot/agent/src/os/win32/Monitor.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _MONITOR_ -#define _MONITOR_ - -#include - -class Monitor { -public: - Monitor(); - ~Monitor(); - - void lock(); - void unlock(); - // Default time is forever (i.e, zero). Returns true if it times-out, otherwise - // false. - bool wait(long timeout = 0); - bool notify(); - bool notifyAll(); - -private: - HANDLE owner(); - void setOwner(HANDLE owner); - bool ownedBySelf(); - - HANDLE _owner; - long _lock_count; - HANDLE _lock_event; // Auto-reset event for blocking in lock() - HANDLE _wait_event; // Manual-reset event for notifications - long _counter; // Current number of notifications - long _waiters; // Number of threads waiting for notification - long _tickets; // Number of waiters to be notified -}; - - -#endif // #defined _MONITOR_ diff --git a/hotspot/agent/src/os/win32/README-commands.txt b/hotspot/agent/src/os/win32/README-commands.txt deleted file mode 100644 index 0a1cb13a59f..00000000000 --- a/hotspot/agent/src/os/win32/README-commands.txt +++ /dev/null @@ -1,246 +0,0 @@ -This debug server uses a largely text-based protocol, except for -certain bulk data transfer operations. All text is in single-byte -US-ASCII except for the strings returned in "proclist". - -NOTE that the character '|' (vertical bar) is used as an escape -character to switch the incoming data stream to the debug server into -binary mode, so no text command may contain that character. - -Commands understood: - -ascii ::= - - Changes to ASCII mode. This affects all outgoing strings. At - startup the system is in unicode mode. - -unicode ::= - - Changes to UNICODE mode. This affects all outgoing strings. This - is the default mode upon startup. - -proclist ::= - [ []...]... - - Returns integer indicating number of processes to follow, followed - by (pid, name) pairs. Names are given by (charSize, numChars, - [char_t]...) tuples; charSize indicates the size of each character - in bytes, numChars the number of characters in the string, and - name the raw data for the string. Each individual character of the - string, if multi-byte, is transmitted in network byte order. - numChars and name are guaranteed to be separated by precisely one - US-ASCII space. If process list is not available because of - limitations of the underlying operating system, number of - processes returned is 0. - -attach ::= - - Attempts to attach to the specified process. Returns 1 if - successful, 0 if not. Will fail if already attached or if the - process ID does not exist. Attaching to a process causes the - process to be suspended. - -detach ::= - - Detaches from the given process. Attaching and detaching multiple - times during a debugging session is allowed. Detaching causes the - process to resume execution. - -libinfo ::= - [ []...
]... - - May only be called once attached and the target process must be - suspended; otherwise, returns 0. Returns list of the full path - names of all of the loaded modules (including the executable - image) in the target process, as well as the base address at which - each module was relocated. See proclist for format of strings, but - NOTE that charSize is ALWAYS 1 for this particular routine, - regardless of the setting of ASCII/UNICODE. - -peek
::= - B - [ []...]... - - NOTE that the binary portion of this message is prefixed by the - uppercase US-ASCII letter 'B', allowing easier synchronization by - clients. There is no data between the 'B' and the rest of the - message. - - May only be called once attached. Reads the address space of the - target process starting at the given address (see below for format - specifications) and extending the given number of bytes. Whether - the read succeeded is indicated by a single byte containing a 1 or - 0 (success or failure). If successful, the return result is given - in a sequence of ranges. _len_, the length of each range, is - indicated by a 32-bit unsigned integer transmitted with big-endian - byte ordering (i.e., most significant byte first). _isMapped_ - indicates whether the range is mapped or unmapped in the target - process's address space, and will contain the value 1 or 0 for - mapped or unmapped, respectively. If the range is mapped, - _isMapped_ is followed by _data_, containing the raw binary data - for the range. The sum of all ranges' lengths is guaranteed to be - equivalent to the number of bytes requested. - -poke
|[ []] ::= - - - NOTE that the binary portion of this message is prefixed by the - uppercase US-ASCII character '|' (vertical bar), allowing easier - synchronization by the server. There is no data between the '|' - and the rest of the message. ('B' is not used here because - addresses can contain that letter; no alphanumeric characters are - used because some of the parsing routines are used by the Solaris - SA port, and in that port any alphanumeric character can show up - as a part of a symbol being looked up.) - - May only be called once attached. Writes the address space of the - target process starting at the given address (see below for format - specifications), extending the given number of bytes, and - containing the given data. The number of bytes is a 32-bit - unsigned integer transmitted with big-endian byte ordering (i.e., - most significant byte first). This is followed by the raw binary - data to be placed at that address. The number of bytes of data - must match the number of bytes specified in the message. - - Returns true if the write succeeded; false if it failed, for - example because a portion of the region was not mapped in the - target address space. - -threadlist ::= [
...] - - May only be called once attached and the target process must be - suspended; otherwise, returns 0. If available, returns handles for - all of the threads in the target process. These handles may be - used as arguments to the getcontext and selectorentry - commands. They do not need to be (and should not be) duplicated - via the duphandle command and must not be closed via the - closehandle command. - -duphandle
::= - [
] - - Duplicates a HANDLE read from the target process's address space. - HANDLE is a Windows construct (typically typedef'd to void *). - The returned handle should ultimately be closed via the - closehandle command; failing to do so can cause resource leaks. - - The purpose of this command is to allow the debugger to read the - value of a thread handle from the target process and query its - register set and thread selector entries via the getcontext and - selectorentry commands, below; such use implies that the target - program has its own notion of the thread list, and further, that - the debugger has a way of locating that thread list. - -closehandle
::= - - Closes a handle retrieved via the duphandle command, above. - -getcontext
::= [] - - Returns the context for the given thread. The handle must either - be one of the handles returned from the threadlist command or the - result of duplicating a thread handle out of the target process - via the duphandle command. The target process must be suspended. - - The context is returned as a series of hex values which represent - the following x86 registers in the following order: - EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, DS, ES, FS, GS, - CS, SS, EFLAGS, DR0, DR1, DR2, DR3, DR6, DR7 - - FIXME: needs to be generalized and/or specified for other - architectures. - -setcontext
::= - - Sets the context of the given thread. The target process must be - suspended. See the getcontext command for the ordering of the - registers in the context. - - Even if the setcontext command succeeds, some of the bits in some - of the registers (like the global enable bits in the debug - registers) may be overridden by the operating system. To ensure - the debugger's notion of the register set is up to date, it is - recommended to follow up a setcontext with a getcontext. - -selectorentry
::= - - [
-
-
] - - Retrieves a descriptor table entry for the given thread and - selector. This data structure allows conversion of a - segment-relative address to a linear virtual address. It is most - useful for locating the Thread Information Block for a given - thread handle to be able to find that thread's ID, to be able to - understand whether two different thread handles in fact refer to - the same underlying thread. - - This command will only work on the X86 architecture and will - return false for the success flag (with no additional information - sent) on other architectures. - -suspend ::= - - Suspends the target process. Must be attached to a target process. - A process is suspended when attached to via the attach command. If - the target process is already suspended then this command has no - effect. - -resume ::= - - Resumes the target process without detaching from it. Must be - attached to a target process. After resuming a target process, the - debugger client must be prepared to poll for events from the - target process fairly frequently in order for execution in the - target process to proceed normally. If the target process is - already resumed then this command has no effect. - -pollevent ::= - [
] - - Additional entries in result for given eventCode: - - LOAD/UNLOAD_DLL_DEBUG_EVENT:
- EXCEPTION_DEBUG_EVENT:
- - Additional entries for given exceptionCode: - - EXCEPTION_ACCESS_VIOLATION:
- - - - Polls once to see whether a debug event has been generated by the - target process. If none is present, returns 0 immediately. - Otherwise, returns 1 along with a series of textual information - about the event. The event is not cleared, and the thread resumed, - until the continueevent command is sent, or the debugger client - detaches from the target process. - - Typically a debugger client will suspend the target process upon - reception of a debug event. Otherwise, it is not guaranteed that - all threads will be suspended upon reception of a debug event, and - any operations requiring that threads be suspended (including - fetching the context for the thread which generated the event) - will fail. - -continueevent ::= - - Indicates that the current debug event has been used by the - debugger client and that the target process should be resumed. The - passEventToClient flag indicates whether the event should be - propagated to the target process. Breakpoint and single-step - events should not be propagated to the target. Returns false if - there was no pending event, true otherwise. - -exit - - Exits this debugger session. - -Format specifications: - -// Data formats and example values: - ::= end of line (typically \n on Unix platforms, or \n\r on Windows) -
::= 0x12345678[9ABCDEF0] /* up to 64-bit hex value */ - ::= 5 /* up to 32-bit integer number; no leading sign */ - ::= 1 /* ASCII '0' or '1' */ - ::=
... diff --git a/hotspot/agent/src/os/win32/README.txt b/hotspot/agent/src/os/win32/README.txt deleted file mode 100644 index e470b471bef..00000000000 --- a/hotspot/agent/src/os/win32/README.txt +++ /dev/null @@ -1,64 +0,0 @@ -This is a "Simple Windows Debug Server" written for the purpose of -enabling the Serviceability Agent on Win32. It has backends both for -Windows NT 4.0 (using internal Windows APIs for a few routines) as -well as for 95/98/ME/2000 via the Tool Help APIs. - -The reason this debug server is necessary is that the Win32 debug APIs -by design tear down the target process when the debugger exits (see -knowledge base article Q164205 on msdn.microsoft.com). On Solaris, one -can attach to and detach from a process with no effect; this is key to -allowing dbx and gcore to work. - -The Simple Windows Debug Server effectively implements attach/detach -functionality for arbitrary debug clients. This allows the SA to -attach non-destructively to a process, and will enable gcore for Win32 -to be written shortly. While the debugger (the "client" in all of the -source code) is attached, the target process is suspended. (Note that -the debug server could be extended to support resumption of the target -process and transmission of debug events over to the debugger, but -this has been left for the future.) - -The makefile (type "nmake") builds two executables: SwDbgSrv.exe, -which is the server process, and SwDbgSub.exe, which is forked by the -server and should not be directly invoked by the user. - -The intent is that these two executables can be installed into -C:\WINNT\SYSTEM32 and SwDbgSrv installed to run as a service (on NT), -for example using ServiceInstaller (http://www.kcmultimedia.com/smaster/). -However, SwDbgSrv can also be run from the command line. It generates -no text output unless the source code is changed to enable debugging -printouts. As long as any processes which have been attached to by the -SA are alive, the SwDbgSrv and any forked SwDbgSub processes must be -left running. Terminating them will cause termination of the target -processes. - -The debug server opens port 27000 and accepts incoming connections -from localhost only. The security model assumes that if one can run a -process on the given machine then one basically has access to most or -all of the machine's facilities; this seems to be in line with the -standard Windows security model. The protocol used is text-based, so -one can debug the debug server using telnet. See README-commands.txt -for documentation on the supported commands. - -Testing indicates that the performance impact of attaching to a -process (and therefore permanently attaching a debugger) is minimal. -Some serious performance problems had been seen which ultimately -appeared to be a lack of physical memory on the machine running the -system. - -Bugs: - -This debug server is fundamentally incompatible with the Visual C++ -debugger. Once the debug server is used to attach to a process, the -Visual C++ IDE will not be able to attach to the same process (even if -the debug server is "detached" from that process). Note that this -system is designed to work with the same primitives that C and C++ -debuggers use (like "symbol lookup" and "read from process memory") -and exposes these primitives to Java, so in the long term we could -solve this problem by implementing platform-specific debug symbol -parsing and a platform-independent C++ debugger in Java. - -Note: - -The files IOBuf.cpp and IOBuf.hpp are also used in -building src/os/solaris/agent. diff --git a/hotspot/agent/src/os/win32/Reaper.cpp b/hotspot/agent/src/os/win32/Reaper.cpp deleted file mode 100644 index 13726c55eb7..00000000000 --- a/hotspot/agent/src/os/win32/Reaper.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include "Reaper.hpp" - -using namespace std; - -Reaper::Reaper(ReaperCB* cb) { - InitializeCriticalSection(&crit); - event = CreateEvent(NULL, TRUE, FALSE, NULL); - this->cb = cb; - - active = false; - shouldShutDown = false; -} - -bool -Reaper::start() { - bool result = false; - - EnterCriticalSection(&crit); - - if (!active) { - DWORD id; - HANDLE reaper = CreateThread(NULL, 0, &Reaper::reaperThreadEntry, - this, 0, &id); - if (reaper != NULL) { - result = true; - } - } - - LeaveCriticalSection(&crit); - - return result; -} - -bool -Reaper::stop() { - bool result = false; - - EnterCriticalSection(&crit); - - if (active) { - shouldShutDown = true; - SetEvent(event); - while (active) { - Sleep(1); - } - shouldShutDown = false; - result = true; - } - - LeaveCriticalSection(&crit); - - return result; -} - -void -Reaper::registerProcess(HANDLE processHandle, void* userData) { - ProcessInfo info; - - info.handle = processHandle; - info.userData = userData; - - EnterCriticalSection(&crit); - - procInfo.push_back(info); - SetEvent(event); - - LeaveCriticalSection(&crit); -} - -void -Reaper::reaperThread() { - while (!shouldShutDown) { - // Take atomic snapshot of the current process list and user data - EnterCriticalSection(&crit); - - int num = procInfo.size(); - HANDLE* handleList = new HANDLE[1 + num]; - void** dataList = new void*[num]; - for (int i = 0; i < num; i++) { - handleList[i] = procInfo[i].handle; - dataList[i] = procInfo[i].userData; - } - - LeaveCriticalSection(&crit); - - // Topmost handle becomes the event object, so other threads can - // signal this one to notice differences in the above list (or - // shut down) - handleList[num] = event; - - // Wait for these objects - DWORD idx = WaitForMultipleObjects(1 + num, handleList, - FALSE, INFINITE); - if ((idx >= WAIT_OBJECT_0) && (idx <= WAIT_OBJECT_0 + num)) { - idx -= WAIT_OBJECT_0; - if (idx < num) { - // A process exited (i.e., it wasn't that we were woken up - // just because the event went off) - (*cb)(dataList[idx]); - // Remove this process from the list (NOTE: requires that - // ordering does not change, i.e., that all additions are to - // the back of the process list) - EnterCriticalSection(&crit); - - std::vector::iterator iter = procInfo.begin(); - iter += idx; - procInfo.erase(iter); - - LeaveCriticalSection(&crit); - } else { - // Notification from other thread - ResetEvent(event); - } - } else { - // Unexpected return value. For now, warn. - cerr << "Reaper::reaperThread(): unexpected return value " - << idx << " from WaitForMultipleObjects" << endl; - } - - // Clean up these lists - delete[] handleList; - delete[] dataList; - } - - // Time to shut down - active = false; -} - -DWORD WINAPI -Reaper::reaperThreadEntry(LPVOID data) { - Reaper* reaper = (Reaper*) data; - reaper->reaperThread(); - return 0; -} diff --git a/hotspot/agent/src/os/win32/Reaper.hpp b/hotspot/agent/src/os/win32/Reaper.hpp deleted file mode 100644 index bee02192a1d..00000000000 --- a/hotspot/agent/src/os/win32/Reaper.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _REAPER_ -#define _REAPER_ - -#include -#include - -typedef void ReaperCB(void* userData); - -/** A Reaper maintains a thread which waits for child processes to - terminate; upon termination it calls a user-specified ReaperCB to - clean up resources associated with those child processes. */ - -class Reaper { -private: - Reaper& operator=(const Reaper&); - Reaper(const Reaper&); - -public: - Reaper(ReaperCB*); - ~Reaper(); - - // Start the reaper thread. - bool start(); - - // Stop the reaper thread. This is called automatically in the - // reaper's destructor. It is not thread safe and should be called - // by at most one thread at a time. - bool stop(); - - // Register a given child process with the reaper. This should be - // called by the application's main thread. When that process - // terminates, the cleanup callback will be called with the - // specified userData in the context of the reaper thread. Callbacks - // are guaranteed to be called serially, so they can safely refer to - // static data as well as the given user data. - void registerProcess(HANDLE processHandle, void* userData); - -private: - // For thread safety of register() - CRITICAL_SECTION crit; - - ReaperCB* cb; - - // State variables - volatile bool active; - volatile bool shouldShutDown; - - struct ProcessInfo { - HANDLE handle; - void* userData; - }; - - // Bookkeeping - std::vector procInfo; - - // Synchronization between application thread and reaper thread - HANDLE event; - - // Entry point for reaper thread - void reaperThread(); - - // Static function which is actual thread entry point - static DWORD WINAPI reaperThreadEntry(LPVOID data); -}; - -#endif // #defined _REAPER_ diff --git a/hotspot/agent/src/os/win32/SwDbgSrv.cpp b/hotspot/agent/src/os/win32/SwDbgSrv.cpp deleted file mode 100644 index 7f49bae3e99..00000000000 --- a/hotspot/agent/src/os/win32/SwDbgSrv.cpp +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -// A Simple Windows Debug Server. -// -// This software provides a socket-based debug server which uses -// mostly ASCII protocols to communicate with its clients. Since the -// Windows security model is largely based around being able to run -// programs on the machine, this server only accepts connections -// coming from localhost. -// -// When run as a service (under Windows NT), this software provides -// clients the ability to attach to and detach from processes without -// killing those processes. Ordinarily this is forbidden by the -// Windows debugging APIs (although more recent debugging environments -// from Microsoft seem to have circumvented this restriction, perhaps -// in a different way). This is achieved by forking a persistent -// subprocess for each debugging session which remains alive as long -// as the target process is. -// -// At this point the client can read information out of the target -// process's address space. Future work includes exposing more -// functionality like writing to the remote address space and -// suspending and resuming threads. - -#include -#include -#include -// Must come before everything else -#include -#include -#include "Dispatcher.hpp" -#include "Handler.hpp" -#include "initWinsock.hpp" -#include "ioUtils.hpp" -#include "isNT4.hpp" -#include "Message.hpp" -#include "nt4internals.hpp" -#include "ports.h" -#include "procList.hpp" -#include "serverLists.hpp" -#include "Reaper.hpp" - -// Uncomment the #define below to get messages on stderr -// #define DEBUGGING - -using namespace std; - -static ChildList childList; -static ClientList clientList; -static Reaper* reaper = NULL; - -// Needed prototypes -void shutdownChild(ChildInfo* childInfo); -void detachClient(ClientInfo* clientInfo); -void shutdownClient(ClientInfo* clientInfo); - -char * -longToDotFormat(long addr) -{ - char *temp_s = new char[20]; - - sprintf(temp_s, "%d.%d.%d.%d", ((addr & 0xff000000) >> 24), - ((addr & 0x00ff0000) >> 16), ((addr & 0x0000ff00) >> 8), - (addr & 0x000000ff)); - - return temp_s; -} - -// NOTE that we do this query every time. It is a bad idea to cache IP -// addresses. For example, we might be hosted on a machine using DHCP -// and the connection addresses might change over time. (Yes, this -// actually happened.) -bool -isConnectionOkay(ULONG connAddr) { - if (connAddr == INADDR_LOOPBACK) { - return true; - } - - const int MAXNAME = 1024; - char myname[MAXNAME]; - gethostname(myname, MAXNAME); - struct hostent* myInfo = gethostbyname(myname); - if (myInfo == NULL) { -#ifdef DEBUGGING - cerr << "My host information was null" << endl; -#endif - } else { - // Run down the list of IP addresses for myself - assert(myInfo->h_length == sizeof(ULONG)); -#ifdef DEBUGGING - cerr << "My known IP addresses: " << endl; -#endif - for (char** pp = myInfo->h_addr_list; *pp != NULL; pp++) { - char* p = *pp; - ULONG altAddr = ntohl(*((ULONG*) p)); -#ifdef DEBUGGING - char* name = longToDotFormat(altAddr); - cerr << name << endl; - delete[] name; -#endif - if (altAddr == connAddr) { -#ifdef DEBUGGING - cerr << "FOUND" << endl; -#endif - return true; - } - } -#ifdef DEBUGGING - cerr << "Done." << endl; -#endif - } - - return false; -} - -SOCKET -setupListeningSocket(short port) { - SOCKET listening = socket(AF_INET, SOCK_STREAM, 0); - if (listening == INVALID_SOCKET) { - cerr << "Error creating listening socket" << endl; - exit(1); - } - - int reuseAddress = 1; - if (setsockopt(listening, SOL_SOCKET, SO_REUSEADDR, - (char *)&reuseAddress, sizeof(reuseAddress)) == -1) { - cerr << "Error reusing address" << endl; - exit(1); - } - - struct sockaddr_in serverInfo; - - memset((char *)&serverInfo, 0, sizeof(serverInfo)); - serverInfo.sin_addr.s_addr = INADDR_ANY; - serverInfo.sin_family = AF_INET; - serverInfo.sin_port = htons(port); - - if (bind(listening, (struct sockaddr *) &serverInfo, sizeof(serverInfo)) < 0) { - cerr << "Error binding socket" << endl; - exit(1); - } - - if (listen(listening, 5) < 0) { - cerr << "Error listening" << endl; - exit(1); - } - - return listening; -} - -/** Accepts a connection from the given listening socket, but only if - the connection came from localhost. Returns INVALID_SOCKET if the - connection came from any other IP address or if an error occurred - during the call to accept(). */ -SOCKET -acceptFromLocalhost(SOCKET listening) { - struct sockaddr_in peerAddr; - int peerAddrLen = sizeof(peerAddr); - SOCKET fd = accept(listening, (sockaddr*) &peerAddr, &peerAddrLen); - if (fd == INVALID_SOCKET) { - return fd; - } - - if (!isConnectionOkay(ntohl(peerAddr.sin_addr.s_addr))) { - // Reject connections from other machines for security purposes. - // The Windows security model seems to assume one user per - // machine, and that security is compromised if another user is - // able to run executables on the given host. (If these - // assumptions are not strict enough, we will have to change - // this.) - shutdown(fd, SD_BOTH); - closesocket(fd); - return INVALID_SOCKET; - } - - // Disable TCP buffering on all sockets. We send small amounts of - // data back and forth and don't want buffering. - int buffer_val = 1; - if (setsockopt(fd, IPPROTO_IP, TCP_NODELAY, - (char *) &buffer_val, sizeof(buffer_val)) < 0) { - shutdown(fd, SD_BOTH); - closesocket(fd); - } - - return fd; -} - -void -reapCB(void* arg) { - ChildInfo* info = (ChildInfo*) arg; - ListsLocker ll; - DWORD pid = info->getPid(); - shutdownChild(info); -#ifdef DEBUGGING - cerr << "Reaped child for process " << pid << endl; -#endif -} - -/** Starts a child process with stdin and stdout redirected to pipes, - handles to which are returned. auxHandle1 and auxHandle2 should be - closed as well when the child process exits. Returns false if - process creation failed. */ -bool -startChildProcess(DWORD pidToDebug, - DWORD childStdinBufSize, - DWORD childStdoutBufSize, - LPHANDLE childProcessHandle, - LPHANDLE writeToStdinHandle, - LPHANDLE readFromStdoutHandle, - LPHANDLE auxHandle1, - LPHANDLE auxHandle2) { - // Code adapted from Microsoft example - // "Creating a Child Process with Redirected Input and Output" - - SECURITY_ATTRIBUTES saAttr; - BOOL fSuccess; - - HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, - hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, - hSaveStdin, hSaveStdout; - - // Set the bInheritHandle flag so pipe handles are inherited. - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - // The steps for redirecting child process's STDOUT: - // 1. Save current STDOUT, to be restored later. - // 2. Create anonymous pipe to be STDOUT for child process. - // 3. Set STDOUT of the parent process to be write handle to - // the pipe, so it is inherited by the child process. - // 4. Create a noninheritable duplicate of the read handle and - // close the inheritable read handle. - - // Save the handle to the current STDOUT. - hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); - // Create a pipe for the child process's STDOUT. - if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, childStdoutBufSize)) { - return false; - } - // Set a write handle to the pipe to be STDOUT. - if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) { - return false; - } - // Create noninheritable read handle and close the inheritable read - // handle. - fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, - GetCurrentProcess(), &hChildStdoutRdDup, - 0, FALSE, - DUPLICATE_SAME_ACCESS); - if( !fSuccess ) { - return false; - } - CloseHandle(hChildStdoutRd); - - // The steps for redirecting child process's STDIN: - // 1. Save current STDIN, to be restored later. - // 2. Create anonymous pipe to be STDIN for child process. - // 3. Set STDIN of the parent to be the read handle to the - // pipe, so it is inherited by the child process. - // 4. Create a noninheritable duplicate of the write handle, - // and close the inheritable write handle. - // Save the handle to the current STDIN. - hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); - // Create a pipe for the child process's STDIN. - if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, childStdinBufSize)) { - return false; - } - // Set a read handle to the pipe to be STDIN. - if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) { - return false; - } - // Duplicate the write handle to the pipe so it is not inherited. - fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, - GetCurrentProcess(), &hChildStdinWrDup, 0, - FALSE, // not inherited - DUPLICATE_SAME_ACCESS); - if (! fSuccess) { - return false; - } - CloseHandle(hChildStdinWr); - - // Create the child process - char cmdLine[256]; - sprintf(cmdLine, "SwDbgSub.exe %u", pidToDebug); - PROCESS_INFORMATION procInfo; - STARTUPINFO startInfo; - memset((char*) &startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); - BOOL res = CreateProcess(NULL, - cmdLine, - NULL, - NULL, - TRUE, // inherit handles: important - 0, - NULL, - NULL, - &startInfo, - &procInfo); - if (!res) { - return false; - } - // After process creation, restore the saved STDIN and STDOUT. - if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) { - return false; - } - if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) { - return false; - } - - // hChildStdinWrDup can be used to write to the child's stdin - // hChildStdoutRdDup can be used to read from the child's stdout - - // NOTE: example code closes hChildStdoutWr before reading from - // hChildStdoutRdDup. "Close the write end of the pipe before - // reading from the read end of the pipe"??? Looks like this is - // example-specific. - - // Set up return arguments - // hChildStdoutRd and hChildStdinWr are already closed at this point - *childProcessHandle = procInfo.hProcess; - *writeToStdinHandle = hChildStdinWrDup; - *readFromStdoutHandle = hChildStdoutRdDup; - *auxHandle1 = hChildStdinRd; - *auxHandle2 = hChildStdoutWr; - return true; -} - -/** Clears the event and writes the message to the child process */ -bool -sendMessage(ChildInfo* child, Message* message) { - DWORD numBytesWritten; - if (!WriteFile(child->getWriteToStdinHandle(), - message, sizeof(Message), &numBytesWritten, NULL)) { - return false; - } - if (numBytesWritten != sizeof(Message)) { - return false; - } - // Follow up "poke" messages with the raw data - if (message->type == Message::POKE) { - if (!WriteFile(child->getWriteToStdinHandle(), - message->pokeArg.data, message->pokeArg.numBytes, &numBytesWritten, NULL)) { - return false; - } - if (numBytesWritten != message->pokeArg.numBytes) { - return false; - } - } - return true; -} - -/** Copies data from child's stdout to the client's IOBuf and sends it - along */ -bool -forwardReplyToClient(ChildInfo* child, ClientInfo* client) { - DWORD total = 0; - IOBuf::FillState ret; - - do { - DWORD temp; - ret = client->getIOBuf()->fillFromFileHandle(child->getReadFromStdoutHandle(), - &temp); - if (ret == IOBuf::DONE || ret == IOBuf::MORE_DATA_PENDING) { - if (!client->getIOBuf()->flush()) { -#ifdef DEBUGGING - cerr << "Forward failed because flush failed" << endl; -#endif - return false; - } - total += temp; - } - } while (ret == IOBuf::MORE_DATA_PENDING); - - return (ret == IOBuf::FAILED) ? false : true; -} - -//---------------------------------------------------------------------- -// Server Handler -// - -class ServerHandler : public Handler { -public: - ServerHandler(); - - // Starts up in Unicode mode by default - bool getASCII(); - - void setIOBuf(IOBuf* ioBuf); - - void procList(char* arg); - - // Must be called before calling one of the routines below - void setClientInfo(ClientInfo* info); - - // Indicates to outer loop that exit was called or that an error - // occurred and that the client exited. - bool exited(); - // Clears this state - void clearExited(); - - void ascii(char* arg); - void unicode(char* arg); - void attach(char* arg); - void detach(char* arg); - void libInfo(char* arg); - void peek(char* arg); - void poke(char* arg); - void threadList(char* arg); - void dupHandle(char* arg); - void closeHandle(char* arg); - void getContext(char* arg); - void setContext(char* arg); - void selectorEntry(char* arg); - void suspend(char* arg); - void resume(char* arg); - void pollEvent(char* arg); - void continueEvent(char* arg); - void exit(char* arg); - - // This is pretty gross. Needed to make the target process know - // about clients that have disconnected unexpectedly while attached. - friend void shutdownClient(ClientInfo*); -private: - // Writes: charSize numChars - // Handles both ASCII and UNICODE modes - void writeString(USHORT len, WCHAR* str); - - // Handles only ASCII mode - void writeString(USHORT len, char* str); - - ClientInfo* clientInfo; - IOBuf* ioBuf; - bool _exited; - bool _ascii; -}; - -static ServerHandler* handler; - -ServerHandler::ServerHandler() { - _exited = false; - _ascii = false; - ioBuf = NULL; -} - -bool -ServerHandler::getASCII() { - return _ascii; -} - -void -ServerHandler::setIOBuf(IOBuf* buf) { - ioBuf = buf; -} - -void -ServerHandler::setClientInfo(ClientInfo* info) { - clientInfo = info; -} - -bool -ServerHandler::exited() { - return _exited; -} - -void -ServerHandler::clearExited() { - _exited = false; -} - -void -ServerHandler::ascii(char* arg) { - _ascii = true; -} - -void -ServerHandler::unicode(char* arg) { - _ascii = false; -} - -void -ServerHandler::procList(char* arg) { -#ifdef DEBUGGING - cerr << "proclist" << endl; -#endif - - ProcEntryList processes; - ::procList(processes); - - ioBuf->writeInt(processes.size()); - - for (ProcEntryList::iterator iter = processes.begin(); - iter != processes.end(); iter++) { - ProcEntry& entry = *iter; - ioBuf->writeSpace(); - ioBuf->writeUnsignedInt(entry.getPid()); - ioBuf->writeSpace(); - writeString(entry.getNameLength(), entry.getName()); - } - - ioBuf->writeEOL(); - ioBuf->flush(); -} - -void -ServerHandler::attach(char* arg) { - // If the client is already attached to a process, fail. - if (clientInfo->getTarget() != NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - // Try to get pid - DWORD pid; - if (!scanUnsignedLong(&arg, &pid)) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - // See whether this pid is already forked - ListsLocker ll; - ChildInfo* childInfo = childList.getChildByPid(pid); - if (childInfo != NULL) { - // If this child already has a client, return false - if (childInfo->getClient() != NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - // Otherwise, can associate this client with this child process - childInfo->setClient(clientInfo); - clientInfo->setTarget(childInfo); - - // Tell the child we are attaching so it can suspend the target - // process - Message msg; - msg.type = Message::ATTACH; - sendMessage(childInfo, &msg); - - ioBuf->writeBoolAsInt(true); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } else { - // Have to fork a new child subprocess - HANDLE childProcessHandle; - HANDLE writeToStdinHandle; - HANDLE readFromStdoutHandle; - HANDLE auxHandle1; - HANDLE auxHandle2; - if (!startChildProcess(pid, - 32768, - 131072, - &childProcessHandle, - &writeToStdinHandle, - &readFromStdoutHandle, - &auxHandle1, - &auxHandle2)) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - // See whether the child succeeded in attaching to the process - char res; - DWORD numRead; - if (!ReadFile(readFromStdoutHandle, - &res, - sizeof(char), - &numRead, - NULL)) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - if (!res) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - // OK, success. - childInfo = new ChildInfo(pid, childProcessHandle, - writeToStdinHandle, readFromStdoutHandle, - auxHandle1, auxHandle2); - childList.addChild(childInfo); - reaper->registerProcess(childProcessHandle, childInfo); - // Associate this client with this child process - childInfo->setClient(clientInfo); - clientInfo->setTarget(childInfo); - - // Tell the child process to actually suspend the target process - Message msg; - msg.type = Message::ATTACH; - sendMessage(childInfo, &msg); - - // Write result to client - ioBuf->writeBoolAsInt(true); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } -} - -void -ServerHandler::detach(char* arg) { - // If the client is not attached, fail. - if (clientInfo->getTarget() == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - detachClient(clientInfo); - - ioBuf->writeBoolAsInt(true); - ioBuf->writeEOL(); - ioBuf->flush(); -} - -void -ServerHandler::libInfo(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeInt(0); - ioBuf->writeEOL(); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::LIBINFO; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::peek(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeString("B"); - ioBuf->writeBinChar(0); - ioBuf->flush(); - return; - } - - // Try to get address - DWORD address; - if (!scanAddress(&arg, &address)) { - ioBuf->writeString("B"); - ioBuf->writeBinChar(0); - ioBuf->flush(); - return; - } - - // Try to get number of bytes - DWORD numBytes; - if (!scanUnsignedLong(&arg, &numBytes)) { - ioBuf->writeString("B"); - ioBuf->writeBinChar(0); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::PEEK; - msg.peekArg.address = address; - msg.peekArg.numBytes = numBytes; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::poke(char* arg) { -#ifdef DEBUGGING - cerr << "ServerHandler::poke" << endl; -#endif - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get address - DWORD address; - if (!scanAddress(&arg, &address)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get number of bytes - if (!scanAndSkipBinEscapeChar(&arg)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - DWORD numBytes; - if (!scanBinUnsignedLong(&arg, &numBytes)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Raw data is now in "arg" - // Send message to child - Message msg; - msg.type = Message::POKE; - msg.pokeArg.address = address; - msg.pokeArg.numBytes = numBytes; - msg.pokeArg.data = arg; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::threadList(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::THREADLIST; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::dupHandle(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get handle - DWORD address; - if (!scanAddress(&arg, &address)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - } - - // Send message to child - Message msg; - msg.type = Message::DUPHANDLE; - msg.handleArg.handle = (HANDLE) address; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::closeHandle(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - return; - } - - // Try to get handle - DWORD address; - if (!scanAddress(&arg, &address)) { - return; - } - - // Send message to child - Message msg; - msg.type = Message::CLOSEHANDLE; - msg.handleArg.handle = (HANDLE) address; - sendMessage(child, &msg); - - // No reply -} - -void -ServerHandler::getContext(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get handle - DWORD address; - if (!scanAddress(&arg, &address)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::GETCONTEXT; - msg.handleArg.handle = (HANDLE) address; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::setContext(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get handle - DWORD address; - if (!scanAddress(&arg, &address)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get context - DWORD regs[NUM_REGS_IN_CONTEXT]; - for (int i = 0; i < NUM_REGS_IN_CONTEXT; i++) { - if (!scanAddress(&arg, ®s[i])) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - } - - // Send message to child - Message msg; - msg.type = Message::SETCONTEXT; - msg.setContextArg.handle = (HANDLE) address; - msg.setContextArg.Eax = regs[0]; - msg.setContextArg.Ebx = regs[1]; - msg.setContextArg.Ecx = regs[2]; - msg.setContextArg.Edx = regs[3]; - msg.setContextArg.Esi = regs[4]; - msg.setContextArg.Edi = regs[5]; - msg.setContextArg.Ebp = regs[6]; - msg.setContextArg.Esp = regs[7]; - msg.setContextArg.Eip = regs[8]; - msg.setContextArg.Ds = regs[9]; - msg.setContextArg.Es = regs[10]; - msg.setContextArg.Fs = regs[11]; - msg.setContextArg.Gs = regs[12]; - msg.setContextArg.Cs = regs[13]; - msg.setContextArg.Ss = regs[14]; - msg.setContextArg.EFlags = regs[15]; - msg.setContextArg.Dr0 = regs[16]; - msg.setContextArg.Dr1 = regs[17]; - msg.setContextArg.Dr2 = regs[18]; - msg.setContextArg.Dr3 = regs[19]; - msg.setContextArg.Dr6 = regs[20]; - msg.setContextArg.Dr7 = regs[21]; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::selectorEntry(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get thread handle - DWORD address; - if (!scanAddress(&arg, &address)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get selector - DWORD selector; - if (!scanUnsignedLong(&arg, &selector)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::SELECTORENTRY; - msg.selectorArg.handle = (HANDLE) address; - msg.selectorArg.selector = selector; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::suspend(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - return; - } - - // Send message to child - Message msg; - msg.type = Message::SUSPEND; - sendMessage(child, &msg); - - // No reply -} - -void -ServerHandler::resume(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - return; - } - - // Send message to child - Message msg; - msg.type = Message::RESUME; - sendMessage(child, &msg); - - // No reply -} - -void -ServerHandler::pollEvent(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::POLLEVENT; - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::continueEvent(char* arg) { - ListsLocker ll; - ChildInfo* child = clientInfo->getTarget(); - if (child == NULL) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Try to get bool arg - int passEventToClient; - if (!scanInt(&arg, &passEventToClient)) { - ioBuf->writeBoolAsInt(false); - ioBuf->flush(); - return; - } - - // Send message to child - Message msg; - msg.type = Message::CONTINUEEVENT; - msg.boolArg.val = ((passEventToClient != 0) ? true : false); - sendMessage(child, &msg); - - // Forward reply to client - forwardReplyToClient(child, clientInfo); -} - -void -ServerHandler::exit(char* arg) { - shutdownClient(clientInfo); - _exited = true; -} - -void -ServerHandler::writeString(USHORT len, WCHAR* str) { - if (_ascii) { - char* cStr = new char[len + 1]; - sprintf(cStr, "%.*ls", len, str); - writeString(len, cStr); - delete[] cStr; - } else { - ioBuf->writeInt(sizeof(unsigned short)); - ioBuf->writeSpace(); - ioBuf->writeInt(len); - ioBuf->writeSpace(); - for (int i = 0; i < len; i++) { - ioBuf->writeBinUnsignedShort(str[i]); - } - } -} - -void -ServerHandler::writeString(USHORT len, char* str) { - ioBuf->writeInt(1); - ioBuf->writeSpace(); - ioBuf->writeInt(len); - ioBuf->writeSpace(); - ioBuf->writeString(str); -} - -// -//---------------------------------------------------------------------- - -//---------------------------------------------------------------------- -// Shutdown routines -// - -void -shutdownChild(ChildInfo* childInfo) { - childList.removeChild(childInfo); - childInfo->closeAll(); - if (childInfo->getClient() != NULL) { - shutdownClient(childInfo->getClient()); - } - delete childInfo; -} - -void -detachClient(ClientInfo* info) { - ListsLocker ll; - // May have been dissociated while not under cover of lock - if (info->getTarget() == NULL) { - return; - } - - // Tell the child that we have detached to let the target process - // continue running - Message msg; - msg.type = Message::DETACH; - sendMessage(info->getTarget(), &msg); - - // Dissociate the client and the target - info->getTarget()->setClient(NULL); - info->setTarget(NULL); -} - -void -shutdownClient(ClientInfo* clientInfo) { -#ifdef DEBUGGING - cerr << "Shutting down client" << endl; -#endif - - // If we're connected, inform the target process that we're - // disconnecting - detachClient(clientInfo); - - // Remove this client from the list and delete it - clientList.removeClient(clientInfo); - if (clientInfo->getTarget() != NULL) { - clientInfo->getTarget()->setClient(NULL); - } - clientInfo->closeAll(); - delete clientInfo; -} - -// -//---------------------------------------------------------------------- - - -/** Main dispatcher for client commands. NOTE: do not refer to this - clientInfo data structure after calling this routine, as it may be - deleted internally. */ -void -readAndDispatch(ClientInfo* clientInfo) { - IOBuf::ReadLineResult res; - IOBuf* ioBuf = clientInfo->getIOBuf(); - unsigned long howMany; - ioctlsocket(clientInfo->getDataSocket(), FIONREAD, &howMany); - if (howMany == 0) { - // Client closed down. - shutdownClient(clientInfo); - return; - } - // Read and process as much data as possible - do { - res = ioBuf->tryReadLine(); - if (res == IOBuf::RL_ERROR) { -#ifdef DEBUGGING - cerr << "Error while reading line" << endl; -#endif - shutdownClient(clientInfo); - return; - } else if (res == IOBuf::RL_GOT_DATA) { -#ifdef DEBUGGING - cerr << "Got data: \"" << ioBuf->getLine() << "\"" << endl; -#endif - handler->setIOBuf(ioBuf); - handler->setClientInfo(clientInfo); - handler->clearExited(); - Dispatcher::dispatch(ioBuf->getLine(), handler); - } - } while (res == IOBuf::RL_GOT_DATA && (!handler->exited())); -#ifdef DEBUGGING - cerr << "Exiting readAndDispatch" << endl; -#endif -} - -int -main(int argc, char **argv) -{ - initWinsock(); - - if (isNT4()) { - loadPSAPIDLL(); // Will exit if not present - } - - SOCKET clientListeningSock = setupListeningSocket(CLIENT_PORT); - - handler = new ServerHandler(); - Lists::init(); - - reaper = new Reaper(&reapCB); - if (!reaper->start()) { - exit(1); - } - - while (true) { - // Select on all sockets: - // - client listening socket - // - sockets for all client connections - - // When one of the client connections closes, close its socket - // handles. - - fd_set set; - SOCKET maxSock = 0; - - // Set up fd_set - { - int i; - FD_ZERO(&set); - FD_SET(clientListeningSock, &set); - if (clientListeningSock > maxSock) { - maxSock = clientListeningSock; - } - for (i = 0; i < clientList.size(); i++) { - ClientInfo* info = clientList.get(i); - if (info->getDataSocket() > maxSock) { - maxSock = info->getDataSocket(); - } - FD_SET(info->getDataSocket(), &set); - } - } - struct timeval timeout; - timeout.tv_sec = 300; // 5 minutes - timeout.tv_usec = 0; - int res = select(maxSock, &set, NULL, NULL, &timeout); - if (res > 0) { - - //////////////// - // New client // - //////////////// - if (FD_ISSET(clientListeningSock, &set)) { - SOCKET fd = acceptFromLocalhost(clientListeningSock); - if (fd != INVALID_SOCKET) { - // Create new client information object - ClientInfo* info = new ClientInfo(fd); - // Add to list of clients - clientList.addClient(info); -#ifdef DEBUGGING - cerr << "New client" << endl; -#endif - } - } - - /////////////////////////// - // Commands from clients // - /////////////////////////// - ClientInfo* clientInfo; - if (clientList.isAnyDataSocketSet(&set, &clientInfo)) { - readAndDispatch(clientInfo); - } - } else if (res < 0) { - // Looks like one of the clients was killed. Try to figure out which one. - bool found = false; - fd_set set; - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - for (int i = 0; i < clientList.size(); i++) { - ClientInfo* info = clientList.get(i); - FD_ZERO(&set); - FD_SET(info->getDataSocket(), &set); - if (select(1 + info->getDataSocket(), &set, NULL, NULL, &timeout) < 0) { - found = true; - clientList.removeClient(info); - info->closeAll(); - delete info; - break; - } - } - if (!found) { - // This indicates trouble -- one of our listening sockets died. - exit(1); - } - } - } - - return 0; -} diff --git a/hotspot/agent/src/os/win32/SwDbgSrv.dsp b/hotspot/agent/src/os/win32/SwDbgSrv.dsp deleted file mode 100644 index 4257278704c..00000000000 --- a/hotspot/agent/src/os/win32/SwDbgSrv.dsp +++ /dev/null @@ -1,146 +0,0 @@ -# Microsoft Developer Studio Project File - Name="SwDbgSrv" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=SwDbgSrv - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "SwDbgSrv.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "SwDbgSrv.mak" CFG="SwDbgSrv - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "SwDbgSrv - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "SwDbgSrv - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "SwDbgSrv - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "SwDbgSrv - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "SwDbgSrv___Win32_Debug" -# PROP BASE Intermediate_Dir "SwDbgSrv___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "SwDbgSrv - Win32 Release" -# Name "SwDbgSrv - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\Buffer.cpp -# End Source File -# Begin Source File - -SOURCE=.\Dispatcher.cpp -# End Source File -# Begin Source File - -SOURCE=.\initWinsock.cpp -# End Source File -# Begin Source File - -SOURCE=.\IOBuf.cpp -# End Source File -# Begin Source File - -SOURCE=.\ioUtils.cpp -# End Source File -# Begin Source File - -SOURCE=.\isNT4.cpp -# End Source File -# Begin Source File - -SOURCE=.\nt4internals.cpp -# End Source File -# Begin Source File - -SOURCE=.\procList.cpp -# End Source File -# Begin Source File - -SOURCE=.\Reaper.cpp -# End Source File -# Begin Source File - -SOURCE=.\serverLists.cpp -# End Source File -# Begin Source File - -SOURCE=.\SwDbgSrv.cpp -# End Source File -# Begin Source File - -SOURCE=.\toolHelp.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/hotspot/agent/src/os/win32/SwDbgSrv.dsw b/hotspot/agent/src/os/win32/SwDbgSrv.dsw deleted file mode 100644 index a1570e459c3..00000000000 --- a/hotspot/agent/src/os/win32/SwDbgSrv.dsw +++ /dev/null @@ -1,41 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "SwDbgSrv"=.\SwDbgSrv.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "SwDbgSub"=.\SwDbgSub.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/hotspot/agent/src/os/win32/SwDbgSub.cpp b/hotspot/agent/src/os/win32/SwDbgSub.cpp deleted file mode 100644 index 7acae51e9ab..00000000000 --- a/hotspot/agent/src/os/win32/SwDbgSub.cpp +++ /dev/null @@ -1,883 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -// This is the source code for the subprocess forked by the Simple -// Windows Debug Server. It assumes most of the responsibility for the -// debug session, and processes all of the commands sent by clients. - -// Disable too-long symbol warnings -#pragma warning ( disable : 4786 ) - -#include -#include -#include -#include -// Must come before windows.h -#include -#include -#include "IOBuf.hpp" -#include "libInfo.hpp" -#include "LockableList.hpp" -#include "Message.hpp" -#include "Monitor.hpp" -#include "nt4internals.hpp" - -// Uncomment the #define below to get messages on stderr -// #define DEBUGGING - -using namespace std; - -DWORD pid; -HANDLE procHandle; -IOBuf* ioBuf; - -// State flags indicating whether the attach to the remote process -// definitively succeeded or failed -volatile bool attachFailed = false; -volatile bool attachSucceeded = false; - -// State flag indicating whether the target process is suspended. -// Modified by suspend()/resume(), viewed by debug thread, but only -// under cover of the threads lock. -volatile bool suspended = false; - -// State flags indicating whether we are considered to be attached to -// the target process and are therefore queuing up events to be sent -// back to the debug server. These flags are only accessed and -// modified under the cover of the eventLock. -Monitor* eventLock; -// The following is set to true when a client is attached to this process -volatile bool generateDebugEvents = false; -// Pointer to current debug event; non-NULL indicates a debug event is -// waiting to be sent to the client. Main thread sets this to NULL to -// indicate that the event has been consumed; also sets -// passEventToClient, below. -volatile DEBUG_EVENT* curDebugEvent = NULL; -// Set by main thread to indicate whether the most recently posted -// debug event should be passed on to the target process. -volatile bool passEventToClient = true; - -void conditionalPostDebugEvent(DEBUG_EVENT* ev, DWORD* continueOrNotHandledFlag) { - // FIXME: make it possible for the client to enable and disable - // certain types of events (have to do so in a platform-independent - // manner) - switch (ev->dwDebugEventCode) { - case EXCEPTION_DEBUG_EVENT: - switch (ev->u.Exception.ExceptionRecord.ExceptionCode) { - case EXCEPTION_BREAKPOINT: break; - case EXCEPTION_SINGLE_STEP: break; - case EXCEPTION_ACCESS_VIOLATION: break; - default: return; - } - } - eventLock->lock(); - if (generateDebugEvents) { - curDebugEvent = ev; - while (curDebugEvent != NULL) { - eventLock->wait(); - } - if (passEventToClient) { - *continueOrNotHandledFlag = DBG_EXCEPTION_NOT_HANDLED; - } else { - *continueOrNotHandledFlag = DBG_CONTINUE; - } - } - eventLock->unlock(); -} - - -//---------------------------------------------------------------------- -// Module list -// - -vector libs; - -//---------------------------------------------------------------------- -// Thread list -// - -struct ThreadInfo { - DWORD tid; - HANDLE thread; - - ThreadInfo(DWORD tid, HANDLE thread) { - this->tid = tid; - this->thread = thread; - } -}; - -class ThreadList : public LockableList { -public: - bool removeByThreadID(DWORD tid) { - for (InternalListType::iterator iter = internalList.begin(); - iter != internalList.end(); iter++) { - if ((*iter).tid == tid) { - internalList.erase(iter); - return true; - } - } - return false; - } - HANDLE threadIDToHandle(DWORD tid) { - for (InternalListType::iterator iter = internalList.begin(); - iter != internalList.end(); iter++) { - if ((*iter).tid == tid) { - return (*iter).thread; - } - } - return NULL; - } -}; - -ThreadList threads; - -//---------------------------------------------------------------------- -// INITIALIZATION AND TERMINATION -// - -void -printError(const char* prefix) { - DWORD detail = GetLastError(); - LPTSTR message; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - 0, - detail, - 0, - (LPTSTR) &message, - 1, - NULL); - // FIXME: This is signaling an error: "The handle is invalid." ? - // Do I have to do all of my WaitForDebugEvent calls from the same thread? - cerr << prefix << ": " << message << endl; - LocalFree(message); -} - -void -endProcess(bool waitForProcess = true) { - NT4::unloadNTDLL(); - if (waitForProcess) { - // Though we're exiting because of an error, do not tear down the - // target process. - WaitForSingleObject(procHandle, INFINITE); - } - CloseHandle(procHandle); - exit(0); -} - -DWORD WINAPI -debugThreadEntry(void*) { -#ifdef DEBUGGING - DWORD lastMsgId = 0; - int count = 0; -#endif - - if (!DebugActiveProcess(pid)) { - attachFailed = true; - return 0; - } - - // Wait for debug events. We keep the information from some of these - // on the side in anticipation of later queries by the client. NOTE - // that we leave the process running. The main thread is responsible - // for suspending and resuming all currently-active threads upon - // client attach and detach. - - while (true) { - DEBUG_EVENT ev; - if (!WaitForDebugEvent(&ev, INFINITE)) { -#ifdef DEBUGGING - if (++count < 10) { - // FIXME: This is signaling an error: "The handle is invalid." ? - // Do I have to do all of my WaitForDebugEvent calls from the same thread? - printError("WaitForDebugEvent failed"); - } -#endif - } else { - -#ifdef DEBUGGING - if (ev.dwDebugEventCode != lastMsgId) { - lastMsgId = ev.dwDebugEventCode; - count = 0; - cerr << "Debug thread received event " << ev.dwDebugEventCode << endl; - } else { - if (++count < 10) { - cerr << "Debug thread received event " << ev.dwDebugEventCode << endl; - } - } -#endif - - DWORD dbgContinueMode = DBG_CONTINUE; - - switch (ev.dwDebugEventCode) { - case LOAD_DLL_DEBUG_EVENT: - conditionalPostDebugEvent(&ev, &dbgContinueMode); - break; - - case UNLOAD_DLL_DEBUG_EVENT: - conditionalPostDebugEvent(&ev, &dbgContinueMode); - break; - - case CREATE_PROCESS_DEBUG_EVENT: - threads.lock(); - // FIXME: will this deal properly with child processes? If - // not, is it possible to make it do so? -#ifdef DEBUGGING - cerr << "CREATE_PROCESS_DEBUG_EVENT " << ev.dwThreadId - << " " << ev.u.CreateProcessInfo.hThread << endl; -#endif - if (ev.u.CreateProcessInfo.hThread != NULL) { - threads.add(ThreadInfo(ev.dwThreadId, ev.u.CreateProcessInfo.hThread)); - } - threads.unlock(); - break; - - case CREATE_THREAD_DEBUG_EVENT: - threads.lock(); -#ifdef DEBUGGING - cerr << "CREATE_THREAD_DEBUG_EVENT " << ev.dwThreadId - << " " << ev.u.CreateThread.hThread << endl; -#endif - if (suspended) { - // Suspend this thread before adding it to the thread list - SuspendThread(ev.u.CreateThread.hThread); - } - threads.add(ThreadInfo(ev.dwThreadId, ev.u.CreateThread.hThread)); - threads.unlock(); - break; - - case EXIT_THREAD_DEBUG_EVENT: - threads.lock(); -#ifdef DEBUGGING - cerr << "EXIT_THREAD_DEBUG_EVENT " << ev.dwThreadId << endl; -#endif - threads.removeByThreadID(ev.dwThreadId); - threads.unlock(); - break; - - case EXCEPTION_DEBUG_EVENT: - // cerr << "EXCEPTION_DEBUG_EVENT" << endl; - switch (ev.u.Exception.ExceptionRecord.ExceptionCode) { - case EXCEPTION_BREAKPOINT: - // cerr << "EXCEPTION_BREAKPOINT" << endl; - if (!attachSucceeded && !attachFailed) { - attachSucceeded = true; - } - break; - - default: - dbgContinueMode = DBG_EXCEPTION_NOT_HANDLED; - break; - } - conditionalPostDebugEvent(&ev, &dbgContinueMode); - break; - - case EXIT_PROCESS_DEBUG_EVENT: - endProcess(false); - // NOT REACHED - break; - - default: -#ifdef DEBUGGING - cerr << "Received debug event " << ev.dwDebugEventCode << endl; -#endif - break; - } - - ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, dbgContinueMode); - } - } -} - -bool -attachToProcess() { - // Create event lock - eventLock = new Monitor(); - - // Get a process handle for later - procHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (procHandle == NULL) { - return false; - } - - // Start up the debug thread - DWORD debugThreadId; - if (CreateThread(NULL, 0, &debugThreadEntry, NULL, 0, &debugThreadId) == NULL) { - // Failed to make background debug thread. Fail. - return false; - } - - while ((!attachSucceeded) && (!attachFailed)) { - Sleep(1); - } - - if (attachFailed) { - return false; - } - - assert(attachSucceeded); - - return true; -} - -bool -readMessage(Message* msg) { - DWORD numRead; - if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), - msg, - sizeof(Message), - &numRead, - NULL)) { - return false; - } - if (numRead != sizeof(Message)) { - return false; - } - // For "poke" messages, must follow up by reading raw data - if (msg->type == Message::POKE) { - char* dataBuf = new char[msg->pokeArg.numBytes]; - if (dataBuf == NULL) { - return false; - } - if (!ReadFile(GetStdHandle(STD_INPUT_HANDLE), - dataBuf, - msg->pokeArg.numBytes, - &numRead, - NULL)) { - delete[] dataBuf; - return false; - } - if (numRead != msg->pokeArg.numBytes) { - delete[] dataBuf; - return false; - } - msg->pokeArg.data = (void *) dataBuf; - } - return true; -} - -void -handlePeek(Message* msg) { -#ifdef DEBUGGING - cerr << "Entering handlePeek()" << endl; -#endif - - char* memBuf = new char[msg->peekArg.numBytes]; - if (memBuf == NULL) { - ioBuf->writeString("B"); - ioBuf->writeBinChar(0); - ioBuf->flush(); - delete[] memBuf; - return; - } - - // Try fast case first - DWORD numRead; - BOOL res = ReadProcessMemory(procHandle, - (LPCVOID) msg->peekArg.address, - memBuf, - msg->peekArg.numBytes, - &numRead); - if (res && (numRead == msg->peekArg.numBytes)) { - - // OK, complete success. Phew. -#ifdef DEBUGGING - cerr << "Peek success case" << endl; -#endif - ioBuf->writeString("B"); - ioBuf->writeBinChar(1); - ioBuf->writeBinUnsignedInt(numRead); - ioBuf->writeBinChar(1); - ioBuf->writeBinBuf(memBuf, numRead); - } else { -#ifdef DEBUGGING - cerr << "*** Peek slow case ***" << endl; -#endif - - ioBuf->writeString("B"); - ioBuf->writeBinChar(1); - - // Use VirtualQuery to speed things up a bit - DWORD numLeft = msg->peekArg.numBytes; - char* curAddr = (char*) msg->peekArg.address; - while (numLeft > 0) { - MEMORY_BASIC_INFORMATION memInfo; - VirtualQueryEx(procHandle, curAddr, &memInfo, sizeof(memInfo)); - DWORD numToRead = memInfo.RegionSize; - if (numToRead > numLeft) { - numToRead = numLeft; - } - DWORD numRead; - if (memInfo.State == MEM_COMMIT) { - // Read the process memory at this address for this length - // FIXME: should check the result of this read - ReadProcessMemory(procHandle, curAddr, memBuf, - numToRead, &numRead); - // Write this out -#ifdef DEBUGGING - cerr << "*** Writing " << numToRead << " bytes as mapped ***" << endl; -#endif - ioBuf->writeBinUnsignedInt(numToRead); - ioBuf->writeBinChar(1); - ioBuf->writeBinBuf(memBuf, numToRead); - } else { - // Indicate region is free -#ifdef DEBUGGING - cerr << "*** Writing " << numToRead << " bytes as unmapped ***" << endl; -#endif - ioBuf->writeBinUnsignedInt(numToRead); - ioBuf->writeBinChar(0); - } - curAddr += numToRead; - numLeft -= numToRead; - } - } - - ioBuf->flush(); - delete[] memBuf; -#ifdef DEBUGGING - cerr << "Exiting handlePeek()" << endl; -#endif -} - -void -handlePoke(Message* msg) { -#ifdef DEBUGGING - cerr << "Entering handlePoke()" << endl; -#endif - DWORD numWritten; - BOOL res = WriteProcessMemory(procHandle, - (LPVOID) msg->pokeArg.address, - msg->pokeArg.data, - msg->pokeArg.numBytes, - &numWritten); - if (res && (numWritten == msg->pokeArg.numBytes)) { - // Success - ioBuf->writeBoolAsInt(true); -#ifdef DEBUGGING - cerr << " (Succeeded)" << endl; -#endif - } else { - // Failure - ioBuf->writeBoolAsInt(false); -#ifdef DEBUGGING - cerr << " (Failed)" << endl; -#endif - } - ioBuf->writeEOL(); - ioBuf->flush(); - // We clean up the data - char* dataBuf = (char*) msg->pokeArg.data; - delete[] dataBuf; -#ifdef DEBUGGING - cerr << "Exiting handlePoke()" << endl; -#endif -} - -bool -suspend() { - if (suspended) { - return false; - } - // Before we suspend, we must take a snapshot of the loaded module - // names and base addresses, since acquiring this snapshot requires - // starting and exiting a thread in the remote process (at least on - // NT 4). - libs.clear(); -#ifdef DEBUGGING - cerr << "Starting suspension" << endl; -#endif - libInfo(pid, libs); -#ifdef DEBUGGING - cerr << " Got lib info" << endl; -#endif - threads.lock(); -#ifdef DEBUGGING - cerr << " Got thread lock" << endl; -#endif - suspended = true; - int j = 0; - for (int i = 0; i < threads.size(); i++) { - j++; - SuspendThread(threads.get(i).thread); - } -#ifdef DEBUGGING - cerr << "Suspended " << j << " threads" << endl; -#endif - threads.unlock(); - return true; -} - -bool -resume() { - if (!suspended) { - return false; - } - threads.lock(); - suspended = false; - for (int i = 0; i < threads.size(); i++) { - ResumeThread(threads.get(i).thread); - } - threads.unlock(); -#ifdef DEBUGGING - cerr << "Resumed process" << endl; -#endif - return true; -} - -int -main(int argc, char **argv) -{ - if (argc != 2) { - // Should only be used by performing CreateProcess within SwDbgSrv - exit(1); - } - - if (sscanf(argv[1], "%u", &pid) != 1) { - exit(1); - } - - // Try to attach to process - if (!attachToProcess()) { - // Attach failed. Notify parent by writing result to stdout file - // handle. - char res = 0; - DWORD numBytes; - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &res, sizeof(res), - &numBytes, NULL); - exit(1); - } - - // Server is expecting success result back. - char res = 1; - DWORD numBytes; - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &res, sizeof(res), - &numBytes, NULL); - - // Initialize our I/O buffer - ioBuf = new IOBuf(32768, 131072); - ioBuf->setOutputFileHandle(GetStdHandle(STD_OUTPUT_HANDLE)); - - // At this point we are attached. Enter our main loop which services - // requests from the server. Note that in order to handle attach/ - // detach properly (i.e., resumption of process upon "detach") we - // will need another thread which handles debug events. - while (true) { - // Read a message from the server - Message msg; - if (!readMessage(&msg)) { - endProcess(); - } - -#ifdef DEBUGGING - cerr << "Main thread read message: " << msg.type << endl; -#endif - - switch (msg.type) { - // ATTACH and DETACH messages MUST come in pairs - case Message::ATTACH: - suspend(); - eventLock->lock(); - generateDebugEvents = true; - eventLock->unlock(); - break; - - case Message::DETACH: - eventLock->lock(); - generateDebugEvents = false; - // Flush remaining event if any - if (curDebugEvent != NULL) { - curDebugEvent = NULL; - eventLock->notifyAll(); - } - eventLock->unlock(); - resume(); - break; - - case Message::LIBINFO: - { - if (!suspended) { - ioBuf->writeInt(0); - } else { - // Send back formatted text - ioBuf->writeInt(libs.size()); - for (int i = 0; i < libs.size(); i++) { - ioBuf->writeSpace(); - ioBuf->writeInt(1); - ioBuf->writeSpace(); - ioBuf->writeInt(libs[i].name.size()); - ioBuf->writeSpace(); - ioBuf->writeString(libs[i].name.c_str()); - ioBuf->writeSpace(); - ioBuf->writeAddress(libs[i].base); - } - } - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - - case Message::PEEK: - handlePeek(&msg); - break; - - case Message::POKE: - handlePoke(&msg); - break; - - case Message::THREADLIST: - { - if (!suspended) { - ioBuf->writeInt(0); - } else { - threads.lock(); - ioBuf->writeInt(threads.size()); - for (int i = 0; i < threads.size(); i++) { - ioBuf->writeSpace(); - ioBuf->writeAddress((void*) threads.get(i).thread); - } - threads.unlock(); - } - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - - case Message::DUPHANDLE: - { - HANDLE dup; - if (DuplicateHandle(procHandle, - msg.handleArg.handle, - GetCurrentProcess(), - &dup, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) { - ioBuf->writeBoolAsInt(true); - ioBuf->writeSpace(); - ioBuf->writeAddress((void*) dup); - } else { - ioBuf->writeBoolAsInt(false); - } - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - - case Message::CLOSEHANDLE: - { - CloseHandle(msg.handleArg.handle); - break; - } - - case Message::GETCONTEXT: - { - if (!suspended) { - ioBuf->writeBoolAsInt(false); - } else { - CONTEXT context; - context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; - if (GetThreadContext(msg.handleArg.handle, &context)) { - ioBuf->writeBoolAsInt(true); - // EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, DS, ES, FS, GS, - // CS, SS, EFLAGS, DR0, DR1, DR2, DR3, DR6, DR7 - // See README-commands.txt - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Eax); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Ebx); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Ecx); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Edx); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Esi); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Edi); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Ebp); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Esp); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Eip); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegDs); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegEs); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegFs); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegGs); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegCs); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.SegSs); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.EFlags); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr0); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr1); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr2); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr3); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr6); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) context.Dr7); - } else { - ioBuf->writeBoolAsInt(false); - } - } - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - - case Message::SETCONTEXT: - { - if (!suspended) { - ioBuf->writeBoolAsInt(false); - } else { - CONTEXT context; - context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; - context.Eax = msg.setContextArg.Eax; - context.Ebx = msg.setContextArg.Ebx; - context.Ecx = msg.setContextArg.Ecx; - context.Edx = msg.setContextArg.Edx; - context.Esi = msg.setContextArg.Esi; - context.Edi = msg.setContextArg.Edi; - context.Ebp = msg.setContextArg.Ebp; - context.Esp = msg.setContextArg.Esp; - context.Eip = msg.setContextArg.Eip; - context.SegDs = msg.setContextArg.Ds; - context.SegEs = msg.setContextArg.Es; - context.SegFs = msg.setContextArg.Fs; - context.SegGs = msg.setContextArg.Gs; - context.SegCs = msg.setContextArg.Cs; - context.SegSs = msg.setContextArg.Ss; - context.EFlags = msg.setContextArg.EFlags; - context.Dr0 = msg.setContextArg.Dr0; - context.Dr1 = msg.setContextArg.Dr1; - context.Dr2 = msg.setContextArg.Dr2; - context.Dr3 = msg.setContextArg.Dr3; - context.Dr6 = msg.setContextArg.Dr6; - context.Dr7 = msg.setContextArg.Dr7; - if (SetThreadContext(msg.setContextArg.handle, &context)) { - ioBuf->writeBoolAsInt(true); - } else { - ioBuf->writeBoolAsInt(false); - } - } - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - - case Message::SELECTORENTRY: - { - LDT_ENTRY entry; - - if (GetThreadSelectorEntry(msg.selectorArg.handle, - msg.selectorArg.selector, - &entry)) { - ioBuf->writeBoolAsInt(true); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.LimitLow); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.BaseLow); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.BaseMid); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.Flags1); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.Flags2); - ioBuf->writeSpace(); ioBuf->writeAddress((void*) entry.HighWord.Bytes.BaseHi); - } else { - ioBuf->writeBoolAsInt(false); - } - - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - - case Message::SUSPEND: - suspend(); - break; - - case Message::RESUME: - resume(); - break; - - case Message::POLLEVENT: - eventLock->lock(); - if (curDebugEvent == NULL) { - ioBuf->writeBoolAsInt(false); - } else { - ioBuf->writeBoolAsInt(true); - ioBuf->writeSpace(); - threads.lock(); - ioBuf->writeAddress((void*) threads.threadIDToHandle(curDebugEvent->dwThreadId)); - threads.unlock(); - ioBuf->writeSpace(); - ioBuf->writeUnsignedInt(curDebugEvent->dwDebugEventCode); - // Figure out what else to write - switch (curDebugEvent->dwDebugEventCode) { - case LOAD_DLL_DEBUG_EVENT: - ioBuf->writeSpace(); - ioBuf->writeAddress(curDebugEvent->u.LoadDll.lpBaseOfDll); - break; - - case UNLOAD_DLL_DEBUG_EVENT: - ioBuf->writeSpace(); - ioBuf->writeAddress(curDebugEvent->u.UnloadDll.lpBaseOfDll); - break; - - case EXCEPTION_DEBUG_EVENT: - { - DWORD code = curDebugEvent->u.Exception.ExceptionRecord.ExceptionCode; - ioBuf->writeSpace(); - ioBuf->writeUnsignedInt(code); - ioBuf->writeSpace(); - ioBuf->writeAddress(curDebugEvent->u.Exception.ExceptionRecord.ExceptionAddress); - switch (curDebugEvent->u.Exception.ExceptionRecord.ExceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: - ioBuf->writeSpace(); - ioBuf->writeBoolAsInt(curDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[0] != 0); - ioBuf->writeSpace(); - ioBuf->writeAddress((void*) curDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[1]); - break; - - default: - break; - } - break; - } - - default: - break; - } - } - eventLock->unlock(); - ioBuf->writeEOL(); - ioBuf->flush(); - break; - - case Message::CONTINUEEVENT: - eventLock->lock(); - if (curDebugEvent == NULL) { - ioBuf->writeBoolAsInt(false); - } else { - curDebugEvent = NULL; - passEventToClient = msg.boolArg.val; - ioBuf->writeBoolAsInt(true); - eventLock->notify(); - } - eventLock->unlock(); - ioBuf->writeEOL(); - ioBuf->flush(); - break; - } - } - - endProcess(); - - // NOT REACHED - return 0; -} diff --git a/hotspot/agent/src/os/win32/SwDbgSub.dsp b/hotspot/agent/src/os/win32/SwDbgSub.dsp deleted file mode 100644 index a918a66845c..00000000000 --- a/hotspot/agent/src/os/win32/SwDbgSub.dsp +++ /dev/null @@ -1,130 +0,0 @@ -# Microsoft Developer Studio Project File - Name="SwDbgSub" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=SwDbgSub - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "SwDbgSub.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "SwDbgSub.mak" CFG="SwDbgSub - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "SwDbgSub - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "SwDbgSub - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "SwDbgSub - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "SwDbgSub - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "SwDbgSub___Win32_Debug" -# PROP BASE Intermediate_Dir "SwDbgSub___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "SwDbgSub - Win32 Release" -# Name "SwDbgSub - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\Buffer.cpp -# End Source File -# Begin Source File - -SOURCE=.\IOBuf.cpp -# End Source File -# Begin Source File - -SOURCE=.\isNT4.cpp -# End Source File -# Begin Source File - -SOURCE=.\libInfo.cpp -# End Source File -# Begin Source File - -SOURCE=.\Monitor.cpp -# End Source File -# Begin Source File - -SOURCE=.\nt4internals.cpp -# End Source File -# Begin Source File - -SOURCE=.\SwDbgSub.cpp -# End Source File -# Begin Source File - -SOURCE=.\toolHelp.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/hotspot/agent/src/os/win32/initWinsock.cpp b/hotspot/agent/src/os/win32/initWinsock.cpp deleted file mode 100644 index 42e481fbf05..00000000000 --- a/hotspot/agent/src/os/win32/initWinsock.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include - -using namespace std; - -void -initWinsock() -{ - static int initted = 0; - WORD wVersionRequested; - WSADATA wsaData; - int err; - - if (!initted) { - wVersionRequested = MAKEWORD( 2, 0 ); - - err = WSAStartup( wVersionRequested, &wsaData ); - if ( err != 0 ) { - { - /* Tell the user that we couldn't find a usable */ - /* WinSock DLL. */ - cerr << "SocketBase::SocketBase: unable to find usable " - << "WinSock DLL" << endl; - exit(1); - } - } - - /* Confirm that the WinSock DLL supports 2.0.*/ - /* Note that if the DLL supports versions greater */ - /* than 2.0 in addition to 2.0, it will still return */ - /* 2.0 in wVersion since that is the version we */ - /* requested. */ - - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 0 ) { - /* Tell the user that we couldn't find a usable */ - /* WinSock DLL. */ - { - cerr << "Unable to find suitable version of WinSock DLL" << endl; - WSACleanup( ); - exit(1); - } - } - - initted = 1; - } -} diff --git a/hotspot/agent/src/os/win32/initWinsock.hpp b/hotspot/agent/src/os/win32/initWinsock.hpp deleted file mode 100644 index 9d07795aca9..00000000000 --- a/hotspot/agent/src/os/win32/initWinsock.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _INIT_WINSOCK_ -#define _INIT_WINSOCK_ - -void initWinsock(); - -#endif // #defined _INIT_WINSOCK_ diff --git a/hotspot/agent/src/os/win32/ioUtils.cpp b/hotspot/agent/src/os/win32/ioUtils.cpp deleted file mode 100644 index e7c727462e8..00000000000 --- a/hotspot/agent/src/os/win32/ioUtils.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include -#include "ioUtils.hpp" -#include "IOBuf.hpp" - -bool -scanInt(char** data, int* num) { - *num = 0; - - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (**data == 0) { - return false; - } - - while ((**data != 0) && (!isspace(**data))) { - char cur = **data; - if ((cur < '0') || (cur > '9')) { - return false; - } - *num *= 10; - *num += cur - '0'; - ++*data; - } - - return true; -} - -bool -scanUnsignedLong(char** data, unsigned long* num) { - *num = 0; - - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (**data == 0) { - return false; - } - - while ((**data != 0) && (!isspace(**data))) { - char cur = **data; - if ((cur < '0') || (cur > '9')) { - return false; - } - *num *= 10; - *num += cur - '0'; - ++*data; - } - - return true; -} - -bool -charToNibble(char ascii, int* value) { - if (ascii >= '0' && ascii <= '9') { - *value = ascii - '0'; - return true; - } else if (ascii >= 'A' && ascii <= 'F') { - *value = 10 + ascii - 'A'; - return true; - } else if (ascii >= 'a' && ascii <= 'f') { - *value = 10 + ascii - 'a'; - return true; - } - - return false; -} - -bool -scanAddress(char** data, unsigned long* addr) { - *addr = 0; - - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (**data == 0) { - return false; - } - - if (strncmp(*data, "0x", 2) != 0) { - return false; - } - - *data += 2; - - while ((**data != 0) && (!isspace(**data))) { - int val; - bool res = charToNibble(**data, &val); - if (!res) { - return false; - } - *addr <<= 4; - *addr |= val; - ++*data; - } - - return true; -} - -bool -scanAndSkipBinEscapeChar(char** data) { - // Skip whitespace - while ((**data != 0) && (isspace(**data))) { - ++*data; - } - - if (!IOBuf::isBinEscapeChar(**data)) { - return false; - } - - ++*data; - - return true; -} - -bool -scanBinUnsignedLong(char** data, unsigned long* num) { - *num = 0; - for (int i = 0; i < 4; i++) { - unsigned char val = (unsigned char) **data; - *num = (*num << 8) | val; - ++*data; - } - return true; -} diff --git a/hotspot/agent/src/os/win32/ioUtils.hpp b/hotspot/agent/src/os/win32/ioUtils.hpp deleted file mode 100644 index 2857acf6931..00000000000 --- a/hotspot/agent/src/os/win32/ioUtils.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _IO_UTILS_ -#define _IO_UTILS_ - -bool scanInt(char** data, int* num); -bool scanUnsignedLong(char** data, unsigned long* num); -bool scanAddress(char** data, unsigned long* addr); - -// Binary utils (for poke) -bool scanAndSkipBinEscapeChar(char** data); -bool scanBinUnsignedLong(char** data, unsigned long* num); - -#endif // #defined _IO_UTILS_ diff --git a/hotspot/agent/src/os/win32/isNT4.cpp b/hotspot/agent/src/os/win32/isNT4.cpp deleted file mode 100644 index 9d68add804c..00000000000 --- a/hotspot/agent/src/os/win32/isNT4.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "isNT4.hpp" -#include - -bool -isNT4() { - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof(info); - - if (!GetVersionEx(&info)) { - return false; - } - - return ((info.dwPlatformId == VER_PLATFORM_WIN32_NT) && - (info.dwMajorVersion == 4)); -} diff --git a/hotspot/agent/src/os/win32/isNT4.hpp b/hotspot/agent/src/os/win32/isNT4.hpp deleted file mode 100644 index f68430f2e8c..00000000000 --- a/hotspot/agent/src/os/win32/isNT4.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _ISNT4_H_ -#define _ISNT4_H_ - -// We need to special-case the Windows NT 4.0 implementations of some -// of the debugging routines because the Tool Help API is not -// available on this platform. - -bool isNT4(); - -#endif // #defined _ISNT4_H_ diff --git a/hotspot/agent/src/os/win32/libInfo.cpp b/hotspot/agent/src/os/win32/libInfo.cpp deleted file mode 100644 index dc9d3dacfcd..00000000000 --- a/hotspot/agent/src/os/win32/libInfo.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -// Disable too-long symbol warnings -#pragma warning ( disable : 4786 ) - -#include "libInfo.hpp" -#include "nt4internals.hpp" -#include "isNT4.hpp" -#include "toolHelp.hpp" -#include - -using namespace std; - -typedef void LibInfoImplFunc(DWORD pid, vector& info); - -static void libInfoImplNT4(DWORD pid, vector& info); -static void libInfoImplToolHelp(DWORD pid, vector& info); - -void -libInfo(DWORD pid, vector& info) { - static LibInfoImplFunc* impl = NULL; - - if (impl == NULL) { - // See which operating system we're on - impl = (isNT4() ? &libInfoImplNT4 : &libInfoImplToolHelp); - } - - assert(impl != NULL); - - (*impl)(pid, info); -} - -static ULONG -ModuleCount(NT4::PDEBUG_BUFFER db) { - return db->ModuleInformation ? *PULONG(db->ModuleInformation) : 0; -} - -#define MAX2(a, b) (((a) < (b)) ? (b) : (a)) - -static void -libInfoImplNT4(DWORD pid, vector& info) { - static EnumProcessModulesFunc* enumFunc = NULL; - static GetModuleFileNameExFunc* fnFunc = NULL; - static GetModuleInformationFunc* infoFunc = NULL; - - if (enumFunc == NULL) { - HMODULE dll = loadPSAPIDLL(); - - enumFunc = (EnumProcessModulesFunc*) GetProcAddress(dll, "EnumProcessModules"); - fnFunc = (GetModuleFileNameExFunc*) GetProcAddress(dll, "GetModuleFileNameExA"); - infoFunc = (GetModuleInformationFunc*) GetProcAddress(dll, "GetModuleInformation"); - - assert(enumFunc != NULL); - assert(fnFunc != NULL); - assert(infoFunc != NULL); - } - - static HMODULE* mods = new HMODULE[256]; - static int numMods = 256; - - if (mods == NULL) { - mods = new HMODULE[numMods]; - if (mods == NULL) { - return; - } - } - - bool done = false; - - HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (proc == NULL) { - return; - } - - do { - DWORD bufSize = numMods * sizeof(HMODULE); - DWORD neededSize; - - if (!(*enumFunc)(proc, mods, bufSize, &neededSize)) { - // Enum failed - CloseHandle(proc); - return; - } - - int numFetched = neededSize / sizeof(HMODULE); - - if (numMods < numFetched) { - // Grow buffer - numMods = MAX2(numFetched, 2 * numMods); - delete[] mods; - mods = new HMODULE[numMods]; - if (mods == NULL) { - CloseHandle(proc); - return; - } - } else { - char filename[MAX_PATH]; - MODULEINFO modInfo; - - // Iterate through and fetch each one's info - for (int i = 0; i < numFetched; i++) { - if (!(*fnFunc)(proc, mods[i], filename, MAX_PATH)) { - CloseHandle(proc); - return; - } - - if (!(*infoFunc)(proc, mods[i], &modInfo, sizeof(MODULEINFO))) { - CloseHandle(proc); - return; - } - - info.push_back(LibInfo(string(filename), (void*) modInfo.lpBaseOfDll)); - } - - done = true; - } - } while (!done); - - CloseHandle(proc); - return; -} - -void -libInfoImplToolHelp(DWORD pid, vector& info) { - using namespace ToolHelp; - - static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL; - static Module32FirstFunc* firstFunc = NULL; - static Module32NextFunc* nextFunc = NULL; - - if (snapshotFunc == NULL) { - HMODULE dll = loadDLL(); - - snapshotFunc = - (CreateToolhelp32SnapshotFunc*) GetProcAddress(dll, - "CreateToolhelp32Snapshot"); - - firstFunc = (Module32FirstFunc*) GetProcAddress(dll, - "Module32First"); - - nextFunc = (Module32NextFunc*) GetProcAddress(dll, - "Module32Next"); - - assert(snapshotFunc != NULL); - assert(firstFunc != NULL); - assert(nextFunc != NULL); - } - - HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPMODULE, pid); - if (snapshot == (HANDLE) -1) { - // Error occurred during snapshot - return; - } - - // Iterate - MODULEENTRY32 module; - if ((*firstFunc)(snapshot, &module)) { - do { - info.push_back(LibInfo(string(module.szExePath), (void*) module.modBaseAddr)); - } while ((*nextFunc)(snapshot, &module)); - } - - CloseHandle(snapshot); -} diff --git a/hotspot/agent/src/os/win32/libInfo.hpp b/hotspot/agent/src/os/win32/libInfo.hpp deleted file mode 100644 index 4b24edc1587..00000000000 --- a/hotspot/agent/src/os/win32/libInfo.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _LIBINFO_ -#define _LIBINFO_ - -#include -#include -#include - -struct LibInfo { - std::string name; - void* base; - - LibInfo(const std::string& name, void* base) { - this->name = name; - this->base = base; - } -}; - -void libInfo(DWORD pid, std::vector& info); - -#endif // #defined _LIBINFO_ diff --git a/hotspot/agent/src/os/win32/nt4internals.cpp b/hotspot/agent/src/os/win32/nt4internals.cpp deleted file mode 100644 index e16dcf89383..00000000000 --- a/hotspot/agent/src/os/win32/nt4internals.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "nt4internals.hpp" -#include -#include -#include - -namespace NT4 { - -static HMODULE ntDLL = NULL; - -HMODULE loadNTDLL() { - if (ntDLL == NULL) { - ntDLL = LoadLibrary("NTDLL.DLL"); - } - - assert(ntDLL != NULL); - return ntDLL; -} - -void unloadNTDLL() { - if (ntDLL != NULL) { - FreeLibrary(ntDLL); - ntDLL = NULL; - } -} - -} // namespace NT4 - -static HMODULE psapiDLL = NULL; - -HMODULE -loadPSAPIDLL() { - if (psapiDLL == NULL) { - psapiDLL = LoadLibrary("PSAPI.DLL"); - } - - if (psapiDLL == NULL) { - fprintf(stderr, "Simple Windows Debug Server requires PSAPI.DLL on Windows NT 4.0.\n"); - fprintf(stderr, "Please install this DLL from the SDK and restart the server.\n"); - exit(1); - } - - return psapiDLL; -} - -void -unloadPSAPIDLL() { - if (psapiDLL != NULL) { - FreeLibrary(psapiDLL); - psapiDLL = NULL; - } -} diff --git a/hotspot/agent/src/os/win32/nt4internals.hpp b/hotspot/agent/src/os/win32/nt4internals.hpp deleted file mode 100644 index eb1513c2b1e..00000000000 --- a/hotspot/agent/src/os/win32/nt4internals.hpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _NT4INTERNALS_H_ -#define _NT4INTERNALS_H_ - -#include - -namespace NT4 { -extern "C" { - -// Data structures and constants required to be able to get necessary -// debugging-related information on Windows NT 4.0 through internal -// (i.e., non-public) APIs. These are adapted from those in the -// _Windows NT/2000 Native API Reference_ by Gary Nebbett, Macmillan -// Technical Publishing, 201 West 103rd Street, Indianapolis, IN -// 46290, 2000. - -typedef LONG NTSTATUS; -typedef LONG KPRIORITY; - -#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) -#define NTAPI __stdcall -#else -#define _cdecl -#define NTAPI -#endif - -#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) - -typedef enum _SYSTEM_INFORMATION_CLASS { - SystemProcessesAndThreadsInformation = 5 -} SYSTEM_INFORMATION_CLASS; - -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING; - -typedef struct _VM_COUNTERS { - ULONG PeakVirtualSize; - ULONG VirtualSize; - ULONG PageFaultCount; - ULONG PeakWorkingSetSize; - ULONG WorkingSetSize; - ULONG QuotaPeakPagedPoolUsage; - ULONG QuotaPagedPoolUsage; - ULONG QuotaPeakNonPagedPoolUsage; - ULONG QuotaNonPagedPoolUsage; - ULONG PagefileUsage; - ULONG PeakPagefileUsage; -} VM_COUNTERS, *PVM_COUNTERS; - -typedef struct _IO_COUNTERS { - LARGE_INTEGER ReadOperationCount; - LARGE_INTEGER WriteOperationCount; - LARGE_INTEGER OtherOperationCount; - LARGE_INTEGER ReadTransferCount; - LARGE_INTEGER WriteTransferCount; - LARGE_INTEGER OtherTransferCount; -} IO_COUNTERS, *PIO_COUNTERS; - -typedef struct _CLIENT_ID { - HANDLE UniqueProcess; - HANDLE UniqueThread; -} CLIENT_ID, *PCLIENT_ID; - -typedef enum { - StateInitialized, - StateReady, - StateRunning, - StateStandby, - StateTerminated, - StateWait, - StateTransition, - StateUnknown -} THREAD_STATE; - -typedef enum { - Executive, - FreePage, - PageIn, - PoolAllocation, - DelayExecution, - Suspended, - UserRequest, - WrExecutive, - WrFreePage, - WrPageIn, - WrPoolAllocation, - WrDelayExecution, - WrSuspended, - WrUserRequest, - WrEventPair, - WrQueue, - WrLpcReceive, - WrLpcReply, - WrVirtualMemory, - WrPageOut, - WrRendezvous, - Spare2, - Spare3, - Spare4, - Spare5, - Spare6, - WrKernel -} KWAIT_REASON; - -typedef struct _SYSTEM_THREADS { - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER CreateTime; - ULONG WaitTime; - PVOID StartAddress; - CLIENT_ID ClientId; - KPRIORITY Priority; - KPRIORITY BasePriority; - ULONG ContextSwitchCount; - THREAD_STATE State; - KWAIT_REASON WaitReason; -} SYSTEM_THREADS, *PSYSTEM_THREADS; - -typedef struct _SYSTEM_PROCESSES { // Information class 5 - ULONG NextEntryDelta; - ULONG ThreadCount; - ULONG Reserved1[6]; - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ProcessName; - KPRIORITY BasePriority; - ULONG ProcessId; - ULONG InheritedFromProcessId; - ULONG HandleCount; - ULONG Reserved2[2]; - ULONG PrivatePageCount; - VM_COUNTERS VmCounters; - IO_COUNTERS IoCounters; // Windows 2000 only - SYSTEM_THREADS Threads[1]; -} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES; - -typedef NTSTATUS NTAPI -ZwQuerySystemInformationFunc(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, - IN OUT PVOID SystemInformation, - IN ULONG SystemInformationLength, - OUT PULONG ReturnLength OPTIONAL - ); - -typedef struct _DEBUG_BUFFER { - HANDLE SectionHandle; - PVOID SectionBase; - PVOID RemoteSectionBase; - ULONG SectionBaseDelta; - HANDLE EventPairHandle; - ULONG Unknown[2]; - HANDLE RemoteThreadHandle; - ULONG InfoClassMask; - ULONG SizeOfInfo; - ULONG AllocatedSize; - ULONG SectionSize; - PVOID ModuleInformation; - PVOID BackTraceInformation; - PVOID HeapInformation; - PVOID LockInformation; - PVOID Reserved[8]; -} DEBUG_BUFFER, *PDEBUG_BUFFER; - -typedef PDEBUG_BUFFER NTAPI -RtlCreateQueryDebugBufferFunc(IN ULONG Size, - IN BOOLEAN EventPair); - -#define PDI_MODULES 0x01 // The loaded modules of the process -#define PDI_BACKTRACE 0x02 // The heap stack back traces -#define PDI_HEAPS 0x04 // The heaps of the process -#define PDI_HEAP_TAGS 0x08 // The heap tags -#define PDI_HEAP_BLOCKS 0x10 // The heap blocks -#define PDI_LOCKS 0x20 // The locks created by the process - -typedef struct _DEBUG_MODULE_INFORMATION { // c.f. SYSTEM_MODULE_INFORMATION - ULONG Reserved[2]; - ULONG Base; - ULONG Size; - ULONG Flags; - USHORT Index; - USHORT Unknown; - USHORT LoadCount; - USHORT ModuleNameOffset; - CHAR ImageName[256]; -} DEBUG_MODULE_INFORMATION, *PDEBUG_MODULE_INFORMATION; - -// Flags -#define LDRP_STATIC_LINK 0x00000002 -#define LDRP_IMAGE_DLL 0x00000004 -#define LDRP_LOAD_IN_PROGRESS 0x00001000 -#define LDRP_UNLOAD_IN_PROGRESS 0x00002000 -#define LDRP_ENTRY_PROCESSED 0x00004000 -#define LDRP_ENTRY_INSERTED 0x00008000 -#define LDRP_CURRENT_LOAD 0x00010000 -#define LDRP_FAILED_BUILTIN_LOAD 0x00020000 -#define LDRP_DONT_CALL_FOR_THREADS 0x00040000 -#define LDRP_PROCESS_ATTACH_CALLED 0x00080000 -#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 -#define LDRP_IMAGE_NOT_AT_BASE 0x00200000 -#define LDRP_WX86_IGNORE_MACHINETYPE 0x00400000 - -// NOTE that this will require creating a thread in the target -// process, implying that we can not call this while the process is -// suspended. May have to run this command in the child processes -// rather than the server. - -typedef NTSTATUS NTAPI -RtlQueryProcessDebugInformationFunc(IN ULONG ProcessId, - IN ULONG DebugInfoClassMask, - IN OUT PDEBUG_BUFFER DebugBuffer); - -typedef NTSTATUS NTAPI -RtlDestroyQueryDebugBufferFunc(IN PDEBUG_BUFFER DebugBuffer); - -// Routines to load and unload NTDLL.DLL. -HMODULE loadNTDLL(); -// Safe to call even if has not been loaded -void unloadNTDLL(); - -} // extern "C" -} // namespace NT4 - -//---------------------------------------------------------------------- - -// On NT 4 only, we now use PSAPI to enumerate the loaded modules in -// the target processes. RtlQueryProcessDebugInformation creates a -// thread in the target process, which causes problems when we are -// handling events like breakpoints in the debugger. The dependence on -// an external DLL which might not be present is unfortunate, but we -// can either redistribute this DLL (if allowed) or refuse to start on -// NT 4 if it is not present. - -typedef struct _MODULEINFO { - LPVOID lpBaseOfDll; - DWORD SizeOfImage; - LPVOID EntryPoint; -} MODULEINFO, *LPMODULEINFO; - -typedef BOOL (WINAPI EnumProcessModulesFunc)(HANDLE, HMODULE *, DWORD, LPDWORD); -typedef DWORD (WINAPI GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD); -typedef BOOL (WINAPI GetModuleInformationFunc)(HANDLE, HMODULE, LPMODULEINFO, DWORD); -// Routines to load and unload PSAPI.DLL. -HMODULE loadPSAPIDLL(); -// Safe to call even if has not been loaded -void unloadPSAPIDLL(); - -#endif // #defined _NT4INTERNALS_H_ diff --git a/hotspot/agent/src/os/win32/ports.h b/hotspot/agent/src/os/win32/ports.h deleted file mode 100644 index 682190fef6c..00000000000 --- a/hotspot/agent/src/os/win32/ports.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _PORTS_H_ -#define _PORTS_H_ - -// This is the "public" port which end-user clients can connect to -// with an arbitrary application, including telnet. -const short CLIENT_PORT = 27000; - -#endif // #defined _PORTS_H_ diff --git a/hotspot/agent/src/os/win32/procList.cpp b/hotspot/agent/src/os/win32/procList.cpp deleted file mode 100644 index 6763bb186dc..00000000000 --- a/hotspot/agent/src/os/win32/procList.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "procList.hpp" -#include "nt4internals.hpp" -#include "isNT4.hpp" -#include "toolHelp.hpp" -#include - -using namespace std; -using namespace NT4; - -typedef void ProcListImplFunc(ProcEntryList& processes); - -void procListImplNT4(ProcEntryList& processes); -void procListImplToolHelp(ProcEntryList& processes); - -ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, WCHAR* name) { - this->pid = pid; - this->nameLength = nameLength; - this->name = new WCHAR[nameLength]; - memcpy(this->name, name, nameLength * sizeof(WCHAR)); -} - -ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, char* name) { - this->pid = pid; - this->nameLength = nameLength; - this->name = new WCHAR[nameLength]; - int j = 0; - for (int i = 0; i < nameLength; i++) { - // FIXME: what is the proper promotion from ASCII to UNICODE? - this->name[i] = name[i] & 0xFF; - } -} - -ProcEntry::ProcEntry(const ProcEntry& arg) { - name = NULL; - copyFrom(arg); -} - -ProcEntry& -ProcEntry::operator=(const ProcEntry& arg) { - copyFrom(arg); - return *this; -} - -ProcEntry::~ProcEntry() { - delete[] name; -} - -void -ProcEntry::copyFrom(const ProcEntry& arg) { - if (name != NULL) { - delete[] name; - } - pid = arg.pid; - nameLength = arg.nameLength; - name = new WCHAR[nameLength]; - memcpy(name, arg.name, nameLength * sizeof(WCHAR)); -} - -ULONG -ProcEntry::getPid() { - return pid; -} - -USHORT -ProcEntry::getNameLength() { - return nameLength; -} - -WCHAR* -ProcEntry::getName() { - return name; -} - -void -procList(ProcEntryList& processes) { - static ProcListImplFunc* impl = NULL; - - if (impl == NULL) { - // See which operating system we're on - impl = (isNT4() ? &procListImplNT4 : &procListImplToolHelp); - } - - assert(impl != NULL); - - (*impl)(processes); -} - -void -procListImplNT4(ProcEntryList& processes) { - using namespace NT4; - - static ZwQuerySystemInformationFunc* query = NULL; - - if (query == NULL) { - HMODULE ntDLL = loadNTDLL(); - query = - (ZwQuerySystemInformationFunc*) GetProcAddress(ntDLL, - "ZwQuerySystemInformation"); - assert(query != NULL); - } - - ULONG n = 0x100; - PSYSTEM_PROCESSES sp = new SYSTEM_PROCESSES[n]; - while ((*query)(SystemProcessesAndThreadsInformation, - sp, n * sizeof(SYSTEM_PROCESSES), 0) == STATUS_INFO_LENGTH_MISMATCH) { - delete[] sp; - n *= 2; - sp = new SYSTEM_PROCESSES[n]; - } - - bool done = false; - for (PSYSTEM_PROCESSES p = sp; !done; - p = PSYSTEM_PROCESSES(PCHAR(p) + p->NextEntryDelta)) { - processes.push_back(ProcEntry(p->ProcessId, - p->ProcessName.Length / 2, - p->ProcessName.Buffer)); - done = p->NextEntryDelta == 0; - } -} - -void -procListImplToolHelp(ProcEntryList& processes) { - using namespace ToolHelp; - - static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL; - static Process32FirstFunc* firstFunc = NULL; - static Process32NextFunc* nextFunc = NULL; - - if (snapshotFunc == NULL) { - HMODULE dll = loadDLL(); - - snapshotFunc = - (CreateToolhelp32SnapshotFunc*) GetProcAddress(dll, - "CreateToolhelp32Snapshot"); - - firstFunc = (Process32FirstFunc*) GetProcAddress(dll, - "Process32First"); - - nextFunc = (Process32NextFunc*) GetProcAddress(dll, - "Process32Next"); - - assert(snapshotFunc != NULL); - assert(firstFunc != NULL); - assert(nextFunc != NULL); - } - - HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPPROCESS, 0 /* ignored */); - if (snapshot == (HANDLE) -1) { - // Error occurred during snapshot - return; - } - - // Iterate - PROCESSENTRY32 proc; - if ((*firstFunc)(snapshot, &proc)) { - do { - // FIXME: could make this uniform to the NT version by cutting - // off the path name just before the executable name - processes.push_back(ProcEntry(proc.th32ProcessID, - strlen(proc.szExeFile), - proc.szExeFile)); - } while ((*nextFunc)(snapshot, &proc)); - } - - CloseHandle(snapshot); -} diff --git a/hotspot/agent/src/os/win32/procList.hpp b/hotspot/agent/src/os/win32/procList.hpp deleted file mode 100644 index 962c7b276c5..00000000000 --- a/hotspot/agent/src/os/win32/procList.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _PROCLIST_ -#define _PROCLIST_ - -#include -#include - -class ProcEntry { -public: - /** name may not be NULL */ - ProcEntry(ULONG pid, USHORT nameLength, wchar_t* name); - ProcEntry(ULONG pid, USHORT nameLength, char* name); - ~ProcEntry(); - ProcEntry(const ProcEntry& arg); - ProcEntry& operator=(const ProcEntry& arg); - - ULONG getPid(); - /** Returns number of WCHAR characters in getName() */ - USHORT getNameLength(); - WCHAR* getName(); - -private: - ULONG pid; - USHORT nameLength; - WCHAR* name; - void copyFrom(const ProcEntry& arg); -}; - -typedef std::vector ProcEntryList; -void procList(ProcEntryList& processes); - -#endif // #defined _PROCLIST_ diff --git a/hotspot/agent/src/os/win32/serverLists.cpp b/hotspot/agent/src/os/win32/serverLists.cpp deleted file mode 100644 index 209d291162d..00000000000 --- a/hotspot/agent/src/os/win32/serverLists.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include "serverLists.hpp" - -//---------------------------------------------------------------------- -// Lists -// - -CRITICAL_SECTION Lists::crit; - -void -Lists::init() { - InitializeCriticalSection(&crit); -} - -void -Lists::lock() { - EnterCriticalSection(&crit); -} - -void -Lists::unlock() { - LeaveCriticalSection(&crit); -} - -//---------------------------------------------------------------------- -// ListsLocker -// - -ListsLocker::ListsLocker() { - Lists::lock(); -} - -ListsLocker::~ListsLocker() { - Lists::unlock(); -} - -//---------------------------------------------------------------------- -// ChildInfo -// - -ChildInfo::ChildInfo(DWORD pid, HANDLE childProcessHandle, - HANDLE writeToStdinHandle, HANDLE readFromStdoutHandle, - HANDLE auxHandle1, HANDLE auxHandle2) { - this->pid = pid; - this->childProcessHandle = childProcessHandle; - this->writeToStdinHandle = writeToStdinHandle; - this->readFromStdoutHandle = readFromStdoutHandle; - this->auxHandle1 = auxHandle1; - this->auxHandle2 = auxHandle2; - client = NULL; -} - -DWORD -ChildInfo::getPid() { - return pid; -} - -HANDLE -ChildInfo::getChildProcessHandle() { - return childProcessHandle; -} - -HANDLE -ChildInfo::getWriteToStdinHandle() { - return writeToStdinHandle; -} - -HANDLE -ChildInfo::getReadFromStdoutHandle() { - return readFromStdoutHandle; -} - -void -ChildInfo::setClient(ClientInfo* clientInfo) { - client = clientInfo; -} - -ClientInfo* -ChildInfo::getClient() { - return client; -} - -void -ChildInfo::closeAll() { - CloseHandle(childProcessHandle); - CloseHandle(writeToStdinHandle); - CloseHandle(readFromStdoutHandle); - CloseHandle(auxHandle1); - CloseHandle(auxHandle2); -} - -//---------------------------------------------------------------------- -// ChildList -// - -ChildList::ChildList() { -} - -ChildList::~ChildList() { -} - -void -ChildList::addChild(ChildInfo* info) { - // Could store these in binary sorted order by pid for efficiency - childList.push_back(info); -} - -ChildInfo* -ChildList::removeChild(HANDLE childProcessHandle) { - for (ChildInfoList::iterator iter = childList.begin(); iter != childList.end(); - iter++) { - ChildInfo* info = *iter; - if (info->getChildProcessHandle() == childProcessHandle) { - childList.erase(iter); - return info; - } - } - assert(false); - return NULL; -} - -void -ChildList::removeChild(ChildInfo* info) { - for (ChildInfoList::iterator iter = childList.begin(); iter != childList.end(); - iter++) { - if (*iter == info) { - childList.erase(iter); - return; - } - } - assert(false); -} - -ChildInfo* -ChildList::getChildByPid(DWORD pid) { - for (ChildInfoList::iterator iter = childList.begin(); iter != childList.end(); - iter++) { - ChildInfo* info = *iter; - if (info->getPid() == pid) { - return info; - } - } - return NULL; -} - -int -ChildList::size() { - return childList.size(); -} - -ChildInfo* -ChildList::getChildByIndex(int index) { - return childList[index]; -} - -//---------------------------------------------------------------------- -// ClientInfo -// - -ClientInfo::ClientInfo(SOCKET dataSocket) { - this->dataSocket = dataSocket; - buf = new IOBuf(32768, 131072); - buf->setSocket(dataSocket); - target = NULL; -} - -ClientInfo::~ClientInfo() { - delete buf; -} - -SOCKET -ClientInfo::getDataSocket() { - return dataSocket; -} - -IOBuf* -ClientInfo::getIOBuf() { - return buf; -} - -void -ClientInfo::setTarget(ChildInfo* childInfo) { - target = childInfo; -} - -ChildInfo* -ClientInfo::getTarget() { - return target; -} - -void -ClientInfo::closeAll() { - shutdown(dataSocket, SD_BOTH); - closesocket(dataSocket); - dataSocket = INVALID_SOCKET; -} - -//---------------------------------------------------------------------- -// ClientList -// - -ClientList::ClientList() { -} - -ClientList::~ClientList() { -} - -void -ClientList::addClient(ClientInfo* info) { - clientList.push_back(info); -} - -bool -ClientList::isAnyDataSocketSet(fd_set* fds, ClientInfo** out) { - for (ClientInfoList::iterator iter = clientList.begin(); iter != clientList.end(); - iter++) { - ClientInfo* info = *iter; - if (FD_ISSET(info->getDataSocket(), fds)) { - *out = info; - return true; - } - } - return false; -} - -void -ClientList::removeClient(ClientInfo* client) { - for (ClientInfoList::iterator iter = clientList.begin(); iter != clientList.end(); - iter++) { - if (*iter == client) { - clientList.erase(iter); - return; - } - } - assert(false); -} - -int -ClientList::size() { - return clientList.size(); -} - -ClientInfo* -ClientList::get(int num) { - return clientList[num]; -} diff --git a/hotspot/agent/src/os/win32/serverLists.hpp b/hotspot/agent/src/os/win32/serverLists.hpp deleted file mode 100644 index 7e293d9830a..00000000000 --- a/hotspot/agent/src/os/win32/serverLists.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _SERVER_LISTS_ -#define _SERVER_LISTS_ - -#include -#include -#include "IOBuf.hpp" - -// -// NOTE: -// -// All of these lists are guarded by the global lock managed by the -// Lists class. Lists::init() must be called at the start of the -// program. -// - -class Lists { - friend class ListsLocker; -public: - static void init(); -private: - static void lock(); - static void unlock(); - static CRITICAL_SECTION crit; -}; - -// Should be allocated on stack. Ensures proper locking/unlocking -// pairing. -class ListsLocker { -public: - ListsLocker(); - ~ListsLocker(); -}; - -// We must keep track of all of the child processes we have forked to -// handle attaching to a target process. This is necessary because we -// allow clients to detach from processes, but the child processes we -// fork must necessarily stay alive for the duration of the target -// application. A subsequent attach operation to the target process -// results in the same child process being reused. For this reason, -// child processes are known to be in one of two states: attached and -// detached. - -class ClientInfo; - -class ChildInfo { -public: - /** The pid of the ChildInfo indicates the process ID of the target - process which the subprocess was created to debug, not the pid - of the subprocess itself. */ - ChildInfo(DWORD pid, HANDLE childProcessHandle, - HANDLE writeToStdinHandle, HANDLE readFromStdoutHandle, - HANDLE auxHandle1, HANDLE auxHandle2); - - DWORD getPid(); - HANDLE getChildProcessHandle(); - HANDLE getWriteToStdinHandle(); - HANDLE getReadFromStdoutHandle(); - - /** Set the client which is currently attached to the target process - via this child process. Set this to NULL to indicate that the - child process is ready to accept another attachment. */ - void setClient(ClientInfo* clientInfo); - - ClientInfo* getClient(); - - /** This is NOT automatically called in the destructor */ - void closeAll(); - -private: - DWORD pid; - HANDLE childProcessHandle; - HANDLE writeToStdinHandle; - HANDLE readFromStdoutHandle; - HANDLE auxHandle1; - HANDLE auxHandle2; - ClientInfo* client; -}; - -// We keep track of a list of child debugger processes, each of which -// is responsible for debugging a certain target process. These -// debugger processes can serve multiple clients during their -// lifetime. When a client detaches from a given process or tells the -// debugger to "exit", the debug server is notified that the child -// process is once again available to accept connections from clients. - -class ChildList { -private: - typedef std::vector ChildInfoList; - -public: - ChildList(); - ~ChildList(); - - void addChild(ChildInfo*); - - /** Removes and returns the ChildInfo* associated with the given - child process handle. */ - ChildInfo* removeChild(HANDLE childProcessHandle); - - /** Removes the given ChildInfo. */ - void removeChild(ChildInfo* info); - - /** Return the ChildInfo* associated with a given process ID without - removing it from the list. */ - ChildInfo* getChildByPid(DWORD pid); - - /** Iteration support */ - int size(); - - /** Iteration support */ - ChildInfo* getChildByIndex(int index); - -private: - ChildInfoList childList; -}; - -// We also keep a list of clients whose requests we are responsible -// for serving. Clients can attach and detach from child processes. - -class ClientInfo { -public: - ClientInfo(SOCKET dataSocket); - ~ClientInfo(); - - SOCKET getDataSocket(); - /** Gets an IOBuf configured for the data socket, which should be - used for all communication with the client. */ - IOBuf* getIOBuf(); - - /** Set the information for the process to which this client is - attached. Set this to NULL to indicate that the client is not - currently attached to any target process. */ - void setTarget(ChildInfo* childInfo); - - /** Get the information for the process to which this client is - currently attached, or NULL if none. */ - ChildInfo* getTarget(); - - /** Close down the socket connection to this client. This is NOT - automatically called by the destructor. */ - void closeAll(); - -private: - SOCKET dataSocket; - IOBuf* buf; - ChildInfo* target; -}; - -class ClientList { -private: - typedef std::vector ClientInfoList; - -public: - ClientList(); - ~ClientList(); - - /** Adds a client to the list. */ - void addClient(ClientInfo* info); - - /** Check to see whether the parent socket of any of the ClientInfo - objects is readable in the given fd_set. If so, returns TRUE and - sets the given ClientInfo* (a non-NULL pointer to which must be - given) appropriately. */ - bool isAnyDataSocketSet(fd_set* fds, ClientInfo** info); - - /** Removes a client from the list. User is responsible for deleting - the ClientInfo* using operator delete. */ - void removeClient(ClientInfo* client); - - /** Iteration support. */ - int size(); - - /** Iteration support. */ - ClientInfo* get(int num); - -private: - ClientInfoList clientList; -}; - -#endif // #defined _SERVER_LISTS_ diff --git a/hotspot/agent/src/os/win32/toolHelp.cpp b/hotspot/agent/src/os/win32/toolHelp.cpp deleted file mode 100644 index be4dca7fd17..00000000000 --- a/hotspot/agent/src/os/win32/toolHelp.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "toolHelp.hpp" -#include - -namespace ToolHelp { - -static HMODULE kernelDLL = NULL; - -HMODULE loadDLL() { - if (kernelDLL == NULL) { - kernelDLL = LoadLibrary("KERNEL32.DLL"); - } - - assert(kernelDLL != NULL); - return kernelDLL; -} - -void unloadDLL() { - if (kernelDLL != NULL) { - FreeLibrary(kernelDLL); - kernelDLL = NULL; - } -} - -} // namespace ToolHelp diff --git a/hotspot/agent/src/os/win32/toolHelp.hpp b/hotspot/agent/src/os/win32/toolHelp.hpp deleted file mode 100644 index deb34557305..00000000000 --- a/hotspot/agent/src/os/win32/toolHelp.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef _TOOLHELP_H_ -#define _TOOLHELP_H_ - -#include -#include - -namespace ToolHelp { -extern "C" { - - /////////////// - // Snapshots // - /////////////// - typedef HANDLE WINAPI - CreateToolhelp32SnapshotFunc(DWORD dwFlags, DWORD th32ProcessID); - - ////////////////// - // Process List // - ////////////////// - typedef BOOL WINAPI Process32FirstFunc(HANDLE hSnapshot, - LPPROCESSENTRY32 lppe); - - typedef BOOL WINAPI Process32NextFunc(HANDLE hSnapshot, - LPPROCESSENTRY32 lppe); - - // NOTE: although these routines are defined in TLHELP32.H, they - // seem to always return false (maybe only under US locales) - typedef BOOL WINAPI Process32FirstWFunc(HANDLE hSnapshot, - LPPROCESSENTRY32W lppe); - - typedef BOOL WINAPI Process32NextWFunc(HANDLE hSnapshot, - LPPROCESSENTRY32W lppe); - - ///////////////// - // Module List // - ///////////////// - typedef BOOL WINAPI - Module32FirstFunc(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - - typedef BOOL WINAPI - Module32NextFunc (HANDLE hSnapshot, LPMODULEENTRY32 lpme); - - - // Routines to load and unload KERNEL32.DLL. - HMODULE loadDLL(); - // Safe to call even if has not been loaded - void unloadDLL(); - -} // extern "C" -} // namespace "ToolHelp" - -#endif // #defined _TOOLHELP_H_ diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java index 1594818f9cf..5071235fa3e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CLHSDB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,6 +170,7 @@ public class CLHSDB { final String errMsg = formatMessage(e.getMessage(), 80); System.err.println("Unable to connect to process ID " + pid + ":\n\n" + errMsg); agent.detach(); + e.printStackTrace(); return; } } @@ -191,6 +192,7 @@ public class CLHSDB { final String errMsg = formatMessage(e.getMessage(), 80); System.err.println("Unable to open core file\n" + corePath + ":\n\n" + errMsg); agent.detach(); + e.printStackTrace(); return; } } @@ -209,6 +211,7 @@ public class CLHSDB { final String errMsg = formatMessage(e.getMessage(), 80); System.err.println("Unable to connect to machine \"" + remoteMachineName + "\":\n\n" + errMsg); agent.detach(); + e.printStackTrace(); return; } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java index 96cfe83e826..8c5f2a6d54f 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -40,6 +40,8 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.interpreter.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.opto.*; +import sun.jvm.hotspot.ci.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.utilities.*; import sun.jvm.hotspot.utilities.soql.*; @@ -48,6 +50,8 @@ import sun.jvm.hotspot.ui.tree.*; import sun.jvm.hotspot.tools.*; import sun.jvm.hotspot.tools.ObjectHistogram; import sun.jvm.hotspot.tools.StackTrace; +import sun.jvm.hotspot.tools.jcore.ClassDump; +import sun.jvm.hotspot.tools.jcore.ClassFilter; public class CommandProcessor { public abstract static class DebuggerInterface { @@ -59,6 +63,27 @@ public class CommandProcessor { public abstract void reattach(); } + public static class BootFilter implements ClassFilter { + public boolean canInclude(InstanceKlass kls) { + return kls.getClassLoader() == null; + } + } + + public static class NonBootFilter implements ClassFilter { + private HashMap emitted = new HashMap(); + public boolean canInclude(InstanceKlass kls) { + if (kls.getClassLoader() == null) return false; + if (emitted.get(kls.getName()) != null) { + // Since multiple class loaders are being shoved + // together duplicate classes are a possibilty. For + // now just ignore them. + return false; + } + emitted.put(kls.getName(), kls); + return true; + } + } + static class Tokens { final String input; int i; @@ -258,9 +283,14 @@ public class CommandProcessor { } void dumpFields(Type type) { + dumpFields(type, true); + } + + void dumpFields(Type type, boolean allowStatic) { Iterator i = type.getFields(); while (i.hasNext()) { Field f = (Field) i.next(); + if (!allowStatic && f.isStatic()) continue; out.print("field "); quote(type.getName()); out.print(" "); @@ -458,13 +488,18 @@ public class CommandProcessor { }); } }, - new Command("flags", "flags [ flag ]", false) { + new Command("flags", "flags [ flag | -nd ]", false) { public void doit(Tokens t) { int tokens = t.countTokens(); if (tokens != 0 && tokens != 1) { usage(); } else { String name = tokens > 0 ? t.nextToken() : null; + boolean nonDefault = false; + if (name != null && name.equals("-nd")) { + name = null; + nonDefault = true; + } VM.Flag[] flags = VM.getVM().getCommandLineFlags(); if (flags == null) { @@ -474,7 +509,12 @@ public class CommandProcessor { for (int f = 0; f < flags.length; f++) { VM.Flag flag = flags[f]; if (name == null || flag.getName().equals(name)) { - out.println(flag.getName() + " = " + flag.getValue()); + + if (nonDefault && flag.getOrigin() == 0) { + // only print flags which aren't their defaults + continue; + } + out.println(flag.getName() + " = " + flag.getValue() + " " + flag.getOrigin()); printed = true; } } @@ -586,6 +626,158 @@ public class CommandProcessor { } } }, + new Command("printmdo", "printmdo [ -a | expression ]", false) { + // Print every MDO in the heap or the one referenced by expression. + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + } else { + String s = t.nextToken(); + if (s.equals("-a")) { + HeapVisitor iterator = new DefaultHeapVisitor() { + public boolean doObj(Oop obj) { + if (obj instanceof MethodData) { + Method m = ((MethodData)obj).getMethod(); + out.println("MethodData " + obj.getHandle() + " for " + + "method " + m.getMethodHolder().getName().asString() + "." + + m.getName().asString() + + m.getSignature().asString() + "@" + m.getHandle()); + ((MethodData)obj).printDataOn(out); + } + return false; + } + }; + VM.getVM().getObjectHeap().iteratePerm(iterator); + } else { + Address a = VM.getVM().getDebugger().parseAddress(s); + OopHandle handle = a.addOffsetToAsOopHandle(0); + MethodData mdo = (MethodData)VM.getVM().getObjectHeap().newOop(handle); + mdo.printDataOn(out); + } + } + } + }, + new Command("dumpideal", "dumpideal { -a | id }", false) { + // Do a full dump of the nodes reachabile from root in each compiler thread. + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + } else { + String name = t.nextToken(); + boolean all = name.equals("-a"); + Threads threads = VM.getVM().getThreads(); + for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + thread.printThreadIDOn(new PrintStream(bos)); + if (all || bos.toString().equals(name)) { + if (thread instanceof CompilerThread) { + CompilerThread ct = (CompilerThread)thread; + out.println(ct); + ciEnv env = ct.env(); + if (env != null) { + Compile c = env.compilerData(); + c.root().dump(9999, out); + } else { + out.println(" not compiling"); + } + } + } + } + } + } + }, + new Command("dumpcfg", "dumpcfg { -a | id }", false) { + // Dump the PhaseCFG for every compiler thread that has one live. + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + } else { + String name = t.nextToken(); + boolean all = name.equals("-a"); + Threads threads = VM.getVM().getThreads(); + for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + thread.printThreadIDOn(new PrintStream(bos)); + if (all || bos.toString().equals(name)) { + if (thread instanceof CompilerThread) { + CompilerThread ct = (CompilerThread)thread; + out.println(ct); + ciEnv env = ct.env(); + if (env != null) { + Compile c = env.compilerData(); + c.cfg().dump(out); + } + } + } + } + } + } + }, + new Command("dumpilt", "dumpilt { -a | id }", false) { + // dumps the InlineTree of a C2 compile + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + } else { + String name = t.nextToken(); + boolean all = name.equals("-a"); + Threads threads = VM.getVM().getThreads(); + for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + thread.printThreadIDOn(new PrintStream(bos)); + if (all || bos.toString().equals(name)) { + if (thread instanceof CompilerThread) { + CompilerThread ct = (CompilerThread)thread; + ciEnv env = ct.env(); + if (env != null) { + Compile c = env.compilerData(); + InlineTree ilt = c.ilt(); + if (ilt != null) { + ilt.print(out); + } + } + } + } + } + } + } + }, + new Command("vmstructsdump", "vmstructsdump", false) { + public void doit(Tokens t) { + if (t.countTokens() != 0) { + usage(); + return; + } + + // Dump a copy of the type database in a form that can + // be read back. + Iterator i = agent.getTypeDataBase().getTypes(); + // Make sure the types are emitted in an order than can be read back in + HashSet emitted = new HashSet(); + Stack pending = new Stack(); + while (i.hasNext()) { + Type n = (Type)i.next(); + if (emitted.contains(n.getName())) { + continue; + } + + while (n != null && !emitted.contains(n.getName())) { + pending.push(n); + n = n.getSuperclass(); + } + while (!pending.empty()) { + n = (Type)pending.pop(); + dumpType(n); + emitted.add(n.getName()); + } + } + i = agent.getTypeDataBase().getTypes(); + while (i.hasNext()) { + dumpFields((Type)i.next(), false); + } + } + }, + new Command("inspect", "inspect expression", false) { public void doit(Tokens t) { if (t.countTokens() != 1) { @@ -760,6 +952,50 @@ public class CommandProcessor { } } }, + new Command("intConstant", "intConstant [ name [ value ] ]", true) { + public void doit(Tokens t) { + if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) { + usage(); + return; + } + HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); + if (t.countTokens() == 1) { + out.println("intConstant " + name + " " + db.lookupIntConstant(name)); + } else if (t.countTokens() == 0) { + Iterator i = db.getIntConstants(); + while (i.hasNext()) { + String name = (String)i.next(); + out.println("intConstant " + name + " " + db.lookupIntConstant(name)); + } + } else if (t.countTokens() == 2) { + String name = t.nextToken(); + Integer value = Integer.valueOf(t.nextToken()); + db.addIntConstant(name, value); + } + } + }, + new Command("longConstant", "longConstant [ name [ value ] ]", true) { + public void doit(Tokens t) { + if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) { + usage(); + return; + } + HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); + if (t.countTokens() == 1) { + out.println("longConstant " + name + " " + db.lookupLongConstant(name)); + } else if (t.countTokens() == 0) { + Iterator i = db.getLongConstants(); + while (i.hasNext()) { + String name = (String)i.next(); + out.println("longConstant " + name + " " + db.lookupLongConstant(name)); + } + } else if (t.countTokens() == 2) { + String name = t.nextToken(); + Long value = Long.valueOf(t.nextToken()); + db.addLongConstant(name, value); + } + } + }, new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) { public void doit(Tokens t) { if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) { @@ -1311,13 +1547,13 @@ public class CommandProcessor { return; } - executeCommand(ln); + executeCommand(ln, prompt); } } static Pattern historyPattern = Pattern.compile("((!\\*)|(!\\$)|(!!-?)|(!-?[0-9][0-9]*)|(![a-zA-Z][^ ]*))"); - public void executeCommand(String ln) { + public void executeCommand(String ln, boolean putInHistory) { if (ln.indexOf('!') != -1) { int size = history.size(); if (size == 0) { @@ -1406,7 +1642,7 @@ public class CommandProcessor { Tokens t = new Tokens(ln); if (t.hasMoreTokens()) { boolean error = false; - history.add(ln); + if (putInHistory) history.add(ln); int len = t.countTokens(); if (len > 2) { String r = t.at(len - 2); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/DebugServer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/DebugServer.java index 3a5e91ae1e1..cb5d21b7a3f 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/DebugServer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/DebugServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.jvm.hotspot; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.oops.*; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java index fddbe3a69c9..0b655b8b1d6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,8 @@ import java.io.PrintStream; import java.net.*; import java.rmi.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.*; import sun.jvm.hotspot.debugger.proc.*; import sun.jvm.hotspot.debugger.remote.*; -import sun.jvm.hotspot.debugger.win32.*; import sun.jvm.hotspot.debugger.windbg.*; import sun.jvm.hotspot.debugger.linux.*; import sun.jvm.hotspot.memory.*; @@ -436,113 +434,35 @@ public class HotSpotAgent { private void setupDebuggerSolaris() { setupJVMLibNamesSolaris(); - if(System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger") != null) { - ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); - debugger = dbg; - attachDebugger(); + ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); + debugger = dbg; + attachDebugger(); - // Set up CPU-dependent stuff - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("sparc")) { - int addressSize = dbg.getRemoteProcessAddressSize(); - if (addressSize == -1) { - throw new DebuggerException("Error occurred while trying to determine the remote process's " + - "address size"); - } - - if (addressSize == 32) { - machDesc = new MachineDescriptionSPARC32Bit(); - } else if (addressSize == 64) { - machDesc = new MachineDescriptionSPARC64Bit(); - } else { - throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); - } - } else if (cpu.equals("amd64")) { - machDesc = new MachineDescriptionAMD64(); - } else { - throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); + // Set up CPU-dependent stuff + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("sparc")) { + int addressSize = dbg.getRemoteProcessAddressSize(); + if (addressSize == -1) { + throw new DebuggerException("Error occurred while trying to determine the remote process's " + + "address size"); } - dbg.setMachineDescription(machDesc); - return; - + if (addressSize == 32) { + machDesc = new MachineDescriptionSPARC32Bit(); + } else if (addressSize == 64) { + machDesc = new MachineDescriptionSPARC64Bit(); + } else { + throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); + } + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); } else { - String dbxPathName; - String dbxPathPrefix; - String dbxSvcAgentDSOPathName; - String dbxSvcAgentDSOPathPrefix; - String[] dbxSvcAgentDSOPathNames = null; - - // use path names/prefixes specified on command - dbxPathName = System.getProperty("dbxPathName"); - if (dbxPathName == null) { - dbxPathPrefix = System.getProperty("dbxPathPrefix"); - if (dbxPathPrefix == null) { - dbxPathPrefix = defaultDbxPathPrefix; - } - dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx"; - } - - dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName"); - if (dbxSvcAgentDSOPathName != null) { - dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName } ; - } else { - dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix"); - if (dbxSvcAgentDSOPathPrefix == null) { - dbxSvcAgentDSOPathPrefix = defaultDbxSvcAgentDSOPathPrefix; - } - if (cpu.equals("sparc")) { - dbxSvcAgentDSOPathNames = new String[] { - // FIXME: bad hack for SPARC v9. This is necessary because - // there are two dbx executables on SPARC, one for v8 and one - // for v9, and it isn't obvious how to tell the two apart - // using the dbx command line. See - // DbxDebuggerLocal.importDbxModule(). - dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" + - fileSep + "libsvc_agent_dbx.so", - dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + - fileSep + "libsvc_agent_dbx.so", - }; - } else { - dbxSvcAgentDSOPathNames = new String[] { - dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + - fileSep + "libsvc_agent_dbx.so" - }; - } - } - - // Note we do not use a cache for the local debugger in server - // mode; it's taken care of on the client side - DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer); - debugger = dbg; - - attachDebugger(); - - // Set up CPU-dependent stuff - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("sparc")) { - int addressSize = dbg.getRemoteProcessAddressSize(); - if (addressSize == -1) { - throw new DebuggerException("Error occurred while trying to determine the remote process's " + - "address size. It's possible that the Serviceability Agent's dbx module failed to " + - "initialize. Examine the standard output and standard error streams from the dbx " + - "process for more information."); - } - - if (addressSize == 32) { - machDesc = new MachineDescriptionSPARC32Bit(); - } else if (addressSize == 64) { - machDesc = new MachineDescriptionSPARC64Bit(); - } else { - throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); - } - } - - dbg.setMachineDescription(machDesc); - + throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); } + + dbg.setMachineDescription(machDesc); + return; } private void connectRemoteDebugger() throws DebuggerException { @@ -589,11 +509,7 @@ public class HotSpotAgent { // mode; it will be taken care of on the client side (once remote // debugging is implemented). - if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) { - debugger = new WindbgDebuggerLocal(machDesc, !isServer); - } else { - debugger = new Win32DebuggerLocal(machDesc, !isServer); - } + debugger = new WindbgDebuggerLocal(machDesc, !isServer); attachDebugger(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java index fd35915831f..fd9ff6222b0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @@ -87,6 +87,7 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { readVMStructs(); readVMIntConstants(); readVMLongConstants(); + readExternalDefinitions(); } public Type lookupType(String cTypeName, boolean throwException) { @@ -98,9 +99,9 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false); } if (fieldType == null) { - if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">*")) { + if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">")) { String ttype = cTypeName.substring("GrowableArray<".length(), - cTypeName.length() - 2); + cTypeName.length() - 1); Type templateType = lookupType(ttype, false); if (templateType == null && typeNameIsPointerType(ttype)) { templateType = recursiveCreateBasicPointerType(ttype); @@ -108,7 +109,21 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { if (templateType == null) { lookupOrFail(ttype); } - fieldType = recursiveCreateBasicPointerType(cTypeName); + + BasicType basicTargetType = createBasicType(cTypeName, false, false, false); + + // transfer fields from GenericGrowableArray to template instance + BasicType generic = lookupOrFail("GenericGrowableArray"); + BasicType specific = lookupOrFail("GrowableArray"); + basicTargetType.setSize(specific.getSize()); + Iterator fields = generic.getFields(); + while (fields.hasNext()) { + Field f = (Field)fields.next(); + basicTargetType.addField(internalCreateField(basicTargetType, f.getName(), + f.getType(), f.isStatic(), + f.getOffset(), null)); + } + fieldType = basicTargetType; } } if (fieldType == null && typeNameIsPointerType(cTypeName)) { @@ -208,6 +223,156 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { return type; } + private void readExternalDefinitions() { + String file = System.getProperty("sun.jvm.hotspot.typedb"); + if (file != null) { + System.out.println("Reading " + file); + BufferedReader in = null; + try { + StreamTokenizer t = new StreamTokenizer(in = new BufferedReader(new InputStreamReader(new FileInputStream(file)))); + t.resetSyntax(); + t.wordChars('\u0000','\uFFFF'); + t.whitespaceChars(' ', ' '); + t.whitespaceChars('\n', '\n'); + t.whitespaceChars('\r', '\r'); + t.quoteChar('\"'); + t.eolIsSignificant(true); + while (t.nextToken() != StreamTokenizer.TT_EOF) { + if (t.ttype == StreamTokenizer.TT_EOL) { + continue; + } + + if (t.sval.equals("field")) { + t.nextToken(); + BasicType containingType = (BasicType)lookupType(t.sval); + t.nextToken(); + String fieldName = t.sval; + + // The field's Type must already be in the database -- no exceptions + t.nextToken(); + Type fieldType = lookupType(t.sval); + t.nextToken(); + boolean isStatic = Boolean.valueOf(t.sval).booleanValue(); + t.nextToken(); + long offset = Long.parseLong(t.sval); + t.nextToken(); + Address staticAddress = null; + if (isStatic) { + throw new InternalError("static fields not supported"); + } + + // check to see if the field already exists + Iterator i = containingType.getFields(); + boolean defined = false; + while (i.hasNext()) { + Field f = (Field) i.next(); + if (f.getName().equals(fieldName)) { + if (f.isStatic() != isStatic) { + throw new RuntimeException("static/nonstatic mismatch: " + fieldName); + } + if (!isStatic) { + if (f.getOffset() != offset) { + throw new RuntimeException("bad redefinition of field offset: " + fieldName); + } + } else { + if (!f.getStaticFieldAddress().equals(staticAddress)) { + throw new RuntimeException("bad redefinition of field location: " + fieldName); + } + } + if (f.getType() != fieldType) { + System.out.println(fieldType); + System.out.println(f.getType()); + throw new RuntimeException("bad redefinition of field type: " + fieldName); + } + defined = true; + break; + } + } + + if (!defined) { + // Create field by type + createField(containingType, + fieldName, fieldType, + isStatic, + offset, + staticAddress); + } + } else if (t.sval.equals("type")) { + t.nextToken(); + String typeName = t.sval; + t.nextToken(); + String superclassName = t.sval; + if (superclassName.equals("null")) { + superclassName = null; + } + t.nextToken(); + boolean isOop = Boolean.valueOf(t.sval).booleanValue(); + t.nextToken(); + boolean isInteger = Boolean.valueOf(t.sval).booleanValue(); + t.nextToken(); + boolean isUnsigned = Boolean.valueOf(t.sval).booleanValue(); + t.nextToken(); + long size = Long.parseLong(t.sval); + + BasicType type = null; + try { + type = (BasicType)lookupType(typeName); + } catch (RuntimeException e) { + } + if (type != null) { + if (type.isOopType() != isOop) { + throw new RuntimeException("oop mismatch in type definition: " + typeName); + } + if (type.isCIntegerType() != isInteger) { + throw new RuntimeException("integer type mismatch in type definition: " + typeName); + } + if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) { + throw new RuntimeException("unsigned mismatch in type definition: " + typeName); + } + if (type.getSuperclass() == null) { + if (superclassName != null) { + if (type.getSize() == -1) { + type.setSuperclass(lookupType(superclassName)); + } else { + throw new RuntimeException("unexpected superclass in type definition: " + typeName); + } + } + } else { + if (superclassName == null) { + throw new RuntimeException("missing superclass in type definition: " + typeName); + } + if (!type.getSuperclass().getName().equals(superclassName)) { + throw new RuntimeException("incorrect superclass in type definition: " + typeName); + } + } + if (type.getSize() != size) { + if (type.getSize() == -1 || type.getSize() == 0) { + type.setSize(size); + } else { + throw new RuntimeException("size mismatch in type definition: " + typeName + ": " + type.getSize() + " != " + size); + } + } + } + + if (lookupType(typeName, false) == null) { + // Create type + createType(typeName, superclassName, isOop, isInteger, isUnsigned, size); + } + } else { + throw new InternalError("\"" + t.sval + "\""); + } + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + try { + in.close(); + } catch (Exception e) { + } + } + } + } + private void readVMStructs() { // Get the variables we need in order to traverse the VMStructEntry[] long structEntryTypeNameOffset; @@ -504,20 +669,6 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); basicTargetType.setSize(1); targetType = basicTargetType; - } else if (targetTypeName.startsWith("GrowableArray<")) { - BasicType basicTargetType = createBasicType(targetTypeName, false, false, false); - - // transfer fields from GenericGrowableArray to template instance - BasicType generic = lookupOrFail("GenericGrowableArray"); - basicTargetType.setSize(generic.getSize()); - Iterator fields = generic.getFields(); - while (fields.hasNext()) { - Field f = (Field)fields.next(); - basicTargetType.addField(internalCreateField(basicTargetType, f.getName(), - f.getType(), f.isStatic(), - f.getOffset(), null)); - } - targetType = basicTargetType; } else { if (DEBUG) { System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); @@ -572,7 +723,7 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { // Classes are created with a size of UNINITIALIZED_SIZE. // Set size if necessary. - if (curType.getSize() == UNINITIALIZED_SIZE) { + if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) { curType.setSize(size); } else { if (curType.getSize() != size) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/TestDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/TestDebugger.java index 5798a408f41..a0b0a993654 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/TestDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/TestDebugger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,12 @@ package sun.jvm.hotspot; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.*; +import sun.jvm.hotspot.debugger.proc.*; // A test of the debugger backend. This should be used to connect to // the helloWorld.cpp program. public class TestDebugger { - // FIXME: make these configurable, i.e., via a dotfile - private static final String dbxPathName = "/export/home/kbr/ws/dbx_61/dev/Derived-sparcv9-S2./src/dbx/dbx"; - private static final String[] dbxSvcAgentDSOPathNames = - new String[] { - "/export/home/kbr/main/sa_baseline/src/os/solaris/agent/libsvc_agent_dbx.so" - }; private static void usage() { System.out.println("usage: java TestDebugger [pid]"); @@ -58,8 +52,7 @@ public class TestDebugger { usage(); } - JVMDebugger debugger = new DbxDebuggerLocal(new MachineDescriptionSPARC64Bit(), - dbxPathName, dbxSvcAgentDSOPathNames, true); + JVMDebugger debugger = new ProcDebuggerLocal(null, true); try { debugger.attach(pid); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java index f92520667b2..668fba78372 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ import javax.swing.filechooser.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.posix.*; -import sun.jvm.hotspot.debugger.win32.*; +import sun.jvm.hotspot.debugger.windbg.*; import sun.jvm.hotspot.livejvm.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; @@ -604,7 +604,7 @@ public class BugSpot extends JPanel { throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Windows"); } - localDebugger = new Win32DebuggerLocal(new MachineDescriptionIntelX86(), true); + localDebugger = new WindbgDebuggerLocal(new MachineDescriptionIntelX86(), true); } else if (os.equals("linux")) { if (!cpu.equals("x86")) { throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Linux"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java index 84071dc247b..8a5abc8a9ff 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,8 @@ import java.net.*; import java.rmi.*; import sun.jvm.hotspot.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.*; import sun.jvm.hotspot.debugger.proc.*; import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.debugger.win32.*; import sun.jvm.hotspot.debugger.windbg.*; import sun.jvm.hotspot.debugger.linux.*; import sun.jvm.hotspot.debugger.sparc.*; @@ -627,104 +625,33 @@ public class BugSpotAgent { private void setupDebuggerSolaris() { setupJVMLibNamesSolaris(); - String prop = System.getProperty("sun.jvm.hotspot.debugger.useProcDebugger"); - if (prop != null && !prop.equals("false")) { - ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); - debugger = dbg; - attachDebugger(); + ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); + debugger = dbg; + attachDebugger(); - // Set up CPU-dependent stuff - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("sparc")) { - int addressSize = dbg.getRemoteProcessAddressSize(); - if (addressSize == -1) { - throw new DebuggerException("Error occurred while trying to determine the remote process's address size"); - } - - if (addressSize == 32) { - machDesc = new MachineDescriptionSPARC32Bit(); - } else if (addressSize == 64) { - machDesc = new MachineDescriptionSPARC64Bit(); - } else { - throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); - } - } else if (cpu.equals("amd64")) { - machDesc = new MachineDescriptionAMD64(); - } else { - throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); + // Set up CPU-dependent stuff + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("sparc")) { + int addressSize = dbg.getRemoteProcessAddressSize(); + if (addressSize == -1) { + throw new DebuggerException("Error occurred while trying to determine the remote process's address size"); } - dbg.setMachineDescription(machDesc); - return; + if (addressSize == 32) { + machDesc = new MachineDescriptionSPARC32Bit(); + } else if (addressSize == 64) { + machDesc = new MachineDescriptionSPARC64Bit(); + } else { + throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); + } + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); } else { - String dbxPathName; - String dbxPathPrefix; - String dbxSvcAgentDSOPathName; - String dbxSvcAgentDSOPathPrefix; - String[] dbxSvcAgentDSOPathNames = null; - - // use path names/prefixes specified on command - dbxPathName = System.getProperty("dbxPathName"); - if (dbxPathName == null) { - dbxPathPrefix = System.getProperty("dbxPathPrefix"); - if (dbxPathPrefix == null) { - dbxPathPrefix = defaultDbxPathPrefix; - } - dbxPathName = dbxPathPrefix + fileSep + os + fileSep + cpu + fileSep + "bin" + fileSep + "dbx"; - } - - dbxSvcAgentDSOPathName = System.getProperty("dbxSvcAgentDSOPathName"); - if (dbxSvcAgentDSOPathName != null) { - dbxSvcAgentDSOPathNames = new String[] { dbxSvcAgentDSOPathName } ; - } else { - dbxSvcAgentDSOPathPrefix = System.getProperty("dbxSvcAgentDSOPathPrefix"); - if (dbxSvcAgentDSOPathPrefix == null) { - dbxSvcAgentDSOPathPrefix = defaultDbxSvcAgentDSOPathPrefix; - } - if (cpu.equals("sparc")) { - dbxSvcAgentDSOPathNames = new String[] { - // FIXME: bad hack for SPARC v9. This is necessary because - // there are two dbx executables on SPARC, one for v8 and one - // for v9, and it isn't obvious how to tell the two apart - // using the dbx command line. See - // DbxDebuggerLocal.importDbxModule(). - dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + "v9" + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so", - dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so", - }; - } else { - dbxSvcAgentDSOPathNames = new String[] { - dbxSvcAgentDSOPathPrefix + fileSep + os + fileSep + cpu + fileSep + "lib" + fileSep + "libsvc_agent_dbx.so" - }; - } - } - // Note we do not use a cache for the local debugger in server - // mode; it's taken care of on the client side - DbxDebuggerLocal dbg = new DbxDebuggerLocal(null, dbxPathName, dbxSvcAgentDSOPathNames, !isServer); - debugger = dbg; - - attachDebugger(); - - // Set up CPU-dependent stuff - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("sparc")) { - int addressSize = dbg.getRemoteProcessAddressSize(); - if (addressSize == -1) { - throw new DebuggerException("Error occurred while trying to determine the remote process's address size. It's possible that the Serviceability Agent's dbx module failed to initialize. Examine the standard output and standard error streams from the dbx process for more information."); - } - - if (addressSize == 32) { - machDesc = new MachineDescriptionSPARC32Bit(); - } else if (addressSize == 64) { - machDesc = new MachineDescriptionSPARC64Bit(); - } else { - throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); - } - } - - dbg.setMachineDescription(machDesc); + throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); } + + dbg.setMachineDescription(machDesc); } private void connectRemoteDebugger() throws DebuggerException { @@ -772,11 +699,7 @@ public class BugSpotAgent { // mode; it will be taken care of on the client side (once remote // debugging is implemented). - if (System.getProperty("sun.jvm.hotspot.debugger.useWindbgDebugger") != null) { - debugger = new WindbgDebuggerLocal(machDesc, !isServer); - } else { - debugger = new Win32DebuggerLocal(machDesc, !isServer); - } + debugger = new WindbgDebuggerLocal(machDesc, !isServer); attachDebugger(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java new file mode 100644 index 00000000000..1be16eac97e --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlass.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciArrayKlass extends ciKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciArrayKlass"); + dimensionField = new IntField(type.getJIntField("_dimension"), 0); + } + + private static IntField dimensionField; + + public ciArrayKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlassKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlassKlass.java new file mode 100644 index 00000000000..d18810587f0 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciArrayKlassKlass.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciArrayKlassKlass extends ciKlassKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciArrayKlassKlass"); + } + + + public ciArrayKlassKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java new file mode 100644 index 00000000000..ab69f43984d --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciConstant extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciConstant"); + valueObjectField = type.getAddressField("_value._object"); + valueDoubleField = type.getJDoubleField("_value._double"); + valueFloatField = type.getJFloatField("_value._float"); + valueLongField = type.getJLongField("_value._long"); + valueIntField = type.getJIntField("_value._int"); + typeField = new CIntField(type.getCIntegerField("_type"), 0); + } + + private static AddressField valueObjectField; + private static JDoubleField valueDoubleField; + private static JFloatField valueFloatField; + private static JLongField valueLongField; + private static JIntField valueIntField; + private static CIntField typeField; + + public ciConstant(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java new file mode 100644 index 00000000000..eb48eedb330 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.opto.*; +import sun.jvm.hotspot.compiler.CompileTask; +import sun.jvm.hotspot.prims.JvmtiExport; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.GrowableArray; + +public class ciEnv extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciEnv"); + dependenciesField = type.getAddressField("_dependencies"); + factoryField = type.getAddressField("_factory"); + compilerDataField = type.getAddressField("_compiler_data"); + taskField = type.getAddressField("_task"); + systemDictionaryModificationCounterField = new CIntField(type.getCIntegerField("_system_dictionary_modification_counter"), 0); + } + + private static AddressField dependenciesField; + private static AddressField factoryField; + private static AddressField compilerDataField; + private static AddressField taskField; + private static CIntField systemDictionaryModificationCounterField; + + public ciEnv(Address addr) { + super(addr); + } + + public Compile compilerData() { + return new Compile(compilerDataField.getValue(this.getAddress())); + } + + public ciObjectFactory factory() { + return new ciObjectFactory(factoryField.getValue(this.getAddress())); + } + + public CompileTask task() { + return new CompileTask(taskField.getValue(this.getAddress())); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciField.java new file mode 100644 index 00000000000..80b1b337394 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciField.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciField extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciField"); + constantValueField = type.getAddressField("_constant_value"); + isConstantField = type.getAddressField("_is_constant"); + offsetField = new CIntField(type.getCIntegerField("_offset"), 0); + signatureField = type.getAddressField("_signature"); + nameField = type.getAddressField("_name"); + holderField = type.getAddressField("_holder"); + } + + private static AddressField constantValueField; + private static AddressField isConstantField; + private static CIntField offsetField; + private static AddressField signatureField; + private static AddressField nameField; + private static AddressField holderField; + + public ciField(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstance.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstance.java new file mode 100644 index 00000000000..6a59cabd7f5 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstance.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciInstance extends ciObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciInstance"); + } + + + public ciInstance(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java new file mode 100644 index 00000000000..df498c17b0b --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.memory.SystemDictionary; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; +import sun.jvm.hotspot.types.WrongTypeException; + +public class ciInstanceKlass extends ciKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciInstanceKlass"); + initStateField = new CIntField(type.getCIntegerField("_init_state"), 0); + isSharedField = new CIntField(type.getCIntegerField("_is_shared"), 0); + CLASS_STATE_LINKED = db.lookupIntConstant("instanceKlass::linked").intValue(); + CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("instanceKlass::fully_initialized").intValue(); + } + + private static CIntField initStateField; + private static CIntField isSharedField; + private static int CLASS_STATE_LINKED; + private static int CLASS_STATE_FULLY_INITIALIZED; + + public ciInstanceKlass(Address addr) { + super(addr); + } + + public int initState() { + int initState = (int)initStateField.getValue(getAddress()); + if (isShared() && initState < CLASS_STATE_LINKED) { + InstanceKlass ik = (InstanceKlass)getOop(); + initState = ik.getInitStateAsInt(); + } + return initState; + } + + public boolean isShared() { + return isSharedField.getValue(getAddress()) != 0; + } + + public boolean isLinked() { + return initState() >= CLASS_STATE_LINKED; + } + + public boolean isInitialized() { + return initState() == CLASS_STATE_FULLY_INITIALIZED; + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThreadFactory.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlassKlass.java similarity index 50% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThreadFactory.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlassKlass.java index 89564cbcef6..b20f036d4b6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThreadFactory.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlassKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,29 +16,35 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. * */ -package sun.jvm.hotspot.debugger.dbx.sparc; +package sun.jvm.hotspot.ci; +import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; -public class DbxSPARCThreadFactory implements DbxThreadFactory { - private DbxDebugger debugger; - - public DbxSPARCThreadFactory(DbxDebugger debugger) { - this.debugger = debugger; +public class ciInstanceKlassKlass extends ciKlassKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); } - public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { - return new DbxSPARCThread(debugger, threadIdentifierAddr); + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciInstanceKlassKlass"); } - public ThreadProxy createThreadWrapper(long id) { - return new DbxSPARCThread(debugger, id); + + public ciInstanceKlassKlass(Address addr) { + super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlass.java new file mode 100644 index 00000000000..fc92044e024 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlass.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciKlass extends ciType { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciKlass"); + nameField = type.getAddressField("_name"); + } + + private static AddressField nameField; + + public String name() { + ciSymbol sym = new ciSymbol(nameField.getValue(getAddress())); + return sym.asUtf88(); + } + + public ciKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlassKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlassKlass.java new file mode 100644 index 00000000000..f8d4db10767 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciKlassKlass.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciKlassKlass extends ciKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciKlassKlass"); + } + + + public ciKlassKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java new file mode 100644 index 00000000000..c0ae5762905 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.code.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciMethod extends ciObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciMethod"); + interpreterThrowoutCountField = new CIntField(type.getCIntegerField("_interpreter_throwout_count"), 0); + interpreterInvocationCountField = new CIntField(type.getCIntegerField("_interpreter_invocation_count"), 0); + try { + // XXX + instructionsSizeField = new CIntField(type.getCIntegerField("_instructions_size"), 0); + } catch (Exception e) { + } + } + + private static CIntField interpreterThrowoutCountField; + private static CIntField interpreterInvocationCountField; + private static CIntField instructionsSizeField; + + public ciMethod(Address addr) { + super(addr); + } + + public Method method() { + return (Method)getOop(); + } + + public int interpreterThrowoutCount() { + return (int) interpreterThrowoutCountField.getValue(getAddress()); + } + + public int interpreterInvocationCount() { + return (int) interpreterInvocationCountField.getValue(getAddress()); + } + + public int instructionsSize() { + if (instructionsSizeField == null) { + // XXX + Method method = (Method)getOop(); + NMethod nm = method.getNativeMethod(); + if (nm != null) return (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint()); + return 0; + } + return (int) instructionsSizeField.getValue(getAddress()); + } + + public void printShortName(PrintStream st) { + Method method = (Method)getOop(); + st.printf(" %s::%s", method.getMethodHolder().getName().asString().replace('/', '.'), + method.getName().asString()); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java new file mode 100644 index 00000000000..ca5628db156 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciMethodData extends ciObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciMethodData"); + origField = type.getAddressField("_orig"); + currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0); + argReturnedField = new CIntField(type.getCIntegerField("_arg_returned"), 0); + argStackField = new CIntField(type.getCIntegerField("_arg_stack"), 0); + argLocalField = new CIntField(type.getCIntegerField("_arg_local"), 0); + eflagsField = new CIntField(type.getCIntegerField("_eflags"), 0); + hintDiField = new CIntField(type.getCIntegerField("_hint_di"), 0); + currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0); + dataField = type.getAddressField("_data"); + extraDataSizeField = new CIntField(type.getCIntegerField("_extra_data_size"), 0); + dataSizeField = new CIntField(type.getCIntegerField("_data_size"), 0); + stateField = new CIntField(type.getCIntegerField("_state"), 0); + sizeofMethodDataOopDesc = (int)db.lookupType("methodDataOopDesc").getSize();; + } + + private static AddressField origField; + private static CIntField currentMileageField; + private static CIntField argReturnedField; + private static CIntField argStackField; + private static CIntField argLocalField; + private static CIntField eflagsField; + private static CIntField hintDiField; + private static AddressField dataField; + private static CIntField extraDataSizeField; + private static CIntField dataSizeField; + private static CIntField stateField; + private static int sizeofMethodDataOopDesc; + + public ciMethodData(Address addr) { + super(addr); + } + + private byte[] fetchDataAt(Address base, long size) { + byte[] result = new byte[(int)size]; + for (int i = 0; i < size; i++) { + result[i] = base.getJByteAt(i); + } + return result; + } + + public byte[] orig() { + // fetch the orig methodDataOopDesc data between header and dataSize + Address base = getAddress().addOffsetTo(origField.getOffset()); + byte[] result = new byte[MethodData.sizeofMethodDataOopDesc]; + for (int i = 0; i < MethodData.sizeofMethodDataOopDesc; i++) { + result[i] = base.getJByteAt(i); + } + return result; + } + + public long[] data() { + // Read the data as an array of intptr_t elements + Address base = dataField.getValue(getAddress()); + int elements = dataSize() / MethodData.cellSize; + long[] result = new long[elements]; + for (int i = 0; i < elements; i++) { + Address value = base.getAddressAt(i * MethodData.cellSize); + if (value != null) { + result[i] = value.minus(null); + } + } + return result; + } + + int dataSize() { + return (int)dataSizeField.getValue(getAddress()); + } + + int state() { + return (int)stateField.getValue(getAddress()); + } + + int currentMileage() { + return (int)currentMileageField.getValue(getAddress()); + } + + boolean outOfBounds(int dataIndex) { + return dataIndex >= dataSize(); + } + + ProfileData dataAt(int dataIndex) { + if (outOfBounds(dataIndex)) { + return null; + } + DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), dataIndex); + + switch (dataLayout.tag()) { + case DataLayout.noTag: + default: + throw new InternalError(); + case DataLayout.bitDataTag: + return new BitData(dataLayout); + case DataLayout.counterDataTag: + return new CounterData(dataLayout); + case DataLayout.jumpDataTag: + return new JumpData(dataLayout); + case DataLayout.receiverTypeDataTag: + return new ciReceiverTypeData(dataLayout); + case DataLayout.virtualCallDataTag: + return new ciVirtualCallData(dataLayout); + case DataLayout.retDataTag: + return new RetData(dataLayout); + case DataLayout.branchDataTag: + return new BranchData(dataLayout); + case DataLayout.multiBranchDataTag: + return new MultiBranchData(dataLayout); + } + } + + int dpToDi(int dp) { + return dp; + } + + int firstDi() { return 0; } + ProfileData firstData() { return dataAt(firstDi()); } + ProfileData nextData(ProfileData current) { + int currentIndex = dpToDi(current.dp()); + int nextIndex = currentIndex + current.sizeInBytes(); + return dataAt(nextIndex); + } + boolean isValid(ProfileData current) { return current != null; } + + public void printDataOn(PrintStream st) { + ProfileData data = firstData(); + for ( ; isValid(data); data = nextData(data)) { + st.print(dpToDi(data.dp())); + st.print(" "); + // st->fillTo(6); + data.printDataOn(st); + } + } + +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodKlass.java new file mode 100644 index 00000000000..918de7766af --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodKlass.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciMethodKlass extends ciKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciMethodKlass"); + } + + + public ciMethodKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java new file mode 100644 index 00000000000..c412dee7237 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlass.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciObjArrayKlass extends ciArrayKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciObjArrayKlass"); + elementKlassField = type.getAddressField("_element_klass"); + baseElementKlassField = type.getAddressField("_base_element_klass"); + } + + private static AddressField elementKlassField; + private static AddressField baseElementKlassField; + + public ciObjArrayKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlassKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlassKlass.java new file mode 100644 index 00000000000..98078b0d277 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjArrayKlassKlass.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciObjArrayKlassKlass extends ciArrayKlassKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciObjArrayKlassKlass"); + } + + + public ciObjArrayKlassKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObject.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObject.java new file mode 100644 index 00000000000..efd33d9ad61 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObject.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciObject extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciObject"); + identField = new CIntField(type.getCIntegerField("_ident"), 0); + klassField = type.getAddressField("_klass"); + handleField = type.getAddressField("_handle"); + } + + private static CIntField identField; + private static AddressField klassField; + private static AddressField handleField; + + public Oop getOop() { + OopHandle oh = handleField.getValue(getAddress()).getOopHandleAt(0); + return VM.getVM().getObjectHeap().newOop(oh); + } + + public ciObject(Address addr) { + super(addr); + } + + public void printOn(PrintStream out) { + getOop().printValueOn(out); + out.println(); + } + + public String toString() { + return getOop().toString(); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java new file mode 100644 index 00000000000..23f074b1b83 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciObjectFactory.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.lang.reflect.Constructor; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciObjectFactory extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciObjectFactory"); + unloadedMethodsField = type.getAddressField("_unloaded_methods"); + ciObjectsField = type.getAddressField("_ci_objects"); + symbolsField = type.getAddressField("_symbols"); + + ciObjectConstructor = new VirtualBaseConstructor(db, db.lookupType("ciObject"), "sun.jvm.hotspot.ci", ciObject.class); + ciSymbolConstructor = new VirtualBaseConstructor(db, db.lookupType("ciSymbol"), "sun.jvm.hotspot.ci", ciSymbol.class); + } + + private static AddressField unloadedMethodsField; + private static AddressField ciObjectsField; + private static AddressField symbolsField; + + private static VirtualBaseConstructor ciObjectConstructor; + private static VirtualBaseConstructor ciSymbolConstructor; + + public static ciObject get(Address addr) { + if (addr == null) return null; + + return (ciObject)ciObjectConstructor.instantiateWrapperFor(addr); + } + + public GrowableArray objects() { + return GrowableArray.create(ciObjectsField.getValue(getAddress()), ciObjectConstructor); + } + + public GrowableArray symbols() { + return GrowableArray.create(symbolsField.getValue(getAddress()), ciSymbolConstructor); + } + + public ciObjectFactory(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciReceiverTypeData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciReceiverTypeData.java new file mode 100644 index 00000000000..f391f5d4ae2 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciReceiverTypeData.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciReceiverTypeData extends ReceiverTypeData { + public ciReceiverTypeData(DataLayout data) { + super(data); + } + + public Klass receiver(int row) { + throw new InternalError("should not call"); + } + + public ciKlass receiverAt(int row) { + //assert((uint)row < rowLimit(), "oob"); + ciObject recv = ciObjectFactory.get(addressAt(receiverCellIndex(row))); + if (recv != null && !(recv instanceof ciKlass)) { + System.err.println(recv); + } + //assert(recv == NULL || recv->isKlass(), "wrong type"); + return (ciKlass)recv; + } + +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciSymbol.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciSymbol.java new file mode 100644 index 00000000000..3023e250f78 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciSymbol.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciSymbol extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciSymbol"); + identField = type.getCIntegerField("_ident"); + symbolField = type.getAddressField("_symbol"); + } + + private static AddressField symbolField; + private static CIntegerField identField; + + public String asUtf88() { + Symbol sym = Symbol.create(symbolField.getValue(getAddress())); + return sym.asString(); + } + + public ciSymbol(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciType.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciType.java new file mode 100644 index 00000000000..5f6d773f093 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciType.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciType extends ciObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciType"); + basicTypeField = new CIntField(type.getCIntegerField("_basic_type"), 0); + } + + private static CIntField basicTypeField; + + public ciType(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java new file mode 100644 index 00000000000..cc0281784d1 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlass.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciTypeArrayKlass extends ciArrayKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciTypeArrayKlass"); + } + + public ciTypeArrayKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlassKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlassKlass.java new file mode 100644 index 00000000000..4432e1f317b --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciTypeArrayKlassKlass.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciTypeArrayKlassKlass extends ciArrayKlassKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ciTypeArrayKlassKlass"); + } + + + public ciTypeArrayKlassKlass(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciVirtualCallData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciVirtualCallData.java new file mode 100644 index 00000000000..37c4f85c421 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ci/ciVirtualCallData.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ci; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class ciVirtualCallData extends VirtualCallData { + public ciVirtualCallData(DataLayout data) { + super(data); + } + + public Klass receiver(int row) { + throw new InternalError("should not call"); + } + + public ciKlass receiverAt(int row) { + //assert((uint)row < rowLimit(), "oob"); + ciObject recv = ciObjectFactory.get(addressAt(receiverCellIndex(row))); + if (recv != null && !(recv instanceof ciKlass)) { + System.err.println(recv); + } + //assert(recv == NULL || recv->isKlass(), "wrong type"); + return (ciKlass)recv; + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java index d33aaecebee..47503e18240 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -190,6 +190,8 @@ public class NMethod extends CodeBlob { public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); } public boolean nulChkTableContains (Address addr) { return nulChkTableBegin() .lessThanOrEqual(addr) && nulChkTableEnd() .greaterThan(addr); } + public int getOopsLength() { return (int) (oopsSize() / VM.getVM().getOopSize()); } + /** Entry points */ public Address getEntryPoint() { return entryPointField.getValue(addr); } public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); } @@ -198,7 +200,7 @@ public class NMethod extends CodeBlob { public OopHandle getOopAt(int index) { if (index == 0) return null; if (Assert.ASSERTS_ENABLED) { - Assert.that(index > 0 && index <= oopsSize(), "must be a valid non-zero index"); + Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index"); } return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize()); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java new file mode 100644 index 00000000000..12779a40382 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.compiler; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.opto.*; +import sun.jvm.hotspot.prims.JvmtiExport; +import sun.jvm.hotspot.types.*; + +public class CompileTask extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("CompileTask"); + methodField = type.getAddressField("_method"); + osrBciField = new CIntField(type.getCIntegerField("_osr_bci"), 0); + } + + private static AddressField methodField; + private static CIntField osrBciField; + + public CompileTask(Address addr) { + super(addr); + } + + public Method method() { + OopHandle oh = methodField.getValue(getAddress()).getOopHandleAt(0); + return (Method)VM.getVM().getObjectHeap().newOop(oh); + } + + public int osrBci() { + return (int)osrBciField.getValue(getAddress()); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/AddressException.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/AddressException.java index 3d3ea750fdb..e45fb49273b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/AddressException.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/AddressException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,4 +39,8 @@ public class AddressException extends RuntimeException { public long getAddress() { return addr; } + + public String getMessage() { + return Long.toHexString(addr); + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java deleted file mode 100644 index a75a7a7a1e4..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx; - -import sun.jvm.hotspot.debugger.*; - -class DbxAddress implements Address { - protected DbxDebugger debugger; - protected long addr; - - DbxAddress(DbxDebugger debugger, long addr) { - this.debugger = debugger; - this.addr = addr; - } - - // - // Basic Java routines - // - - public boolean equals(Object arg) { - if (arg == null) { - return false; - } - - if (!(arg instanceof DbxAddress)) { - return false; - } - - return (addr == ((DbxAddress) arg).addr); - } - - public int hashCode() { - // FIXME: suggestions on a better hash code? - return (int) addr; - } - - public String toString() { - return debugger.addressValueToString(addr); - } - - // - // C/C++-related routines - // - - public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readCInteger(addr + offset, numBytes, isUnsigned); - } - - public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readAddress(addr + offset); - } - public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readCompOopAddress(addr + offset); - } - - // - // Java-related routines - // - - public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJBoolean(addr + offset); - } - - public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJByte(addr + offset); - } - - public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJChar(addr + offset); - } - - public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJDouble(addr + offset); - } - - public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJFloat(addr + offset); - } - - public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJInt(addr + offset); - } - - public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJLong(addr + offset); - } - - public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJShort(addr + offset); - } - - public OopHandle getOopHandleAt(long offset) - throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { - return debugger.readOopHandle(addr + offset); - } - - public OopHandle getCompOopHandleAt(long offset) - throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { - return debugger.readCompOopHandle(addr + offset); - } - - // Mutators -- not implemented for now (FIXME) - public void setCIntegerAt(long offset, long numBytes, long value) { - throw new DebuggerException("Unimplemented"); - } - public void setAddressAt(long offset, Address value) { - throw new DebuggerException("Unimplemented"); - } - public void setJBooleanAt (long offset, boolean value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJByteAt (long offset, byte value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJCharAt (long offset, char value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJDoubleAt (long offset, double value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJFloatAt (long offset, float value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJIntAt (long offset, int value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJLongAt (long offset, long value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setJShortAt (long offset, short value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - public void setOopHandleAt (long offset, OopHandle value) - throws UnmappedAddressException, UnalignedAddressException { - throw new DebuggerException("Unimplemented"); - } - - // - // Arithmetic operations -- necessary evil. - // - - public Address addOffsetTo (long offset) throws UnsupportedOperationException { - long value = addr + offset; - if (value == 0) { - return null; - } - return new DbxAddress(debugger, value); - } - - public OopHandle addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException { - long value = addr + offset; - if (value == 0) { - return null; - } - return new DbxOopHandle(debugger, value); - } - - /** (FIXME: any signed/unsigned issues? Should this work for - OopHandles?) */ - public long minus(Address arg) { - if (arg == null) { - return addr; - } - return addr - ((DbxAddress) arg).addr; - } - - // Two's complement representation. - // All negative numbers are larger than positive numbers. - // Numbers with the same sign can be compared normally. - // Test harness is below in main(). - - public boolean lessThan (Address arg) { - if (arg == null) { - return false; - } - DbxAddress dbxArg = (DbxAddress) arg; - if ((addr >= 0) && (dbxArg.addr < 0)) { - return true; - } - if ((addr < 0) && (dbxArg.addr >= 0)) { - return false; - } - return (addr < dbxArg.addr); - } - - public boolean lessThanOrEqual (Address arg) { - if (arg == null) { - return false; - } - DbxAddress dbxArg = (DbxAddress) arg; - if ((addr >= 0) && (dbxArg.addr < 0)) { - return true; - } - if ((addr < 0) && (dbxArg.addr >= 0)) { - return false; - } - return (addr <= dbxArg.addr); - } - - public boolean greaterThan (Address arg) { - if (arg == null) { - return true; - } - DbxAddress dbxArg = (DbxAddress) arg; - if ((addr >= 0) && (dbxArg.addr < 0)) { - return false; - } - if ((addr < 0) && (dbxArg.addr >= 0)) { - return true; - } - return (addr > dbxArg.addr); - } - - public boolean greaterThanOrEqual(Address arg) { - if (arg == null) { - return true; - } - DbxAddress dbxArg = (DbxAddress) arg; - if ((addr >= 0) && (dbxArg.addr < 0)) { - return false; - } - if ((addr < 0) && (dbxArg.addr >= 0)) { - return true; - } - return (addr >= dbxArg.addr); - } - - public Address andWithMask(long mask) throws UnsupportedOperationException { - long value = addr & mask; - if (value == 0) { - return null; - } - return new DbxAddress(debugger, value); - } - - public Address orWithMask(long mask) throws UnsupportedOperationException { - long value = addr | mask; - if (value == 0) { - return null; - } - return new DbxAddress(debugger, value); - } - - public Address xorWithMask(long mask) throws UnsupportedOperationException { - long value = addr ^ mask; - if (value == 0) { - return null; - } - return new DbxAddress(debugger, value); - } - - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - long getValue() { - return addr; - } - - - private static void check(boolean arg, String failMessage) { - if (!arg) { - System.err.println(failMessage + ": FAILED"); - System.exit(1); - } - } - - // Test harness - public static void main(String[] args) { - // p/n indicates whether the interior address is really positive - // or negative. In unsigned terms, p1 < p2 < n1 < n2. - - DbxAddress p1 = new DbxAddress(null, 0x7FFFFFFFFFFFFFF0L); - DbxAddress p2 = (DbxAddress) p1.addOffsetTo(10); - DbxAddress n1 = (DbxAddress) p2.addOffsetTo(10); - DbxAddress n2 = (DbxAddress) n1.addOffsetTo(10); - - // lessThan positive tests - check(p1.lessThan(p2), "lessThan 1"); - check(p1.lessThan(n1), "lessThan 2"); - check(p1.lessThan(n2), "lessThan 3"); - check(p2.lessThan(n1), "lessThan 4"); - check(p2.lessThan(n2), "lessThan 5"); - check(n1.lessThan(n2), "lessThan 6"); - - // lessThan negative tests - check(!p1.lessThan(p1), "lessThan 7"); - check(!p2.lessThan(p2), "lessThan 8"); - check(!n1.lessThan(n1), "lessThan 9"); - check(!n2.lessThan(n2), "lessThan 10"); - - check(!p2.lessThan(p1), "lessThan 11"); - check(!n1.lessThan(p1), "lessThan 12"); - check(!n2.lessThan(p1), "lessThan 13"); - check(!n1.lessThan(p2), "lessThan 14"); - check(!n2.lessThan(p2), "lessThan 15"); - check(!n2.lessThan(n1), "lessThan 16"); - - // lessThanOrEqual positive tests - check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1"); - check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2"); - check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3"); - check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4"); - - check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5"); - check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6"); - check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7"); - check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8"); - check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9"); - check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10"); - - // lessThanOrEqual negative tests - check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11"); - check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12"); - check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13"); - check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14"); - check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15"); - check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16"); - - // greaterThan positive tests - check(n2.greaterThan(p1), "greaterThan 1"); - check(n2.greaterThan(p2), "greaterThan 2"); - check(n2.greaterThan(n1), "greaterThan 3"); - check(n1.greaterThan(p1), "greaterThan 4"); - check(n1.greaterThan(p2), "greaterThan 5"); - check(p2.greaterThan(p1), "greaterThan 6"); - - // greaterThan negative tests - check(!p1.greaterThan(p1), "greaterThan 7"); - check(!p2.greaterThan(p2), "greaterThan 8"); - check(!n1.greaterThan(n1), "greaterThan 9"); - check(!n2.greaterThan(n2), "greaterThan 10"); - - check(!p1.greaterThan(n2), "greaterThan 11"); - check(!p2.greaterThan(n2), "greaterThan 12"); - check(!n1.greaterThan(n2), "greaterThan 13"); - check(!p1.greaterThan(n1), "greaterThan 14"); - check(!p2.greaterThan(n1), "greaterThan 15"); - check(!p1.greaterThan(p2), "greaterThan 16"); - - // greaterThanOrEqual positive tests - check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1"); - check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2"); - check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3"); - check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4"); - - check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5"); - check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6"); - check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7"); - check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8"); - check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9"); - check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10"); - - // greaterThanOrEqual negative tests - check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11"); - check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12"); - check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13"); - check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14"); - check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15"); - check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16"); - - System.err.println("DbxAddress: all tests passed successfully."); - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java deleted file mode 100644 index 9bf32d57173..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx; - -import sun.jvm.hotspot.debugger.*; - -/** An extension of the JVMDebugger interface with a few additions to - support 32-bit vs. 64-bit debugging as well as features required - by the architecture-specific subpackages. */ - -public interface DbxDebugger extends JVMDebugger { - public String addressValueToString(long address) throws DebuggerException; - public boolean readJBoolean(long address) throws DebuggerException; - public byte readJByte(long address) throws DebuggerException; - public char readJChar(long address) throws DebuggerException; - public double readJDouble(long address) throws DebuggerException; - public float readJFloat(long address) throws DebuggerException; - public int readJInt(long address) throws DebuggerException; - public long readJLong(long address) throws DebuggerException; - public short readJShort(long address) throws DebuggerException; - public long readCInteger(long address, long numBytes, boolean isUnsigned) - throws DebuggerException; - public DbxAddress readAddress(long address) throws DebuggerException; - public DbxAddress readCompOopAddress(long address) throws DebuggerException; - public DbxOopHandle readOopHandle(long address) throws DebuggerException; - public DbxOopHandle readCompOopHandle(long address) throws DebuggerException; - public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException; - public Address newAddress(long value) throws DebuggerException; - - // NOTE: this interface implicitly contains the following methods: - // From the Debugger interface via JVMDebugger - // public void attach(int processID) throws DebuggerException; - // public void attach(String executableName, String coreFileName) throws DebuggerException; - // public boolean detach(); - // public Address parseAddress(String addressString) throws NumberFormatException; - // public long getAddressValue(Address addr) throws DebuggerException; - // public String getOS(); - // public String getCPU(); - // From the SymbolLookup interface via Debugger and JVMDebugger - // public Address lookup(String objectName, String symbol); - // public OopHandle lookupOop(String objectName, String symbol); - // From the JVMDebugger interface - // public void configureJavaPrimitiveTypeSizes(long jbooleanSize, - // long jbyteSize, - // long jcharSize, - // long jdoubleSize, - // long jfloatSize, - // long jintSize, - // long jlongSize, - // long jshortSize); - // From the ThreadAccess interface via Debugger and JVMDebugger - // public ThreadProxy getThreadForIdentifierAddress(Address addr); - // public ThreadProxy getThreadForThreadId(long id); -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java deleted file mode 100644 index b11c019ccdf..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx; - -import java.io.*; -import java.net.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.sparc.*; -import sun.jvm.hotspot.debugger.dbx.x86.*; -import sun.jvm.hotspot.debugger.cdbg.CDebugger; -import sun.jvm.hotspot.utilities.*; - -/**

An implementation of the JVMDebugger interface which sits on - top of dbx and relies on the SA's dbx import module for - communication with the debugger.

- -

NOTE that since we have the notion of fetching "Java - primitive types" from the remote process (which might have - different sizes than we expect) we have a bootstrapping - problem. We need to know the sizes of these types before we can - fetch them. The current implementation solves this problem by - requiring that it be configured with these type sizes before they - can be fetched. The readJ(Type) routines here will throw a - RuntimeException if they are called before the debugger is - configured with the Java primitive type sizes.

-*/ - -public class DbxDebuggerLocal extends DebuggerBase implements DbxDebugger { - // These may be set by DbxDebuggerRemote - protected boolean unalignedAccessesOkay; - protected DbxThreadFactory threadFactory; - - private String dbxPathName; - private String[] dbxSvcAgentDSOPathNames; - private Process dbxProcess; - private StreamMonitor dbxOutStreamMonitor; - private StreamMonitor dbxErrStreamMonitor; - private PrintWriter dbxOstr; - private PrintWriter out; - private InputLexer in; - private Socket importModuleSocket; - private static final int PORT = 21928; - private static final int LONG_TIMEOUT = 60000; - private static final int DBX_MODULE_NOT_FOUND = 101; - private static final int DBX_MODULE_LOADED = 102; - - //-------------------------------------------------------------------------------- - // Implementation of Debugger interface - // - - /**

machDesc may be null if it couldn't be determined yet; i.e., - if we're on SPARC, we need to ask the remote process whether - we're in 32- or 64-bit mode.

- -

useCache should be set to true if debugging is being done - locally, and to false if the debugger is being created for the - purpose of supporting remote debugging.

*/ - public DbxDebuggerLocal(MachineDescription machDesc, - String dbxPathName, - String[] dbxSvcAgentDSOPathNames, - boolean useCache) { - this.machDesc = machDesc; - this.dbxPathName = dbxPathName; - this.dbxSvcAgentDSOPathNames = dbxSvcAgentDSOPathNames; - int cacheNumPages; - int cachePageSize; - if (PlatformInfo.getCPU().equals("sparc")) { - cacheNumPages = parseCacheNumPagesProperty(2048); - cachePageSize = 8192; - threadFactory = new DbxSPARCThreadFactory(this); - } else if (PlatformInfo.getCPU().equals("x86")) { - cacheNumPages = 4096; - cachePageSize = 4096; - threadFactory = new DbxX86ThreadFactory(this); - unalignedAccessesOkay = true; - } else { - throw new RuntimeException("Thread access for CPU architecture " + PlatformInfo.getCPU() + " not yet supported"); - } - if (useCache) { - // Cache portion of the remote process's address space. - // Fetching data over the socket connection to dbx is relatively - // slow. For now, this cache works best if it covers the entire - // heap of the remote process. FIXME: at least should make this - // tunable from the outside, i.e., via the UI. This is a 16 MB - // cache divided on SPARC into 2048 8K pages and on x86 into - // 4096 4K pages; the page size must be adjusted to be the OS's - // page size. (FIXME: should pick this up from the debugger.) - initCache(cachePageSize, cacheNumPages); - } - } - - /** Only called by DbxDebuggerRemote */ - protected DbxDebuggerLocal() { - } - - /** FIXME: implement this with a Runtime.exec() of ps followed by - parsing of its output */ - public boolean hasProcessList() throws DebuggerException { - return false; - } - - public List getProcessList() throws DebuggerException { - throw new DebuggerException("Not yet supported"); - } - - /** From the Debugger interface via JVMDebugger */ - public synchronized void attach(int processID) throws DebuggerException { - try { - launchProcess(); - dbxErrStreamMonitor.addTrigger("dbx: no process", 1); - dbxErrStreamMonitor.addTrigger("dbx: Cannot open", 1); - dbxErrStreamMonitor.addTrigger("dbx: Cannot find", DBX_MODULE_NOT_FOUND); - dbxOstr = new PrintWriter(dbxProcess.getOutputStream(), true); - dbxOstr.println("debug - " + processID); - dbxOstr.println("kprint -u2 \\(ready\\)"); - boolean seen = dbxErrStreamMonitor.waitFor("(ready)", LONG_TIMEOUT); - if (!seen) { - detach(); - throw new DebuggerException("Timed out while connecting to process " + processID); - } - List retVals = dbxErrStreamMonitor.getTriggersSeen(); - if (retVals.contains(new Integer(1))) { - detach(); - throw new DebuggerException("No such process " + processID); - } - - // Throws DebuggerException upon failure - importDbxModule(); - - dbxOstr.println("svc_agent_run"); - - connectToImportModule(); - - // Set "fail fast" mode on process memory reads - printlnToOutput("peek_fail_fast 1"); - } - catch (IOException e) { - detach(); - throw new DebuggerException("Error while connecting to dbx process", e); - } - } - - /** From the Debugger interface via JVMDebugger */ - public synchronized void attach(String executableName, String coreFileName) throws DebuggerException { - try { - launchProcess(); - // Missing executable - dbxErrStreamMonitor.addTrigger("dbx: Cannot open", 1); - // Missing core file - dbxErrStreamMonitor.addTrigger("dbx: can't read", 2); - // Corrupt executable - dbxErrStreamMonitor.addTrigger("dbx: File", 3); - // Corrupt core file - dbxErrStreamMonitor.addTrigger("dbx: Unable to read", 4); - // Mismatched core and executable - dbxErrStreamMonitor.addTrigger("dbx: core object name", 5); - // Missing loadobject - dbxErrStreamMonitor.addTrigger("dbx: can't stat", 6); - // Successful load of svc module - dbxOstr = new PrintWriter(dbxProcess.getOutputStream(), true); - dbxOstr.println("debug " + executableName + " " + coreFileName); - dbxOstr.println("kprint -u2 \\(ready\\)"); - boolean seen = dbxErrStreamMonitor.waitFor("(ready)", LONG_TIMEOUT); - if (!seen) { - detach(); - throw new DebuggerException("Timed out while attaching to core file"); - } - List retVals = dbxErrStreamMonitor.getTriggersSeen(); - if (retVals.size() > 0) { - detach(); - - if (retVals.contains(new Integer(1))) { - throw new DebuggerException("Can not find executable \"" + executableName + "\""); - } else if (retVals.contains(new Integer(2))) { - throw new DebuggerException("Can not find core file \"" + coreFileName + "\""); - } else if (retVals.contains(new Integer(3))) { - throw new DebuggerException("Corrupt executable \"" + executableName + "\""); - } else if (retVals.contains(new Integer(4))) { - throw new DebuggerException("Corrupt core file \"" + coreFileName + "\""); - } else if (retVals.contains(new Integer(5))) { - throw new DebuggerException("Mismatched core file/executable \"" + coreFileName + "\"/\"" + executableName + "\""); - } else { - throw new DebuggerException("Couldn't find all loaded libraries for executable \"" + executableName + "\""); - } - } - - // Throws DebuggerException upon failure - importDbxModule(); - - dbxOstr.println("svc_agent_run"); - - connectToImportModule(); - - // Set "fail fast" mode on process memory reads - printlnToOutput("peek_fail_fast 1"); - } - catch (IOException e) { - detach(); - throw new DebuggerException("Error while connecting to dbx process", e); - } - } - - /** From the Debugger interface via JVMDebugger */ - public synchronized boolean detach() { - try { - if (dbxProcess == null) { - return false; - } - - if (out != null && dbxOstr != null) { - printlnToOutput("exit"); - dbxOstr.println("exit"); - - // Wait briefly for the process to exit (FIXME: should make this - // nicer) - try { - Thread.sleep(500); - } - catch (InterruptedException e) { - } - } - - shutdown(); - - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - - /** From the Debugger interface via JVMDebugger */ - public Address parseAddress(String addressString) throws NumberFormatException { - long addr = utils.scanAddress(addressString); - if (addr == 0) { - return null; - } - return new DbxAddress(this, addr); - } - - /** From the Debugger interface via JVMDebugger */ - public String getOS() { - return PlatformInfo.getOS(); - } - - /** From the Debugger interface via JVMDebugger */ - public String getCPU() { - return PlatformInfo.getCPU(); - } - - public boolean hasConsole() throws DebuggerException { - return true; - } - - public synchronized String consoleExecuteCommand(String cmd) throws DebuggerException { - try { - // A little tricky. We need to cause the dbx import module to - // exit, then print our command on dbx's stdin along with a - // command which will allow our StreamMonitors to - // resynchronize. We need save the output from the StreamMonitors - // along the way. - printlnToOutput("exit"); - importModuleSocket.close(); - importModuleSocket = null; - out = null; - in = null; - dbxOstr.println("kprint \\(ready\\)"); - dbxOstr.flush(); - dbxOutStreamMonitor.waitFor("(ready)", LONG_TIMEOUT); - - dbxOutStreamMonitor.startCapture(); - dbxErrStreamMonitor.startCapture(); - dbxOstr.println(cmd); - dbxOstr.println("kprint \\(ready\\)"); - dbxOutStreamMonitor.waitFor("(ready)", LONG_TIMEOUT); - String result = dbxOutStreamMonitor.stopCapture(); - String result2 = dbxErrStreamMonitor.stopCapture(); - result = result + result2; - // Cut out the "(ready)" string - StringBuffer outBuf = new StringBuffer(result.length()); - BufferedReader reader = new BufferedReader(new StringReader(result)); - // FIXME: bug in BufferedReader? readLine returns null when - // ready() returns true. - String line = null; - do { - line = reader.readLine(); - if ((line != null) && (!line.equals("(ready)"))) { - outBuf.append(line); - outBuf.append("\n"); - } - } while (line != null); - dbxOstr.println("svc_agent_run"); - dbxOstr.flush(); - - connectToImportModule(); - - return outBuf.toString(); - } - catch (IOException e) { - detach(); - throw new DebuggerException("Error while executing command on dbx console", e); - } - } - - public String getConsolePrompt() throws DebuggerException { - return "(dbx) "; - } - - public CDebugger getCDebugger() throws DebuggerException { - return null; - } - - /** From the SymbolLookup interface via Debugger and JVMDebugger */ - public synchronized Address lookup(String objectName, String symbol) { - long addr = lookupInProcess(objectName, symbol); - if (addr == 0) { - return null; - } - return new DbxAddress(this, addr); - } - - /** From the SymbolLookup interface via Debugger and JVMDebugger */ - public synchronized OopHandle lookupOop(String objectName, String symbol) { - long addr = lookupInProcess(objectName, symbol); - if (addr == 0) { - return null; - } - return new DbxOopHandle(this, addr); - } - - /** From the Debugger interface */ - public MachineDescription getMachineDescription() { - return machDesc; - } - - /** Internal routine supporting lazy setting of MachineDescription, - since on SPARC we will need to query the remote process to ask - it what its data model is (32- or 64-bit). NOTE that this is NOT - present in the DbxDebugger interface because it should not be - called across the wire (until we support attaching to multiple - remote processes via RMI -- see the documentation for - DbxDebuggerRemoteIntf.) */ - public void setMachineDescription(MachineDescription machDesc) { - this.machDesc = machDesc; - setBigEndian(machDesc.isBigEndian()); - utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian()); - } - - /** Internal routine which queries the remote process about its data - model -- i.e., size of addresses. Returns -1 upon error. - Currently supported return values are 32 and 64. NOTE that this - is NOT present in the DbxDebugger interface because it should - not be called across the wire (until we support attaching to - multiple remote processes via RMI -- see the documentation for - DbxDebuggerRemoteIntf.) */ - public int getRemoteProcessAddressSize() { - if (dbxProcess == null) { - throw new RuntimeException("Not attached to remote process"); - } - - try { - printlnToOutput("address_size"); - int i = in.parseInt(); - return i; - } - catch (IOException e) { - return -1; - } - } - - //-------------------------------------------------------------------------------- - // Implementation of ThreadAccess interface - // - - /** From the ThreadAccess interface via Debugger and JVMDebugger */ - public ThreadProxy getThreadForIdentifierAddress(Address addr) { - return threadFactory.createThreadWrapper(addr); - } - - public ThreadProxy getThreadForThreadId(long id) { - return threadFactory.createThreadWrapper(id); - } - - //---------------------------------------------------------------------- - // Overridden from DebuggerBase because we need to relax alignment - // constraints on x86 - - public long readJLong(long address) - throws UnmappedAddressException, UnalignedAddressException { - checkJavaConfigured(); - // FIXME: allow this to be configurable. Undesirable to add a - // dependency on the runtime package here, though, since this - // package should be strictly underneath it. - if (unalignedAccessesOkay) { - utils.checkAlignment(address, jintSize); - } else { - utils.checkAlignment(address, jlongSize); - } - byte[] data = readBytes(address, jlongSize); - return utils.dataToJLong(data, jlongSize); - } - - //-------------------------------------------------------------------------------- - // Internal routines (for implementation of DbxAddress). - // These must not be called until the MachineDescription has been set up. - // - - /** From the DbxDebugger interface */ - public String addressValueToString(long address) { - return utils.addressValueToString(address); - } - - /** Need to override this to relax alignment checks on Solaris/x86. */ - public long readCInteger(long address, long numBytes, boolean isUnsigned) - throws UnmappedAddressException, UnalignedAddressException { - checkConfigured(); - if (!unalignedAccessesOkay) { - utils.checkAlignment(address, numBytes); - } else { - // Only slightly relaxed semantics -- this is a hack, but is - // necessary on Solaris/x86 where it seems the compiler is - // putting some global 64-bit data on 32-bit boundaries - if (numBytes == 8) { - utils.checkAlignment(address, 4); - } else { - utils.checkAlignment(address, numBytes); - } - } - byte[] data = readBytes(address, numBytes); - return utils.dataToCInteger(data, isUnsigned); - } - - /** From the DbxDebugger interface */ - public DbxAddress readAddress(long address) - throws UnmappedAddressException, UnalignedAddressException { - long value = readAddressValue(address); - return (value == 0 ? null : new DbxAddress(this, value)); - } - - public DbxAddress readCompOopAddress(long address) - throws UnmappedAddressException, UnalignedAddressException { - long value = readCompOopAddressValue(address); - return (value == 0 ? null : new DbxAddress(this, value)); - } - - /** From the DbxDebugger interface */ - public DbxOopHandle readOopHandle(long address) - throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { - long value = readAddressValue(address); - return (value == 0 ? null : new DbxOopHandle(this, value)); - } - public DbxOopHandle readCompOopHandle(long address) - throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { - long value = readCompOopAddressValue(address); - return (value == 0 ? null : new DbxOopHandle(this, value)); - } - - //-------------------------------------------------------------------------------- - // Thread context access. Can not be package private, but should - // only be accessed by the architecture-specific subpackages. - - /** From the DbxDebugger interface. May have to redefine this later. */ - public synchronized long[] getThreadIntegerRegisterSet(int tid) { - try { - printlnToOutput("thr_gregs " + tid); - int num = in.parseInt(); - long[] res = new long[num]; - for (int i = 0; i < num; i++) { - res[i] = in.parseAddress(); - } - return res; - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //-------------------------------------------------------------------------------- - // Address access. Can not be package private, but should only be - // accessed by the architecture-specific subpackages. - - /** From the Debugger interface */ - public long getAddressValue(Address addr) { - if (addr == null) return 0; - return ((DbxAddress) addr).getValue(); - } - - /** From the DbxDebugger interface */ - public Address newAddress(long value) { - if (value == 0) return null; - return new DbxAddress(this, value); - } - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - private void launchProcess() throws IOException { - dbxProcess = Runtime.getRuntime().exec(dbxPathName); - // dbxOutStreamMonitor = new StreamMonitor(dbxProcess.getInputStream()); - // dbxErrStreamMonitor = new StreamMonitor(dbxProcess.getErrorStream()); - dbxOutStreamMonitor = new StreamMonitor(dbxProcess.getInputStream(), "dbx stdout", true); - dbxErrStreamMonitor = new StreamMonitor(dbxProcess.getErrorStream(), "dbx stderr", true); - } - - /** Requires that dbxErrStreamMonitor has a trigger on "dbx: Cannot - find" with number DBX_MODULE_NOT_FOUND as well as one on "dbx: - warning:" (plus the serviceability agent's dbx module path name, - to avoid conflation with inability to load individual object - files) with number DBX_MODULE_FAILED_TO_LOAD. The former - indicates an absence of libsvc_agent_dbx.so, while the latter - indicates that the module failed to load, specifically because - the architecture was mismatched. (I don't see a way to detect - from the dbx command prompt whether it's running the v8 or v9 - executbale, so we try to import both flavors of the import - module; the "v8" file name convention doesn't actually include - the v8 prefix, so this code should work for Intel as well.) */ - private void importDbxModule() throws DebuggerException { - // Trigger for a successful load - dbxOutStreamMonitor.addTrigger("Defining svc_agent_run", DBX_MODULE_LOADED); - for (int i = 0; i < dbxSvcAgentDSOPathNames.length; i++) { - dbxOstr.println("import " + dbxSvcAgentDSOPathNames[i]); - dbxOstr.println("kprint -u2 \\(Ready\\)"); - boolean seen = dbxErrStreamMonitor.waitFor("(Ready)", LONG_TIMEOUT); - if (!seen) { - detach(); - throw new DebuggerException("Timed out while importing dbx module from file\n" + dbxSvcAgentDSOPathNames[i]); - } - List retVals = dbxErrStreamMonitor.getTriggersSeen(); - if (retVals.contains(new Integer(DBX_MODULE_NOT_FOUND))) { - detach(); - throw new DebuggerException("Unable to find the Serviceability Agent's dbx import module at pathname \"" + - dbxSvcAgentDSOPathNames[i] + "\""); - } else { - retVals = dbxOutStreamMonitor.getTriggersSeen(); - if (retVals.contains(new Integer(DBX_MODULE_LOADED))) { - System.out.println("importDbxModule: imported " + dbxSvcAgentDSOPathNames[i]); - return; - } - } - } - - // Failed to load all flavors - detach(); - String errMsg = ("Unable to find a version of the Serviceability Agent's dbx import module\n" + - "matching the architecture of dbx at any of the following locations:"); - for (int i = 0; i < dbxSvcAgentDSOPathNames.length; i++) { - errMsg = errMsg + "\n" + dbxSvcAgentDSOPathNames[i]; - } - throw new DebuggerException(errMsg); - } - - /** Terminate the debugger forcibly */ - private void shutdown() { - - if (dbxProcess != null) { - // See whether the process has exited and, if not, terminate it - // forcibly - try { - dbxProcess.exitValue(); - } - catch (IllegalThreadStateException e) { - dbxProcess.destroy(); - } - } - - try { - if (importModuleSocket != null) { - importModuleSocket.close(); - } - } - catch (IOException e) { - } - - // Release references to all objects - clear(); - clearCache(); - } - - /** Looks up an address in the remote process's address space. - Returns 0 if symbol not found or upon error. Package private to - allow DbxDebuggerRemoteIntfImpl access. */ - synchronized long lookupInProcess(String objectName, String symbol) { - try { - printlnToOutput("lookup " + objectName + " " + symbol); - return in.parseAddress(); - } - catch (Exception e) { - return 0; - } - } - - /** This reads bytes from the remote process. */ - public synchronized ReadResult readBytesFromProcess(long address, long numBytes) - throws DebuggerException { - if (numBytes < 0) { - throw new DebuggerException("Can not read negative number (" + numBytes + ") of bytes from process"); - } - try { - String cmd = "peek " + utils.addressValueToString(address) + " " + numBytes; - printlnToOutput(cmd); - while (in.readByte() != 'B') { - } - byte res = in.readByte(); - if (res == 0) { - System.err.println("Failing command: " + cmd); - throw new DebuggerException("Read of remote process address space failed"); - } - // NOTE: must read ALL of the data regardless of whether we need - // to throw an UnmappedAddressException. Otherwise will corrupt - // the input stream each time we have a failure. Not good. Do - // not want to risk "flushing" the input stream in case a huge - // read has a hangup in the middle and we leave data on the - // stream. - byte[] buf = new byte[(int) numBytes]; - boolean bailOut = false; - long failureAddress = 0; - int numReads = 0; - while (numBytes > 0) { - long len = in.readUnsignedInt(); - boolean isMapped = ((in.readByte() == 0) ? false : true); - if (!isMapped) { - if (!bailOut) { - bailOut = true; - failureAddress = address; - } - } else { - // This won't work if we have unmapped regions, but if we do - // then we're going to throw an exception anyway - - // NOTE: there is a factor of 20 speed difference between - // these two ways of doing this read. - in.readBytes(buf, 0, (int) len); - } - - // Do NOT do this: - // for (int i = 0; i < (int) len; i++) { - // buf[i] = in.readByte(); - // } - - numBytes -= len; - address += len; - ++numReads; - } - if (Assert.ASSERTS_ENABLED) { - Assert.that(numBytes == 0, "Bug in debug server's implementation of peek: numBytesLeft == " + - numBytes + ", should be 0 (did " + numReads + " reads)"); - } - if (bailOut) { - return new ReadResult(failureAddress); - } - return new ReadResult(buf); - } - catch (IOException e) { - throw new DebuggerException(e); - } - } - - public void writeBytesToProcess(long address, long numBytes, byte[] data) - throws UnmappedAddressException, DebuggerException { - // FIXME - throw new DebuggerException("Unimplemented"); - } - - /** This provides DbxDebuggerRemoteIntfImpl access to readBytesFromProcess */ - ReadResult readBytesFromProcessInternal(long address, long numBytes) - throws DebuggerException { - return readBytesFromProcess(address, numBytes); - } - - /** Convenience routine */ - private void printlnToOutput(String s) throws IOException { - out.println(s); - if (out.checkError()) { - throw new IOException("Error occurred while writing to debug server"); - } - } - - private void clear() { - dbxProcess = null; - dbxOstr = null; - out = null; - in = null; - importModuleSocket = null; - } - - /** Connects to the dbx import module, setting up out and in - streams. Factored out to allow access to the dbx console. */ - private void connectToImportModule() throws IOException { - // Try for 20 seconds to connect to dbx import module; time out - // with failure if didn't succeed - importModuleSocket = null; - long endTime = System.currentTimeMillis() + LONG_TIMEOUT; - - while ((importModuleSocket == null) && (System.currentTimeMillis() < endTime)) { - try { - importModuleSocket = new Socket(InetAddress.getLocalHost(), PORT); - importModuleSocket.setTcpNoDelay(true); - } - catch (IOException e) { - // Swallow IO exceptions while attempting connection - try { - // Don't swamp the CPU - Thread.sleep(1000); - } - catch (InterruptedException ex) { - } - } - } - - if (importModuleSocket == null) { - // Failed to connect because of timeout - detach(); - throw new DebuggerException("Timed out while attempting to connect to remote dbx process"); - } - - out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(importModuleSocket.getOutputStream(), "US-ASCII")), true); - in = new InputLexer(new BufferedInputStream(importModuleSocket.getInputStream())); - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxOopHandle.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxOopHandle.java deleted file mode 100644 index 53290088b11..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxOopHandle.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx; - -import sun.jvm.hotspot.debugger.*; - -class DbxOopHandle extends DbxAddress implements OopHandle { - DbxOopHandle(DbxDebugger debugger, long addr) { - super(debugger, addr); - } - - public Address addOffsetTo (long offset) throws UnsupportedOperationException { - throw new UnsupportedOperationException("addOffsetTo not applicable to OopHandles (interior object pointers not allowed)"); - } - - public Address andWithMask(long mask) throws UnsupportedOperationException { - throw new UnsupportedOperationException("andWithMask not applicable to OopHandles (i.e., anything but C addresses)"); - } - - public Address orWithMask(long mask) throws UnsupportedOperationException { - throw new UnsupportedOperationException("orWithMask not applicable to OopHandles (i.e., anything but C addresses)"); - } - - public Address xorWithMask(long mask) throws UnsupportedOperationException { - throw new UnsupportedOperationException("xorWithMask not applicable to OopHandles (i.e., anything but C addresses)"); - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxThreadFactory.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxThreadFactory.java deleted file mode 100644 index ea7dc6e5978..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxThreadFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx; - -import sun.jvm.hotspot.debugger.*; - -/** An interface used only internally by the DbxDebugger to be able to - create platform-specific Thread objects */ - -public interface DbxThreadFactory { - public ThreadProxy createThreadWrapper(Address threadIdentifierAddr); - public ThreadProxy createThreadWrapper(long id); -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThread.java deleted file mode 100644 index b753c2369a9..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThread.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx.sparc; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.sparc.*; -import sun.jvm.hotspot.debugger.dbx.*; -import sun.jvm.hotspot.utilities.*; - -public class DbxSPARCThread implements ThreadProxy { - private DbxDebugger debugger; - private int id; - - public DbxSPARCThread(DbxDebugger debugger, Address addr) { - this.debugger = debugger; - - // FIXME: the size here should be configurable. However, making it - // so would produce a dependency on the "types" package from the - // debugger package, which is not desired. - this.id = (int) addr.getCIntegerAt(0, 4, true); - } - - public DbxSPARCThread(DbxDebugger debugger, long id) { - this.debugger = debugger; - this.id = (int) id; - } - - public boolean equals(Object obj) { - if ((obj == null) || !(obj instanceof DbxSPARCThread)) { - return false; - } - - return (((DbxSPARCThread) obj).id == id); - } - - public int hashCode() { - return id; - } - - public ThreadContext getContext() throws IllegalThreadStateException { - DbxSPARCThreadContext context = new DbxSPARCThreadContext(debugger); - long[] regs = debugger.getThreadIntegerRegisterSet(id); - if (Assert.ASSERTS_ENABLED) { - Assert.that(regs.length == SPARCThreadContext.NPRGREG, "size of register set must match"); - } - for (int i = 0; i < regs.length; i++) { - context.setRegister(i, regs[i]); - } - return context; - } - - public boolean canSetContext() throws DebuggerException { - return false; - } - - public void setContext(ThreadContext context) - throws IllegalThreadStateException, DebuggerException { - throw new DebuggerException("Unimplemented"); - } - - public String toString() { - return "t@" + id; - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86Thread.java deleted file mode 100644 index 8dcb9c4e39b..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86Thread.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.dbx.x86; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.x86.*; -import sun.jvm.hotspot.debugger.dbx.*; -import sun.jvm.hotspot.utilities.*; - -public class DbxX86Thread implements ThreadProxy { - private DbxDebugger debugger; - private int id; - - public DbxX86Thread(DbxDebugger debugger, Address addr) { - this.debugger = debugger; - - // FIXME: the size here should be configurable. However, making it - // so would produce a dependency on the "types" package from the - // debugger package, which is not desired. - this.id = (int) addr.getCIntegerAt(0, 4, true); - } - - public DbxX86Thread(DbxDebugger debugger, long id) { - this.debugger = debugger; - this.id = (int) id; - } - - public boolean equals(Object obj) { - if ((obj == null) || !(obj instanceof DbxX86Thread)) { - return false; - } - - return (((DbxX86Thread) obj).id == id); - } - - public int hashCode() { - return id; - } - - public ThreadContext getContext() throws IllegalThreadStateException { - DbxX86ThreadContext context = new DbxX86ThreadContext(debugger); - long[] regs = debugger.getThreadIntegerRegisterSet(id); - if (Assert.ASSERTS_ENABLED) { - Assert.that(regs.length == 19, "unknown size of register set -- adjust this code"); - } - for (int i = 0; i < regs.length; i++) { - context.setRegister(i, regs[i]); - } - return context; - } - - public boolean canSetContext() throws DebuggerException { - return false; - } - - public void setContext(ThreadContext context) - throws IllegalThreadStateException, DebuggerException { - throw new DebuggerException("Unimplemented"); - } - - public String toString() { - return "t@" + id; - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/AddressDataSource.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/AddressDataSource.java deleted file mode 100644 index 2e2fa1004b1..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/AddressDataSource.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.io.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.win32.coff.*; - -class AddressDataSource implements DataSource { - AddressDataSource(Address addr) { - this.addr = addr; - offset = 0; - } - - public byte readByte() throws IOException { - try { - byte res = (byte) addr.getCIntegerAt(offset, 1, false); - ++offset; - return res; - } catch (UnmappedAddressException e) { - throw (IOException) new IOException("Unmapped address at 0x" + Long.toHexString(e.getAddress())).initCause(e); - } catch (DebuggerException e) { - throw (IOException) new IOException(e.toString()).initCause(e); - } - } - - public short readShort() throws IOException { - // NOTE: byte swapping is taken care of at the COFFFileImpl level - int b1 = readByte() & 0xFF; - int b2 = readByte() & 0xFF; - return (short) ((b1 << 8) | b2); - } - - public int readInt() throws IOException { - // NOTE: byte swapping is taken care of at the COFFFileImpl level - int b1 = ((int) readByte()) & 0xFF; - int b2 = ((int) readByte()) & 0xFF; - int b3 = ((int) readByte()) & 0xFF; - int b4 = ((int) readByte()) & 0xFF; - return ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4); - } - - public long readLong() throws IOException { - // NOTE: byte swapping is taken care of at the COFFFileImpl level - long b1 = ((long) readByte()) & 0xFFL; - long b2 = ((long) readByte()) & 0xFFL; - long b3 = ((long) readByte()) & 0xFFL; - long b4 = ((long) readByte()) & 0xFFL; - long b5 = ((long) readByte()) & 0xFFL; - long b6 = ((long) readByte()) & 0xFFL; - long b7 = ((long) readByte()) & 0xFFL; - long b8 = ((long) readByte()) & 0xFFL; - return (((((b1 << 24) | (b2 << 16) | (b3 << 8) | b4)) << 32) | - ((((b5 << 24) | (b6 << 16) | (b7 << 8) | b8)))); - } - - public int read(byte[] b) throws IOException { - for (int i = 0; i < b.length; i++) { - b[i] = readByte(); - } - return b.length; - } - - public void seek(long pos) throws IOException { - offset = pos; - } - - public long getFilePointer() throws IOException { - return offset; - } - - public void close() throws IOException { - } - - private Address addr; - private long offset; -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/DLL.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/DLL.java deleted file mode 100644 index 70007b433d3..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/DLL.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.win32.coff.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.utilities.Assert; -import sun.jvm.hotspot.utilities.memo.*; - -/** Provides a simple wrapper around the COFF library which handles - relocation. A DLL can represent either a DLL or an EXE file. */ - -class DLL implements LoadObject { - - DLL(Win32Debugger dbg, String filename, long size, Address relocation) throws COFFException { - this.dbg = dbg; - fullPathName = filename; - this.size = size; - file = new MemoizedObject() { - public Object computeValue() { - return COFFFileParser.getParser().parse(fullPathName); - } - }; - addr = relocation; - } - - /** This constructor was originally used to fetch the DLL's name out - of the target process to match it up with the known DLL names, - before the fetching of the DLL names and bases was folded into - one command. It is no longer used. If it is used, getName() will - return null and getSize() will return 0. */ - DLL(Address base) throws COFFException { - this.addr = base; - file = new MemoizedObject() { - public Object computeValue() { - return COFFFileParser.getParser().parse(new AddressDataSource(addr)); - } - }; - } - - /** Indicates whether this is really a DLL or actually a .EXE - file. */ - boolean isDLL() { - return getFile().getHeader().hasCharacteristic(Characteristics.IMAGE_FILE_DLL); - } - - /** Look up a symbol; returns absolute address or null if symbol was - not found. */ - Address lookupSymbol(String symbol) throws COFFException { - if (!isDLL()) { - return null; - } - ExportDirectoryTable exports = getExportDirectoryTable(); - return lookupSymbol(symbol, exports, - 0, exports.getNumberOfNamePointers() - 1); - } - - public Address getBase() { - return addr; - } - - /** Returns the full path name of this DLL/EXE, or null if this DLL - object was created by parsing the target process's address - space. */ - public String getName() { - return fullPathName; - } - - public long getSize() { - return size; - } - - public CDebugInfoDataBase getDebugInfoDataBase() throws DebuggerException { - if (db != null) { - return db; - } - - // Try to parse - if (dbg == null) { - return null; // Need Win32Debugger - } - - if (Assert.ASSERTS_ENABLED) { - Assert.that(fullPathName != null, "Need full path name to build debug info database"); - } - - db = new Win32CDebugInfoBuilder(dbg).buildDataBase(fullPathName, addr); - return db; - } - - public BlockSym debugInfoForPC(Address pc) throws DebuggerException { - CDebugInfoDataBase db = getDebugInfoDataBase(); - if (db == null) { - return null; - } - return db.debugInfoForPC(pc); - } - - public ClosestSymbol closestSymbolToPC(Address pcAsAddr) throws DebuggerException { - ExportDirectoryTable exports = getExportDirectoryTable(); - if (exports == null) { - return null; - } - String name = null; - long pc = dbg.getAddressValue(pcAsAddr); - long diff = Long.MAX_VALUE; - long base = dbg.getAddressValue(addr); - for (int i = 0; i < exports.getNumberOfNamePointers(); i++) { - if (!exports.isExportAddressForwarder(exports.getExportOrdinal(i))) { - long tmp = base + (exports.getExportAddress(exports.getExportOrdinal(i)) & 0xFFFFFFFF); - if ((tmp <= pc) && ((pc - tmp) < diff)) { - diff = pc - tmp; - name = exports.getExportName(i); - } - } - } - if (name == null) { - return null; - } - return new ClosestSymbol(name, diff); - } - - public LineNumberInfo lineNumberForPC(Address pc) throws DebuggerException { - CDebugInfoDataBase db = getDebugInfoDataBase(); - if (db == null) { - return null; - } - return db.lineNumberForPC(pc); - } - - void close() { - getFile().close(); - file = null; - } - - //---------------------------------------------------------------------- - // Internals only below this point - // - - private COFFFile getFile() { - return (COFFFile) file.getValue(); - } - - private Address lookupSymbol(String symbol, ExportDirectoryTable exports, - int loIdx, int hiIdx) { - do { - int curIdx = ((loIdx + hiIdx) >> 1); - String cur = exports.getExportName(curIdx); - if (symbol.equals(cur)) { - return addr.addOffsetTo( - ((long) exports.getExportAddress(exports.getExportOrdinal(curIdx))) & 0xFFFFFFFFL - ); - } - if (symbol.compareTo(cur) < 0) { - if (hiIdx == curIdx) { - hiIdx = curIdx - 1; - } else { - hiIdx = curIdx; - } - } else { - if (loIdx == curIdx) { - loIdx = curIdx + 1; - } else { - loIdx = curIdx; - } - } - } while (loIdx <= hiIdx); - - return null; - } - - private ExportDirectoryTable getExportDirectoryTable() { - return - getFile().getHeader().getOptionalHeader().getDataDirectories().getExportDirectoryTable(); - } - - private Win32Debugger dbg; - private String fullPathName; - private long size; - // MemoizedObject contains a COFFFile - private MemoizedObject file; - // Base address of module in target process - private Address addr; - // Debug info database for this DLL - private CDebugInfoDataBase db; -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestDebugger.java deleted file mode 100644 index ec97a87e9fb..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestDebugger.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; - -public class TestDebugger { - private static void usage() { - System.out.println("usage: java TestDebugger [pid]"); - System.exit(1); - } - - public static void main(String[] args) { - try { - if (args.length != 1) { - usage(); - } - - int pid = 0; - try { - pid = Integer.parseInt(args[0]); - } - catch (NumberFormatException e) { - usage(); - } - - JVMDebugger debugger = new Win32DebuggerLocal(new MachineDescriptionIntelX86(), true); - System.err.println("Process list: "); - List processes = debugger.getProcessList(); - for (Iterator iter = processes.iterator(); iter.hasNext(); ) { - ProcessInfo info = (ProcessInfo) iter.next(); - System.err.println(info.getPid() + " " + info.getName()); - } - System.err.println("Trying to attach..."); - debugger.attach(pid); - System.err.println("Attach succeeded."); - System.err.println("Trying to detach..."); - if (!debugger.detach()) { - System.err.println("ERROR: detach failed."); - System.exit(0); - } - System.err.println("Detach succeeded."); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestHelloWorld.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestHelloWorld.java deleted file mode 100644 index 8a567666f52..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/TestHelloWorld.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; - -/** Tests to see whether we can find the "Hello, World" string in a - target process */ - -public class TestHelloWorld { - private static void usage() { - System.out.println("usage: java TestHelloWorld [pid]"); - System.out.println("pid must be the process ID of the HelloWorldDLL programs"); - System.exit(1); - } - - public static void main(String[] args) { - try { - if (args.length != 1) { - usage(); - } - - int pid = 0; - try { - pid = Integer.parseInt(args[0]); - } - catch (NumberFormatException e) { - usage(); - } - - JVMDebugger debugger = new Win32DebuggerLocal(new MachineDescriptionIntelX86(), true); - System.err.println("Trying to attach..."); - debugger.attach(pid); - System.err.println("Attach succeeded."); - Address addr = debugger.lookup("helloworld.dll", "helloWorldString"); - System.err.println("helloWorldString address = " + addr); - System.err.println("Trying to detach..."); - if (!debugger.detach()) { - System.err.println("ERROR: detach failed."); - System.exit(0); - } - System.err.println("Detach succeeded."); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java deleted file mode 100644 index 6d465ab7c58..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import sun.jvm.hotspot.debugger.*; - -class Win32Address implements Address { - protected Win32Debugger debugger; - protected long addr; - - Win32Address(Win32Debugger debugger, long addr) { - this.debugger = debugger; - this.addr = addr; - } - - // - // Basic Java routines - // - - public boolean equals(Object arg) { - if (arg == null) { - return false; - } - - if (!(arg instanceof Win32Address)) { - return false; - } - - return (addr == ((Win32Address) arg).addr); - } - - public int hashCode() { - // FIXME: suggestions on a better hash code? - return (int) addr; - } - - public String toString() { - return debugger.addressValueToString(addr); - } - - // - // C/C++-related routines - // - - public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readCInteger(addr + offset, numBytes, isUnsigned); - } - - public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readAddress(addr + offset); - } - - public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readCompOopAddress(addr + offset); - } - - // - // Java-related routines - // - - public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJBoolean(addr + offset); - } - - public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJByte(addr + offset); - } - - public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJChar(addr + offset); - } - - public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJDouble(addr + offset); - } - - public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJFloat(addr + offset); - } - - public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJInt(addr + offset); - } - - public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJLong(addr + offset); - } - - public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readJShort(addr + offset); - } - - public OopHandle getOopHandleAt(long offset) - throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { - return debugger.readOopHandle(addr + offset); - } - public OopHandle getCompOopHandleAt(long offset) - throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { - return debugger.readCompOopHandle(addr + offset); - } - - // - // C/C++-related mutators - // - - public void setCIntegerAt(long offset, long numBytes, long value) { - debugger.writeCInteger(addr + offset, numBytes, value); - } - public void setAddressAt(long offset, Address value) { - debugger.writeAddress(addr + offset, (Win32Address) value); - } - - // - // Java-related mutators - // - - public void setJBooleanAt (long offset, boolean value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJBoolean(addr + offset, value); - } - public void setJByteAt (long offset, byte value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJByte(addr + offset, value); - } - public void setJCharAt (long offset, char value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJChar(addr + offset, value); - } - public void setJDoubleAt (long offset, double value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJDouble(addr + offset, value); - } - public void setJFloatAt (long offset, float value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJFloat(addr + offset, value); - } - public void setJIntAt (long offset, int value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJInt(addr + offset, value); - } - public void setJLongAt (long offset, long value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJLong(addr + offset, value); - } - public void setJShortAt (long offset, short value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeJShort(addr + offset, value); - } - public void setOopHandleAt (long offset, OopHandle value) - throws UnmappedAddressException, UnalignedAddressException { - debugger.writeOopHandle(addr + offset, (Win32OopHandle) value); - } - - // - // Arithmetic operations -- necessary evil. - // - - public Address addOffsetTo (long offset) throws UnsupportedOperationException { - long value = addr + offset; - if (value == 0) { - return null; - } - return new Win32Address(debugger, value); - } - - public OopHandle addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException { - long value = addr + offset; - if (value == 0) { - return null; - } - return new Win32OopHandle(debugger, value); - } - - /** (FIXME: any signed/unsigned issues? Should this work for - OopHandles?) */ - public long minus(Address arg) { - if (arg == null) { - return addr; - } - return addr - ((Win32Address) arg).addr; - } - - // Two's complement representation. - // All negative numbers are larger than positive numbers. - // Numbers with the same sign can be compared normally. - // Test harness is below in main(). - - public boolean lessThan (Address a) { - if (a == null) { - return false; - } - Win32Address arg = (Win32Address) a; - if ((addr >= 0) && (arg.addr < 0)) { - return true; - } - if ((addr < 0) && (arg.addr >= 0)) { - return false; - } - return (addr < arg.addr); - } - - public boolean lessThanOrEqual (Address a) { - if (a == null) { - return false; - } - Win32Address arg = (Win32Address) a; - if ((addr >= 0) && (arg.addr < 0)) { - return true; - } - if ((addr < 0) && (arg.addr >= 0)) { - return false; - } - return (addr <= arg.addr); - } - - public boolean greaterThan (Address a) { - if (a == null) { - return true; - } - Win32Address arg = (Win32Address) a; - if ((addr >= 0) && (arg.addr < 0)) { - return false; - } - if ((addr < 0) && (arg.addr >= 0)) { - return true; - } - return (addr > arg.addr); - } - - public boolean greaterThanOrEqual(Address a) { - if (a == null) { - return true; - } - Win32Address arg = (Win32Address) a; - if ((addr >= 0) && (arg.addr < 0)) { - return false; - } - if ((addr < 0) && (arg.addr >= 0)) { - return true; - } - return (addr >= arg.addr); - } - - public Address andWithMask(long mask) throws UnsupportedOperationException { - long value = addr & mask; - if (value == 0) { - return null; - } - return new Win32Address(debugger, value); - } - - public Address orWithMask(long mask) throws UnsupportedOperationException { - long value = addr | mask; - if (value == 0) { - return null; - } - return new Win32Address(debugger, value); - } - - public Address xorWithMask(long mask) throws UnsupportedOperationException { - long value = addr ^ mask; - if (value == 0) { - return null; - } - return new Win32Address(debugger, value); - } - - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - long getValue() { - return addr; - } - - - private static void check(boolean arg, String failMessage) { - if (!arg) { - System.err.println(failMessage + ": FAILED"); - System.exit(1); - } - } - - // Test harness - public static void main(String[] args) { - // p/n indicates whether the interior address is really positive - // or negative. In unsigned terms, p1 < p2 < n1 < n2. - - Win32Address p1 = new Win32Address(null, 0x7FFFFFFFFFFFFFF0L); - Win32Address p2 = (Win32Address) p1.addOffsetTo(10); - Win32Address n1 = (Win32Address) p2.addOffsetTo(10); - Win32Address n2 = (Win32Address) n1.addOffsetTo(10); - - // lessThan positive tests - check(p1.lessThan(p2), "lessThan 1"); - check(p1.lessThan(n1), "lessThan 2"); - check(p1.lessThan(n2), "lessThan 3"); - check(p2.lessThan(n1), "lessThan 4"); - check(p2.lessThan(n2), "lessThan 5"); - check(n1.lessThan(n2), "lessThan 6"); - - // lessThan negative tests - check(!p1.lessThan(p1), "lessThan 7"); - check(!p2.lessThan(p2), "lessThan 8"); - check(!n1.lessThan(n1), "lessThan 9"); - check(!n2.lessThan(n2), "lessThan 10"); - - check(!p2.lessThan(p1), "lessThan 11"); - check(!n1.lessThan(p1), "lessThan 12"); - check(!n2.lessThan(p1), "lessThan 13"); - check(!n1.lessThan(p2), "lessThan 14"); - check(!n2.lessThan(p2), "lessThan 15"); - check(!n2.lessThan(n1), "lessThan 16"); - - // lessThanOrEqual positive tests - check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1"); - check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2"); - check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3"); - check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4"); - - check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5"); - check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6"); - check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7"); - check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8"); - check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9"); - check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10"); - - // lessThanOrEqual negative tests - check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11"); - check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12"); - check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13"); - check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14"); - check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15"); - check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16"); - - // greaterThan positive tests - check(n2.greaterThan(p1), "greaterThan 1"); - check(n2.greaterThan(p2), "greaterThan 2"); - check(n2.greaterThan(n1), "greaterThan 3"); - check(n1.greaterThan(p1), "greaterThan 4"); - check(n1.greaterThan(p2), "greaterThan 5"); - check(p2.greaterThan(p1), "greaterThan 6"); - - // greaterThan negative tests - check(!p1.greaterThan(p1), "greaterThan 7"); - check(!p2.greaterThan(p2), "greaterThan 8"); - check(!n1.greaterThan(n1), "greaterThan 9"); - check(!n2.greaterThan(n2), "greaterThan 10"); - - check(!p1.greaterThan(n2), "greaterThan 11"); - check(!p2.greaterThan(n2), "greaterThan 12"); - check(!n1.greaterThan(n2), "greaterThan 13"); - check(!p1.greaterThan(n1), "greaterThan 14"); - check(!p2.greaterThan(n1), "greaterThan 15"); - check(!p1.greaterThan(p2), "greaterThan 16"); - - // greaterThanOrEqual positive tests - check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1"); - check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2"); - check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3"); - check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4"); - - check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5"); - check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6"); - check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7"); - check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8"); - check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9"); - check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10"); - - // greaterThanOrEqual negative tests - check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11"); - check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12"); - check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13"); - check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14"); - check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15"); - check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16"); - - System.err.println("Win32Address: all tests passed successfully."); - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugInfoBuilder.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugInfoBuilder.java deleted file mode 100644 index ed153849fdc..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugInfoBuilder.java +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.util.*; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.win32.coff.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.debugger.cdbg.basic.*; -import sun.jvm.hotspot.utilities.Assert; - -class Win32CDebugInfoBuilder - implements DebugVC50SubsectionTypes, DebugVC50TypeLeafIndices, DebugVC50TypeEnums, DebugVC50SymbolTypes, DebugVC50MemberAttributes, CVAttributes, AccessControl { - private Win32Debugger dbg; - private Address base; - - private DebugVC50 vc50; - private BasicCDebugInfoDataBase db; - private DebugVC50TypeIterator iter; - - private DebugVC50SymbolIterator symIter; - - // Logical->physical segment mapping - private COFFFile file; - private DebugVC50SSSegMap segMap; - - // Canonicalization of primitive types - private Map primIndexToTypeMap; - - // Global unnamed enumeration - // (FIXME: must figure out how to handle nested type descriptions) - private BasicEnumType unnamedEnum; - - private Stack blockStack; - private int endsToSkip; - - private static final int POINTER_SIZE = 4; - - Win32CDebugInfoBuilder(Win32Debugger dbg) { - this.dbg = dbg; - } - - CDebugInfoDataBase buildDataBase(String dllName, Address base) { - this.base = base; - file = COFFFileParser.getParser().parse(dllName); - vc50 = getDebugVC50(file); - - if (vc50 == null) return null; - - segMap = getSegMap(); - - primIndexToTypeMap = new HashMap(); - blockStack = new Stack(); - endsToSkip = 0; - - db = new BasicCDebugInfoDataBase(); - db.beginConstruction(); - - // Get global types and add them to the database - DebugVC50SSGlobalTypes types = getGlobalTypes(); - for (iter = types.getTypeIterator(); !iter.done(); iter.next()) { - while (!iter.typeStringDone()) { - switch (iter.typeStringLeaf()) { - case LF_MODIFIER: { - int idx = iter.getModifierIndex(); - BasicType target = getTypeByIndex(idx); - short windowsMods = iter.getModifierAttribute(); - short mods = 0; - if ((windowsMods & MODIFIER_CONST_MASK) != 0) mods |= CONST; - if ((windowsMods & MODIFIER_VOLATILE_MASK) != 0) mods |= VOLATILE; - putType(target.getCVVariant(mods)); - break; - } - case LF_POINTER: { - int idx = iter.getPointerType(); - BasicType target = getTypeByIndex(idx); - short windowsMods = iter.getModifierAttribute(); - short mods = 0; - if ((windowsMods & POINTER_CONST_MASK) != 0) mods |= CONST; - if ((windowsMods & POINTER_VOLATILE_MASK) != 0) mods |= VOLATILE; - BasicPointerType ptrType = new BasicPointerType(POINTER_SIZE, target); - if (mods != 0) { - ptrType = (BasicPointerType) ptrType.getCVVariant(mods); - } - - putType(ptrType); - break; - } - case LF_ARRAY: { - BasicType elemType = getTypeByIndex(iter.getArrayElementType()); - putType(new BasicArrayType(iter.getArrayName(), elemType, iter.getArrayLength())); - break; - } - case LF_CLASS: - case LF_STRUCTURE: { - CompoundTypeKind kind = ((iter.typeStringLeaf() == LF_CLASS) ? CompoundTypeKind.CLASS - : CompoundTypeKind.STRUCT); - BasicCompoundType type = new BasicCompoundType(iter.getClassName(), - iter.getClassSize(), - kind); - // Skip parsing of forward references to types - // FIXME: do we have to resolve these later? - if ((iter.getClassProperty() & PROPERTY_FWDREF) == 0) { - DebugVC50TypeIterator fieldIter = iter.getClassFieldListIterator(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(fieldIter.typeStringLeaf() == LF_FIELDLIST, "Expected field list"); - } - boolean advance = false; - while (!fieldIter.typeStringDone()) { - advance = true; - switch (fieldIter.typeStringLeaf()) { - case LF_FIELDLIST: break; - case LF_BCLASS: { - int accessControl = memberAttributeToAccessControl(fieldIter.getBClassAttribute()); - Type baseType = getTypeByIndex(fieldIter.getBClassType()); - // FIXME: take offset into account - type.addBaseClass(new BasicBaseClass(accessControl, false, baseType)); - break; - } - case LF_VBCLASS: { - int accessControl = memberAttributeToAccessControl(fieldIter.getVBClassAttribute()); - Type baseType = getTypeByIndex(fieldIter.getVBClassBaseClassType()); - // FIXME: take offset and virtual base offset into account - type.addBaseClass(new BasicBaseClass(accessControl, true, baseType)); - break; - } - // I don't think we need to handle indirect virtual base - // classes since they should be handled indirectly through - // the modeling of the type hierarchy - case LF_IVBCLASS: break; - case LF_INDEX: { - fieldIter = fieldIter.getIndexIterator(); - advance = false; - break; - } - case LF_MEMBER: { - BasicField field = new BasicField(fieldIter.getMemberName(), - getTypeByIndex(fieldIter.getMemberType()), - memberAttributeToAccessControl(fieldIter.getMemberAttribute()), - false); - field.setOffset(fieldIter.getMemberOffset()); - type.addField(field); - break; - } - case LF_STMEMBER: { - BasicField field = new BasicField(fieldIter.getStaticName(), - getTypeByIndex(fieldIter.getStaticType()), - memberAttributeToAccessControl(fieldIter.getStaticAttribute()), - true); - // The field's address will be found during resolution - // of the debug info database - type.addField(field); - break; - } - // FIXME: handle methods - case LF_METHOD: break; - case LF_ONEMETHOD: break; - // FIXME: handle nested types - case LF_NESTTYPE: break; - case LF_NESTTYPEEX: break; - // NOTE: virtual functions not needed/handled yet for - // this debugging system (because we are not planning to - // handle calling methods in the target process at - // runtime) - case LF_VFUNCTAB: break; - case LF_FRIENDCLS: break; - case LF_VFUNCOFF: break; - case LF_MEMBERMODIFY: break; - case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3: - case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7: - case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11: - case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break; - default: System.err.println("WARNING: unexpected leaf index " + - fieldIter.typeStringLeaf() + - " in field list for type " + iter.getTypeIndex()); - } - if (advance) { - fieldIter.typeStringNext(); - } - } - } - putType(type); - break; - } - case LF_UNION: { - BasicCompoundType type = new BasicCompoundType(iter.getUnionName(), - iter.getUnionSize(), - CompoundTypeKind.UNION); - // Skip parsing of forward references to types - // FIXME: do we have to resolve these later? - if ((iter.getClassProperty() & PROPERTY_FWDREF) == 0) { - DebugVC50TypeIterator fieldIter = iter.getUnionFieldListIterator(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(fieldIter.typeStringLeaf() == LF_FIELDLIST, "Expected field list"); - } - boolean advance = false; - while (!fieldIter.typeStringDone()) { - advance = true; - switch (fieldIter.typeStringLeaf()) { - case LF_FIELDLIST: break; - case LF_BCLASS: break; - case LF_VBCLASS: break; - case LF_IVBCLASS: break; - case LF_INDEX: { - fieldIter = fieldIter.getIndexIterator(); - advance = false; - break; - } - case LF_MEMBER: { - BasicField field = new BasicField(fieldIter.getMemberName(), - getTypeByIndex(fieldIter.getMemberType()), - memberAttributeToAccessControl(fieldIter.getMemberAttribute()), - false); - field.setOffset(fieldIter.getMemberOffset()); - type.addField(field); - break; - } - case LF_STMEMBER: { - System.err.println("WARNING: I didn't think unions could contain static fields..."); - BasicField field = new BasicField(fieldIter.getStaticName(), - getTypeByIndex(fieldIter.getStaticType()), - memberAttributeToAccessControl(fieldIter.getStaticAttribute()), - true); - // The field's address will be found during resolution - // of the debug info database - type.addField(field); - break; - } - case LF_METHOD: break; - case LF_ONEMETHOD: break; - // FIXME: handle nested types - case LF_NESTTYPE: break; - case LF_NESTTYPEEX: break; - case LF_VFUNCTAB: break; - case LF_FRIENDCLS: break; - case LF_VFUNCOFF: break; - case LF_MEMBERMODIFY: break; - case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3: - case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7: - case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11: - case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break; - - default: System.err.println("WARNING: unexpected leaf index " + - fieldIter.typeStringLeaf() + - " in field list for union of type " + iter.getTypeIndex()); - } - if (advance) { - fieldIter.typeStringNext(); - } - } - } - putType(type); - break; - } - case LF_ENUM: { - String name = iter.getEnumName(); - BasicEnumType enumType = null; - if ((name == null) || (name.equals(""))) { - if (unnamedEnum == null) { - unnamedEnum = new BasicEnumType(null, getTypeByIndex(iter.getEnumType())); - } - enumType = unnamedEnum; - } else { - enumType = new BasicEnumType(name, getTypeByIndex(iter.getEnumType())); - } - DebugVC50TypeIterator fieldIter = iter.getEnumFieldListIterator(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(fieldIter.typeStringLeaf() == LF_FIELDLIST, "Expected field list"); - } - boolean advance = false; - while (!fieldIter.typeStringDone()) { - advance = true; - switch (fieldIter.typeStringLeaf()) { - case LF_FIELDLIST: break; - case LF_ENUMERATE: { - String enumName = fieldIter.getEnumerateName(); - long enumVal = fieldIter.getEnumerateValue(); - enumType.addEnum(enumName, enumVal); - break; - } - case LF_INDEX: { - fieldIter = fieldIter.getIndexIterator(); - advance = false; - break; - } - - case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3: - case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7: - case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11: - case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break; - - default: System.err.println("WARNING: unexpected leaf index " + - fieldIter.typeStringLeaf() + - " in field list for enum of type " + iter.getTypeIndex()); - } - - if (advance) { - fieldIter.typeStringNext(); - } - } - - putType(enumType); - break; - } - case LF_PROCEDURE: { - Type retType = getTypeByIndex(iter.getProcedureReturnType()); - BasicFunctionType func = new BasicFunctionType(null, POINTER_SIZE, retType); - DebugVC50TypeIterator argIter = iter.getProcedureArgumentListIterator(); - if (Assert.ASSERTS_ENABLED) { - Assert.that(argIter.typeStringLeaf() == LF_ARGLIST, "Expected argument list"); - } - for (int i = 0; i < argIter.getArgListCount(); i++) { - func.addArgumentType(getTypeByIndex(argIter.getArgListType(i))); - } - putType(func); - break; - } - case LF_MFUNCTION: { - Type retType = getTypeByIndex(iter.getMFunctionReturnType()); - Type container = getTypeByIndex(iter.getMFunctionContainingClass()); - Type thisType = getTypeByIndex(iter.getMFunctionThis()); - long thisAdjust = iter.getMFunctionThisAdjust(); - BasicMemberFunctionType func = new BasicMemberFunctionType(null, - POINTER_SIZE, - retType, - container, - thisType, - thisAdjust); - DebugVC50TypeIterator argIter = iter.getMFunctionArgumentListIterator(); - for (int i = 0; i < argIter.getArgListCount(); i++) { - func.addArgumentType(getTypeByIndex(argIter.getArgListType(i))); - } - putType(func); - break; - } - // FIXME: handle virtual function table shape description - case LF_VTSHAPE: break; - case LF_BARRAY: System.err.println("FIXME: don't know what to do with LF_BARRAY leaves (convert to pointers?"); break; - case LF_LABEL: break; - case LF_NULL: break; // FIXME: do we need to handle this? With what? - case LF_DIMARRAY: System.err.println("FIXME: don't know what to do with LF_DIMARRAY leaves yet"); break; - case LF_VFTPATH: break; - case LF_PRECOMP: break; - case LF_ENDPRECOMP: break; - case LF_OEM: break; - case LF_TYPESERVER: break; - - // Type records referenced from other type records - - case LF_SKIP: break; - case LF_ARGLIST: skipTypeRecord(); break; - case LF_DEFARG: System.err.println("FIXME: handle default arguments (dereference the type)"); break; - case LF_FIELDLIST: skipTypeRecord(); break; - case LF_DERIVED: break; - case LF_BITFIELD: { - Type underlyingType = getTypeByIndex(iter.getBitfieldFieldType()); - BasicBitType bit = new BasicBitType(underlyingType, - (iter.getBitfieldLength() & 0xFF), - (iter.getBitfieldPosition() & 0xFF)); - putType(bit); - break; - } - case LF_METHODLIST: break; - case LF_DIMCONU: - case LF_DIMCONLU: - case LF_DIMVARU: - case LF_DIMVARLU: break; - case LF_REFSYM: break; - - case LF_PAD0: case LF_PAD1: case LF_PAD2: case LF_PAD3: - case LF_PAD4: case LF_PAD5: case LF_PAD6: case LF_PAD7: - case LF_PAD8: case LF_PAD9: case LF_PAD10: case LF_PAD11: - case LF_PAD12: case LF_PAD13: case LF_PAD14: case LF_PAD15: break; - - default: { - System.err.println("Unexpected leaf index " + - iter.typeStringLeaf() + " at offset 0x" + - Integer.toHexString(iter.typeStringOffset())); - break; - } - } - - - if (!iter.typeStringDone()) { - iter.typeStringNext(); - } - } - } - - // Add all symbol directories to debug info - // (FIXME: must figure out how to handle module-by-module - // arrangement of at least the static symbols to have proper - // lookup -- should probably also take advantage of the PROCREF - // and UDT references to understand how to build the global - // database vs. the module-by-module one) - DebugVC50SubsectionDirectory dir = vc50.getSubsectionDirectory(); - int moduleNumber = 0; // Debugging - for (int i = 0; i < dir.getNumEntries(); i++) { - DebugVC50Subsection ss = dir.getSubsection(i); - int ssType = ss.getSubsectionType(); - boolean process = false; - - if ((ssType == SST_GLOBAL_SYM) || - (ssType == SST_GLOBAL_PUB) || - (ssType == SST_STATIC_SYM)) { - DebugVC50SSSymbolBase syms = (DebugVC50SSSymbolBase) ss; - symIter = syms.getSymbolIterator(); - process = true; - } - - if (ssType == SST_ALIGN_SYM) { - DebugVC50SSAlignSym syms = (DebugVC50SSAlignSym) ss; - symIter = syms.getSymbolIterator(); - process = true; - } - - if (process) { - for (; !symIter.done(); symIter.next()) { - switch (symIter.getType()) { - case S_COMPILE: break; - case S_SSEARCH: break; // FIXME: may need this later - case S_END: { - try { - // FIXME: workaround for warnings until we figure out - // what to do with THUNK32 symbols - if (endsToSkip == 0) { - blockStack.pop(); - } else { - --endsToSkip; - } - } catch (EmptyStackException e) { - System.err.println("WARNING: mismatched block begins/ends in debug information"); - } - break; - } - case S_SKIP: break; - case S_CVRESERVE: break; - case S_OBJNAME: break; // FIXME: may need this later - case S_ENDARG: break; - case S_COBOLUDT: break; - case S_MANYREG: break; // FIXME: may need to add support for this - case S_RETURN: break; // NOTE: would need this if adding support for calling functions - case S_ENTRYTHIS: break; // FIXME: may need to add support for this - case S_REGISTER: break; // FIXME: may need to add support for this - case S_CONSTANT: break; // FIXME: will need to add support for this - case S_UDT: break; // FIXME: need to see how these are used; are - // they redundant, or are they used to describe - // global variables as opposed to types? - case S_COBOLUDT2: break; - case S_MANYREG2: break; - case S_BPREL32: { - LocalSym sym = new BasicLocalSym(symIter.getBPRelName(), - getTypeByIndex(symIter.getBPRelType()), - symIter.getBPRelOffset()); - addLocalToCurBlock(sym); - break; - } - case S_LDATA32: - case S_GDATA32: { - // FIXME: must handle these separately from global data (have - // module scoping and only add these at the module level) - boolean isModuleLocal = (symIter.getType() == S_LDATA32); - - GlobalSym sym = new BasicGlobalSym(symIter.getLGDataName(), - getTypeByIndex(symIter.getLGDataType()), - newAddress(symIter.getLGDataOffset(), symIter.getLGDataSegment()), - isModuleLocal); - // FIXME: must handle module-local symbols differently - addGlobalSym(sym); - break; - } - case S_PUB32: break; // FIXME: figure out how these differ from - // above and how they are used - case S_LPROC32: - case S_GPROC32: { - BasicFunctionSym sym = new BasicFunctionSym(newLazyBlockSym(symIter.getLGProcParentOffset()), - symIter.getLGProcLength(), - newAddress(symIter.getLGProcOffset(), symIter.getLGProcSegment()), - symIter.getLGProcName(), - getTypeByIndex(symIter.getLGProcType()), - (symIter.getType() == S_LPROC32)); - - // FIXME: have to handle local procedures differently (have - // notion of modules and only add those procedures to the - // module they are defined in) - addBlock(sym); - break; - } - case S_THUNK32: { - // FIXME: see whether we need to handle these - skipEnd(); - break; - } - case S_BLOCK32: { - BasicBlockSym sym = new BasicBlockSym(newLazyBlockSym(symIter.getBlockParentOffset()), - symIter.getBlockLength(), - newAddress(symIter.getBlockOffset(), symIter.getBlockSegment()), - symIter.getBlockName()); - addBlock(sym); - break; - } - case S_WITH32: break; - case S_LABEL32: break; - case S_CEXMODEL32: break; - case S_VFTTABLE32: break; // FIXME: may need to handle this - // (most likely for run-time type determination) - case S_REGREL32: break; // FIXME: may need to add support for this - case S_LTHREAD32: break; - case S_GTHREAD32: break; // FIXME: may need to add support for these - case S_PROCREF: break; - case S_DATAREF: break; - case S_ALIGN: break; - default: - // These two unknown symbol types show up very frequently. - // Symbol type 0 appears to always be a no-op symbol of - // length 2 (i.e., length just covers the symbol type.) - // Symbol type 4115 appears to be a copyright notice for - // the Microsoft linker. - if ((symIter.getType() != 0) && (symIter.getType() != 4115)) { - System.err.println(" NOTE: Unexpected symbol of type " + - symIter.getType() + " at offset 0x" + - Integer.toHexString(symIter.getOffset())); - } - break; - } - } - } - } - - // Add line number information for all modules - for (int i = 0; i < dir.getNumEntries(); i++) { - DebugVC50Subsection ss = dir.getSubsection(i); - if (ss.getSubsectionType() == SST_SRC_MODULE) { - DebugVC50SSSrcModule srcMod = (DebugVC50SSSrcModule) ss; - for (int sf = 0; sf < srcMod.getNumSourceFiles(); sf++) { - DebugVC50SrcModFileDesc desc = srcMod.getSourceFileDesc(sf); - // Uniquify these to save space - String name = desc.getSourceFileName().intern(); - for (int cs = 0; cs < desc.getNumCodeSegments(); cs++) { - DebugVC50SrcModLineNumberMap map = desc.getLineNumberMap(cs); - SectionHeader seg = file.getHeader().getSectionHeader(map.getSegment()); - for (int lp = 0; lp < map.getNumSourceLinePairs(); lp++) { - Address startPC = base.addOffsetTo(seg.getVirtualAddress() + map.getCodeOffset(lp)); - // Fake address for endPC -- will be filled in by BasicLineNumberMapping - Address endPC = base.addOffsetTo(seg.getSize()); - db.addLineNumberInfo(new BasicLineNumberInfo(name, map.getLineNumber(lp), startPC, endPC)); - } - } - } - } - } - - // Finish assembly of database - db.resolve(new ResolveListener() { - public void resolveFailed(Type containingType, LazyType failedResolve, String detail) { - System.err.println("WARNING: failed to resolve type of index " + - ((Integer) failedResolve.getKey()).intValue() + - " in type " + containingType.getName() + " (class " + - containingType.getClass().getName() + ") while " + detail); - } - - public void resolveFailed(Type containingType, String staticFieldName) { - System.err.println("WARNING: failed to resolve address of static field \"" + - staticFieldName + "\" in type " + containingType.getName()); - } - - public void resolveFailed(Sym containingSymbol, LazyType failedResolve, String detail) { - System.err.println("WARNING: failed to resolve type of index " + - ((Integer) failedResolve.getKey()).intValue() + - " in symbol of type " + containingSymbol.getClass().getName() + - " while " + detail); - } - - public void resolveFailed(Sym containingSymbol, LazyBlockSym failedResolve, String detail) { - System.err.println("WARNING: failed to resolve block at offset 0x" + - Integer.toHexString(((Integer) failedResolve.getKey()).intValue()) + - " in symbol of type " + containingSymbol.getClass().getName() + - " while " + detail); - } - }); - - db.endConstruction(); - - return db; - } - - - //---------------------------------------------------------------------- - // Internals only below this point - // - - private static DebugVC50 getDebugVC50(COFFFile file) { - COFFHeader header = file.getHeader(); - OptionalHeader opt = header.getOptionalHeader(); - if (opt == null) { - // Optional header not found - return null; - } - OptionalHeaderDataDirectories dd = opt.getDataDirectories(); - if (dd == null) { - // Optional header data directories not found - return null; - } - DebugDirectory debug = dd.getDebugDirectory(); - if (debug == null) { - // Debug directory not found - return null; - } - for (int i = 0; i < debug.getNumEntries(); i++) { - DebugDirectoryEntry entry = debug.getEntry(i); - if (entry.getType() == DebugTypes.IMAGE_DEBUG_TYPE_CODEVIEW) { - return entry.getDebugVC50(); - } - } - - // CodeView information not found in debug directory - return null; - } - - private DebugVC50SSSegMap getSegMap() { - return (DebugVC50SSSegMap) findSubsection(SST_SEG_MAP); - } - - private DebugVC50SSGlobalTypes getGlobalTypes() { - return (DebugVC50SSGlobalTypes) findSubsection(SST_GLOBAL_TYPES); - } - - private DebugVC50SSGlobalSym getGlobalSymbols() { - return (DebugVC50SSGlobalSym) findSubsection(SST_GLOBAL_SYM); - } - - private DebugVC50Subsection findSubsection(short ssType) { - DebugVC50SubsectionDirectory dir = vc50.getSubsectionDirectory(); - for (int i = 0; i < dir.getNumEntries(); i++) { - DebugVC50Subsection ss = dir.getSubsection(i); - if (ss.getSubsectionType() == ssType) { - return ss; - } - } - throw new DebuggerException("Unable to find subsection of type " + ssType); - } - - private void putType(Type t) { - db.addType(new Integer(iter.getTypeIndex()), t); - } - - private Address newAddress(int offset, short segment) { - int seg = segment & 0xFFFF; - // NOTE: it isn't clear how to use the segMap to map from logical - // to physical segments. It seems it would make more sense if the - // SegDescs contained a physical segment number in addition to the - // offset within the physical segment of the logical one. - - // Get the section header corresponding to this segment - SectionHeader section = file.getHeader().getSectionHeader(seg); - - // Result is relative to image base - return base.addOffsetTo(section.getVirtualAddress() + offset); - } - - private BasicType getTypeByIndex(int intIndex) { - Integer index = new Integer(intIndex); - - // Handle primitive types here. - if (intIndex <= 0x0FFF) { - BasicType type = (BasicType) primIndexToTypeMap.get(index); - if (type != null) { - return type; - } - // Construct appropriate new primitive type - int primMode = intIndex & RESERVED_MODE_MASK; - if (primMode == RESERVED_MODE_DIRECT) { - int primType = intIndex & RESERVED_TYPE_MASK; - switch (primType) { - case RESERVED_TYPE_SIGNED_INT: - case RESERVED_TYPE_UNSIGNED_INT: { - boolean unsigned = (primType == RESERVED_TYPE_UNSIGNED_INT); - int size = 0; - String name = null; - switch (intIndex & RESERVED_SIZE_MASK) { - case RESERVED_SIZE_INT_1_BYTE: size = 1; name = "char"; break; - case RESERVED_SIZE_INT_2_BYTE: size = 2; name = "short"; break; - case RESERVED_SIZE_INT_4_BYTE: size = 4; name = "int"; break; - case RESERVED_SIZE_INT_8_BYTE: size = 8; name = "__int64"; break; - default: throw new DebuggerException("Illegal size of integer type " + intIndex); - } - type = new BasicIntType(name, size, unsigned); - break; - } - case RESERVED_TYPE_BOOLEAN: { - int size = 0; - switch (intIndex & RESERVED_SIZE_MASK) { - case RESERVED_SIZE_INT_1_BYTE: size = 1; break; - case RESERVED_SIZE_INT_2_BYTE: size = 2; break; - case RESERVED_SIZE_INT_4_BYTE: size = 4; break; - case RESERVED_SIZE_INT_8_BYTE: size = 8; break; - default: throw new DebuggerException("Illegal size of boolean type " + intIndex); - } - type = new BasicIntType("bool", size, false); - break; - } - case RESERVED_TYPE_REAL: { - switch (intIndex & RESERVED_SIZE_MASK) { - case RESERVED_SIZE_REAL_32_BIT: - type = new BasicFloatType("float", 4); - break; - case RESERVED_SIZE_REAL_64_BIT: - type = new BasicDoubleType("double", 8); - break; - default: - throw new DebuggerException("Unsupported floating-point size in type " + intIndex); - } - break; - } - case RESERVED_TYPE_REALLY_INT: { - switch (intIndex & RESERVED_SIZE_MASK) { - case RESERVED_SIZE_REALLY_INT_CHAR: type = new BasicIntType("char", 1, false); break; - case RESERVED_SIZE_REALLY_INT_WCHAR: type = new BasicIntType("wchar", 2, false); break; - case RESERVED_SIZE_REALLY_INT_2_BYTE: type = new BasicIntType("short", 2, false); break; - case RESERVED_SIZE_REALLY_INT_2_BYTE_U: type = new BasicIntType("short", 2, true); break; - case RESERVED_SIZE_REALLY_INT_4_BYTE: type = new BasicIntType("int", 4, false); break; - case RESERVED_SIZE_REALLY_INT_4_BYTE_U: type = new BasicIntType("int", 4, true); break; - case RESERVED_SIZE_REALLY_INT_8_BYTE: type = new BasicIntType("__int64", 8, false); break; - case RESERVED_SIZE_REALLY_INT_8_BYTE_U: type = new BasicIntType("__int64", 8, true); break; - default: throw new DebuggerException("Illegal REALLY_INT size in type " + intIndex); - } - break; - } - case RESERVED_TYPE_SPECIAL: { - switch (intIndex & RESERVED_SIZE_MASK) { - case RESERVED_SIZE_SPECIAL_NO_TYPE: - case RESERVED_SIZE_SPECIAL_VOID: type = new BasicVoidType(); break; - default: throw new DebuggerException("Don't know how to handle reserved special type " + intIndex); - } - break; - } - - default: - throw new DebuggerException("Don't know how to handle reserved type " + intIndex); - } - } else { - // Fold all pointer types together since we only support - // flat-mode addressing anyway - Type targetType = getTypeByIndex(intIndex & (~RESERVED_MODE_MASK)); - - type = new BasicPointerType(POINTER_SIZE, targetType); - } - if (Assert.ASSERTS_ENABLED) { - Assert.that(type != null, "Got null Type for primitive type " + intIndex); - } - primIndexToTypeMap.put(index, type); - return type; - } - - // Not primitive type. Construct lazy reference to target type. - // (Is it worth canonicalizing these as well to save space?) - return new LazyType(index); - } - - private void addBlock(BlockSym block) { - db.addBlock(new Integer(symIter.getOffset()), block); - blockStack.push(block); - } - - private void skipEnd() { - ++endsToSkip; - } - - private BlockSym newLazyBlockSym(int offset) { - if (offset == 0) { - return null; - } - - return new LazyBlockSym(new Integer(offset)); - } - - private int memberAttributeToAccessControl(short memberAttribute) { - int acc = memberAttribute & MEMATTR_ACCESS_MASK; - switch (acc) { - case MEMATTR_ACCESS_NO_PROTECTION: return NO_PROTECTION; - case MEMATTR_ACCESS_PRIVATE: return PRIVATE; - case MEMATTR_ACCESS_PROTECTED: return PROTECTED; - case MEMATTR_ACCESS_PUBLIC: return PUBLIC; - default: throw new RuntimeException("Should not reach here"); - } - } - - private void addLocalToCurBlock(LocalSym local) { - ((BasicBlockSym) blockStack.peek()).addLocal(local); - } - - private void addGlobalSym(GlobalSym sym) { - db.addGlobalSym(sym); - } - - private void skipTypeRecord() { - while (!iter.typeStringDone()) { - iter.typeStringNext(); - } - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugger.java deleted file mode 100644 index 488440f78e0..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32CDebugger.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.debugger.cdbg.basic.x86.*; -import sun.jvm.hotspot.debugger.x86.*; -import sun.jvm.hotspot.utilities.AddressOps; - -class Win32CDebugger implements CDebugger, ProcessControl { - // FIXME: think about how to make this work in a remote debugging - // scenario; who should keep open DLLs? Need local copies of these - // DLLs on the debugging machine? - private Win32Debugger dbg; - - Win32CDebugger(Win32Debugger dbg) { - this.dbg = dbg; - } - - public List getThreadList() throws DebuggerException { - return dbg.getThreadList(); - } - - public List/**/ getLoadObjectList() throws DebuggerException{ - return dbg.getLoadObjectList(); - } - - public LoadObject loadObjectContainingPC(Address pc) throws DebuggerException { - // FIXME: could keep sorted list of these to be able to do binary - // searches, for better scalability - if (pc == null) { - return null; - } - List objs = getLoadObjectList(); - for (Iterator iter = objs.iterator(); iter.hasNext(); ) { - LoadObject obj = (LoadObject) iter.next(); - if (AddressOps.lte(obj.getBase(), pc) && (pc.minus(obj.getBase()) < obj.getSize())) { - return obj; - } - } - return null; - } - - public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException { - X86ThreadContext context = (X86ThreadContext) thread.getContext(); - Address ebp = context.getRegisterAsAddress(X86ThreadContext.EBP); - if (ebp == null) return null; - Address pc = context.getRegisterAsAddress(X86ThreadContext.EIP); - if (pc == null) return null; - return new X86CFrame(this, ebp, pc); - } - - public String getNameOfFile(String fileName) { - return new File(fileName).getName(); - } - - public ProcessControl getProcessControl() throws DebuggerException { - return this; - } - - // C++ name demangling - public boolean canDemangle() { - return false; - } - - public String demangle(String sym) { - throw new UnsupportedOperationException(); - } - - // - // Support for ProcessControl interface - // - - public void suspend() throws DebuggerException { - dbg.suspend(); - } - public void resume() throws DebuggerException { - dbg.resume(); - } - public boolean isSuspended() throws DebuggerException { - return dbg.isSuspended(); - } - public void setBreakpoint(Address addr) throws DebuggerException { - dbg.setBreakpoint(addr); - } - public void clearBreakpoint(Address addr) throws DebuggerException { - dbg.clearBreakpoint(addr); - } - public boolean isBreakpointSet(Address addr) throws DebuggerException { - return dbg.isBreakpointSet(addr); - } - public DebugEvent debugEventPoll() throws DebuggerException { - return dbg.debugEventPoll(); - } - public void debugEventContinue() throws DebuggerException { - dbg.debugEventContinue(); - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java deleted file mode 100644 index 160c8e1e252..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.util.List; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; - -/** An extension of the JVMDebugger interface with a few additions to - support 32-bit vs. 64-bit debugging as well as features required - by the architecture-specific subpackages. */ - -public interface Win32Debugger extends JVMDebugger { - public String addressValueToString(long address) throws DebuggerException; - public boolean readJBoolean(long address) throws DebuggerException; - public byte readJByte(long address) throws DebuggerException; - public char readJChar(long address) throws DebuggerException; - public double readJDouble(long address) throws DebuggerException; - public float readJFloat(long address) throws DebuggerException; - public int readJInt(long address) throws DebuggerException; - public long readJLong(long address) throws DebuggerException; - public short readJShort(long address) throws DebuggerException; - public long readCInteger(long address, long numBytes, boolean isUnsigned) - throws DebuggerException; - public Win32Address readAddress(long address) throws DebuggerException; - public Win32Address readCompOopAddress(long address) throws DebuggerException; - public Win32OopHandle readOopHandle(long address) throws DebuggerException; - public Win32OopHandle readCompOopHandle(long address) throws DebuggerException; - public void writeJBoolean(long address, boolean value) throws DebuggerException; - public void writeJByte(long address, byte value) throws DebuggerException; - public void writeJChar(long address, char value) throws DebuggerException; - public void writeJDouble(long address, double value) throws DebuggerException; - public void writeJFloat(long address, float value) throws DebuggerException; - public void writeJInt(long address, int value) throws DebuggerException; - public void writeJLong(long address, long value) throws DebuggerException; - public void writeJShort(long address, short value) throws DebuggerException; - public void writeCInteger(long address, long numBytes, long value) throws DebuggerException; - public void writeAddress(long address, Win32Address value) throws DebuggerException; - public void writeOopHandle(long address, Win32OopHandle value) throws DebuggerException; - - // On Windows the int is actually the value of a HANDLE which - // currently must be read from the target process; that is, the - // target process must maintain its own thread list, each element of - // which holds a HANDLE to its underlying OS thread. FIXME: should - // add access to the OS-level thread list, but there are too many - // limitations imposed by Windows to usefully do so; see - // src/os/win32/agent/README-commands.txt, command "duphandle". - // - // The returned array of register contents is guaranteed to be in - // the same order as in the DbxDebugger for Solaris/x86; that is, - // the indices match those in debugger/x86/X86ThreadContext.java. - public long[] getThreadIntegerRegisterSet(int threadHandleValue, - boolean mustDuplicateHandle) throws DebuggerException; - // Implmentation of setContext - public void setThreadIntegerRegisterSet(int threadHandleValue, - boolean mustDuplicateHandle, - long[] contents) throws DebuggerException; - - public Address newAddress(long value) throws DebuggerException; - - // Routine supporting the ThreadProxy implementation, in particular - // the ability to get a thread ID from a thread handle via - // examination of the Thread Information Block. Fetch the LDT entry - // for a given selector. - public Win32LDTEntry getThreadSelectorEntry(int threadHandleValue, - boolean mustDuplicateHandle, - int selector) throws DebuggerException; - - // Support for the CDebugger interface. Retrieves the thread list of - // the target process as a List of ThreadProxy objects. - public List/**/ getThreadList() throws DebuggerException; - - // Support for the CDebugger interface. Retrieves a List of the - // loadobjects in the target process. - public List/**/ getLoadObjectList() throws DebuggerException; - - // Support for the ProcessControl interface - public void writeBytesToProcess(long startAddress, long numBytes, byte[] data) throws UnmappedAddressException, DebuggerException; - public void suspend() throws DebuggerException; - public void resume() throws DebuggerException; - public boolean isSuspended() throws DebuggerException; - public void setBreakpoint(Address addr) throws DebuggerException; - public void clearBreakpoint(Address addr) throws DebuggerException; - public boolean isBreakpointSet(Address addr) throws DebuggerException; - // FIXME: do not want to expose complicated data structures (like - // the DebugEvent) in this interface due to serialization issues - public DebugEvent debugEventPoll() throws DebuggerException; - public void debugEventContinue() throws DebuggerException; - - // NOTE: this interface implicitly contains the following methods: - // From the Debugger interface via JVMDebugger - // public void attach(int processID) throws DebuggerException; - // public void attach(String executableName, String coreFileName) throws DebuggerException; - // public boolean detach(); - // public Address parseAddress(String addressString) throws NumberFormatException; - // public long getAddressValue(Address addr) throws DebuggerException; - // public String getOS(); - // public String getCPU(); - // From the SymbolLookup interface via Debugger and JVMDebugger - // public Address lookup(String objectName, String symbol); - // public OopHandle lookupOop(String objectName, String symbol); - // From the JVMDebugger interface - // public void configureJavaPrimitiveTypeSizes(long jbooleanSize, - // long jbyteSize, - // long jcharSize, - // long jdoubleSize, - // long jfloatSize, - // long jintSize, - // long jlongSize, - // long jshortSize); - // From the ThreadAccess interface via Debugger and JVMDebugger - // public ThreadProxy getThreadForIdentifierAddress(Address addr); -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java deleted file mode 100644 index c45bd6f8159..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.io.*; -import java.net.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.x86.*; -import sun.jvm.hotspot.debugger.win32.coff.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent; -import sun.jvm.hotspot.utilities.*; -import sun.jvm.hotspot.utilities.memo.*; - -/**

An implementation of the JVMDebugger interface which talks to - the Free Windows Debug Server (FwDbgSrv) over a socket to - implement attach/detach and read from process memory. All DLL and - symbol table management is done in Java.

- -

NOTE that since we have the notion of fetching "Java - primitive types" from the remote process (which might have - different sizes than we expect) we have a bootstrapping - problem. We need to know the sizes of these types before we can - fetch them. The current implementation solves this problem by - requiring that it be configured with these type sizes before they - can be fetched. The readJ(Type) routines here will throw a - RuntimeException if they are called before the debugger is - configured with the Java primitive type sizes.

*/ - -public class Win32DebuggerLocal extends DebuggerBase implements Win32Debugger { - private Socket debuggerSocket; - private boolean attached; - // FIXME: update when core files supported - private long pid; - // Communication with debug server - private PrintWriter out; - private DataOutputStream rawOut; - private InputLexer in; - private static final int PORT = 27000; - private PageCache cache; - private static final long SHORT_TIMEOUT = 2000; - private static final long LONG_TIMEOUT = 20000; - - // Symbol lookup support - // This is a map of library names to DLLs - private Map nameToDllMap; - - // C/C++ debugging support - private List/**/ loadObjects; - private CDebugger cdbg; - - // ProcessControl support - private boolean suspended; - // Maps Long objects (addresses) to Byte objects (original instructions) - // (Longs used instead of Addresses to properly represent breakpoints at 0x0 if needed) - private Map breakpoints; - // Current debug event, if any - private DebugEvent curDebugEvent; - - //-------------------------------------------------------------------------------- - // Implementation of Debugger interface - // - - /**

machDesc may not be null.

- -

useCache should be set to true if debugging is being done - locally, and to false if the debugger is being created for the - purpose of supporting remote debugging.

*/ - public Win32DebuggerLocal(MachineDescription machDesc, - boolean useCache) throws DebuggerException { - this.machDesc = machDesc; - utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian()); - if (useCache) { - // Cache portion of the remote process's address space. - // Fetching data over the socket connection to dbx is slow. - // Might be faster if we were using a binary protocol to talk to - // dbx, but would have to test. For now, this cache works best - // if it covers the entire heap of the remote process. FIXME: at - // least should make this tunable from the outside, i.e., via - // the UI. This is a cache of 4096 4K pages, or 16 MB. The page - // size must be adjusted to be the hardware's page size. - // (FIXME: should pick this up from the debugger.) - initCache(4096, parseCacheNumPagesProperty(4096)); - } - // FIXME: add instantiation of thread factory - - try { - connectToDebugServer(); - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - /** From the Debugger interface via JVMDebugger */ - public boolean hasProcessList() throws DebuggerException { - return true; - } - - /** From the Debugger interface via JVMDebugger */ - public List getProcessList() throws DebuggerException { - List processes = new ArrayList(); - - try { - printlnToOutput("proclist"); - int num = in.parseInt(); - for (int i = 0; i < num; i++) { - int pid = in.parseInt(); - String name = parseString(); - // NOTE: Win32 hack - if (name.equals("")) { - name = "System Idle Process"; - } - processes.add(new ProcessInfo(name, pid)); - } - return processes; - } - catch (IOException e) { - throw new DebuggerException(e); - } - } - - /** From the Debugger interface via JVMDebugger */ - public synchronized void attach(int processID) throws DebuggerException { - if (attached) { - // FIXME: update when core files supported - throw new DebuggerException("Already attached to process " + pid); - } - - try { - printlnToOutput("attach " + processID); - if (!in.parseBoolean()) { - throw new DebuggerException("Error attaching to process, or no such process"); - } - - attached = true; - pid = processID; - suspended = true; - breakpoints = new HashMap(); - curDebugEvent = null; - nameToDllMap = null; - loadObjects = null; - } - catch (IOException e) { - throw new DebuggerException(e); - } - } - - /** From the Debugger interface via JVMDebugger */ - public synchronized void attach(String executableName, String coreFileName) throws DebuggerException { - throw new DebuggerException("Core files not yet supported on Win32"); - } - - /** From the Debugger interface via JVMDebugger */ - public synchronized boolean detach() { - if (!attached) { - return false; - } - - attached = false; - suspended = false; - breakpoints = null; - - // Close all open DLLs - if (nameToDllMap != null) { - for (Iterator iter = nameToDllMap.values().iterator(); iter.hasNext(); ) { - DLL dll = (DLL) iter.next(); - dll.close(); - } - nameToDllMap = null; - loadObjects = null; - } - - cdbg = null; - clearCache(); - - try { - printlnToOutput("detach"); - return in.parseBoolean(); - } - catch (IOException e) { - throw new DebuggerException(e); - } - } - - /** From the Debugger interface via JVMDebugger */ - public Address parseAddress(String addressString) throws NumberFormatException { - return newAddress(utils.scanAddress(addressString)); - } - - /** From the Debugger interface via JVMDebugger */ - public String getOS() { - return PlatformInfo.getOS(); - } - - /** From the Debugger interface via JVMDebugger */ - public String getCPU() { - return PlatformInfo.getCPU(); - } - - public boolean hasConsole() throws DebuggerException { - return false; - } - - public String consoleExecuteCommand(String cmd) throws DebuggerException { - throw new DebuggerException("No debugger console available on Win32"); - } - - public String getConsolePrompt() throws DebuggerException { - return null; - } - - public CDebugger getCDebugger() throws DebuggerException { - if (cdbg == null) { - cdbg = new Win32CDebugger(this); - } - return cdbg; - } - - /** From the SymbolLookup interface via Debugger and JVMDebugger */ - public synchronized Address lookup(String objectName, String symbol) { - if (!attached) { - return null; - } - return newAddress(lookupInProcess(objectName, symbol)); - } - - /** From the SymbolLookup interface via Debugger and JVMDebugger */ - public synchronized OopHandle lookupOop(String objectName, String symbol) { - Address addr = lookup(objectName, symbol); - if (addr == null) { - return null; - } - return addr.addOffsetToAsOopHandle(0); - } - - /** From the Debugger interface */ - public MachineDescription getMachineDescription() { - return machDesc; - } - - //-------------------------------------------------------------------------------- - // Implementation of ThreadAccess interface - // - - /** From the ThreadAccess interface via Debugger and JVMDebugger */ - public ThreadProxy getThreadForIdentifierAddress(Address addr) { - return new Win32Thread(this, addr); - } - - public ThreadProxy getThreadForThreadId(long handle) { - return new Win32Thread(this, handle); - } - - //---------------------------------------------------------------------- - // Overridden from DebuggerBase because we need to relax alignment - // constraints on x86 - - public long readJLong(long address) - throws UnmappedAddressException, UnalignedAddressException { - checkJavaConfigured(); - // FIXME: allow this to be configurable. Undesirable to add a - // dependency on the runtime package here, though, since this - // package should be strictly underneath it. - // utils.checkAlignment(address, jlongSize); - utils.checkAlignment(address, jintSize); - byte[] data = readBytes(address, jlongSize); - return utils.dataToJLong(data, jlongSize); - } - - //-------------------------------------------------------------------------------- - // Internal routines (for implementation of Win32Address). - // These must not be called until the MachineDescription has been set up. - // - - /** From the Win32Debugger interface */ - public String addressValueToString(long address) { - return utils.addressValueToString(address); - } - - /** From the Win32Debugger interface */ - public Win32Address readAddress(long address) - throws UnmappedAddressException, UnalignedAddressException { - return (Win32Address) newAddress(readAddressValue(address)); - } - - public Win32Address readCompOopAddress(long address) - throws UnmappedAddressException, UnalignedAddressException { - return (Win32Address) newAddress(readCompOopAddressValue(address)); - } - - /** From the Win32Debugger interface */ - public Win32OopHandle readOopHandle(long address) - throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { - long value = readAddressValue(address); - return (value == 0 ? null : new Win32OopHandle(this, value)); - } - public Win32OopHandle readCompOopHandle(long address) - throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { - long value = readCompOopAddressValue(address); - return (value == 0 ? null : new Win32OopHandle(this, value)); - } - - /** From the Win32Debugger interface */ - public void writeAddress(long address, Win32Address value) { - writeAddressValue(address, getAddressValue(value)); - } - - /** From the Win32Debugger interface */ - public void writeOopHandle(long address, Win32OopHandle value) { - writeAddressValue(address, getAddressValue(value)); - } - - //-------------------------------------------------------------------------------- - // Thread context access - // - - public synchronized long[] getThreadIntegerRegisterSet(int threadHandleValue, - boolean mustDuplicateHandle) - throws DebuggerException { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - - try { - int handle = threadHandleValue; - if (mustDuplicateHandle) { - printlnToOutput("duphandle 0x" + Integer.toHexString(threadHandleValue)); - if (!in.parseBoolean()) { - throw new DebuggerException("Error duplicating thread handle 0x" + threadHandleValue); - } - handle = (int) in.parseAddress(); // Must close to avoid leaks - } - printlnToOutput("getcontext 0x" + Integer.toHexString(handle)); - if (!in.parseBoolean()) { - if (mustDuplicateHandle) { - printlnToOutput("closehandle 0x" + Integer.toHexString(handle)); - } - String failMessage = "GetThreadContext failed for thread handle 0x" + - Integer.toHexString(handle); - if (mustDuplicateHandle) { - failMessage = failMessage + ", duplicated from thread handle " + - Integer.toHexString(threadHandleValue); - } - throw new DebuggerException(failMessage); - } - // Otherwise, parse all registers. See - // src/os/win32/agent/README-commands.txt for the format. - // Note the array we have to return has to match that specified by - // X86ThreadContext.java. - int numRegs = 22; - long[] winRegs = new long[numRegs]; - for (int i = 0; i < numRegs; i++) { - winRegs[i] = in.parseAddress(); - } - if (mustDuplicateHandle) { - // Clean up after ourselves - printlnToOutput("closehandle 0x" + Integer.toHexString(handle)); - } - // Now create the real return value - long[] retval = new long[X86ThreadContext.NPRGREG]; - retval[X86ThreadContext.EAX] = winRegs[0]; - retval[X86ThreadContext.EBX] = winRegs[1]; - retval[X86ThreadContext.ECX] = winRegs[2]; - retval[X86ThreadContext.EDX] = winRegs[3]; - retval[X86ThreadContext.ESI] = winRegs[4]; - retval[X86ThreadContext.EDI] = winRegs[5]; - retval[X86ThreadContext.EBP] = winRegs[6]; - retval[X86ThreadContext.ESP] = winRegs[7]; - retval[X86ThreadContext.EIP] = winRegs[8]; - retval[X86ThreadContext.DS] = winRegs[9]; - retval[X86ThreadContext.ES] = winRegs[10]; - retval[X86ThreadContext.FS] = winRegs[11]; - retval[X86ThreadContext.GS] = winRegs[12]; - retval[X86ThreadContext.CS] = winRegs[13]; - retval[X86ThreadContext.SS] = winRegs[14]; - retval[X86ThreadContext.EFL] = winRegs[15]; - retval[X86ThreadContext.DR0] = winRegs[16]; - retval[X86ThreadContext.DR1] = winRegs[17]; - retval[X86ThreadContext.DR2] = winRegs[18]; - retval[X86ThreadContext.DR3] = winRegs[19]; - retval[X86ThreadContext.DR6] = winRegs[20]; - retval[X86ThreadContext.DR7] = winRegs[21]; - return retval; - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - public synchronized void setThreadIntegerRegisterSet(int threadHandleValue, - boolean mustDuplicateHandle, - long[] context) - throws DebuggerException { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - - try { - int handle = threadHandleValue; - if (mustDuplicateHandle) { - printlnToOutput("duphandle 0x" + Integer.toHexString(threadHandleValue)); - if (!in.parseBoolean()) { - throw new DebuggerException("Error duplicating thread handle 0x" + threadHandleValue); - } - handle = (int) in.parseAddress(); // Must close to avoid leaks - } - // Change order of registers to match that of debug server - long[] winRegs = new long[context.length]; - winRegs[0] = context[X86ThreadContext.EAX]; - winRegs[1] = context[X86ThreadContext.EBX]; - winRegs[2] = context[X86ThreadContext.ECX]; - winRegs[3] = context[X86ThreadContext.EDX]; - winRegs[4] = context[X86ThreadContext.ESI]; - winRegs[5] = context[X86ThreadContext.EDI]; - winRegs[6] = context[X86ThreadContext.EBP]; - winRegs[7] = context[X86ThreadContext.ESP]; - winRegs[8] = context[X86ThreadContext.EIP]; - winRegs[9] = context[X86ThreadContext.DS]; - winRegs[10] = context[X86ThreadContext.ES]; - winRegs[11] = context[X86ThreadContext.FS]; - winRegs[12] = context[X86ThreadContext.GS]; - winRegs[13] = context[X86ThreadContext.CS]; - winRegs[14] = context[X86ThreadContext.SS]; - winRegs[15] = context[X86ThreadContext.EFL]; - winRegs[16] = context[X86ThreadContext.DR0]; - winRegs[17] = context[X86ThreadContext.DR1]; - winRegs[18] = context[X86ThreadContext.DR2]; - winRegs[19] = context[X86ThreadContext.DR3]; - winRegs[20] = context[X86ThreadContext.DR6]; - winRegs[21] = context[X86ThreadContext.DR7]; - StringBuffer cmd = new StringBuffer(); - cmd.append("setcontext 0x"); - cmd.append(Integer.toHexString(threadHandleValue)); - for (int i = 0; i < context.length; i++) { - cmd.append(" 0x"); - cmd.append(Long.toHexString(winRegs[i])); - } - printlnToOutput(cmd.toString()); - boolean res = in.parseBoolean(); - if (mustDuplicateHandle) { - printlnToOutput("closehandle 0x" + Integer.toHexString(handle)); - } - if (!res) { - String failMessage = "SetThreadContext failed for thread handle 0x" + - Integer.toHexString(handle); - if (mustDuplicateHandle) { - failMessage = failMessage + ", duplicated from thread handle " + - Integer.toHexString(threadHandleValue); - } - throw new DebuggerException(failMessage); - } - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - /** Fetches the Win32 LDT_ENTRY for the given thread and selector. - This data structure allows the conversion of a segment-relative - address to a linear virtual address. For example, it allows the - expression of operations like "mov eax, fs:[18h]", which fetches - the thread information block, allowing access to the thread - ID. */ - public synchronized Win32LDTEntry getThreadSelectorEntry(int threadHandleValue, - boolean mustDuplicateHandle, - int selector) - throws DebuggerException { - try { - int handle = threadHandleValue; - if (mustDuplicateHandle) { - printlnToOutput("duphandle 0x" + Integer.toHexString(threadHandleValue)); - if (!in.parseBoolean()) { - throw new DebuggerException("Error duplicating thread handle 0x" + threadHandleValue); - } - handle = (int) in.parseAddress(); // Must close to avoid leaks - } - printlnToOutput("selectorentry 0x" + Integer.toHexString(handle) + " " + selector); - if (!in.parseBoolean()) { - if (mustDuplicateHandle) { - printlnToOutput("closehandle 0x" + Integer.toHexString(handle)); - } - throw new DebuggerException("GetThreadContext failed for thread handle 0x" + handle + - ", duplicated from thread handle " + threadHandleValue); - } - // Parse result. See - // src/os/win32/agent/README-commands.txt for the format. - short limitLow = (short) in.parseAddress(); - short baseLow = (short) in.parseAddress(); - byte baseMid = (byte) in.parseAddress(); - byte flags1 = (byte) in.parseAddress(); - byte flags2 = (byte) in.parseAddress(); - byte baseHi = (byte) in.parseAddress(); - return new Win32LDTEntry(limitLow, baseLow, baseMid, flags1, flags2, baseHi); - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - public synchronized List getThreadList() throws DebuggerException { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - - try { - printlnToOutput("threadlist"); - List ret = new ArrayList(); - int numThreads = in.parseInt(); - for (int i = 0; i < numThreads; i++) { - int handle = (int) in.parseAddress(); - ret.add(new Win32Thread(this, handle)); - } - return ret; - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - public synchronized List getLoadObjectList() throws DebuggerException { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - - try { - if (loadObjects == null) { - loadObjects = new ArrayList(); - nameToDllMap = new HashMap(); - // Get list of library names and base addresses - printlnToOutput("libinfo"); - int numInfo = in.parseInt(); - - for (int i = 0; i < numInfo; i++) { - // NOTE: because Win32 is case insensitive, we standardize on - // lowercase file names. - String fullPathName = parseString().toLowerCase(); - Address base = newAddress(in.parseAddress()); - - File file = new File(fullPathName); - long size = file.length(); - DLL dll = new DLL(this, fullPathName, size, base); - String name = file.getName(); - nameToDllMap.put(name, dll); - loadObjects.add(dll); - } - } - } catch (IOException e) { - throw new DebuggerException(e); - } - - return loadObjects; - } - - //---------------------------------------------------------------------- - // Process control access - // - - public synchronized void writeBytesToProcess(long startAddress, long numBytes, byte[] data) - throws UnmappedAddressException, DebuggerException { - try { - printToOutput("poke 0x" + Long.toHexString(startAddress) + - " |"); - writeIntToOutput((int) numBytes); - writeToOutput(data, 0, (int) numBytes); - printlnToOutput(""); - if (!in.parseBoolean()) { - throw new UnmappedAddressException(startAddress); - } - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - public synchronized void suspend() throws DebuggerException { - try { - if (suspended) { - throw new DebuggerException("Process already suspended"); - } - printlnToOutput("suspend"); - suspended = true; - enableCache(); - reresolveLoadObjects(); - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - public synchronized void resume() throws DebuggerException { - try { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - disableCache(); - printlnToOutput("resume"); - suspended = false; - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - public synchronized boolean isSuspended() throws DebuggerException { - return suspended; - } - - public synchronized void setBreakpoint(Address addr) throws DebuggerException { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - - long addrVal = getAddressValue(addr); - Long where = new Long(addrVal); - if (breakpoints.get(where) != null) { - throw new DebuggerException("Breakpoint already set at " + addr); - } - Byte what = new Byte(readBytes(addrVal, 1)[0]); - // Now put 0xCC (int 3) at the target address, fail if can not - writeBytesToProcess(addrVal, 1, new byte[] { (byte) 0xCC }); - // OK, the breakpoint is set. - breakpoints.put(where, what); - } - - public synchronized void clearBreakpoint(Address addr) throws DebuggerException { - if (!suspended) { - throw new DebuggerException("Process not suspended"); - } - - long addrVal = getAddressValue(addr); - Long where = new Long(addrVal); - Byte what = (Byte) breakpoints.get(where); - if (what == null) { - throw new DebuggerException("Breakpoint not set at " + addr); - } - // Put original data back at address - writeBytesToProcess(addrVal, 1, new byte[] { what.byteValue() }); - // OK, breakpoint is cleared - breakpoints.remove(where); - } - - public synchronized boolean isBreakpointSet(Address addr) throws DebuggerException { - return (breakpoints.get(new Long(getAddressValue(addr))) != null); - } - - // Following constants taken from winnt.h - private static final int EXCEPTION_DEBUG_EVENT = 1; - private static final int LOAD_DLL_DEBUG_EVENT = 6; - private static final int UNLOAD_DLL_DEBUG_EVENT = 7; - private static final int EXCEPTION_ACCESS_VIOLATION = 0xC0000005; - private static final int EXCEPTION_BREAKPOINT = 0x80000003; - private static final int EXCEPTION_SINGLE_STEP = 0x80000004; - - public synchronized DebugEvent debugEventPoll() throws DebuggerException { - if (curDebugEvent != null) { - return curDebugEvent; - } - - try { - printlnToOutput("pollevent"); - if (!in.parseBoolean()) { - return null; - } - // Otherwise, got a debug event. Need to figure out what kind it is. - int handle = (int) in.parseAddress(); - ThreadProxy thread = new Win32Thread(this, handle); - int code = in.parseInt(); - DebugEvent ev = null; - switch (code) { - case LOAD_DLL_DEBUG_EVENT: { - Address addr = newAddress(in.parseAddress()); - ev = BasicDebugEvent.newLoadObjectLoadEvent(thread, addr); - break; - } - - case UNLOAD_DLL_DEBUG_EVENT: { - Address addr = newAddress(in.parseAddress()); - ev = BasicDebugEvent.newLoadObjectUnloadEvent(thread, addr); - break; - } - - case EXCEPTION_DEBUG_EVENT: { - int exceptionCode = in.parseInt(); - Address pc = newAddress(in.parseAddress()); - switch (exceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: - boolean wasWrite = in.parseBoolean(); - Address addr = newAddress(in.parseAddress()); - ev = BasicDebugEvent.newAccessViolationEvent(thread, pc, wasWrite, addr); - break; - - case EXCEPTION_BREAKPOINT: - ev = BasicDebugEvent.newBreakpointEvent(thread, pc); - break; - - case EXCEPTION_SINGLE_STEP: - ev = BasicDebugEvent.newSingleStepEvent(thread, pc); - break; - - default: - ev = BasicDebugEvent.newUnknownEvent(thread, - "Exception 0x" + Integer.toHexString(exceptionCode) + - " at PC " + pc); - break; - } - break; - } - - default: - ev = BasicDebugEvent.newUnknownEvent(thread, - "Debug event " + code + " occurred"); - break; - } - if (Assert.ASSERTS_ENABLED) { - Assert.that(ev != null, "Must have created event"); - } - curDebugEvent = ev; - } catch (IOException e) { - throw new DebuggerException(e); - } - - return curDebugEvent; - } - - public synchronized void debugEventContinue() throws DebuggerException { - if (curDebugEvent == null) { - throw new DebuggerException("No debug event pending"); - } - - try { - /////////////////////////////////////////////////////////////////// - // // - // FIXME: this **must** be modified to handle breakpoint events - // properly. Must temporarily remove the breakpoint and enable - // single-stepping mode (hiding those single-step events from - // the user unless they have been requested; currently there is - // no way to request single-step events; and it isn't clear how - // to enable them or how the hardware and/or OS typically - // supports them, i.e., are they on a per-process or per-thread - // level?) until the process steps past the breakpoint, then put - // the breakpoint back. - // // - /////////////////////////////////////////////////////////////////// - - DebugEvent.Type t = curDebugEvent.getType(); - boolean shouldPassOn = true; - if (t == DebugEvent.Type.BREAKPOINT) { - // FIXME: correct algorithm appears to be as follows: - // - // 1. Check to see whether we know about this breakpoint. If - // not, it's requested by the user's program and we should - // ignore it (not pass it on to the program). - // - // 2. Replace the original opcode. - // - // 3. Set single-stepping mode in the debug registers. - // - // 4. Back up the PC. - // - // 5. In debugEventPoll(), watch for a single-step event on - // this thread. When we get it, put the breakpoint back. Only - // deliver that single-step event if the user has requested - // single-step events (FIXME: must figure out whether they are - // per-thread or per-process, and also expose a way to turn - // them on.) - - // To make breakpoints work for now, we will just back up the - // PC, which we have to do in order to not disrupt the program - // execution in case the user decides to disable the breakpoint. - - if (breakpoints.get(new Long(getAddressValue(curDebugEvent.getPC()))) != null) { - System.err.println("Backing up PC due to breakpoint"); - X86ThreadContext ctx = (X86ThreadContext) curDebugEvent.getThread().getContext(); - ctx.setRegister(X86ThreadContext.EIP, ctx.getRegister(X86ThreadContext.EIP) - 1); - curDebugEvent.getThread().setContext(ctx); - } else { - System.err.println("Skipping back up of PC since I didn't know about this breakpoint"); - System.err.println("Known breakpoints:"); - for (Iterator iter = breakpoints.keySet().iterator(); iter.hasNext(); ) { - System.err.println(" 0x" + Long.toHexString(((Long) iter.next()).longValue())); - } - } - shouldPassOn = false; - } else if (t == DebugEvent.Type.SINGLE_STEP) { - shouldPassOn = false; - } - // Other kinds of debug events are either ignored if passed on - // or probably should be passed on so the program exits - // FIXME: generate process exiting events (should be easy) - - int val = (shouldPassOn ? 1 : 0); - printlnToOutput("continueevent " + val); - if (!in.parseBoolean()) { - throw new DebuggerException("Unknown error while attempting to continue past debug event"); - } - curDebugEvent = null; - } catch (IOException e) { - throw new DebuggerException(e); - } - } - - //-------------------------------------------------------------------------------- - // Address access - // - - /** From the Debugger interface */ - public long getAddressValue(Address addr) { - if (addr == null) return 0; - return ((Win32Address) addr).getValue(); - } - - /** From the Win32Debugger interface */ - public Address newAddress(long value) { - if (value == 0) return null; - return new Win32Address(this, value); - } - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - private String parseString() throws IOException { - int charSize = in.parseInt(); - int numChars = in.parseInt(); - in.skipByte(); - String str; - if (charSize == 1) { - str = in.readByteString(numChars); - } else { - str = in.readCharString(numChars); - } - return str; - } - - /** Looks up an address in the remote process's address space. - Returns 0 if symbol not found or upon error. Package private to - allow Win32DebuggerRemoteIntfImpl access. NOTE that this returns - a long instead of an Address because we do not want to serialize - Addresses. */ - synchronized long lookupInProcess(String objectName, String symbol) { - // NOTE: this assumes that process is suspended (which is probably - // necessary assumption given that DLLs can be loaded/unloaded as - // process runs). Should update documentation. - if (nameToDllMap == null) { - getLoadObjectList(); - } - DLL dll = (DLL) nameToDllMap.get(objectName); - // The DLL can be null because we use this to search through known - // DLLs in HotSpotTypeDataBase (for example) - if (dll != null) { - Win32Address addr = (Win32Address) dll.lookupSymbol(symbol); - if (addr != null) { - return addr.getValue(); - } - } - return 0; - } - - /** This reads bytes from the remote process. */ - public synchronized ReadResult readBytesFromProcess(long address, long numBytes) - throws UnmappedAddressException, DebuggerException { - try { - String cmd = "peek " + utils.addressValueToString(address) + " " + numBytes; - printlnToOutput(cmd); - while (in.readByte() != 'B') { - } - byte res = in.readByte(); - if (res == 0) { - System.err.println("Failing command: " + cmd); - throw new DebuggerException("Read of remote process address space failed"); - } - // NOTE: must read ALL of the data regardless of whether we need - // to throw an UnmappedAddressException. Otherwise will corrupt - // the input stream each time we have a failure. Not good. Do - // not want to risk "flushing" the input stream in case a huge - // read has a hangup in the middle and we leave data on the - // stream. - byte[] buf = new byte[(int) numBytes]; - boolean bailOut = false; - long failureAddress = 0; - while (numBytes > 0) { - long len = in.readUnsignedInt(); - boolean isMapped = ((in.readByte() == 0) ? false : true); - if (!isMapped) { - if (!bailOut) { - bailOut = true; - failureAddress = address; - } - } else { - // This won't work if we have unmapped regions, but if we do - // then we're going to throw an exception anyway - - // NOTE: there is a factor of 20 speed difference between - // these two ways of doing this read. - in.readBytes(buf, 0, (int) len); - } - - // Do NOT do this: - // for (int i = 0; i < (int) len; i++) { - // buf[i] = in.readByte(); - // } - - numBytes -= len; - address += len; - } - if (Assert.ASSERTS_ENABLED) { - Assert.that(numBytes == 0, "Bug in debug server's implementation of peek"); - } - if (bailOut) { - return new ReadResult(failureAddress); - } - return new ReadResult(buf); - } - catch (IOException e) { - throw new DebuggerException(e); - } - } - - /** Convenience routines */ - private void printlnToOutput(String s) throws IOException { - out.println(s); - if (out.checkError()) { - throw new IOException("Error occurred while writing to debug server"); - } - } - - private void printToOutput(String s) throws IOException { - out.print(s); - if (out.checkError()) { - throw new IOException("Error occurred while writing to debug server"); - } - } - - private void writeIntToOutput(int val) throws IOException { - rawOut.writeInt(val); - rawOut.flush(); - } - - private void writeToOutput(byte[] buf, int off, int len) throws IOException { - rawOut.write(buf, off, len); - rawOut.flush(); - } - - /** Connects to the debug server, setting up out and in streams. */ - private void connectToDebugServer() throws IOException { - // Try for a short period of time to connect to debug server; time out - // with failure if didn't succeed - debuggerSocket = null; - long endTime = System.currentTimeMillis() + SHORT_TIMEOUT; - - while ((debuggerSocket == null) && (System.currentTimeMillis() < endTime)) { - try { - // FIXME: this does not work if we are on a DHCP machine which - // did not get an IP address this session. It appears to use - // an old cached address and the connection does not actually - // succeed. Must file a bug. - // debuggerSocket = new Socket(InetAddress.getLocalHost(), PORT); - debuggerSocket = new Socket(InetAddress.getByName("127.0.0.1"), PORT); - debuggerSocket.setTcpNoDelay(true); - } - catch (IOException e) { - // Swallow IO exceptions while attempting connection - debuggerSocket = null; - try { - // Don't swamp the CPU - Thread.sleep(750); - } - catch (InterruptedException ex) { - } - } - } - - if (debuggerSocket == null) { - // Failed to connect because of timeout - throw new DebuggerException("Timed out while attempting to connect to debug server (please start SwDbgSrv.exe)"); - } - - out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(debuggerSocket.getOutputStream(), "US-ASCII")), true); - rawOut = new DataOutputStream(new BufferedOutputStream(debuggerSocket.getOutputStream())); - in = new InputLexer(new BufferedInputStream(debuggerSocket.getInputStream())); - } - - private DLL findDLLByName(String fullPathName) { - for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) { - DLL dll = (DLL) iter.next(); - if (dll.getName().equals(fullPathName)) { - return dll; - } - } - return null; - } - - private void reresolveLoadObjects() throws DebuggerException { - try { - // It is too expensive to throw away the loadobject list every - // time the process is suspended, largely because of debug - // information re-parsing. When we suspend the target process we - // instead fetch the list of loaded libraries in the target and - // see whether any loadobject needs to be thrown away (because it - // was unloaded) or invalidated (because it was unloaded and - // reloaded at a different target address). Note that we don't - // properly handle the case of a loaded DLL being unloaded, - // recompiled, and reloaded. We could handle this by keeping a - // time stamp. - - if (loadObjects == null) { - return; - } - - // Need to create new list since have to figure out which ones - // were unloaded - List newLoadObjects = new ArrayList(); - - // Get list of library names and base addresses - printlnToOutput("libinfo"); - int numInfo = in.parseInt(); - - for (int i = 0; i < numInfo; i++) { - // NOTE: because Win32 is case insensitive, we standardize on - // lowercase file names. - String fullPathName = parseString().toLowerCase(); - Address base = newAddress(in.parseAddress()); - - // Look for full path name in DLL list - DLL dll = findDLLByName(fullPathName); - boolean mustLoad = true; - if (dll != null) { - loadObjects.remove(dll); - - // See whether base addresses match; otherwise, need to reload - if (AddressOps.equal(base, dll.getBase())) { - mustLoad = false; - } - } - - if (mustLoad) { - // Create new DLL - File file = new File(fullPathName); - long size = file.length(); - String name = file.getName(); - dll = new DLL(this, fullPathName, size, base); - nameToDllMap.put(name, dll); - } - newLoadObjects.add(dll); - } - - // All remaining entries in loadObjects have to be removed from - // the nameToDllMap - for (Iterator dllIter = loadObjects.iterator(); dllIter.hasNext(); ) { - DLL dll = (DLL) dllIter.next(); - for (Iterator iter = nameToDllMap.keySet().iterator(); iter.hasNext(); ) { - String name = (String) iter.next(); - if (nameToDllMap.get(name) == dll) { - nameToDllMap.remove(name); - break; - } - } - } - - loadObjects = newLoadObjects; - } catch (IOException e) { - loadObjects = null; - nameToDllMap = null; - throw new DebuggerException(e); - } - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntry.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntry.java deleted file mode 100644 index 03878e7260d..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntry.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import java.io.Serializable; - -/** Describes an LDT entry. (Some of the descriptions are taken - directly from Microsoft's documentation and are copyrighted by - Microsoft.) */ - -class Win32LDTEntry implements Serializable { - private short limitLow; - private short baseLow; - private byte baseMid; - private byte flags1; - private byte flags2; - private byte baseHi; - - private Win32LDTEntry() {} - - public Win32LDTEntry(short limitLow, - short baseLow, - byte baseMid, - byte flags1, - byte flags2, - byte baseHi) { - this.limitLow = limitLow; - this.baseLow = baseLow; - this.baseMid = baseMid; - this.flags1 = flags1; - this.flags2 = flags2; - this.baseHi = baseHi; - } - - /** Returns base address of segment */ - public long getBase() { return ( (baseLow & 0xFFFF) | - ((baseMid & 0xFF) << 16) | - ((baseHi & 0xFF) << 24)) & 0xFFFFFFFF; } - - public short getLimitLow() { return limitLow; } - public short getBaseLow() { return baseLow; } - public byte getBaseMid() { return baseMid; } - public byte getBaseHi() { return baseHi; } - - // FIXME: must verify mask and shift are correct - /** Describes type of segment. See TYPE_ portion of {@link - sun.jvm.hotspot.debugger.win32.Win32LDTEntryConstants}. */ - public int getType() { return (flags1 & 0x1F); } - - // FIXME: verify mask and shift are correct - /** Privilege level of descriptor: 0 = most privileged, 3 = least privileged */ - public int getPrivilegeLevel() { return ((flags1 & 0x60) >> 5); } - - // FIXME: verify mask is correct - /** Is segment present in physical memory? */ - public boolean isSegmentPhysical() { return ((flags1 & 0x70) != 0); } - - // FIXME: verify mask and shift are correct - /** High bits (16-19) of the address of the last byte of the segment */ - public int getLimitHi() { return (flags2 & 0x0F); } - - // FIXME: verify mask is correct - /**

Size of segment. If the segment is a data segment, this - member contains 1 if the segment is larger than 64 kilobytes (K) - or 0 if the segment is smaller than or equal to 64K.

- -

If the segment is a code segment, this member contains 1 if - the segment is a code segment and runs with the default (native - mode) instruction set. This member contains 0 if the code - segment is an 80286 code segment and runs with 16-bit offsets - and the 80286-compatible instruction set.

*/ - public boolean isDefaultBig() { return ((flags2 & 0x40) != 0); } - - // FIXME: verify mask is correct - /** Returns true if segment is page granular, false if byte - granular. */ - public boolean isPageGranular() { return ((flags2 & 0x80) != 0); } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntryConstants.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntryConstants.java deleted file mode 100644 index 46a0f7d3999..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32LDTEntryConstants.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -/** Enumerates flags in Win32LDTEntry */ - -interface Win32LDTEntryConstants { - // Types of segments - public static final int TYPE_READ_ONLY_DATA = 0; - public static final int TYPE_READ_WRITE_DATA = 1; - public static final int TYPE_UNUSED = 2; - public static final int TYPE_READ_WRITE_EXPAND_DOWN_DATA = 3; - public static final int TYPE_EXECUTE_ONLY_CODE = 4; - public static final int TYPE_EXECUTABLE_READABLE_CODE = 5; - public static final int TYPE_EXECUTE_ONLY_CONFORMING_CODE = 6; - public static final int TYPE_EXECUTABLE_READABLE_CONFORMING_CODE = 7; -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32OopHandle.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32OopHandle.java deleted file mode 100644 index 8491d9ab717..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32OopHandle.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import sun.jvm.hotspot.debugger.*; - -class Win32OopHandle extends Win32Address implements OopHandle { - Win32OopHandle(Win32Debugger debugger, long addr) { - super(debugger, addr); - } - - public boolean equals(Object arg) { - if (arg == null) { - return false; - } - - if (!(arg instanceof Win32OopHandle)) { - return false; - } - - return (addr == ((Win32Address) arg).addr); - } - - public Address addOffsetTo (long offset) throws UnsupportedOperationException { - throw new UnsupportedOperationException("addOffsetTo not applicable to OopHandles (interior object pointers not allowed)"); - } - - public Address andWithMask(long mask) throws UnsupportedOperationException { - throw new UnsupportedOperationException("andWithMask not applicable to OopHandles (i.e., anything but C addresses)"); - } - - public Address orWithMask(long mask) throws UnsupportedOperationException { - throw new UnsupportedOperationException("orWithMask not applicable to OopHandles (i.e., anything but C addresses)"); - } - - public Address xorWithMask(long mask) throws UnsupportedOperationException { - throw new UnsupportedOperationException("xorWithMask not applicable to OopHandles (i.e., anything but C addresses)"); - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Thread.java deleted file mode 100644 index 38eb3f52df3..00000000000 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Thread.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.debugger.win32; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.x86.*; - -class Win32Thread implements ThreadProxy { - private Win32Debugger debugger; - private int handle; - private boolean mustDuplicate; - private boolean gotID; - private int id; - - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ - Win32Thread(Win32Debugger debugger, Address addr) { - this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - this.handle = (int) addr.getCIntegerAt(0, 4, true); - // Thread handles in the target process must be duplicated before - // fetching their contexts - mustDuplicate = true; - gotID = false; - } - - /** The integer argument must be the value of a HANDLE received from - the "threadlist" operation. */ - Win32Thread(Win32Debugger debugger, long handle) { - this.debugger = debugger; - this.handle = (int) handle; - mustDuplicate = false; - gotID = false; - } - - public ThreadContext getContext() throws IllegalThreadStateException { - if (!debugger.isSuspended()) { - throw new IllegalThreadStateException("Target process must be suspended"); - } - long[] data = debugger.getThreadIntegerRegisterSet(handle, mustDuplicate); - Win32ThreadContext context = new Win32ThreadContext(debugger); - for (int i = 0; i < data.length; i++) { - context.setRegister(i, data[i]); - } - return context; - } - - public boolean canSetContext() throws DebuggerException { - return true; - } - - public void setContext(ThreadContext thrCtx) - throws IllegalThreadStateException, DebuggerException { - if (!debugger.isSuspended()) { - throw new IllegalThreadStateException("Target process must be suspended"); - } - X86ThreadContext context = (X86ThreadContext) thrCtx; - long[] data = new long[X86ThreadContext.NPRGREG]; - for (int i = 0; i < data.length; i++) { - data[i] = context.getRegister(i); - } - debugger.setThreadIntegerRegisterSet(handle, mustDuplicate, data); - } - - public boolean equals(Object obj) { - if ((obj == null) || !(obj instanceof Win32Thread)) { - return false; - } - - return (((Win32Thread) obj).getThreadID() == getThreadID()); - } - - public int hashCode() { - return getThreadID(); - } - - public String toString() { - return Integer.toString(getThreadID()); - } - - /** Retrieves the thread ID of this thread by examining the Thread - Information Block. */ - private int getThreadID() { - if (!gotID) { - try { - // Get thread context - X86ThreadContext context = (X86ThreadContext) getContext(); - // Get LDT entry for FS register - Win32LDTEntry ldt = - debugger.getThreadSelectorEntry(handle, - mustDuplicate, - (int) context.getRegister(X86ThreadContext.FS)); - // Get base address of segment = Thread Environment Block (TEB) - Address teb = debugger.newAddress(ldt.getBase()); - // Thread ID is at offset 0x24 - id = (int) teb.getCIntegerAt(0x24, 4, true); - gotID = true; - } catch (AddressException e) { - throw new DebuggerException(e); - } - } - - return id; - } -} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/SADebugServer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/SADebugServer.java index df1fb81a58b..df5cf24f437 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/SADebugServer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/SADebugServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,14 +51,6 @@ public final class SADebugServer { usage(); } - // By default, SA agent classes prefer dbx debugger to proc debugger - // and Windows process debugger to windbg debugger. SA expects - // special properties to be set to choose other debuggers. For SA/JDI, - // we choose proc, windbg debuggers instead of the defaults. - - System.setProperty("sun.jvm.hotspot.debugger.useProcDebugger", "true"); - System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); - // delegate to the actual SA debug server. sun.jvm.hotspot.DebugServer.main(args); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java index d6e4e61b9f9..4cbc1447ea9 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java @@ -263,14 +263,6 @@ public class VirtualMachineImpl extends MirrorImpl implements PathSearchingVirtu this.hashCode() + "]"); ((com.sun.tools.jdi.VirtualMachineManagerImpl)mgr).addVirtualMachine(this); - - // By default SA agent classes prefer dbx debugger to proc debugger - // and Windows process debugger to windbg debugger. SA expects - // special properties to be set to choose other debuggers. We will set - // those here before attaching to SA agent. - - System.setProperty("sun.jvm.hotspot.debugger.useProcDebugger", "true"); - System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); } // we reflectively use newly spec'ed class because our ALT_BOOTDIR diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayData.java new file mode 100644 index 00000000000..4a92692725e --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayData.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// ArrayData +// +// A ArrayData is a base class for accessing profiling data which does +// not have a statically known size. It consists of an array length +// and an array start. +abstract class ArrayData extends ProfileData { + + static final int arrayLenOffSet = 0; + static final int arrayStartOffSet = 1; + + int arrayUintAt(int index) { + int aindex = index + arrayStartOffSet; + return uintAt(aindex); + } + int arrayIntAt(int index) { + int aindex = index + arrayStartOffSet; + return intAt(aindex); + } + Oop arrayOopAt(int index) { + int aindex = index + arrayStartOffSet; + return oopAt(aindex); + } + + // Code generation support for subclasses. + static int arrayElementOffset(int index) { + return cellOffset(arrayStartOffSet + index); + } + + ArrayData(DataLayout layout) { + super(layout); + } + + static int staticCellCount() { + return -1; + } + + int arrayLen() { + return intAt(arrayLenOffSet); + } + + public int cellCount() { + return arrayLen() + 1; + } + + // Code generation support + static int arrayLenOffset() { + return cellOffset(arrayLenOffSet); + } + static int arrayStartOffset() { + return cellOffset(arrayStartOffSet); + } + +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BitData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BitData.java new file mode 100644 index 00000000000..80902b0b090 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BitData.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// BitData +// +// A BitData holds a flag or two in its header. +public class BitData extends ProfileData { + + // nullSeen: + // saw a null operand (cast/aastore/instanceof) + static final int nullSeenFlag = DataLayout.firstFlag + 0; + static final int bitCellCount = 0; + + public BitData(DataLayout layout) { + super(layout); + } + + static int staticCellCount() { + return bitCellCount; + } + + public int cellCount() { + return staticCellCount(); + } + + // Accessor + + // The nullSeen flag bit is specially known to the interpreter. + // Consulting it allows the compiler to avoid setting up nullCheck traps. + boolean nullSeen() { return flagAt(nullSeenFlag); } + + // Code generation support + // static int nullSeenByteConstant() { + // return flagNumberToByteConstant(nullSeenFlag); + // } + + static int bitDataSize() { + return cellOffset(bitCellCount); + } + + public void printDataOn(PrintStream st) { + printShared(st, "BitData"); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BranchData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BranchData.java new file mode 100644 index 00000000000..a80382fc15d --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/BranchData.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// BranchData +// +// A BranchData is used to access profiling data for a two-way branch. +// It consists of taken and notTaken counts as well as a data displacement +// for the taken case. +public class BranchData extends JumpData { + + static final int notTakenOffSet = jumpCellCount; + static final int branchCellCount = notTakenOffSet + 1; + + public BranchData(DataLayout layout) { + super(layout); + //assert(layout.tag() == DataLayout.branchDataTag, "wrong type"); + } + + static int staticCellCount() { + return branchCellCount; + } + + public int cellCount() { + return staticCellCount(); + } + + // Direct accessor + int notTaken() { + return uintAt(notTakenOffSet); + } + + // Code generation support + static int notTakenOffset() { + return cellOffset(notTakenOffSet); + } + static int branchDataSize() { + return cellOffset(branchCellCount); + } + + public void printDataOn(PrintStream st) { + printShared(st, "BranchData"); + st.println("taken(" + taken() + ") displacement(" + displacement() + ")"); + tab(st); + st.println("not taken(" + notTaken() + ")"); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CIntField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CIntField.java index 91d2807cb66..1cb99ad3fd1 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CIntField.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CIntField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,9 @@ public class CIntField extends Field { public long getValue(Oop obj) { return obj.getHandle().getCIntegerAt(getOffset(), size, isUnsigned); } + public long getValue(Address addr) { + return addr.getCIntegerAt(getOffset(), size, isUnsigned); + } public void setValue(Oop obj, long value) throws MutationException { // Fix this: set* missing in Address } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CounterData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CounterData.java new file mode 100644 index 00000000000..41b3dd217ef --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/CounterData.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// CounterData +// +// A CounterData corresponds to a simple counter. +public class CounterData extends BitData { + + static final int countOff = 0; + static final int counterCellCount = 1; + + public CounterData(DataLayout layout) { + super(layout); + } + + static int staticCellCount() { + return counterCellCount; + } + + public int cellCount() { + return staticCellCount(); + } + + // Direct accessor + int count() { + return uintAt(countOff); + } + + // Code generation support + static int countOffset() { + return cellOffset(countOff); + } + static int counterDataSize() { + return cellOffset(counterCellCount); + } + + public void printDataOn(PrintStream st) { + printShared(st, "CounterData"); + st.println("count(" + count() + ")"); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DataLayout.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DataLayout.java new file mode 100644 index 00000000000..1a63eae5f4f --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DataLayout.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +public class DataLayout { + public static final int noTag = 0; + public static final int bitDataTag = 1; + public static final int counterDataTag = 2; + public static final int jumpDataTag= 3; + public static final int receiverTypeDataTag = 4; + public static final int virtualCallDataTag = 5; + public static final int retDataTag = 6; + public static final int branchDataTag = 7; + public static final int multiBranchDataTag = 8; + + // The _struct._flags word is formatted as [trapState:4 | flags:4]. + // The trap state breaks down further as [recompile:1 | reason:3]. + // This further breakdown is defined in deoptimization.cpp. + // See Deoptimization.trapStateReason for an assert that + // trapBits is big enough to hold reasons < reasonRecordedLimit. + // + // The trapState is collected only if ProfileTraps is true. + public static final int trapBits = 1+3; // 3: enough to distinguish [0..reasonRecordedLimit]. + public static final int trapShift = 8 - trapBits; + public static final int trapMask = Bits.rightNBits(trapBits); + public static final int trapMaskInPlace = (trapMask << trapShift); + public static final int flagLimit = trapShift; + public static final int flagMask = Bits.rightNBits(flagLimit); + public static final int firstFlag = 0; + + private Address data; + + private int offset; + + private boolean handlized; + + public DataLayout(MethodData d, int o) { + data = d.getHandle(); + offset = o; + } + + public DataLayout(Address d, int o) { + data = d; + offset = o; + handlized = true; + } + + public int dp() { return offset; } + + private int getU11(int at) { + return data.getJByteAt(offset + at) & 0xff; + } + + private int getU22(int at) { + return data.getJShortAt(offset + at) & 0xffff; + } + + int cellAt(int index) { + // Cells are intptr_t sized but only contain ints as raw values + return (int)data.getCIntegerAt(offset + cellOffset(index), MethodData.cellSize, false); + } + + Oop oopAt(int index) { + OopHandle handle; + if (handlized) { + throw new InternalError("unsupported"); + } + handle = data.getOopHandleAt(offset + cellOffset(index)); + return VM.getVM().getObjectHeap().newOop(handle); + } + + public Address addressAt(int index) { + OopHandle handle; + if (handlized) { + return data.getAddressAt(offset + cellOffset(index)); + } else { + return data.getOopHandleAt(offset + cellOffset(index)); + } + } + + // Every data layout begins with a header. This header + // contains a tag, which is used to indicate the size/layout + // of the data, 4 bits of flags, which can be used in any way, + // 4 bits of trap history (none/one reason/many reasons), + // and a bci, which is used to tie this piece of data to a + // specific bci in the bytecodes. + // union { + // intptrT _bits; + // struct { + // u1 _tag; + // u1 _flags; + // u2 _bci; + // } _struct; + // } _header; + + // Some types of data layouts need a length field. + static boolean needsArrayLen(int tag) { + return (tag == multiBranchDataTag); + } + + public static final int counterIncrement = 1; + + // Size computation + static int headerSizeInBytes() { + return MethodData.cellSize; + } + static int headerSizeInCells() { + return 1; + } + + static int computeSizeInBytes(int cellCount) { + return headerSizeInBytes() + cellCount * MethodData.cellSize; + } + + // Initialization + // void initialize(int tag, int bci, int cellCount); + + // Accessors + public int tag() { + return getU11(0); + } + + // Return a few bits of trap state. Range is [0..trapMask]. + // The state tells if traps with zero, one, or many reasons have occurred. + // It also tells whether zero or many recompilations have occurred. + // The associated trap histogram in the MDO itself tells whether + // traps are common or not. If a BCI shows that a trap X has + // occurred, and the MDO shows N occurrences of X, we make the + // simplifying assumption that all N occurrences can be blamed + // on that BCI. + int trapState() { + return (flags() >> trapShift) & trapMask; + } + + int flags() { + return getU11(1); + } + + int bci() { + return getU22(2); + } + + boolean flagAt(int flagNumber) { + // assert(flagNumber < flagLimit, "oob"); + return (flags() & (0x1 << flagNumber)) != 0; + } + + // Low-level support for code generation. + static int headerOffset() { + return 0; + } + static int tagOffset() { + return 0; + } + static int flagsOffset() { + return 1; + } + static int bciOffset() { + return 2; + } + public static int cellOffset(int index) { + return MethodData.cellSize + index * MethodData.cellSize; + } + // // Return a value which, when or-ed as a byte into _flags, sets the flag. + // static int flagNumberToByteConstant(int flagNumber) { + // assert(0 <= flagNumber && flagNumber < flagLimit, "oob"); + // DataLayout temp; temp.setHeader(0); + // temp.setFlagAt(flagNumber); + // return temp._header._struct._flags; + // } + // // Return a value which, when or-ed as a word into _header, sets the flag. + // static intptrT flagMaskToHeaderMask(int byteConstant) { + // DataLayout temp; temp.setHeader(0); + // temp._header._struct._flags = byteConstant; + // return temp._header._bits; + // } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java index e130e9edf8e..6c3130ca582 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/FieldType.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/FieldType.java index 2f340b01aa0..b7a37662c7a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/FieldType.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/FieldType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,8 @@ public class FieldType { public boolean isObject() { return first == 'L'; } public boolean isArray() { return first == '['; } + public Symbol getSignature() { return signature; } + public static class ArrayInfo { private int dimension; private int elementBasicType; // See BasicType.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index bf49cc3f152..ebdd2633692 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -174,7 +174,7 @@ public class InstanceKlass extends Klass { private String value; } - private int getInitStateAsInt() { return (int) initState.getValue(this); } + public int getInitStateAsInt() { return (int) initState.getValue(this); } public ClassState getInitState() { int state = getInitStateAsInt(); if (state == CLASS_STATE_UNPARSABLE_BY_GC) { @@ -528,6 +528,16 @@ public class InstanceKlass extends Klass { return getSuper(); } + public static class StaticField { + public AccessFlags flags; + public Field field; + + StaticField(Field field, AccessFlags flags) { + this.field = field; + this.flags = flags; + } + } + public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { if (getSuper() != null) { ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/JumpData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/JumpData.java new file mode 100644 index 00000000000..b7921c5b6f4 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/JumpData.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// JumpData +// +// A JumpData is used to access profiling information for a direct +// branch. It is a counter, used for counting the number of branches, +// plus a data displacement, used for realigning the data pointer to +// the corresponding target bci. +public class JumpData extends ProfileData { + static final int takenOffSet = 0; + static final int displacementOffSet = 1; + static final int jumpCellCount = 2; + + public JumpData(DataLayout layout) { + super(layout); + //assert(layout.tag() == DataLayout.jumpDataTag || + // layout.tag() == DataLayout.branchDataTag, "wrong type"); + } + + static int staticCellCount() { + return jumpCellCount; + } + + public int cellCount() { + return staticCellCount(); + } + + // Direct accessor + int taken() { + return uintAt(takenOffSet); + } + + int displacement() { + return intAt(displacementOffSet); + } + + // Code generation support + static int takenOffset() { + return cellOffset(takenOffSet); + } + + static int displacementOffset() { + return cellOffset(displacementOffSet); + } + + public void printDataOn(PrintStream st) { + printShared(st, "JumpData"); + st.println("taken(" + taken() + ") displacement(" + displacement() + ")"); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java index fa4dbfa878f..d42115b90e3 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java @@ -49,6 +49,7 @@ public class Method extends Oop { Type type = db.lookupType("methodOopDesc"); constMethod = new OopField(type.getOopField("_constMethod"), 0); constants = new OopField(type.getOopField("_constants"), 0); + methodData = new OopField(type.getOopField("_method_data"), 0); methodSize = new CIntField(type.getCIntegerField("_method_size"), 0); maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0); maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0); @@ -58,9 +59,13 @@ public class Method extends Oop { vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0); if (!VM.getVM().isCore()) { invocationCounter = new CIntField(type.getCIntegerField("_invocation_counter"), 0); + backedgeCounter = new CIntField(type.getCIntegerField("_backedge_counter"), 0); } bytecodeOffset = type.getSize(); + interpreterThrowoutCountField = new CIntField(type.getCIntegerField("_interpreter_throwout_count"), 0); + interpreterInvocationCountField = new CIntField(type.getCIntegerField("_interpreter_invocation_count"), 0); + /* interpreterEntry = type.getAddressField("_interpreter_entry"); fromCompiledCodeEntryPoint = type.getAddressField("_from_compiled_code_entry_point"); @@ -79,6 +84,7 @@ public class Method extends Oop { // Fields private static OopField constMethod; private static OopField constants; + private static OopField methodData; private static CIntField methodSize; private static CIntField maxStack; private static CIntField maxLocals; @@ -86,10 +92,14 @@ public class Method extends Oop { private static CIntField accessFlags; private static CIntField vtableIndex; private static CIntField invocationCounter; + private static CIntField backedgeCounter; private static long bytecodeOffset; private static AddressField code; + private static CIntField interpreterThrowoutCountField; + private static CIntField interpreterInvocationCountField; + // constant method names - , // Initialized lazily to avoid initialization ordering dependencies between Method and SymbolTable private static Symbol objectInitializerName; @@ -116,6 +126,7 @@ public class Method extends Oop { // Accessors for declared fields public ConstMethod getConstMethod() { return (ConstMethod) constMethod.getValue(this); } public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } + public MethodData getMethodData() { return (MethodData) methodData.getValue(this); } public TypeArray getExceptionTable() { return getConstMethod().getExceptionTable(); } /** WARNING: this is in words, not useful in this system; use getObjectSize() instead */ public long getMethodSize() { return methodSize.getValue(this); } @@ -134,6 +145,12 @@ public class Method extends Oop { } return invocationCounter.getValue(this); } + public long getBackedgeCounter() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(!VM.getVM().isCore(), "must not be used in core build"); + } + return backedgeCounter.getValue(this); + } // get associated compiled native method, if available, else return null. public NMethod getNativeMethod() { @@ -333,4 +350,11 @@ public class Method extends Oop { buf.append(")"); return buf.toString().replace('/', '.'); } + public int interpreterThrowoutCount() { + return (int) interpreterThrowoutCountField.getValue(getHandle()); + } + + public int interpreterInvocationCount() { + return (int) interpreterInvocationCountField.getValue(getHandle()); + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java index 53dad607b96..83c36b6d84e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,92 @@ import sun.jvm.hotspot.utilities.*; // A MethodData provides interpreter profiling information public class MethodData extends Oop { + static int TypeProfileWidth = 2; + static int BciProfileWidth = 2; + static int CompileThreshold; + + static int Reason_many; // indicates presence of several reasons + static int Reason_none; // indicates absence of a relevant deopt. + static int Reason_LIMIT; + static int Reason_RECORDED_LIMIT; // some are not recorded per bc + + private static String[] trapReasonName; + + static String trapReasonName(int reason) { + if (reason == Reason_many) return "many"; + if (reason < Reason_LIMIT) + return trapReasonName[reason]; + return "reason" + reason; + } + + + static int trapStateReason(int trapState) { + // This assert provides the link between the width of DataLayout.trapBits + // and the encoding of "recorded" reasons. It ensures there are enough + // bits to store all needed reasons in the per-BCI MDO profile. + // assert(dsReasonMask >= reasonRecordedLimit, "enough bits"); + int recompileBit = (trapState & dsRecompileBit); + trapState -= recompileBit; + if (trapState == dsReasonMask) { + return Reason_many; + } else { + // assert((int)reasonNone == 0, "state=0 => Reason_none"); + return trapState; + } + } + + + static final int dsReasonMask = DataLayout.trapMask >> 1; + static final int dsRecompileBit = DataLayout.trapMask - dsReasonMask; + + static boolean trapStateIsRecompiled(int trapState) { + return (trapState & dsRecompileBit) != 0; + } + + static boolean reasonIsRecordedPerBytecode(int reason) { + return reason > Reason_none && reason < Reason_RECORDED_LIMIT; + } + static int trapStateAddReason(int trapState, int reason) { + // assert(reasonIsRecordedPerBytecode((DeoptReason)reason) || reason == reasonMany, "valid reason"); + int recompileBit = (trapState & dsRecompileBit); + trapState -= recompileBit; + if (trapState == dsReasonMask) { + return trapState + recompileBit; // already at state lattice bottom + } else if (trapState == reason) { + return trapState + recompileBit; // the condition is already true + } else if (trapState == 0) { + return reason + recompileBit; // no condition has yet been true + } else { + return dsReasonMask + recompileBit; // fall to state lattice bottom + } + } + static int trapStateSetRecompiled(int trapState, boolean z) { + if (z) return trapState | dsRecompileBit; + else return trapState & ~dsRecompileBit; + } + + static String formatTrapState(int trapState) { + int reason = trapStateReason(trapState); + boolean recompFlag = trapStateIsRecompiled(trapState); + // Re-encode the state from its decoded components. + int decodedState = 0; + if (reasonIsRecordedPerBytecode(reason) || reason == Reason_many) + decodedState = trapStateAddReason(decodedState, reason); + if (recompFlag) + decodedState = trapStateSetRecompiled(decodedState, recompFlag); + // If the state re-encodes properly, format it symbolically. + // Because this routine is used for debugging and diagnostics, + // be robust even if the state is a strange value. + if (decodedState != trapState) { + // Random buggy state that doesn't decode?? + return "#" + trapState; + } else { + return trapReasonName(reason) + (recompFlag ? " recompiled" : ""); + } + } + + + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -48,7 +134,58 @@ public class MethodData extends Oop { size = new CIntField(type.getCIntegerField("_size"), 0); method = new OopField(type.getOopField("_method"), 0); - // FIXME: add more fields and accessors + + VM.Flag[] flags = VM.getVM().getCommandLineFlags(); + for (int f = 0; f < flags.length; f++) { + VM.Flag flag = flags[f]; + if (flag.getName().equals("TypeProfileWidth")) { + TypeProfileWidth = (int)flag.getIntx(); + } else if (flag.getName().equals("BciProfileWidth")) { + BciProfileWidth = (int)flag.getIntx(); + } else if (flag.getName().equals("CompileThreshold")) { + CompileThreshold = (int)flag.getIntx(); + } + } + + cellSize = (int)VM.getVM().getAddressSize(); + + dataSize = new CIntField(type.getCIntegerField("_data_size"), 0); + data = type.getAddressField("_data[0]"); + + sizeofMethodDataOopDesc = (int)type.getSize();; + + Reason_many = db.lookupIntConstant("Deoptimization::Reason_many").intValue(); + Reason_none = db.lookupIntConstant("Deoptimization::Reason_none").intValue(); + Reason_LIMIT = db.lookupIntConstant("Deoptimization::Reason_LIMIT").intValue(); + Reason_RECORDED_LIMIT = db.lookupIntConstant("Deoptimization::Reason_RECORDED_LIMIT").intValue(); + + trapReasonName = new String[Reason_LIMIT]; + + // Find Deopt reasons + Iterator i = db.getIntConstants(); + String prefix = "Deoptimization::Reason_"; + while (i.hasNext()) { + String name = (String)i.next(); + if (name.startsWith(prefix)) { + // Strip prefix + if (!name.endsWith("Reason_many") && + !name.endsWith("Reason_LIMIT") && + !name.endsWith("Reason_RECORDED_LIMIT")) { + String trimmed = name.substring(prefix.length()); + int value = db.lookupIntConstant(name).intValue(); + if (trapReasonName[value] != null) { + throw new InternalError("duplicate reasons: " + trapReasonName[value] + " " + trimmed); + } + trapReasonName[value] = trimmed; + } + } + } + for (int index = 0; index < trapReasonName.length; index++) { + if (trapReasonName[index] == null) { + throw new InternalError("missing reason for " + index); + } + System.out.println(trapReasonName[index]); + } } MethodData(OopHandle handle, ObjectHeap heap) { @@ -60,6 +197,11 @@ public class MethodData extends Oop { private static long baseOffset; private static CIntField size; private static OopField method; + private static CIntField dataSize; + private static AddressField data; + + public static int sizeofMethodDataOopDesc; + public static int cellSize; public long getObjectSize() { return alignObjectSize(size.getValue(this)); @@ -81,4 +223,119 @@ public class MethodData extends Oop { visitor.doCInt(size, true); } } + + int dataSize() { + if (dataSize == null) { + return 0; + } else { + return (int)dataSize.getValue(this); + } + } + + boolean outOfBounds(int dataIndex) { + return dataIndex >= dataSize(); + } + + ProfileData dataAt(int dataIndex) { + if (outOfBounds(dataIndex)) { + return null; + } + DataLayout dataLayout = new DataLayout(this, dataIndex + (int)data.getOffset()); + + switch (dataLayout.tag()) { + case DataLayout.noTag: + default: + throw new InternalError(dataIndex + " " + dataSize() + " " + dataLayout.tag()); + case DataLayout.bitDataTag: + return new BitData(dataLayout); + case DataLayout.counterDataTag: + return new CounterData(dataLayout); + case DataLayout.jumpDataTag: + return new JumpData(dataLayout); + case DataLayout.receiverTypeDataTag: + return new ReceiverTypeData(dataLayout); + case DataLayout.virtualCallDataTag: + return new VirtualCallData(dataLayout); + case DataLayout.retDataTag: + return new RetData(dataLayout); + case DataLayout.branchDataTag: + return new BranchData(dataLayout); + case DataLayout.multiBranchDataTag: + return new MultiBranchData(dataLayout); + } + } + + int dpToDi(int dp) { + // this in an offset from the base of the MDO, so convert to offset into _data + return dp - (int)data.getOffset(); + } + + int firstDi() { return 0; } + public ProfileData firstData() { return dataAt(firstDi()); } + public ProfileData nextData(ProfileData current) { + int currentIndex = dpToDi(current.dp()); + int nextIndex = currentIndex + current.sizeInBytes(); + return dataAt(nextIndex); + } + boolean isValid(ProfileData current) { return current != null; } + + public void printDataOn(PrintStream st) { + ProfileData data = firstData(); + for ( ; isValid(data); data = nextData(data)) { + st.print(dpToDi(data.dp())); + st.print(" "); + // st->fillTo(6); + data.printDataOn(st); + } + } + + private byte[] fetchDataAt(Address base, long offset, long size) { + byte[] result = new byte[(int)size]; + for (int i = 0; i < size; i++) { + result[i] = base.getJByteAt(offset + i); + } + return result; + } + + public byte[] orig() { + // fetch the orig methodDataOopDesc data between header and dataSize + return fetchDataAt(this.getHandle(), 0, sizeofMethodDataOopDesc); + } + + public long[] data() { + // Read the data as an array of intptr_t elements + OopHandle base = getHandle(); + long offset = data.getOffset(); + int elements = dataSize() / cellSize; + long[] result = new long[elements]; + for (int i = 0; i < elements; i++) { + Address value = base.getAddressAt(offset + i * MethodData.cellSize); + if (value != null) { + result[i] = value.minus(null); + } + } + return result; + } + + // Get a measure of how much mileage the method has on it. + int mileageOf(Method method) { + long mileage = 0; + int iic = method.interpreterInvocationCount(); + if (mileage < iic) mileage = iic; + + long ic = method.getInvocationCounter(); + long bc = method.getBackedgeCounter(); + + long icval = ic >> 3; + if ((ic & 4) != 0) icval += CompileThreshold; + if (mileage < icval) mileage = icval; + long bcval = bc >> 3; + if ((bc & 4) != 0) bcval += CompileThreshold; + if (mileage < bcval) mileage = bcval; + return (int)mileage; + } + + public int currentMileage() { + return 20000; + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MultiBranchData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MultiBranchData.java new file mode 100644 index 00000000000..565d493b906 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MultiBranchData.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// MultiBranchData +// +// A MultiBranchData is used to access profiling information for +// a multi-way branch (*switch bytecodes). It consists of a series +// of (count, displacement) pairs, which count the number of times each +// case was taken and specify the data displacment for each branch target. +public class MultiBranchData extends ArrayData { + static final int defaultCountOffSet = 0; + static final int defaultDisaplacementOffSet = 1; + static final int caseArrayStart = 2; + static final int relativeCountOffSet = 0; + static final int relativeDisplacementOffSet = 1; + static final int perCaseCellCount = 2; + + public MultiBranchData(DataLayout layout) { + super(layout); + //assert(layout.tag() == DataLayout.multiBranchDataTag, "wrong type"); + } + + // static int computeCellCount(BytecodeStream stream); + + int numberOfCases() { + int alen = arrayLen() - 2; // get rid of default case here. + //assert(alen % perCaseCellCount == 0, "must be even"); + return (alen / perCaseCellCount); + } + + int defaultCount() { + return arrayUintAt(defaultCountOffSet); + } + int defaultDisplacement() { + return arrayIntAt(defaultDisaplacementOffSet); + } + + int countAt(int index) { + return arrayUintAt(caseArrayStart + + index * perCaseCellCount + + relativeCountOffSet); + } + int displacementAt(int index) { + return arrayIntAt(caseArrayStart + + index * perCaseCellCount + + relativeDisplacementOffSet); + } + + // Code generation support + static int defaultCountOffset() { + return arrayElementOffset(defaultCountOffSet); + } + static int defaultDisplacementOffset() { + return arrayElementOffset(defaultDisaplacementOffSet); + } + static int caseCountOffset(int index) { + return caseArrayOffset() + + (perCaseSize() * index) + + relativeCountOffset(); + } + static int caseArrayOffset() { + return arrayElementOffset(caseArrayStart); + } + static int perCaseSize() { + return (perCaseCellCount) * MethodData.cellSize; + } + static int relativeCountOffset() { + return (relativeCountOffSet) * MethodData.cellSize; + } + static int relativeDisplacementOffset() { + return (relativeDisplacementOffSet) * MethodData.cellSize; + } + + public void printDataOn(PrintStream st) { + printShared(st, "MultiBranchData"); + st.println("default_count(" + defaultCount() + ") displacement(" + defaultDisplacement() + ")"); + int cases = numberOfCases(); + for (int i = 0; i < cases; i++) { + tab(st); + st.println("count(" + countAt(i) + ") displacement(" + displacementAt(i) + ")"); + } + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java index e6887b12b1a..edd8a806442 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @@ -112,6 +112,32 @@ public class OopUtilities implements /* imports */ JVMTIThreadState { return buf.toString(); } + public static String escapeString(String s) { + StringBuilder sb = null; + for (int index = 0; index < s.length(); index++) { + char value = s.charAt(index); + if (value >= 32 && value < 127 || value == '\'' || value == '\\') { + if (sb != null) { + sb.append(value); + } + } else { + if (sb == null) { + sb = new StringBuilder(s.length() * 2); + sb.append(s, 0, index); + } + sb.append("\\u"); + if (value < 0x10) sb.append("000"); + else if (value < 0x100) sb.append("00"); + else if (value < 0x1000) sb.append("0"); + sb.append(Integer.toHexString(value)); + } + } + if (sb != null) { + return sb.toString(); + } + return s; + } + public static String stringOopToString(Oop stringOop) { if (offsetField == null) { InstanceKlass k = (InstanceKlass) stringOop.getKlass(); @@ -129,6 +155,10 @@ public class OopUtilities implements /* imports */ JVMTIThreadState { countField.getValue(stringOop)); } + public static String stringOopToEscapedString(Oop stringOop) { + return escapeString(stringOopToString(stringOop)); + } + private static void initThreadGroupFields() { if (threadGroupParentField == null) { SystemDictionary sysDict = VM.getVM().getSystemDictionary(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ProfileData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ProfileData.java new file mode 100644 index 00000000000..24b62e4104f --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ProfileData.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +public abstract class ProfileData { + // This is a pointer to a section of profiling data. + private DataLayout _data; + + public DataLayout data() { return _data; } + + // How many cells are in this? + public abstract int cellCount(); + + + // Return the size of this data. + public int sizeInBytes() { + return DataLayout.computeSizeInBytes(cellCount()); + } + + public int dp() { + return data().dp(); + } + + // Low-level accessors for underlying data + int intptrAt(int index) { + //assert(0 <= index && index < cellCount(), "oob"); + return data().cellAt(index); + } + int intAt(int index) { + return (int)intptrAt(index); + } + int uintAt(int index) { + return (int)intptrAt(index); + } + Oop oopAt(int index) { + return data().oopAt(index); + } + + public Address addressAt(int index) { + return data().addressAt(index); + } + + boolean flagAt(int flagNumber) { + return data().flagAt(flagNumber); + } + + // two convenient imports for use by subclasses: + public static int cellOffset(int index) { + return DataLayout.cellOffset(index); + } + + public ProfileData(DataLayout data) { + _data = data; + } + + // Constructor for invalid ProfileData. + ProfileData() { + _data = null; + } + + int bci() { + return data().bci(); + } + + int trapState() { + return data().trapState(); + } + public abstract void printDataOn(PrintStream st); + + void tab(PrintStream st) { + st.print("\t"); + } + + void printShared(PrintStream st, String name) { + st.print("bci: " + bci()); + // st.fillTo(tabWidthOne); + st.print(" " + name + " "); + tab(st); + int trap = trapState(); + if (trap != 0) { + st.print("trap(" + MethodData.formatTrapState(trap) + ") "); + } + int flags = data().flags(); + if (flags != 0) + st.print("flags(" + flags + ") "); + } + + public String toString() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + try { + printDataOn(ps); + } finally { + ps.close(); + } + return baos.toString(); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java new file mode 100644 index 00000000000..c6a7ac8ad8a --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// ReceiverTypeData +// +// A ReceiverTypeData is used to access profiling information about a +// dynamic type check. It consists of a counter which counts the total times +// that the check is reached, and a series of (Klass, count) pairs +// which are used to store a type profile for the receiver of the check. +public class ReceiverTypeData extends CounterData { + static final int receiver0Offset = counterCellCount; + static final int count0Offset = receiver0Offset + 1; + static final int receiverTypeRowCellCount = (count0Offset + 1) - receiver0Offset; + + public ReceiverTypeData(DataLayout layout) { + super(layout); + //assert(layout.tag() == DataLayout.receiverTypeDataTag || + // layout.tag() == DataLayout.virtualCallDataTag, "wrong type"); + } + + boolean isReceivertypedata() { return true; } + + static int staticCellCount() { + return counterCellCount + MethodData.TypeProfileWidth * receiverTypeRowCellCount; + } + + public int cellCount() { + return staticCellCount(); + } + + // Direct accessors + public static int rowLimit() { + return MethodData.TypeProfileWidth; + } + public static int receiverCellIndex(int row) { + return receiver0Offset + row * receiverTypeRowCellCount; + } + public static int receiverCountCellIndex(int row) { + return count0Offset + row * receiverTypeRowCellCount; + } + + // Get the receiver at row. The 'unchecked' version is needed by parallel old + // gc; it does not assert the receiver is a klass. During compaction of the + // perm gen, the klass may already have moved, so the isKlass() predicate + // would fail. The 'normal' version should be used whenever possible. + Klass receiverUnchecked(int row) { + //assert(row < rowLimit(), "oob"); + Oop recv = oopAt(receiverCellIndex(row)); + return (Klass)recv; + } + + public Klass receiver(int row) { + Klass recv = receiverUnchecked(row); + //assert(recv == NULL || ((oop)recv).isKlass(), "wrong type"); + return recv; + } + + public int receiverCount(int row) { + //assert(row < rowLimit(), "oob"); + return uintAt(receiverCountCellIndex(row)); + } + + // Code generation support + static int receiverOffset(int row) { + return cellOffset(receiverCellIndex(row)); + } + static int receiverCountOffset(int row) { + return cellOffset(receiverCountCellIndex(row)); + } + static int receiverTypeDataSize() { + return cellOffset(staticCellCount()); + } + + void printReceiverDataOn(PrintStream st) { + int row; + int entries = 0; + for (row = 0; row < rowLimit(); row++) { + if (receiver(row) != null) entries++; + } + st.println("count(" + count() + ") entries(" + entries + ")"); + for (row = 0; row < rowLimit(); row++) { + if (receiver(row) != null) { + tab(st); + receiver(row).printValueOn(st); + st.println("(" + receiverCount(row) + ")"); + } + } + } + public void printDataOn(PrintStream st) { + printShared(st, "ReceiverTypeData"); + printReceiverDataOn(st); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/RetData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/RetData.java new file mode 100644 index 00000000000..374623b852b --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/RetData.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// RetData +// +// A RetData is used to access profiling information for a ret bytecode. +// It is composed of a count of the number of times that the ret has +// been executed, followed by a series of triples of the form +// (bci, count, di) which count the number of times that some bci was the +// target of the ret and cache a corresponding data displacement. +public class RetData extends CounterData { + + static final int bci0Offset = counterCellCount; + static final int count0Offset = bci0Offset + 1; + static final int displacement0Offset = count0Offset + 1; + static final int retRowCellCount = (displacement0Offset + 1) - bci0Offset; + + public RetData(DataLayout layout) { + super(layout); + //assert(layout.tag() == DataLayout.retDataTag, "wrong type"); + } + + static final int noBci = -1; // value of bci when bci1/2 are not in use. + + static int staticCellCount() { + return counterCellCount + MethodData.BciProfileWidth * retRowCellCount; + } + + public int cellCount() { + return staticCellCount(); + } + + static int rowLimit() { + return MethodData.BciProfileWidth; + } + static int bciCellIndex(int row) { + return bci0Offset + row * retRowCellCount; + } + static int bciCountCellIndex(int row) { + return count0Offset + row * retRowCellCount; + } + static int bciDisplacementCellIndex(int row) { + return displacement0Offset + row * retRowCellCount; + } + + // Direct accessors + int bci(int row) { + return intAt(bciCellIndex(row)); + } + int bciCount(int row) { + return uintAt(bciCountCellIndex(row)); + } + int bciDisplacement(int row) { + return intAt(bciDisplacementCellIndex(row)); + } + + // Code generation support + static int bciOffset(int row) { + return cellOffset(bciCellIndex(row)); + } + static int bciCountOffset(int row) { + return cellOffset(bciCountCellIndex(row)); + } + static int bciDisplacementOffset(int row) { + return cellOffset(bciDisplacementCellIndex(row)); + } + + public void printDataOn(PrintStream st) { + printShared(st, "RetData"); + int row; + int entries = 0; + for (row = 0; row < rowLimit(); row++) { + if (bci(row) != noBci) entries++; + } + st.println("count(" + count() + ") entries(" + entries + ")"); + for (row = 0; row < rowLimit(); row++) { + if (bci(row) != noBci) { + tab(st); + st.println(" bci(" + bci(row) + ": count(" + bciCount(row) + ") displacement(" + bciDisplacement(row) + "))"); + } + } + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java new file mode 100644 index 00000000000..a1eed08c440 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// VirtualCallData +// +// A VirtualCallData is used to access profiling information about a +// call. For now, it has nothing more than a ReceiverTypeData. +public class VirtualCallData extends ReceiverTypeData { + public VirtualCallData(DataLayout layout) { + super(layout); + //assert(layout.tag() == DataLayout.virtualCallDataTag, "wrong type"); + } + + static int staticCellCount() { + // At this point we could add more profile state, e.g., for arguments. + // But for now it's the same size as the base record type. + return ReceiverTypeData.staticCellCount(); + } + + public int cellCount() { + return staticCellCount(); + } + + // Direct accessors + static int virtualCallDataSize() { + return cellOffset(staticCellCount()); + } + + public void printDataOn(PrintStream st) { + printShared(st, "VirtualCallData"); + printReceiverDataOn(st); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java new file mode 100644 index 00000000000..106713fce11 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Block.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class Block extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("Block"); + nodesField = type.getAddressField("_nodes"); + succsField = type.getAddressField("_succs"); + numSuccsField = new CIntField(type.getCIntegerField("_num_succs"), 0); + preOrderField = new CIntField(type.getCIntegerField("_pre_order"), 0); + domDepthField = new CIntField(type.getCIntegerField("_dom_depth"), 0); + idomField = type.getAddressField("_idom"); + freqField = type.getJFloatField("_freq"); + } + + private static AddressField nodesField; + private static AddressField succsField; + private static CIntField numSuccsField; + private static CIntField preOrderField; + private static CIntField domDepthField; + private static AddressField idomField; + private static JFloatField freqField; + + public Block(Address addr) { + super(addr); + } + + public int preOrder() { + return (int)preOrderField.getValue(getAddress()); + } + + public float freq() { + return (float)freqField.getValue(getAddress()); + } + + public Node_List nodes() { + return new Node_List(getAddress().addOffsetTo(nodesField.getOffset())); + } + + public void dump(PrintStream out) { + out.print("B" + preOrder()); + out.print(" Freq: " + freq()); + out.println(); + Node_List nl = nodes(); + int cnt = nl.size(); + for( int i=0; idumpOn(st); + // if (_cnt != countUnknown) st->print(" C=%f",_cnt); + JVMState jvms = jvms(); + if (jvms != null) jvms.dumpSpec(out); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java new file mode 100644 index 00000000000..7f730ef680f --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallRuntimeNode.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.utilities.CStringUtilities; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class CallRuntimeNode extends CallNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("CallRuntimeNode"); + nameField = type.getAddressField("_name"); + } + + static private AddressField nameField; + + public String name() { + return CStringUtilities.getString(nameField.getValue(getAddress())); + } + + public CallRuntimeNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream out) { + out.print(" #"); + out.print(name()); + super.dumpSpec(out); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java new file mode 100644 index 00000000000..47ff13f1280 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/CallStaticJavaNode.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.utilities.CStringUtilities; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class CallStaticJavaNode extends CallJavaNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("CallStaticJavaNode"); + nameField = type.getAddressField("_name"); + } + + static private AddressField nameField; + + public String name() { + return CStringUtilities.getString(nameField.getValue(getAddress())); + } + + public CallStaticJavaNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream out) { + out.print(" Static "); + String name = name(); + if (name != null) { + out.print(name); + // int trapReq = uncommonTrapRequest(); + // if (trapReq != 0) { + // char buf[100]; + // st->print("(%s)", + // Deoptimization::formatTrapRequest(buf, sizeof(buf), + // trapReq)); + // } + out.print(" "); + } + super.dumpSpec(out); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Compile.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Compile.java new file mode 100644 index 00000000000..31aacd5898a --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Compile.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.ci.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class Compile extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("Compile"); + rootField = type.getAddressField("_root"); + uniqueField = new CIntField(type.getCIntegerField("_unique"), 0); + entryBciField = new CIntField(type.getCIntegerField("_entry_bci"), 0); + topField = type.getAddressField("_top"); + cfgField = type.getAddressField("_cfg"); + regallocField = type.getAddressField("_regalloc"); + methodField = type.getAddressField("_method"); + iltField = type.getAddressField("_ilt"); + } + + private static AddressField rootField; + private static CIntField uniqueField; + private static CIntField entryBciField; + private static AddressField topField; + private static AddressField cfgField; + private static AddressField regallocField; + private static AddressField methodField; + private static AddressField iltField; + + public Compile(Address addr) { + super(addr); + } + + public Node root() { + return new RootNode(rootField.getValue(this.getAddress())); + } + + public int entryBci() { + return (int)entryBciField.getValue(getAddress()); + } + + public ciMethod method() { + return (ciMethod) ciObjectFactory.get(methodField.getValue(getAddress())); + } + + public PhaseCFG cfg() { + Address a = cfgField.getValue(this.getAddress()); + if (a != null) { + return new PhaseCFG(a); + } + return null; + } + + public InlineTree ilt() { + Address a = iltField.getValue(this.getAddress()); + if (a != null) { + return new InlineTree(a); + } + return null; + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/HaltNode.java similarity index 51% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThreadContext.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/HaltNode.java index 80e5cdaafec..ea8ef89a1c9 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/sparc/DbxSPARCThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/HaltNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,31 +16,35 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. * */ -package sun.jvm.hotspot.debugger.dbx.sparc; +package sun.jvm.hotspot.opto; +import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.sparc.*; -import sun.jvm.hotspot.debugger.dbx.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; -public class DbxSPARCThreadContext extends SPARCThreadContext { - private DbxDebugger debugger; - - public DbxSPARCThreadContext(DbxDebugger debugger) { - super(); - this.debugger = debugger; +public class HaltNode extends Node { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); } - public void setRegisterAsAddress(int index, Address value) { - setRegister(index, debugger.getAddressValue(value)); + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("HaltNode"); } - public Address getRegisterAsAddress(int index) { - return debugger.newAddress(getRegister(index)); + + public HaltNode(Address addr) { + super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/InlineTree.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/InlineTree.java new file mode 100644 index 00000000000..0a0f6fe0042 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/InlineTree.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.ci.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.utilities.GrowableArray; +import sun.jvm.hotspot.types.*; + +public class InlineTree extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("InlineTree"); + callerJvmsField = type.getAddressField("_caller_jvms"); + methodField = type.getAddressField("_method"); + callerTreeField = type.getAddressField("_caller_tree"); + subtreesField = type.getAddressField("_subtrees"); + } + + private static AddressField callerJvmsField; + private static AddressField methodField; + private static AddressField callerTreeField; + private static AddressField subtreesField; + + private static StaticBaseConstructor inlineTreeConstructor = new StaticBaseConstructor(InlineTree.class); + + public InlineTree(Address addr) { + super(addr); + } + + public InlineTree callerTree() { + Address addr = callerTreeField.getValue(getAddress()); + if (addr == null) return null; + + return new InlineTree(addr); + } + + public ciMethod method() { + return (ciMethod) ciObjectFactory.get(methodField.getValue(getAddress())); + } + + public JVMState callerJvms() { + return JVMState.create(callerJvmsField.getValue(getAddress())); + } + + public int callerBci() { + JVMState jvms = callerJvms(); + return (jvms != null) ? jvms.bci() : -1; + } + + public GrowableArray subtrees() { + Address addr = getAddress().addOffsetTo(subtreesField.getOffset()); + + return GrowableArray.create(addr, inlineTreeConstructor); + } + + public void printImpl(PrintStream st, int indent) { + for (int i = 0; i < indent; i++) st.print(" "); + st.printf(" @ %d ", callerBci()); + method().printShortName(st); + st.println(); + + GrowableArray subt = subtrees(); + for (int i = 0 ; i < subt.length(); i++) { + subt.at(i).printImpl(st, indent + 2); + } + } + public void print(PrintStream st) { + printImpl(st, 2); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/JVMState.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/JVMState.java new file mode 100644 index 00000000000..40147a19c2b --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/JVMState.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.ci.*; +import sun.jvm.hotspot.types.*; + +public class JVMState extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("JVMState"); + mapField = type.getAddressField("_map"); + methodField = type.getAddressField("_method"); + bciField = new CIntField(type.getCIntegerField("_bci"), 0); + spField = new CIntField(type.getCIntegerField("_sp"), 0); + endoffField = new CIntField(type.getCIntegerField("_endoff"), 0); + try { + scloffField = new CIntField(type.getCIntegerField("_scloff"), 0); + } catch (Exception e) { + } + monoffField = new CIntField(type.getCIntegerField("_monoff"), 0); + stkoffField = new CIntField(type.getCIntegerField("_stkoff"), 0); + locoffField = new CIntField(type.getCIntegerField("_locoff"), 0); + depthField = new CIntField(type.getCIntegerField("_depth"), 0); + callerField = type.getAddressField("_caller"); + } + + private static AddressField mapField; + private static AddressField methodField; + private static CIntField bciField; + private static CIntField spField; + private static CIntField endoffField; + private static CIntField scloffField; + private static CIntField monoffField; + private static CIntField stkoffField; + private static CIntField locoffField; + private static CIntField depthField; + private static AddressField callerField; + + public static JVMState create(Address addr) { + if (addr == null) return null; + return new JVMState(addr); + } + + public JVMState(Address addr) { + super(addr); + } + + public ciMethod method() { + return (ciMethod) ciObjectFactory.get(methodField.getValue(getAddress())); + } + + public int bci() { + return (int)bciField.getValue(getAddress()); + } + + public JVMState caller() { + return create(callerField.getValue(getAddress())); + } + + public void dumpSpec(PrintStream out) { + ciMethod m = method(); + if (m != null) { + Method meth = m.method(); + out.print(" " + meth.getMethodHolder().getName().asString().replace('/', '.') + "::" + + meth.getName().asString() + " @ bci:" + bci()); + } else { + out.print(" runtime stub"); + } + if (caller() != null) caller().dumpSpec(out); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/LoopNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/LoopNode.java new file mode 100644 index 00000000000..c62ad089e1d --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/LoopNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class LoopNode extends RegionNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("LoopNode"); + } + + + public LoopNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java new file mode 100644 index 00000000000..5d227193ffb --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallJavaNode.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.ci.ciMethod; +import sun.jvm.hotspot.ci.ciObjectFactory; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MachCallJavaNode extends MachCallNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachCallJavaNode"); + methodField = type.getAddressField("_method"); + bciField = new CIntField(type.getCIntegerField("_bci"), 0); + } + + private static AddressField methodField; + private static CIntField bciField; + + public ciMethod method() { + return (ciMethod) ciObjectFactory.get(methodField.getValue(getAddress())); + } + + public MachCallJavaNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream st) { + ciMethod m = method(); + if (m != null) { + m.printShortName(st); + st.print(" "); + } + super.dumpSpec(st); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallNode.java new file mode 100644 index 00000000000..7f3691e57bb --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallNode.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MachCallNode extends MachSafePointNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachCallNode"); + } + + public MachCallNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream st) { + st.print("# "); + // tf()->dump_on(st); + // if (_cnt != COUNT_UNKNOWN) st->print(" C=%f",_cnt); + if (jvms() != null) jvms().dumpSpec(st); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java new file mode 100644 index 00000000000..9a6655f3b03 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallRuntimeNode.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.CStringUtilities; + +public class MachCallRuntimeNode extends MachCallJavaNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachCallRuntimeNode"); + nameField = type.getAddressField("_name"); + } + + private static AddressField nameField; + + public String name() { + return CStringUtilities.getString(nameField.getValue(getAddress())); + } + + public MachCallRuntimeNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream out) { + out.printf("%s ", name()); + super.dumpSpec(out); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java new file mode 100644 index 00000000000..4668acb827e --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachCallStaticJavaNode.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.CStringUtilities; + +public class MachCallStaticJavaNode extends MachCallJavaNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachCallStaticJavaNode"); + nameField = type.getAddressField("_name"); + } + + private static AddressField nameField; + + public String name() { + return CStringUtilities.getString(nameField.getValue(getAddress())); + } + + public MachCallStaticJavaNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream st) { + st.print("Static "); + String n = name(); + if (n != null) { + st.printf("wrapper for: %s", n); + // dump_trap_args(st); + st.print(" "); + } + super.dumpSpec(st); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachIfNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachIfNode.java new file mode 100644 index 00000000000..dc47e131297 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachIfNode.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MachIfNode extends MachNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachIfNode"); + probField = type.getJFloatField("_prob"); + fcntField = type.getJFloatField("_fcnt"); + } + + private static JFloatField probField; + private static JFloatField fcntField; + + float prob() { + return probField.getValue(getAddress()); + } + + float cnt() { + return fcntField.getValue(getAddress()); + } + + public MachIfNode(Address addr) { + super(addr); + } + + public void dumpSpec(PrintStream out) { + out.print("P=" + prob() + ", C=" + cnt()); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachNode.java new file mode 100644 index 00000000000..c59ef7a758f --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachNode.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MachNode extends Node { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachNode"); + } + + public MachNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java new file mode 100644 index 00000000000..a9bd39abff4 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachReturnNode.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MachReturnNode extends MachNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachReturnNode"); + } + + public MachReturnNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java new file mode 100644 index 00000000000..630f2690eff --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MachSafePointNode.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MachSafePointNode extends MachReturnNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MachSafePointNode"); + jvmsField = type.getAddressField("_jvms"); + jvmadjField = new CIntField(type.getCIntegerField("_jvmadj"), 0); + } + + private static AddressField jvmsField; + private static CIntField jvmadjField; + + public MachSafePointNode(Address addr) { + super(addr); + } + + public JVMState jvms() { + return JVMState.create(jvmsField.getValue(getAddress())); + } + + public void dumpSpec(PrintStream out) { + try { + JVMState jvms = jvms(); + if (jvms != null) out.print(" !"); + if (jvms == null) out.print("empty jvms"); + while (jvms != null) { + Method m = jvms.method().method(); + int bci = jvms.bci(); + out.print(" " + m.getMethodHolder().getName().asString().replace('/', '.') + "::" + m.getName().asString() + " @ bci:" + bci); + jvms = jvms.caller(); + } + } catch (Exception e) { + out.print(e); + } + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MultiNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MultiNode.java new file mode 100644 index 00000000000..69d666ed6ce --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/MultiNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class MultiNode extends Node { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("MultiNode"); + } + + + public MultiNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node.java new file mode 100644 index 00000000000..e393383c4c7 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node.java @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class Node extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("Node"); + outmaxField = new CIntField(type.getCIntegerField("_outmax"), 0); + outcntField = new CIntField(type.getCIntegerField("_outcnt"), 0); + maxField = new CIntField(type.getCIntegerField("_max"), 0); + cntField = new CIntField(type.getCIntegerField("_cnt"), 0); + idxField = new CIntField(type.getCIntegerField("_idx"), 0); + outField = type.getAddressField("_out"); + inField = type.getAddressField("_in"); + + nodeType = db.lookupType("Node"); + + virtualConstructor = new VirtualBaseConstructor(db, nodeType, "sun.jvm.hotspot.opto", Node.class); + } + + private static CIntField outmaxField; + private static CIntField outcntField; + private static CIntField maxField; + private static CIntField cntField; + private static CIntField idxField; + private static AddressField outField; + private static AddressField inField; + + private static VirtualBaseConstructor virtualConstructor; + + private static Type nodeType; + + static HashMap nodes = new HashMap(); + + static HashMap constructors = new HashMap(); + + static abstract class Instantiator { + abstract Node create(Address addr); + } + + static public Node create(Address addr) { + if (addr == null) return null; + Node result = (Node)nodes.get(addr); + if (result == null) { + result = (Node)virtualConstructor.instantiateWrapperFor(addr); + nodes.put(addr, result); + } + return result; + } + + public Node(Address addr) { + super(addr); + } + + public int outcnt() { + return (int)outcntField.getValue(this.getAddress()); + } + + public int req() { + return (int)cntField.getValue(this.getAddress()); + } + + public int len() { + return (int)maxField.getValue(this.getAddress()); + } + + public int idx() { + return (int)idxField.getValue(this.getAddress()); + } + + private Node[] _out; + private Node[] _in; + + public Node rawOut(int i) { + if (_out == null) { + int addressSize = (int)VM.getVM().getAddressSize(); + _out = new Node[outcnt()]; + Address ptr = outField.getValue(this.getAddress()); + for (int j = 0; j < outcnt(); j++) { + _out[j] = Node.create(ptr.getAddressAt(j * addressSize)); + } + } + return _out[i]; + } + + public Node in(int i) { + if (_in == null) { + int addressSize = (int)VM.getVM().getAddressSize(); + _in = new Node[len()]; + Address ptr = inField.getValue(this.getAddress()); + for (int j = 0; j < len(); j++) { + _in[j] = Node.create(ptr.getAddressAt(j * addressSize)); + } + } + return _in[i]; + } + + public ArrayList collect(int d, boolean onlyCtrl) { + int depth = Math.abs(d); + ArrayList nstack = new ArrayList(); + BitSet set = new BitSet(); + + nstack.add(this); + set.set(idx()); + int begin = 0; + int end = 0; + for (int i = 0; i < depth; i++) { + end = nstack.size(); + for(int j = begin; j < end; j++) { + Node tp = (Node)nstack.get(j); + int limit = d > 0 ? tp.len() : tp.outcnt(); + for(int k = 0; k < limit; k++) { + Node n = d > 0 ? tp.in(k) : tp.rawOut(k); + + // if (NotANode(n)) continue; + if (n == null) continue; + // do not recurse through top or the root (would reach unrelated stuff) + // if (n.isRoot() || n.isTop()) continue; + // if (onlyCtrl && !n.isCfg()) continue; + + if (!set.get(n.idx())) { + nstack.add(n); + set.set(n.idx()); + } + } + } + begin = end; + } + return nstack; + } + + protected void dumpNodes(Node s, int d, boolean onlyCtrl, PrintStream out) { + if (s == null) return; + + ArrayList nstack = s.collect(d, onlyCtrl); + int end = nstack.size(); + if (d > 0) { + for(int j = end-1; j >= 0; j--) { + ((Node)nstack.get(j)).dump(out); + } + } else { + for(int j = 0; j < end; j++) { + ((Node)nstack.get(j)).dump(out); + } + } + } + + public void dump(int depth, PrintStream out) { + dumpNodes(this, depth, false, out); + } + + public String Name() { + Type t = VM.getVM().getTypeDataBase().findDynamicTypeForAddress(getAddress(), nodeType); + String name = null; + if (t != null) { + name = t.toString(); + } else { + Class c = getClass(); + if (c == Node.class) { + // couldn't identify class type + return "UnknownNode<" + getAddress().getAddressAt(0) + ">"; + } + name = getClass().getName(); + if (name.startsWith("sun.jvm.hotspot.opto.")) { + name = name.substring("sun.jvm.hotspot.opto.".length()); + } + } + if (name.endsWith("Node")) { + return name.substring(0, name.length() - 4); + } + return name; + } + + public void dump(PrintStream out) { + out.print(" "); + out.print(idx()); + out.print("\t"); + out.print(Name()); + out.print("\t=== "); + int i = 0; + for (i = 0; i < req(); i++) { + Node n = in(i); + if (n != null) { + out.print(' '); + out.print(in(i).idx()); + } else { + out.print("_"); + } + out.print(" "); + } + if (len() != req()) { + int prec = 0; + for (; i < len(); i++) { + Node n = in(i); + if (n != null) { + if (prec++ == 0) { + out.print("| "); + } + out.print(in(i).idx()); + } + out.print(" "); + } + } + dumpOut(out); + dumpSpec(out); + out.println(); + } + + void dumpOut(PrintStream out) { + // Delimit the output edges + out.print(" [["); + // Dump the output edges + for (int i = 0; i < outcnt(); i++) { // For all outputs + Node u = rawOut(i); + if (u == null) { + out.print("_ "); + // } else if (NotANode(u)) { + // out.print("NotANode "); + } else { + // out.print("%c%d ", Compile::current()->nodeArena()->contains(u) ? ' ' : 'o', u->_idx); + out.print(' '); + out.print(u.idx()); + out.print(' '); + } + } + out.print("]] "); + } + + public void dumpSpec(PrintStream out) { + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_Array.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_Array.java new file mode 100644 index 00000000000..c4a2734202b --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_Array.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class Node_Array extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("Node_Array"); + maxField = new CIntField(type.getCIntegerField("_max"), 0); + nodesField = type.getAddressField("_nodes"); + aField = type.getAddressField("_a"); + } + + private static CIntField maxField; + private static AddressField nodesField; + private static AddressField aField; + + public Node_Array(Address addr) { + super(addr); + } + + public int Size() { + return (int) maxField.getValue(getAddress()); + } + + public Node at(int i) { + return Node.create(nodesField.getValue(getAddress()).getAddressAt(i * (int)VM.getVM().getAddressSize())); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_List.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_List.java new file mode 100644 index 00000000000..0828bf56650 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Node_List.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class Node_List extends Node_Array { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("Node_List"); + cntField = new CIntField(type.getCIntegerField("_cnt"), 0); + } + + private static CIntField cntField; + + public Node_List(Address addr) { + super(addr); + } + + public int size() { + return (int) cntField.getValue(getAddress()); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86ThreadFactory.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Phase.java similarity index 51% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86ThreadFactory.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Phase.java index 74c91c83434..5c010b0a7ab 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86ThreadFactory.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/Phase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,29 +16,35 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. * */ -package sun.jvm.hotspot.debugger.dbx.x86; +package sun.jvm.hotspot.opto; +import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.dbx.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; -public class DbxX86ThreadFactory implements DbxThreadFactory { - private DbxDebugger debugger; - - public DbxX86ThreadFactory(DbxDebugger debugger) { - this.debugger = debugger; +public class Phase extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); } - public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { - return new DbxX86Thread(debugger, threadIdentifierAddr); + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("Phase"); } - public ThreadProxy createThreadWrapper(long id) { - return new DbxX86Thread(debugger, id); + + public Phase(Address addr) { + super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java new file mode 100644 index 00000000000..986214f9e0f --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseCFG.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import java.io.PrintStream; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class PhaseCFG extends Phase { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("PhaseCFG"); + numBlocksField = new CIntField(type.getCIntegerField("_num_blocks"), 0); + blocksField = type.getAddressField("_blocks"); + bbsField = type.getAddressField("_bbs"); + brootField = type.getAddressField("_broot"); + } + + private static CIntField numBlocksField; + private static AddressField blocksField; + private static AddressField bbsField; + private static AddressField brootField; + + public PhaseCFG(Address addr) { + super(addr); + } + + public void dump(PrintStream out) { + int addressSize = (int)VM.getVM().getAddressSize(); + int numBlocks = (int)numBlocksField.getValue(getAddress()); + Block_List blocks = new Block_List(getAddress().addOffsetTo(blocksField.getOffset())); + int offset = 0; + for (int i = 0; i < numBlocks; i++) { + blocks.at(i).dump(out); + } + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java new file mode 100644 index 00000000000..c51d952a97c --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhaseRegAlloc.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class PhaseRegAlloc extends Phase { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("PhaseRegAlloc"); + nodeRegsField = type.getAddressField("_node_regs"); + nodeRegsMaxIndexField = new CIntField(type.getCIntegerField("_node_regs_max_index"), 0); + framesizeField = new CIntField(type.getCIntegerField("_framesize"), 0); + maxRegField = new CIntField(type.getCIntegerField("_max_reg"), 0); + } + + private static AddressField nodeRegsField; + private static CIntField nodeRegsMaxIndexField; + private static CIntField framesizeField; + private static CIntField maxRegField; + + public PhaseRegAlloc(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhiNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhiNode.java new file mode 100644 index 00000000000..6565e0372f2 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/PhiNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class PhiNode extends TypeNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("PhiNode"); + } + + + public PhiNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86ThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/ProjNode.java similarity index 51% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86ThreadContext.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/ProjNode.java index 565c020e87c..6f3e9d4cc16 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/x86/DbxX86ThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/ProjNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,31 +16,35 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. * */ -package sun.jvm.hotspot.debugger.dbx.x86; +package sun.jvm.hotspot.opto; +import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.x86.*; -import sun.jvm.hotspot.debugger.dbx.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; -public class DbxX86ThreadContext extends X86ThreadContext { - private DbxDebugger debugger; - - public DbxX86ThreadContext(DbxDebugger debugger) { - super(); - this.debugger = debugger; +public class ProjNode extends Node { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); } - public void setRegisterAsAddress(int index, Address value) { - setRegister(index, debugger.getAddressValue(value)); + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ProjNode"); } - public Address getRegisterAsAddress(int index) { - return debugger.newAddress(getRegister(index)); + + public ProjNode(Address addr) { + super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RegionNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RegionNode.java new file mode 100644 index 00000000000..5aa7763fd73 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RegionNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class RegionNode extends Node { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("RegionNode"); + } + + + public RegionNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RootNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RootNode.java new file mode 100644 index 00000000000..9a050da6360 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/RootNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class RootNode extends LoopNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("RootNode"); + } + + + public RootNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/SafePointNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/SafePointNode.java new file mode 100644 index 00000000000..51585927bb1 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/SafePointNode.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.io.PrintStream; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class SafePointNode extends MultiNode { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("SafePointNode"); + jvmsField = type.getAddressField("_jvms"); + } + + private static AddressField jvmsField; + + public SafePointNode(Address addr) { + super(addr); + } + + public JVMState jvms() { + return JVMState.create(jvmsField.getValue(getAddress())); + } + + public void dumpSpec(PrintStream out) { + JVMState jvms = jvms(); + if (jvms != null) out.print(" !"); + while (jvms != null) { + Method m = jvms.method().method(); + int bci = jvms.bci(); + out.print(" " + m.getMethodHolder().getName().asString().replace('/', '.') + "::" + m.getName().asString() + " @ bci:" + bci); + jvms = jvms.caller(); + } + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/TypeNode.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/TypeNode.java new file mode 100644 index 00000000000..33e423a2337 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/opto/TypeNode.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.opto; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class TypeNode extends Node { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("TypeNode"); + } + + + public TypeNode(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/prims/JvmtiExport.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/prims/JvmtiExport.java new file mode 100644 index 00000000000..83602a3bff4 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/prims/JvmtiExport.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.prims; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class JvmtiExport { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("JvmtiExport"); + // XXX + // canAccessLocalVariables = type.getCIntegerField("_can_access_local_variables"); + // canHotswapOrPostBreakpoint = type.getCIntegerField("_can_hotswap_or_post_breakpoint"); + // canPostOnExceptions = type.getCIntegerField("_can_post_on_exceptions"); + } + + private static CIntegerField canAccessLocalVariables; + private static CIntegerField canHotswapOrPostBreakpoint; + private static CIntegerField canPostOnExceptions; + + public static boolean canAccessLocalVariables() { + // return canAccessLocalVariables.getValue() != 0; + return false; + } + public static boolean canHotswapOrPostBreakpoint() { + // return canHotswapOrPostBreakpoint.getValue() != 0; + return false; + } + public static boolean canPostOnExceptions() { + // return canPostOnExceptions.getValue() != 0; + return false; + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java index 7c8defce388..7a28c660938 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,40 @@ package sun.jvm.hotspot.runtime; import java.io.*; +import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.ci.*; public class CompilerThread extends JavaThread { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static AddressField _env_field; + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("CompilerThread"); + + _env_field = type.getAddressField("_env"); + } + + private ciEnv _env; + + public synchronized ciEnv env() { + if (_env == null) { + Address v = _env_field.getValue(this.getAddress()); + if (v != null) { + _env = new ciEnv(v); + } + } + return _env; + } + public CompilerThread(Address addr) { super(addr); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InstanceConstructor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InstanceConstructor.java new file mode 100644 index 00000000000..725dfda11c4 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InstanceConstructor.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.CDebugger; +import sun.jvm.hotspot.debugger.cdbg.ClosestSymbol; +import sun.jvm.hotspot.debugger.cdbg.LoadObject; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.HotSpotTypeDataBase; + +/** Given a pointer to some memory return an appropriate wrapper. + Various subclasses provide different mechanisms for identifying the + appropriate wrapper. */ + +abstract public class InstanceConstructor { + /** Instantiate the most-precisely typed wrapper object available + for the type of the given Address. If no type in the mapping + matched the type of the Address, throws a WrongTypeException. + Returns null for a null address (similar behavior to + VMObjectFactory). */ + abstract public T instantiateWrapperFor(Address addr) throws WrongTypeException; + + protected WrongTypeException newWrongTypeException(Address addr) { + String message = "No suitable match for type of address " + addr; + CDebugger cdbg = VM.getVM().getDebugger().getCDebugger(); + if (cdbg != null) { + // Most common case: V-table pointer is the first field + Address vtblPtr = addr.getAddressAt(0); + LoadObject lo = cdbg.loadObjectContainingPC(vtblPtr); + if (lo != null) { + ClosestSymbol symbol = lo.closestSymbolToPC(vtblPtr); + if (symbol != null) { + message += " (nearest symbol is " + symbol.getName() + ")"; + } + } + } + + return new WrongTypeException(message); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32ThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StaticBaseConstructor.java similarity index 56% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32ThreadContext.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StaticBaseConstructor.java index 831d7893cb3..c45f5249d38 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32ThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StaticBaseConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,24 +22,31 @@ * */ -package sun.jvm.hotspot.debugger.win32; +package sun.jvm.hotspot.runtime; +import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.x86.*; +import sun.jvm.hotspot.debugger.cdbg.CDebugger; +import sun.jvm.hotspot.debugger.cdbg.ClosestSymbol; +import sun.jvm.hotspot.debugger.cdbg.LoadObject; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.HotSpotTypeDataBase; -class Win32ThreadContext extends X86ThreadContext { - private Win32Debugger debugger; +/** Instantiate wrappers for statically typed instances. */ - public Win32ThreadContext(Win32Debugger debugger) { - super(); - this.debugger = debugger; +public class StaticBaseConstructor extends InstanceConstructor { + private Class staticType; + + public StaticBaseConstructor(Class t) { + staticType = t; } - public void setRegisterAsAddress(int index, Address value) { - setRegister(index, debugger.getAddressValue(value)); - } + /** Instantiate a wrapper using staticType */ + public VMObject instantiateWrapperFor(Address addr) throws WrongTypeException { + if (addr == null) { + return null; + } - public Address getRegisterAsAddress(int index) { - return debugger.newAddress(getRegister(index)); + return (VMObject) VMObjectFactory.newObject(staticType, addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index b1c52a35319..2d1b62bf914 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -135,12 +135,14 @@ public class VM { private String name; private Address addr; private String kind; + private int origin; - private Flag(String type, String name, Address addr, String kind) { + private Flag(String type, String name, Address addr, String kind, int origin) { this.type = type; this.name = name; this.addr = addr; this.kind = kind; + this.origin = origin; } public String getType() { @@ -159,6 +161,10 @@ public class VM { return kind; } + public int getOrigin() { + return origin; + } + public boolean isBool() { return type.equals("bool"); } @@ -804,42 +810,40 @@ public class VM { private void readCommandLineFlags() { // get command line flags TypeDataBase db = getTypeDataBase(); - try { - Type flagType = db.lookupType("Flag"); - int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); - // NOTE: last flag contains null values. - commandLineFlags = new Flag[numFlags - 1]; + Type flagType = db.lookupType("Flag"); + int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); + // NOTE: last flag contains null values. + commandLineFlags = new Flag[numFlags - 1]; - Address flagAddr = flagType.getAddressField("flags").getValue(); + Address flagAddr = flagType.getAddressField("flags").getValue(); - AddressField typeFld = flagType.getAddressField("type"); - AddressField nameFld = flagType.getAddressField("name"); - AddressField addrFld = flagType.getAddressField("addr"); - AddressField kindFld = flagType.getAddressField("kind"); + AddressField typeFld = flagType.getAddressField("type"); + AddressField nameFld = flagType.getAddressField("name"); + AddressField addrFld = flagType.getAddressField("addr"); + AddressField kindFld = flagType.getAddressField("kind"); + CIntField originFld = new CIntField(flagType.getCIntegerField("origin"), 0); - long flagSize = flagType.getSize(); // sizeof(Flag) + long flagSize = flagType.getSize(); // sizeof(Flag) - // NOTE: last flag contains null values. - for (int f = 0; f < numFlags - 1; f++) { - String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); - String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); - Address addr = addrFld.getValue(flagAddr); - String kind = CStringUtilities.getString(kindFld.getValue(flagAddr)); - commandLineFlags[f] = new Flag(type, name, addr, kind); - flagAddr = flagAddr.addOffsetTo(flagSize); - } - - // sort flags by name - Arrays.sort(commandLineFlags, new Comparator() { - public int compare(Object o1, Object o2) { - Flag f1 = (Flag) o1; - Flag f2 = (Flag) o2; - return f1.getName().compareTo(f2.getName()); - } - }); - } catch (Exception exp) { - // ignore. may be older version. command line flags not available. + // NOTE: last flag contains null values. + for (int f = 0; f < numFlags - 1; f++) { + String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); + String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); + Address addr = addrFld.getValue(flagAddr); + String kind = CStringUtilities.getString(kindFld.getValue(flagAddr)); + int origin = (int)originFld.getValue(flagAddr); + commandLineFlags[f] = new Flag(type, name, addr, kind, origin); + flagAddr = flagAddr.addOffsetTo(flagSize); } + + // sort flags by name + Arrays.sort(commandLineFlags, new Comparator() { + public int compare(Object o1, Object o2) { + Flag f1 = (Flag) o1; + Flag f2 = (Flag) o2; + return f1.getName().compareTo(f2.getName()); + } + }); } public String getSystemProperty(String key) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualBaseConstructor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualBaseConstructor.java new file mode 100644 index 00000000000..a73ce129df2 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualBaseConstructor.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.CDebugger; +import sun.jvm.hotspot.debugger.cdbg.ClosestSymbol; +import sun.jvm.hotspot.debugger.cdbg.LoadObject; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.HotSpotTypeDataBase; + +/** This provides a factory to create instances where the base virtual + * type is know and the expected subclasses are within a particular + * package. */ + +public class VirtualBaseConstructor extends InstanceConstructor { + private TypeDataBase db; + private HashMap map; // Map + private Type baseType; + private Class unknownTypeHandler; + + public VirtualBaseConstructor(TypeDataBase db, Type baseType, String packageName, Class unknownTypeHandler) { + this.db = (HotSpotTypeDataBase)db; + map = new HashMap(); + this.baseType = baseType; + this.unknownTypeHandler = unknownTypeHandler; + // Try to find mirror types for each of the types. If there isn't + // a direct mirror then try to find an instantiable superclass and + // treat it as that. + for (Iterator iter = db.getTypes(); iter.hasNext(); ) { + Type t = (Type) iter.next(); + Type superType = t; + while (superType != null && superType != baseType) { + superType = superType.getSuperclass(); + } + if (superType == baseType) { + superType = t; + Class c = null; + while (c == null && superType != null) { + try { + c = Class.forName(packageName + "." + superType.getName()); + } catch (Exception e) { + } + if (c == null) superType = superType.getSuperclass(); + } + if (c == null) { + c = unknownTypeHandler; + } + map.put(t.getName(), c); + } + } + } + + /** Instantiate the most-precisely typed wrapper object available + for the type of the given Address. If no type in the mapping + matched the type of the Address, throws a WrongTypeException. + Returns null for a null address (similar behavior to + VMObjectFactory). */ + public VMObject instantiateWrapperFor(Address addr) throws WrongTypeException { + if (addr == null) { + return null; + } + + Type type = db.findDynamicTypeForAddress(addr, baseType); + if (type != null) { + return (VMObject) VMObjectFactory.newObject((Class) map.get(type.getName()), addr); + } else if (unknownTypeHandler != null) { + return (VMObject) VMObjectFactory.newObject(unknownTypeHandler, addr); + } + + throw newWrongTypeException(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualConstructor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualConstructor.java index 4e45a3cd0ac..acca1670c86 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualConstructor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VirtualConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.jvm.hotspot.runtime; import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.types.*; /** This class provides generalized "virtual constructor" @@ -39,7 +38,7 @@ import sun.jvm.hotspot.types.*; type "DefNewGeneration" to class sun.jvm.hotspot.memory.DefNewGeneration has been set up. */ -public class VirtualConstructor { +public class VirtualConstructor extends InstanceConstructor { private TypeDataBase db; private Map map; // Map @@ -78,20 +77,6 @@ public class VirtualConstructor { } } - String message = "No suitable match for type of address " + addr; - CDebugger cdbg = VM.getVM().getDebugger().getCDebugger(); - if (cdbg != null) { - // Most common case: V-table pointer is the first field - Address vtblPtr = addr.getAddressAt(0); - LoadObject lo = cdbg.loadObjectContainingPC(vtblPtr); - if (lo != null) { - ClosestSymbol symbol = lo.closestSymbolToPC(vtblPtr); - if (symbol != null) { - message += " (nearest symbol is " + symbol.getName() + ")"; - } - } - } - - throw new WrongTypeException(message); + throw newWrongTypeException(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java index 64785ee8c1f..e18dd4f8053 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package sun.jvm.hotspot.runtime.win32_amd64; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.win32.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.amd64.*; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java index 0a038e92f32..dff6615a008 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package sun.jvm.hotspot.runtime.win32_x86; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.win32.*; import sun.jvm.hotspot.debugger.x86.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.x86.*; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java index efa37e681df..34ccc102acb 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,9 @@ package sun.jvm.hotspot.tools.jcore; import java.io.*; +import java.util.jar.JarOutputStream; +import java.util.jar.JarEntry; +import java.util.jar.Manifest; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.debugger.*; @@ -34,27 +37,33 @@ import sun.jvm.hotspot.tools.*; public class ClassDump extends Tool { private ClassFilter classFilter; private String outputDirectory; + private JarOutputStream jarStream; + + public void setClassFilter(ClassFilter cf) { + classFilter = cf; + } + + public void setOutputDirectory(String od) { + outputDirectory = od; + if (jarStream != null) { + try { + jarStream.close(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + jarStream = null; + } + + public void setJarOutput(String jarFileName) throws IOException { + jarStream = new JarOutputStream(new FileOutputStream(jarFileName), new Manifest()); + outputDirectory = null; + } public void run() { // Ready to go with the database... try { - // load class filters - - String filterClassName = System.getProperty("sun.jvm.hotspot.tools.jcore.filter"); - if (filterClassName != null) { - try { - Class filterClass = Class.forName(filterClassName); - classFilter = (ClassFilter) filterClass.newInstance(); - } catch(Exception exp) { - System.err.println("Warning: Can not create class filter!"); - } - } - - outputDirectory = System.getProperty("sun.jvm.hotspot.tools.jcore.outputDir"); - if (outputDirectory == null) - outputDirectory = "."; - // walk through the system dictionary SystemDictionary dict = VM.getVM().getSystemDictionary(); dict.classesDo(new SystemDictionary.ClassVisitor() { @@ -75,6 +84,14 @@ public class ClassDump extends Tool { + Long.toHexString(e.getAddress())); e.printStackTrace(); } + if (jarStream != null) { + try { + jarStream.close(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + jarStream = null; + } } public String getName() { @@ -88,26 +105,33 @@ public class ClassDump extends Tool { String klassName = kls.getName().asString(); klassName = klassName.replace('/', File.separatorChar); - int index = klassName.lastIndexOf(File.separatorChar); - File dir = null; - if (index != -1) { - String dirName = klassName.substring(0, index); - dir = new File(outputDirectory, dirName); - } else { - dir = new File(outputDirectory); - } - - dir.mkdirs(); - File f = new File(dir, klassName.substring(klassName.lastIndexOf(File.separatorChar) + 1) - + ".class"); try { - f.createNewFile(); - OutputStream os = new BufferedOutputStream(new FileOutputStream(f)); + OutputStream os = null; + if (jarStream != null) { + jarStream.putNextEntry(new JarEntry(klassName + ".class")); + os = jarStream; + } else { + int index = klassName.lastIndexOf(File.separatorChar); + File dir = null; + if (index != -1) { + String dirName = klassName.substring(0, index); + dir = new File(outputDirectory, dirName); + } else { + dir = new File(outputDirectory); + } + + dir.mkdirs(); + File f = new File(dir, klassName.substring(index + 1) + ".class"); + f.createNewFile(); + os = new BufferedOutputStream(new FileOutputStream(f)); + } try { ClassWriter cw = new ClassWriter(kls, os); cw.write(); } finally { - os.close(); + if (os != jarStream) { + os.close(); + } } } catch(IOException exp) { exp.printStackTrace(); @@ -115,7 +139,26 @@ public class ClassDump extends Tool { } public static void main(String[] args) { + // load class filters + ClassFilter classFilter = null; + String filterClassName = System.getProperty("sun.jvm.hotspot.tools.jcore.filter"); + if (filterClassName != null) { + try { + Class filterClass = Class.forName(filterClassName); + classFilter = (ClassFilter) filterClass.newInstance(); + } catch(Exception exp) { + System.err.println("Warning: Can not create class filter!"); + } + } + + String outputDirectory = System.getProperty("sun.jvm.hotspot.tools.jcore.outputDir"); + if (outputDirectory == null) + outputDirectory = "."; + + ClassDump cd = new ClassDump(); + cd.setClassFilter(classFilter); + cd.setOutputDirectory(outputDirectory); cd.start(args); cd.stop(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/TypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/TypeDataBase.java index 76c145c77a6..6eb9e37ba40 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/TypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/TypeDataBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,6 +120,11 @@ public interface TypeDataBase { found. */ public Type guessTypeForAddress(Address addr); + /** Helper routine for guessing the most derived type of a + polymorphic C++ object. Requires a baseType that must be virtual + so that lookup can be performed without false positives */ + public Type findDynamicTypeForAddress(Address addr, Type baseType); + /** Returns an Iterator over the Types in the database. */ public Iterator getTypes(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java index 92b03014247..f88335c1bff 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,6 +150,19 @@ public class BasicTypeDataBase implements TypeDataBase { return VM.getVM().getOopSize(); } + static HashMap typeToVtbl = new HashMap(); + + private Address vtblForType(Type type) { + Address vtblAddr = (Address)typeToVtbl.get(type); + if (vtblAddr == null) { + vtblAddr = vtblAccess.getVtblForType(type); + if (vtblAddr != null) { + typeToVtbl.put(type, vtblAddr); + } + } + return vtblAddr; + } + public boolean addressTypeIsEqualToType(Address addr, Type type) { if (addr == null) { return false; @@ -158,7 +171,7 @@ public class BasicTypeDataBase implements TypeDataBase { // This implementation should be suitably platform-independent; we // search nearby memory for the vtbl value of the given type. - Address vtblAddr = vtblAccess.getVtblForType(type); + Address vtblAddr = vtblForType(type); if (vtblAddr == null) { // Type was not polymorphic, or an error occurred during lookup @@ -251,6 +264,78 @@ public class BasicTypeDataBase implements TypeDataBase { return false; } + public Type findDynamicTypeForAddress(Address addr, Type baseType) { + // This implementation should be suitably platform-independent; we + // search nearby memory for the vtbl value of the given type. + + if (vtblForType(baseType) == null) { + // Type was not polymorphic which is an error of some sort + throw new InternalError(baseType + " does not appear to be polymorphic"); + } + + // This is a more restricted version of guessTypeForAddress since + // that function has some limitations since it doesn't really know + // where in the hierarchy a virtual type starts and just poking + // around in memory is likely to trip over some vtable address, + // resulting in false positives. Eventually all uses should + // switch to this logic but in the interests of stability it will + // be separate for the moment. + + // Assuming that the base type is truly the first polymorphic type + // then the vtbl for all subclasss should be at several defined + // locations so only those locations will be checked. It's also + // required that the caller knows that the static type is at least + // baseType. See the notes in guessTypeForAddress for the logic of + // the locations searched. + + Address loc1 = addr.getAddressAt(0); + Address loc2 = null; + Address loc3 = null; + long offset2 = baseType.getSize(); + // I don't think this should be misaligned under any + // circumstances, but I'm not sure (FIXME: also not sure which + // way to go here, up or down -- assuming down) + offset2 = offset2 - (offset2 % getAddressSize()) - getAddressSize(); + if (offset2 > 0) { + loc2 = addr.getAddressAt(offset2); + } + long offset3 = offset2 - getAddressSize(); + if (offset3 > 0) { + loc3 = addr.getAddressAt(offset3); + } + + Type loc2Match = null; + Type loc3Match = null; + for (Iterator iter = getTypes(); iter.hasNext(); ) { + Type type = (Type) iter.next(); + Type superClass = type; + while (superClass != baseType && superClass != null) { + superClass = superClass.getSuperclass(); + } + if (superClass == null) continue; + Address vtblAddr = vtblForType(type); + if (vtblAddr == null) { + // This occurs sometimes for intermediate types that are never + // instantiated. + if (DEBUG) { + System.err.println("null vtbl for " + type); + } + continue; + } + // Prefer loc1 match + if (vtblAddr.equals(loc1)) return type; + if (loc2 != null && loc2Match == null && vtblAddr.equals(loc2)) { + loc2Match = type; + } + if (loc3 != null && loc3Match == null && vtblAddr.equals(loc3)) { + loc3Match = type; + } + } + if (loc2Match != null) return loc2Match; + if (loc3Match != null) return loc3Match; + return null; + } + public Type guessTypeForAddress(Address addr) { for (Iterator iter = getTypes(); iter.hasNext(); ) { Type t = (Type) iter.next(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/CommandProcessorPanel.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/CommandProcessorPanel.java index 1dd159ad266..8b4acaeaec6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/CommandProcessorPanel.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/CommandProcessorPanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ public class CommandProcessorPanel extends JPanel { public void run() { beginUpdate(); try { - commands.executeCommand(ln); + commands.executeCommand(ln, true); commands.printPrompt(); Document d = editor.getDocument(); try { @@ -149,7 +149,7 @@ public class CommandProcessorPanel extends JPanel { public void clear() { EditableAtEndDocument d = (EditableAtEndDocument) editor.getDocument(); d.clear(); - commands.executeCommand(""); + commands.executeCommand("", false); setMark(); editor.requestFocus(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GenericGrowableArray.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GenericGrowableArray.java new file mode 100644 index 00000000000..a0fcac8f40e --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GenericGrowableArray.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.utilities; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class GenericGrowableArray extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("GenericGrowableArray"); + _arena_field = type.getAddressField("_arena"); + _max_field = new CIntField(type.getCIntegerField("_max"), 0); + _len_field = new CIntField(type.getCIntegerField("_len"), 0); + } + + private static AddressField _arena_field; + private static CIntField _max_field; + private static CIntField _len_field; + + public int max() { + return (int)_max_field.getValue(getAddress()); + } + + public int length() { + return (int)_len_field.getValue(getAddress()); + } + + public GenericGrowableArray(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GrowableArray.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GrowableArray.java new file mode 100644 index 00000000000..4a6f1af5a93 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/GrowableArray.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.utilities; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.types.*; + +public class GrowableArray extends GenericGrowableArray { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("GrowableArray"); + dataField = type.getAddressField("_data"); + } + + private static AddressField dataField; + + private InstanceConstructor virtualConstructor; + + public static GrowableArray create(Address addr, InstanceConstructor v) { + if (addr == null) return null; + return new GrowableArray(addr, v); + } + + public T at(int i) { + if (i < 0 || i >= length()) throw new ArrayIndexOutOfBoundsException(i); + Address data = dataField.getValue(getAddress()); + Address addr = data.getAddressAt(i * VM.getVM().getAddressSize()); + if (addr == null) return null; + return (T) virtualConstructor.instantiateWrapperFor(addr); + } + + private GrowableArray(Address addr, InstanceConstructor v) { + super(addr); + virtualConstructor = v; + } +} diff --git a/hotspot/make/sa.files b/hotspot/make/sa.files index dd9a0fd7c53..92984320268 100644 --- a/hotspot/make/sa.files +++ b/hotspot/make/sa.files @@ -46,6 +46,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/tree/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \ @@ -54,9 +55,6 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dbx/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dbx/sparc/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dbx/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dummy/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ia64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/*.java \ @@ -75,7 +73,6 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/amd64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/sparc/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/sparc/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/amd64/*.java \ @@ -89,7 +86,9 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/interpreter/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/jdi/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/livejvm/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java +$(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java AGENT_FILES2 = \ @@ -106,9 +105,6 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_amd64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_sparc/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/sparc/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_amd64/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_ia64/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/jcore/*.java \ diff --git a/hotspot/src/share/vm/ci/ciArrayKlass.hpp b/hotspot/src/share/vm/ci/ciArrayKlass.hpp index 98b005156a5..aae2f3393ff 100644 --- a/hotspot/src/share/vm/ci/ciArrayKlass.hpp +++ b/hotspot/src/share/vm/ci/ciArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ // This class, and its subclasses represent klassOops in the // HotSpot virtual machine whose Klass part is an arrayKlass. class ciArrayKlass : public ciKlass { + CI_PACKAGE_ACCESS private: jint _dimension; diff --git a/hotspot/src/share/vm/ci/ciClassList.hpp b/hotspot/src/share/vm/ci/ciClassList.hpp index bc96594a3eb..4d19439faa0 100644 --- a/hotspot/src/share/vm/ci/ciClassList.hpp +++ b/hotspot/src/share/vm/ci/ciClassList.hpp @@ -77,12 +77,14 @@ class ciTypeArrayKlassKlass; // Everyone gives access to ciObjectFactory #define CI_PACKAGE_ACCESS \ -friend class ciObjectFactory; +friend class ciObjectFactory; \ +friend class VMStructs; // These are the packages that have access to ciEnv // Any more access must be given explicitly. #define CI_PACKAGE_ACCESS_TO \ friend class ciObjectFactory; \ +friend class VMStructs; \ friend class ciCallSite; \ friend class ciConstantPoolCache; \ friend class ciField; \ diff --git a/hotspot/src/share/vm/ci/ciConstant.hpp b/hotspot/src/share/vm/ci/ciConstant.hpp index 392c6bbd12a..8cdc893fd2b 100644 --- a/hotspot/src/share/vm/ci/ciConstant.hpp +++ b/hotspot/src/share/vm/ci/ciConstant.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ // // This class represents a constant value. class ciConstant VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; private: friend class ciEnv; friend class ciField; diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.hpp b/hotspot/src/share/vm/ci/ciObjectFactory.hpp index 12185f2262f..6222b9f85bc 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp @@ -36,6 +36,9 @@ // which ensures that for each oop, at most one ciObject is created. // This invariant allows efficient implementation of ciObject. class ciObjectFactory : public ResourceObj { + friend class VMStructs; + friend class ciEnv; + private: static volatile bool _initialized; static GrowableArray* _shared_ci_objects; diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index eb571eebba3..7abc37e54dd 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -37,6 +37,8 @@ class nmethodLocker; // An entry in the compile queue. It represents a pending or current // compilation. class CompileTask : public CHeapObj { + friend class VMStructs; + private: Monitor* _lock; uint _compile_id; diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index b923cd4701f..4c2f1e8c836 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -151,6 +151,8 @@ class AllStatic { //------------------------------Chunk------------------------------------------ // Linked list of raw memory chunks class Chunk: public CHeapObj { + friend class VMStructs; + protected: Chunk* _next; // Next Chunk in list const size_t _len; // Size of this Chunk @@ -200,6 +202,8 @@ protected: friend class ResourceMark; friend class HandleMark; friend class NoHandleMark; + friend class VMStructs; + Chunk *_first; // First chunk Chunk *_chunk; // current chunk char *_hwm, *_max; // High water mark and max in current chunk diff --git a/hotspot/src/share/vm/memory/resourceArea.hpp b/hotspot/src/share/vm/memory/resourceArea.hpp index 728a12f575d..3bb84b5e12b 100644 --- a/hotspot/src/share/vm/memory/resourceArea.hpp +++ b/hotspot/src/share/vm/memory/resourceArea.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ class ResourceArea: public Arena { friend class ResourceMark; friend class DeoptResourceMark; + friend class VMStructs; debug_only(int _nesting;) // current # of nested ResourceMarks debug_only(static int _warned;) // to suppress multiple warnings diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 8a3c247b216..692dbc7422e 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1371,37 +1371,6 @@ int instanceKlass::cached_itable_index(size_t idnum) { } -// -// nmethodBucket is used to record dependent nmethods for -// deoptimization. nmethod dependencies are actually -// pairs but we really only care about the klass part for purposes of -// finding nmethods which might need to be deoptimized. Instead of -// recording the method, a count of how many times a particular nmethod -// was recorded is kept. This ensures that any recording errors are -// noticed since an nmethod should be removed as many times are it's -// added. -// -class nmethodBucket { - private: - nmethod* _nmethod; - int _count; - nmethodBucket* _next; - - public: - nmethodBucket(nmethod* nmethod, nmethodBucket* next) { - _nmethod = nmethod; - _next = next; - _count = 1; - } - int count() { return _count; } - int increment() { _count += 1; return _count; } - int decrement() { _count -= 1; assert(_count >= 0, "don't underflow"); return _count; } - nmethodBucket* next() { return _next; } - void set_next(nmethodBucket* b) { _next = b; } - nmethod* get_nmethod() { return _nmethod; } -}; - - // // Walk the list of dependent nmethods searching for nmethods which // are dependent on the changes that were passed in and mark them for diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 8fb55ada382..a87448a7680 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1012,4 +1012,36 @@ class PreviousVersionWalker : public StackObj { PreviousVersionInfo* next_previous_version(); }; + +// +// nmethodBucket is used to record dependent nmethods for +// deoptimization. nmethod dependencies are actually +// pairs but we really only care about the klass part for purposes of +// finding nmethods which might need to be deoptimized. Instead of +// recording the method, a count of how many times a particular nmethod +// was recorded is kept. This ensures that any recording errors are +// noticed since an nmethod should be removed as many times are it's +// added. +// +class nmethodBucket: public CHeapObj { + friend class VMStructs; + private: + nmethod* _nmethod; + int _count; + nmethodBucket* _next; + + public: + nmethodBucket(nmethod* nmethod, nmethodBucket* next) { + _nmethod = nmethod; + _next = next; + _count = 1; + } + int count() { return _count; } + int increment() { _count += 1; return _count; } + int decrement() { _count -= 1; assert(_count >= 0, "don't underflow"); return _count; } + nmethodBucket* next() { return _next; } + void set_next(nmethodBucket* b) { _next = b; } + nmethod* get_nmethod() { return _nmethod; } +}; + #endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index 7a3c224ef4b..51869c8da6b 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ struct Tarjan; // Note that the constructor just zeros things, and since I use Arena // allocation I do not need a destructor to reclaim storage. class Block_Array : public ResourceObj { + friend class VMStructs; uint _size; // allocated size, as opposed to formal limit debug_only(uint _limit;) // limit to formal domain protected: @@ -72,6 +73,7 @@ public: class Block_List : public Block_Array { + friend class VMStructs; public: uint _cnt; Block_List() : Block_Array(Thread::current()->resource_area()), _cnt(0) {} @@ -87,6 +89,7 @@ public: class CFGElement : public ResourceObj { + friend class VMStructs; public: float _freq; // Execution frequency (estimate) @@ -102,6 +105,7 @@ class CFGElement : public ResourceObj { // Basic blocks are used during the output routines, and are not used during // any optimization pass. They are created late in the game. class Block : public CFGElement { + friend class VMStructs; public: // Nodes in this block, in order Node_List _nodes; @@ -341,6 +345,7 @@ class Block : public CFGElement { //------------------------------PhaseCFG--------------------------------------- // Build an array of Basic Block pointers, one per Node. class PhaseCFG : public Phase { + friend class VMStructs; private: // Build a proper looking cfg. Return count of basic blocks uint build_cfg(); @@ -515,6 +520,7 @@ public: //------------------------------CFGLoop------------------------------------------- class CFGLoop : public CFGElement { + friend class VMStructs; int _id; int _depth; CFGLoop *_parent; // root of loop tree is the method level "pseudo" loop, it's parent is null @@ -566,6 +572,7 @@ class CFGLoop : public CFGElement { // A edge between two basic blocks that will be embodied by a branch or a // fall-through. class CFGEdge : public ResourceObj { + friend class VMStructs; private: Block * _from; // Source basic block Block * _to; // Destination basic block @@ -702,6 +709,7 @@ class Trace : public ResourceObj { //------------------------------PhaseBlockLayout------------------------------- // Rearrange blocks into some canonical order, based on edges and their frequencies class PhaseBlockLayout : public Phase { + friend class VMStructs; PhaseCFG &_cfg; // Control flow graph GrowableArray *edges; diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index a29159686e4..71754274b9b 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -610,3 +610,22 @@ InlineTree* InlineTree::find_subtree_from_root(InlineTree* root, JVMState* jvms, } return iltp; } + + + +#ifndef PRODUCT +void InlineTree::print_impl(outputStream* st, int indent) const { + for (int i = 0; i < indent; i++) st->print(" "); + st->print(" @ %d ", caller_bci()); + method()->print_short_name(st); + st->cr(); + + for (int i = 0 ; i < _subtrees.length(); i++) { + _subtrees.at(i)->print_impl(st, indent + 2); + } +} + +void InlineTree::print_value_on(outputStream* st) const { + print_impl(st, 2); +} +#endif diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index ee72a6e3a87..6e81a7e8da3 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,6 +187,7 @@ public: // This provides a way to map the optimized program back into the interpreter, // or to let the GC mark the stack. class JVMState : public ResourceObj { + friend class VMStructs; public: typedef enum { Reexecute_Undefined = -1, // not defined -- will be translated into false later @@ -500,6 +501,7 @@ public: // Call nodes now subsume the function of debug nodes at callsites, so they // contain the functionality of a full scope chain of debug nodes. class CallNode : public SafePointNode { + friend class VMStructs; public: const TypeFunc *_tf; // Function type address _entry_point; // Address of method being called @@ -565,6 +567,7 @@ public: // convention. (The "Java" calling convention is the compiler's calling // convention, as opposed to the interpreter's or that of native C.) class CallJavaNode : public CallNode { + friend class VMStructs; protected: virtual uint cmp( const Node &n ) const; virtual uint size_of() const; // Size is bigger diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index af116050c11..999a7922709 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ class PhaseChaitin; //------------------------------LRG-------------------------------------------- // Live-RanGe structure. class LRG : public ResourceObj { + friend class VMStructs; public: enum { SPILL_REG=29999 }; // Register number of a spilled LRG @@ -181,6 +182,7 @@ public: // Map Node indices to Live RanGe indices. // Array lookup in the optimized case. class LRG_List : public ResourceObj { + friend class VMStructs; uint _cnt, _max; uint* _lidxs; ReallocMark _nesting; // assertion check for reallocations @@ -211,6 +213,7 @@ public: // abstract! It needs abstraction so I can fiddle with the implementation to // get even more speed. class PhaseIFG : public Phase { + friend class VMStructs; // Current implementation: a triangular adjacency list. // Array of adjacency-lists, indexed by live-range number @@ -294,6 +297,7 @@ public: //------------------------------Chaitin---------------------------------------- // Briggs-Chaitin style allocation, mostly. class PhaseChaitin : public PhaseRegAlloc { + friend class VMStructs; int _trip_cnt; int _alternate; diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 3a883188d16..82e33a93ace 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -80,6 +80,8 @@ class WarmCallInfo; // This class defines a top-level Compiler invocation. class Compile : public Phase { + friend class VMStructs; + public: // Fixed alias indexes. (See also MergeMemNode.) enum { diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index e88c4b96fe8..8564a7775be 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,6 +184,8 @@ typedef Node** DUIterator_Last; // whenever I have phase-specific information. class Node { + friend class VMStructs; + // Lots of restrictions on cloning Nodes Node(const Node&); // not defined; linker error to use these Node &operator=(const Node &rhs); @@ -1286,6 +1288,7 @@ class SimpleDUIterator : public StackObj { // Note that the constructor just zeros things, and since I use Arena // allocation I do not need a destructor to reclaim storage. class Node_Array : public ResourceObj { + friend class VMStructs; protected: Arena *_a; // Arena to allocate in uint _max; @@ -1316,6 +1319,7 @@ public: }; class Node_List : public Node_Array { + friend class VMStructs; uint _cnt; public: Node_List() : Node_Array(Thread::current()->resource_area()), _cnt(0) {} @@ -1339,6 +1343,7 @@ public: //------------------------------Unique_Node_List------------------------------- class Unique_Node_List : public Node_List { + friend class VMStructs; VectorSet _in_worklist; uint _clock_index; // Index in list where to pop from next public: @@ -1389,6 +1394,7 @@ inline void Compile::record_for_igvn(Node* n) { //------------------------------Node_Stack------------------------------------- class Node_Stack { + friend class VMStructs; protected: struct INode { Node *node; // Processed node @@ -1461,6 +1467,7 @@ public: // Debugging or profiling annotations loosely and sparsely associated // with some nodes. See Compile::node_notes_at for the accessor. class Node_Notes VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; JVMState* _jvms; public: diff --git a/hotspot/src/share/vm/opto/optoreg.hpp b/hotspot/src/share/vm/opto/optoreg.hpp index 58c9f1c69be..e6427ea459a 100644 --- a/hotspot/src/share/vm/opto/optoreg.hpp +++ b/hotspot/src/share/vm/opto/optoreg.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,6 +172,7 @@ class OptoReg VALUE_OBJ_CLASS_SPEC { // and converting that will return OptoReg::Bad losing the identity of the OptoReg. class OptoRegPair { + friend class VMStructs; private: short _second; short _first; diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index ea793f02908..ec9a08358c5 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -41,6 +41,8 @@ class SwitchRange; //------------------------------InlineTree------------------------------------- class InlineTree : public ResourceObj { + friend class VMStructs; + Compile* C; // cache JVMState* _caller_jvms; // state of caller ciMethod* _method; // method being called by the caller_jvms @@ -54,7 +56,8 @@ class InlineTree : public ResourceObj { float compute_callee_frequency( int caller_bci ) const; GrowableArray _subtrees; - friend class Compile; + + void print_impl(outputStream* stj, int indent) const PRODUCT_RETURN; protected: InlineTree(Compile* C, @@ -121,6 +124,8 @@ public: uint count_inlines() const { return _count_inlines; }; #endif GrowableArray subtrees() { return _subtrees; } + + void print_value_on(outputStream* st) const PRODUCT_RETURN; }; diff --git a/hotspot/src/share/vm/opto/regalloc.hpp b/hotspot/src/share/vm/opto/regalloc.hpp index 71f4defc2f2..d0a993e57c4 100644 --- a/hotspot/src/share/vm/opto/regalloc.hpp +++ b/hotspot/src/share/vm/opto/regalloc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ class PhaseCFG; //------------------------------PhaseRegAlloc------------------------------------ // Abstract register allocator class PhaseRegAlloc : public Phase { + friend class VMStructs; static void (*_alloc_statistics[MAX_REG_ALLOCATORS])(); static int _num_allocators; diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 4d08d50d542..133ce78f061 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -64,6 +64,8 @@ class TypeKlassPtr; // different kind of Type exists. Types are never modified after creation, so // all their interesting fields are constant. class Type { + friend class VMStructs; + public: enum TYPES { Bad=0, // Type check diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 07702b1d226..1bfefa05c99 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -66,6 +66,7 @@ class AttachOperation; // This class contains the JVMTI interface for the rest of hotspot. // class JvmtiExport : public AllStatic { + friend class VMStructs; private: static int _field_access_count; static int _field_modification_count; diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index 161d3a31afe..18225467921 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.hpp +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp @@ -34,6 +34,8 @@ class MonitorValue; class ObjectValue; class Deoptimization : AllStatic { + friend class VMStructs; + public: // What condition caused the deoptimization? enum DeoptReason { diff --git a/hotspot/src/share/vm/runtime/vframeArray.hpp b/hotspot/src/share/vm/runtime/vframeArray.hpp index 7072d22e074..6f8d436c6ca 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.hpp +++ b/hotspot/src/share/vm/runtime/vframeArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,8 @@ class StackValueCollection; // represent an interpreter frame which will eventually be created. class vframeArrayElement : public _ValueObj { + friend class VMStructs; + private: frame _frame; // the interpreter frame we will unpack into @@ -107,6 +109,8 @@ class vframeArrayElement : public _ValueObj { // at the data in each vframeElement class vframeArray: public CHeapObj { + friend class VMStructs; + private: diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 40b703f15a6..69b3ab653f8 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -29,6 +29,11 @@ #include "classfile/placeholders.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" +#include "ci/ciField.hpp" +#include "ci/ciInstance.hpp" +#include "ci/ciObjArrayKlass.hpp" +#include "ci/ciMethodData.hpp" +#include "ci/ciSymbol.hpp" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" #include "code/compressedStream.hpp" @@ -38,6 +43,7 @@ #include "code/stubs.hpp" #include "code/vmreg.hpp" #include "compiler/oopMap.hpp" +#include "compiler/compileBroker.hpp" #include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp" #include "gc_implementation/shared/immutableSpace.hpp" #include "gc_implementation/shared/markSweep.hpp" @@ -90,6 +96,8 @@ #include "oops/typeArrayOop.hpp" #include "prims/jvmtiAgentThread.hpp" #include "runtime/arguments.hpp" +#include "runtime/deoptimization.hpp" +#include "runtime/vframeArray.hpp" #include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -167,7 +175,23 @@ #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp" #endif #ifdef COMPILER2 +#include "opto/addnode.hpp" +#include "opto/block.hpp" +#include "opto/callnode.hpp" +#include "opto/cfgnode.hpp" +#include "opto/chaitin.hpp" +#include "opto/divnode.hpp" +#include "opto/locknode.hpp" +#include "opto/loopnode.hpp" +#include "opto/machnode.hpp" #include "opto/matcher.hpp" +#include "opto/mulnode.hpp" +#include "opto/phaseX.hpp" +#include "opto/parse.hpp" +#include "opto/regalloc.hpp" +#include "opto/rootnode.hpp" +#include "opto/subnode.hpp" +#include "opto/vectornode.hpp" #ifdef TARGET_ARCH_MODEL_x86_32 # include "adfiles/adGlobals_x86_32.hpp" #endif @@ -294,6 +318,10 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(instanceKlass, _methods_annotations, objArrayOop) \ nonstatic_field(instanceKlass, _methods_parameter_annotations, objArrayOop) \ nonstatic_field(instanceKlass, _methods_default_annotations, objArrayOop) \ + nonstatic_field(instanceKlass, _dependencies, nmethodBucket*) \ + nonstatic_field(nmethodBucket, _nmethod, nmethod*) \ + nonstatic_field(nmethodBucket, _count, int) \ + nonstatic_field(nmethodBucket, _next, nmethodBucket*) \ nonstatic_field(Klass, _super_check_offset, juint) \ nonstatic_field(Klass, _secondary_super_cache, klassOop) \ nonstatic_field(Klass, _secondary_supers, objArrayOop) \ @@ -312,17 +340,26 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(methodKlass, _alloc_size, juint) \ nonstatic_field(methodDataOopDesc, _size, int) \ nonstatic_field(methodDataOopDesc, _method, methodOop) \ + nonstatic_field(methodDataOopDesc, _data_size, int) \ + nonstatic_field(methodDataOopDesc, _data[0], intptr_t) \ + nonstatic_field(methodDataOopDesc, _nof_decompiles, uint) \ + nonstatic_field(methodDataOopDesc, _nof_overflow_recompiles, uint) \ + nonstatic_field(methodDataOopDesc, _nof_overflow_traps, uint) \ + nonstatic_field(methodDataOopDesc, _eflags, intx) \ + nonstatic_field(methodDataOopDesc, _arg_local, intx) \ + nonstatic_field(methodDataOopDesc, _arg_stack, intx) \ + nonstatic_field(methodDataOopDesc, _arg_returned, intx) \ nonstatic_field(methodOopDesc, _constMethod, constMethodOop) \ nonstatic_field(methodOopDesc, _constants, constantPoolOop) \ - c2_nonstatic_field(methodOopDesc, _method_data, methodDataOop) \ - c2_nonstatic_field(methodOopDesc, _interpreter_invocation_count, int) \ + nonstatic_field(methodOopDesc, _method_data, methodDataOop) \ + nonstatic_field(methodOopDesc, _interpreter_invocation_count, int) \ nonstatic_field(methodOopDesc, _access_flags, AccessFlags) \ nonstatic_field(methodOopDesc, _vtable_index, int) \ nonstatic_field(methodOopDesc, _method_size, u2) \ nonstatic_field(methodOopDesc, _max_stack, u2) \ nonstatic_field(methodOopDesc, _max_locals, u2) \ nonstatic_field(methodOopDesc, _size_of_parameters, u2) \ - c2_nonstatic_field(methodOopDesc, _interpreter_throwout_count, u2) \ + nonstatic_field(methodOopDesc, _interpreter_throwout_count, u2) \ nonstatic_field(methodOopDesc, _number_of_breakpoints, u2) \ nonstatic_field(methodOopDesc, _invocation_counter, InvocationCounter) \ nonstatic_field(methodOopDesc, _backedge_counter, InvocationCounter) \ @@ -408,7 +445,7 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(Universe, _constantPoolCacheKlassObj, klassOop) \ static_field(Universe, _compiledICHolderKlassObj, klassOop) \ static_field(Universe, _systemObjArrayKlassObj, klassOop) \ - static_field(Universe, _mirrors[0], oop) \ + static_field(Universe, _mirrors[0], oop) \ static_field(Universe, _main_thread_group, oop) \ static_field(Universe, _system_thread_group, oop) \ static_field(Universe, _the_empty_byte_array, typeArrayOop) \ @@ -709,6 +746,15 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(LoaderConstraintEntry, _max_loaders, int) \ nonstatic_field(LoaderConstraintEntry, _loaders, oop*) \ \ + /*******************/ \ + /* GrowableArrays */ \ + /*******************/ \ + \ + nonstatic_field(GenericGrowableArray, _len, int) \ + nonstatic_field(GenericGrowableArray, _max, int) \ + nonstatic_field(GenericGrowableArray, _arena, Arena*) \ + nonstatic_field(GrowableArray, _data, int*) \ + \ /********************************/ \ /* CodeCache (NOTE: incomplete) */ \ /********************************/ \ @@ -814,11 +860,14 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(nmethod, _lock_count, jint) \ nonstatic_field(nmethod, _stack_traversal_mark, long) \ nonstatic_field(nmethod, _compile_id, int) \ + nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ nonstatic_field(nmethod, _marked_for_deoptimization, bool) \ \ nonstatic_field(RicochetBlob, _bounce_offset, int) \ nonstatic_field(RicochetBlob, _exception_offset, int) \ \ + unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \ + \ /********************************/ \ /* JavaCalls (NOTE: incomplete) */ \ /********************************/ \ @@ -839,6 +888,9 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(Threads, _number_of_non_daemon_threads, int) \ static_field(Threads, _return_code, int) \ \ + nonstatic_field(ThreadShadow, _pending_exception, oop) \ + nonstatic_field(ThreadShadow, _exception_file, const char*) \ + nonstatic_field(ThreadShadow, _exception_line, int) \ volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \ nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \ nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \ @@ -850,10 +902,22 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(JavaThread, _next, JavaThread*) \ nonstatic_field(JavaThread, _threadObj, oop) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ + nonstatic_field(JavaThread, _vm_result, oop) \ + nonstatic_field(JavaThread, _vm_result_2, oop) \ + nonstatic_field(JavaThread, _pending_async_exception, oop) \ + volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ + volatile_nonstatic_field(JavaThread, _exception_pc, address) \ + nonstatic_field(JavaThread, _is_compiling, bool) \ + nonstatic_field(JavaThread, _special_runtime_exit_condition, JavaThread::AsyncRequests) \ + nonstatic_field(JavaThread, _saved_exception_pc, address) \ volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \ nonstatic_field(JavaThread, _osthread, OSThread*) \ nonstatic_field(JavaThread, _stack_base, address) \ nonstatic_field(JavaThread, _stack_size, size_t) \ + nonstatic_field(JavaThread, _vframe_array_head, vframeArray*) \ + nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \ + nonstatic_field(Thread, _resource_area, ResourceArea*) \ + nonstatic_field(CompilerThread, _env, ciEnv*) \ \ /************/ \ /* OSThread */ \ @@ -903,7 +967,83 @@ static inline uint64_t cast_uint64_t(size_t x) /* Runtime1 (NOTE: incomplete) */ \ /*******************************/ \ \ - unchecked_c1_static_field(Runtime1, _blobs, sizeof(Runtime1::_blobs)) /* NOTE: no type */ \ + unchecked_c1_static_field(Runtime1, _blobs, sizeof(Runtime1::_blobs)) /* NOTE: no type */ \ + \ + /**************/ \ + /* allocation */ \ + /**************/ \ + \ + nonstatic_field(Chunk, _next, Chunk*) \ + nonstatic_field(Chunk, _len, const size_t) \ + \ + nonstatic_field(Arena, _first, Chunk*) \ + nonstatic_field(Arena, _chunk, Chunk*) \ + nonstatic_field(Arena, _hwm, char*) \ + nonstatic_field(Arena, _max, char*) \ + \ + /************/ \ + /* CI */ \ + /************/ \ + \ + nonstatic_field(ciEnv, _system_dictionary_modification_counter, int) \ + nonstatic_field(ciEnv, _compiler_data, void*) \ + nonstatic_field(ciEnv, _failure_reason, const char*) \ + nonstatic_field(ciEnv, _factory, ciObjectFactory*) \ + nonstatic_field(ciEnv, _dependencies, Dependencies*) \ + nonstatic_field(ciEnv, _task, CompileTask*) \ + nonstatic_field(ciEnv, _arena, Arena*) \ + \ + nonstatic_field(ciObject, _handle, jobject) \ + nonstatic_field(ciObject, _klass, ciKlass*) \ + nonstatic_field(ciObject, _ident, uint) \ + \ + nonstatic_field(ciSymbol, _ident, uint) \ + nonstatic_field(ciSymbol, _symbol, Symbol*) \ + \ + nonstatic_field(ciType, _basic_type, BasicType) \ + \ + nonstatic_field(ciKlass, _name, ciSymbol*) \ + \ + nonstatic_field(ciArrayKlass, _dimension, jint) \ + \ + nonstatic_field(ciObjArrayKlass, _element_klass, ciKlass*) \ + nonstatic_field(ciObjArrayKlass, _base_element_klass, ciKlass*) \ + \ + nonstatic_field(ciInstanceKlass, _init_state, instanceKlass::ClassState) \ + nonstatic_field(ciInstanceKlass, _is_shared, bool) \ + \ + nonstatic_field(ciMethod, _interpreter_invocation_count, int) \ + nonstatic_field(ciMethod, _interpreter_throwout_count, int) \ + \ + nonstatic_field(ciMethodData, _data_size, int) \ + nonstatic_field(ciMethodData, _state, u_char) \ + nonstatic_field(ciMethodData, _extra_data_size, int) \ + nonstatic_field(ciMethodData, _data, intptr_t*) \ + nonstatic_field(ciMethodData, _hint_di, int) \ + nonstatic_field(ciMethodData, _eflags, intx) \ + nonstatic_field(ciMethodData, _arg_local, intx) \ + nonstatic_field(ciMethodData, _arg_stack, intx) \ + nonstatic_field(ciMethodData, _arg_returned, intx) \ + nonstatic_field(ciMethodData, _current_mileage, int) \ + nonstatic_field(ciMethodData, _orig, methodDataOopDesc) \ + \ + nonstatic_field(ciField, _holder, ciInstanceKlass*) \ + nonstatic_field(ciField, _name, ciSymbol*) \ + nonstatic_field(ciField, _signature, ciSymbol*) \ + nonstatic_field(ciField, _offset, int) \ + nonstatic_field(ciField, _is_constant, bool) \ + nonstatic_field(ciField, _constant_value, ciConstant) \ + \ + nonstatic_field(ciObjectFactory, _ci_objects, GrowableArray*) \ + nonstatic_field(ciObjectFactory, _symbols, GrowableArray*) \ + nonstatic_field(ciObjectFactory, _unloaded_methods, GrowableArray*) \ + \ + nonstatic_field(ciConstant, _type, BasicType) \ + nonstatic_field(ciConstant, _value._int, jint) \ + nonstatic_field(ciConstant, _value._long, jlong) \ + nonstatic_field(ciConstant, _value._float, jfloat) \ + nonstatic_field(ciConstant, _value._double, jdouble) \ + nonstatic_field(ciConstant, _value._object, ciObject*) \ \ /************/ \ /* Monitors */ \ @@ -925,7 +1065,114 @@ static inline uint64_t cast_uint64_t(size_t x) /* Matcher (C2 only) */ \ /*********************/ \ \ - unchecked_c2_static_field(Matcher, _regEncode, sizeof(Matcher::_regEncode)) /* NOTE: no type */ \ + unchecked_c2_static_field(Matcher, _regEncode, sizeof(Matcher::_regEncode)) /* NOTE: no type */ \ + \ + c2_nonstatic_field(Node, _in, Node**) \ + c2_nonstatic_field(Node, _out, Node**) \ + c2_nonstatic_field(Node, _cnt, node_idx_t) \ + c2_nonstatic_field(Node, _max, node_idx_t) \ + c2_nonstatic_field(Node, _outcnt, node_idx_t) \ + c2_nonstatic_field(Node, _outmax, node_idx_t) \ + c2_nonstatic_field(Node, _idx, const node_idx_t) \ + c2_nonstatic_field(Node, _class_id, jushort) \ + c2_nonstatic_field(Node, _flags, jushort) \ + \ + c2_nonstatic_field(Compile, _root, RootNode*) \ + c2_nonstatic_field(Compile, _unique, uint) \ + c2_nonstatic_field(Compile, _entry_bci, int) \ + c2_nonstatic_field(Compile, _top, Node*) \ + c2_nonstatic_field(Compile, _cfg, PhaseCFG*) \ + c2_nonstatic_field(Compile, _regalloc, PhaseRegAlloc*) \ + c2_nonstatic_field(Compile, _method, ciMethod*) \ + c2_nonstatic_field(Compile, _compile_id, const int) \ + c2_nonstatic_field(Compile, _save_argument_registers, const bool) \ + c2_nonstatic_field(Compile, _subsume_loads, const bool) \ + c2_nonstatic_field(Compile, _do_escape_analysis, const bool) \ + c2_nonstatic_field(Compile, _ilt, InlineTree*) \ + \ + c2_nonstatic_field(InlineTree, _caller_jvms, JVMState*) \ + c2_nonstatic_field(InlineTree, _method, ciMethod*) \ + c2_nonstatic_field(InlineTree, _caller_tree, InlineTree*) \ + c2_nonstatic_field(InlineTree, _subtrees, GrowableArray) \ + \ + c2_nonstatic_field(OptoRegPair, _first, short) \ + c2_nonstatic_field(OptoRegPair, _second, short) \ + \ + c2_nonstatic_field(JVMState, _caller, JVMState*) \ + c2_nonstatic_field(JVMState, _depth, uint) \ + c2_nonstatic_field(JVMState, _locoff, uint) \ + c2_nonstatic_field(JVMState, _stkoff, uint) \ + c2_nonstatic_field(JVMState, _monoff, uint) \ + c2_nonstatic_field(JVMState, _scloff, uint) \ + c2_nonstatic_field(JVMState, _endoff, uint) \ + c2_nonstatic_field(JVMState, _sp, uint) \ + c2_nonstatic_field(JVMState, _bci, int) \ + c2_nonstatic_field(JVMState, _method, ciMethod*) \ + c2_nonstatic_field(JVMState, _map, SafePointNode*) \ + \ + c2_nonstatic_field(SafePointNode, _jvms, JVMState* const) \ + \ + c2_nonstatic_field(MachSafePointNode, _jvms, JVMState*) \ + c2_nonstatic_field(MachSafePointNode, _jvmadj, uint) \ + \ + c2_nonstatic_field(MachIfNode, _prob, jfloat) \ + c2_nonstatic_field(MachIfNode, _fcnt, jfloat) \ + \ + c2_nonstatic_field(CallNode, _entry_point, address) \ + \ + c2_nonstatic_field(CallJavaNode, _method, ciMethod*) \ + \ + c2_nonstatic_field(CallRuntimeNode, _name, const char*) \ + \ + c2_nonstatic_field(CallStaticJavaNode, _name, const char*) \ + \ + c2_nonstatic_field(MachCallJavaNode, _method, ciMethod*) \ + c2_nonstatic_field(MachCallJavaNode, _bci, int) \ + \ + c2_nonstatic_field(MachCallStaticJavaNode, _name, const char*) \ + \ + c2_nonstatic_field(MachCallRuntimeNode, _name, const char*) \ + \ + c2_nonstatic_field(PhaseCFG, _num_blocks, uint) \ + c2_nonstatic_field(PhaseCFG, _blocks, Block_List) \ + c2_nonstatic_field(PhaseCFG, _bbs, Block_Array) \ + c2_nonstatic_field(PhaseCFG, _broot, Block*) \ + \ + c2_nonstatic_field(PhaseRegAlloc, _node_regs, OptoRegPair*) \ + c2_nonstatic_field(PhaseRegAlloc, _node_regs_max_index, uint) \ + c2_nonstatic_field(PhaseRegAlloc, _framesize, uint) \ + c2_nonstatic_field(PhaseRegAlloc, _max_reg, OptoReg::Name) \ + \ + c2_nonstatic_field(PhaseChaitin, _trip_cnt, int) \ + c2_nonstatic_field(PhaseChaitin, _alternate, int) \ + c2_nonstatic_field(PhaseChaitin, _lo_degree, uint) \ + c2_nonstatic_field(PhaseChaitin, _lo_stk_degree, uint) \ + c2_nonstatic_field(PhaseChaitin, _hi_degree, uint) \ + c2_nonstatic_field(PhaseChaitin, _simplified, uint) \ + c2_nonstatic_field(PhaseChaitin, _maxlrg, uint) \ + \ + c2_nonstatic_field(Block, _nodes, Node_List) \ + c2_nonstatic_field(Block, _succs, Block_Array) \ + c2_nonstatic_field(Block, _num_succs, uint) \ + c2_nonstatic_field(Block, _pre_order, uint) \ + c2_nonstatic_field(Block, _dom_depth, uint) \ + c2_nonstatic_field(Block, _idom, Block*) \ + c2_nonstatic_field(Block, _freq, jfloat) \ + \ + c2_nonstatic_field(CFGElement, _freq, jfloat) \ + \ + c2_nonstatic_field(Block_List, _cnt, uint) \ + \ + c2_nonstatic_field(Block_Array, _size, uint) \ + c2_nonstatic_field(Block_Array, _blocks, Block**) \ + c2_nonstatic_field(Block_Array, _arena, Arena*) \ + \ + c2_nonstatic_field(Node_List, _cnt, uint) \ + \ + c2_nonstatic_field(Node_Array, _max, uint) \ + c2_nonstatic_field(Node_Array, _nodes, Node**) \ + c2_nonstatic_field(Node_Array, _a, Arena*) \ + \ \ /*********************/ \ /* -XX flags */ \ @@ -935,6 +1182,7 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(Flag, name, const char*) \ unchecked_nonstatic_field(Flag, addr, sizeof(void*)) /* NOTE: no type */ \ nonstatic_field(Flag, kind, const char*) \ + nonstatic_field(Flag, origin, FlagValueOrigin) \ static_field(Flag, flags, Flag*) \ static_field(Flag, numFlags, size_t) \ \ @@ -952,7 +1200,14 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(JDK_Version, _partially_initialized, bool) \ nonstatic_field(JDK_Version, _major, unsigned char) \ \ + /*************************/ \ + /* JVMTI */ \ + /*************************/ \ \ + static_field(JvmtiExport, _can_access_local_variables, bool) \ + static_field(JvmtiExport, _can_hotswap_or_post_breakpoint, bool) \ + static_field(JvmtiExport, _can_post_on_exceptions, bool) \ + static_field(JvmtiExport, _can_walk_any_space, bool) \ \ /*************/ \ /* Arguments */ \ @@ -978,10 +1233,26 @@ static inline uint64_t cast_uint64_t(size_t x) /* Miscellaneous fields */ \ /************************/ \ \ - nonstatic_field(AccessFlags, _flags, jint) \ - nonstatic_field(elapsedTimer, _counter, jlong) \ - nonstatic_field(elapsedTimer, _active, bool) \ - nonstatic_field(InvocationCounter, _counter, unsigned int) + nonstatic_field(CompileTask, _method, jobject) \ + nonstatic_field(CompileTask, _osr_bci, int) \ + nonstatic_field(CompileTask, _comp_level, int) \ + nonstatic_field(CompileTask, _compile_id, uint) \ + nonstatic_field(CompileTask, _next, CompileTask*) \ + nonstatic_field(CompileTask, _prev, CompileTask*) \ + \ + nonstatic_field(vframeArray, _next, vframeArray*) \ + nonstatic_field(vframeArray, _original, frame) \ + nonstatic_field(vframeArray, _caller, frame) \ + nonstatic_field(vframeArray, _frames, int) \ + \ + nonstatic_field(vframeArrayElement, _frame, frame) \ + nonstatic_field(vframeArrayElement, _bci, int) \ + nonstatic_field(vframeArrayElement, _method, methodOop) \ + \ + nonstatic_field(AccessFlags, _flags, jint) \ + nonstatic_field(elapsedTimer, _counter, jlong) \ + nonstatic_field(elapsedTimer, _active, bool) \ + nonstatic_field(InvocationCounter, _counter, unsigned int) /* NOTE that we do not use the last_entry() macro here; it is used */ /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ @@ -1061,11 +1332,14 @@ static inline uint64_t cast_uint64_t(size_t x) /* and are valid types for Fields. */ \ /*********************************************************************/ \ declare_integer_type(bool) \ + declare_integer_type(short) \ declare_integer_type(int) \ declare_integer_type(long) \ declare_integer_type(char) \ declare_unsigned_integer_type(unsigned char) \ + declare_unsigned_integer_type(u_char) \ declare_unsigned_integer_type(unsigned int) \ + declare_unsigned_integer_type(uint) \ declare_unsigned_integer_type(unsigned short) \ declare_unsigned_integer_type(unsigned long) \ /* The compiler thinks this is a different type than */ \ @@ -1080,7 +1354,6 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(int*) \ declare_toplevel_type(char*) \ declare_toplevel_type(char**) \ - declare_toplevel_type(const char*) \ declare_toplevel_type(u_char*) \ declare_toplevel_type(unsigned char*) \ \ @@ -1092,14 +1365,12 @@ static inline uint64_t cast_uint64_t(size_t x) \ declare_unsigned_integer_type(size_t) \ declare_integer_type(ssize_t) \ - declare_unsigned_integer_type(const size_t) \ declare_integer_type(intx) \ declare_integer_type(intptr_t) \ declare_unsigned_integer_type(uintx) \ declare_unsigned_integer_type(uintptr_t) \ declare_unsigned_integer_type(uint32_t) \ declare_unsigned_integer_type(uint64_t) \ - declare_integer_type(const int) \ \ /*******************************************************************************/ \ /* OopDesc and Klass hierarchies (NOTE: missing methodDataOop-related classes) */ \ @@ -1125,8 +1396,8 @@ static inline uint64_t cast_uint64_t(size_t x) declare_type(klassKlass, Klass) \ declare_type(klassOopDesc, oopDesc) \ declare_type(markOopDesc, oopDesc) \ - declare_type(methodDataKlass, Klass) \ - declare_type(methodDataOopDesc, oopDesc) \ + declare_type(methodDataKlass, Klass) \ + declare_type(methodDataOopDesc, oopDesc) \ declare_type(methodKlass, Klass) \ declare_type(constMethodKlass, Klass) \ declare_type(methodOopDesc, oopDesc) \ @@ -1140,6 +1411,8 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(Symbol) \ declare_toplevel_type(Symbol*) \ \ + declare_toplevel_type(nmethodBucket) \ + \ /********/ \ /* Oops */ \ /********/ \ @@ -1207,7 +1480,6 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(GenerationSpec) \ declare_toplevel_type(HeapWord) \ declare_toplevel_type(MemRegion) \ - declare_toplevel_type(const MemRegion) \ declare_toplevel_type(PermanentGenerationSpec) \ declare_toplevel_type(ThreadLocalAllocBuffer) \ declare_toplevel_type(VirtualSpace) \ @@ -1268,6 +1540,12 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(SystemDictionary) \ declare_toplevel_type(ProtectionDomainEntry) \ \ + declare_toplevel_type(GenericGrowableArray) \ + declare_toplevel_type(GrowableArray) \ + declare_toplevel_type(Arena) \ + declare_type(ResourceArea, Arena) \ + declare_toplevel_type(Chunk) \ + \ /***********************************************************/ \ /* Thread hierarchy (needed for run-time type information) */ \ /***********************************************************/ \ @@ -1280,7 +1558,7 @@ static inline uint64_t cast_uint64_t(size_t x) declare_type(JavaThread, Thread) \ declare_type(JvmtiAgentThread, JavaThread) \ declare_type(ServiceThread, JavaThread) \ - declare_type(CompilerThread, JavaThread) \ + declare_type(CompilerThread, JavaThread) \ declare_toplevel_type(OSThread) \ declare_toplevel_type(JavaFrameAnchor) \ \ @@ -1346,6 +1624,11 @@ static inline uint64_t cast_uint64_t(size_t x) /***************************************/ \ \ declare_toplevel_type(PcDesc) \ + declare_toplevel_type(ExceptionCache) \ + declare_toplevel_type(PcDescCache) \ + declare_toplevel_type(Dependencies) \ + declare_toplevel_type(CompileTask) \ + declare_toplevel_type(Deoptimization) \ \ /************************/ \ /* OopMap and OopMapSet */ \ @@ -1372,6 +1655,7 @@ static inline uint64_t cast_uint64_t(size_t x) \ declare_toplevel_type(JNIHandles) \ declare_toplevel_type(JNIHandleBlock) \ + declare_toplevel_type(jobject) \ \ /**********************/ \ /* Runtime1 (C1 only) */ \ @@ -1392,9 +1676,349 @@ static inline uint64_t cast_uint64_t(size_t x) /* Matcher (C2 only) */ \ /*********************/ \ \ - /* NOTE: this is not really a toplevel type, but we only need */ \ - /* this one -- FIXME later if necessary */ \ declare_c2_toplevel_type(Matcher) \ + declare_c2_toplevel_type(Compile) \ + declare_c2_toplevel_type(InlineTree) \ + declare_c2_toplevel_type(OptoRegPair) \ + declare_c2_toplevel_type(JVMState) \ + declare_c2_toplevel_type(Phase) \ + declare_c2_type(PhaseCFG, Phase) \ + declare_c2_type(PhaseRegAlloc, Phase) \ + declare_c2_type(PhaseChaitin, PhaseRegAlloc) \ + declare_c2_toplevel_type(CFGElement) \ + declare_c2_type(Block, CFGElement) \ + declare_c2_toplevel_type(Block_Array) \ + declare_c2_type(Block_List, Block_Array) \ + declare_c2_toplevel_type(Node_Array) \ + declare_c2_type(Node_List, Node_Array) \ + declare_c2_type(Unique_Node_List, Node_List) \ + declare_c2_toplevel_type(Node) \ + declare_c2_type(AddNode, Node) \ + declare_c2_type(AddINode, AddNode) \ + declare_c2_type(AddLNode, AddNode) \ + declare_c2_type(AddFNode, AddNode) \ + declare_c2_type(AddDNode, AddNode) \ + declare_c2_type(AddPNode, Node) \ + declare_c2_type(OrINode, AddNode) \ + declare_c2_type(OrLNode, AddNode) \ + declare_c2_type(XorINode, AddNode) \ + declare_c2_type(XorLNode, AddNode) \ + declare_c2_type(MaxNode, AddNode) \ + declare_c2_type(MaxINode, MaxNode) \ + declare_c2_type(MinINode, MaxNode) \ + declare_c2_type(StartNode, MultiNode) \ + declare_c2_type(StartOSRNode, StartNode) \ + declare_c2_type(ParmNode, ProjNode) \ + declare_c2_type(ReturnNode, Node) \ + declare_c2_type(RethrowNode, Node) \ + declare_c2_type(TailCallNode, ReturnNode) \ + declare_c2_type(TailJumpNode, ReturnNode) \ + declare_c2_type(SafePointNode, MultiNode) \ + declare_c2_type(CallNode, SafePointNode) \ + declare_c2_type(CallJavaNode, CallNode) \ + declare_c2_type(CallStaticJavaNode, CallJavaNode) \ + declare_c2_type(CallDynamicJavaNode, CallJavaNode) \ + declare_c2_type(CallRuntimeNode, CallNode) \ + declare_c2_type(CallLeafNode, CallRuntimeNode) \ + declare_c2_type(CallLeafNoFPNode, CallLeafNode) \ + declare_c2_type(AllocateNode, CallNode) \ + declare_c2_type(AllocateArrayNode, AllocateNode) \ + declare_c2_type(LockNode, AbstractLockNode) \ + declare_c2_type(UnlockNode, AbstractLockNode) \ + declare_c2_type(FastLockNode, CmpNode) \ + declare_c2_type(FastUnlockNode, CmpNode) \ + declare_c2_type(RegionNode, Node) \ + declare_c2_type(JProjNode, ProjNode) \ + declare_c2_type(PhiNode, TypeNode) \ + declare_c2_type(GotoNode, Node) \ + declare_c2_type(CProjNode, ProjNode) \ + declare_c2_type(MultiBranchNode, MultiNode) \ + declare_c2_type(IfNode, MultiBranchNode) \ + declare_c2_type(IfTrueNode, CProjNode) \ + declare_c2_type(IfFalseNode, CProjNode) \ + declare_c2_type(PCTableNode, MultiBranchNode) \ + declare_c2_type(JumpNode, PCTableNode) \ + declare_c2_type(JumpProjNode, JProjNode) \ + declare_c2_type(CatchNode, PCTableNode) \ + declare_c2_type(CatchProjNode, CProjNode) \ + declare_c2_type(CreateExNode, TypeNode) \ + declare_c2_type(ClearArrayNode, Node) \ + declare_c2_type(NeverBranchNode, MultiBranchNode) \ + declare_c2_type(ConNode, TypeNode) \ + declare_c2_type(ConINode, ConNode) \ + declare_c2_type(ConPNode, ConNode) \ + declare_c2_type(ConNNode, ConNode) \ + declare_c2_type(ConLNode, ConNode) \ + declare_c2_type(ConFNode, ConNode) \ + declare_c2_type(ConDNode, ConNode) \ + declare_c2_type(BinaryNode, Node) \ + declare_c2_type(CMoveNode, TypeNode) \ + declare_c2_type(CMoveDNode, CMoveNode) \ + declare_c2_type(CMoveFNode, CMoveNode) \ + declare_c2_type(CMoveINode, CMoveNode) \ + declare_c2_type(CMoveLNode, CMoveNode) \ + declare_c2_type(CMovePNode, CMoveNode) \ + declare_c2_type(CMoveNNode, CMoveNode) \ + declare_c2_type(EncodePNode, TypeNode) \ + declare_c2_type(DecodeNNode, TypeNode) \ + declare_c2_type(ConstraintCastNode, TypeNode) \ + declare_c2_type(CastIINode, ConstraintCastNode) \ + declare_c2_type(CastPPNode, ConstraintCastNode) \ + declare_c2_type(CheckCastPPNode, TypeNode) \ + declare_c2_type(Conv2BNode, Node) \ + declare_c2_type(ConvD2FNode, Node) \ + declare_c2_type(ConvD2INode, Node) \ + declare_c2_type(ConvD2LNode, Node) \ + declare_c2_type(ConvF2DNode, Node) \ + declare_c2_type(ConvF2INode, Node) \ + declare_c2_type(ConvF2LNode, Node) \ + declare_c2_type(ConvI2DNode, Node) \ + declare_c2_type(ConvI2FNode, Node) \ + declare_c2_type(ConvI2LNode, TypeNode) \ + declare_c2_type(ConvL2DNode, Node) \ + declare_c2_type(ConvL2FNode, Node) \ + declare_c2_type(ConvL2INode, Node) \ + declare_c2_type(CastX2PNode, Node) \ + declare_c2_type(CastP2XNode, Node) \ + declare_c2_type(MemBarNode, MultiNode) \ + declare_c2_type(MemBarAcquireNode, MemBarNode) \ + declare_c2_type(MemBarReleaseNode, MemBarNode) \ + declare_c2_type(MemBarVolatileNode, MemBarNode) \ + declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ + declare_c2_type(InitializeNode, MemBarNode) \ + declare_c2_type(ThreadLocalNode, Node) \ + declare_c2_type(Opaque1Node, Node) \ + declare_c2_type(Opaque2Node, Node) \ + declare_c2_type(PartialSubtypeCheckNode, Node) \ + declare_c2_type(MoveI2FNode, Node) \ + declare_c2_type(MoveL2DNode, Node) \ + declare_c2_type(MoveF2INode, Node) \ + declare_c2_type(MoveD2LNode, Node) \ + declare_c2_type(DivINode, Node) \ + declare_c2_type(DivLNode, Node) \ + declare_c2_type(DivFNode, Node) \ + declare_c2_type(DivDNode, Node) \ + declare_c2_type(ModINode, Node) \ + declare_c2_type(ModLNode, Node) \ + declare_c2_type(ModFNode, Node) \ + declare_c2_type(ModDNode, Node) \ + declare_c2_type(DivModNode, MultiNode) \ + declare_c2_type(DivModINode, DivModNode) \ + declare_c2_type(DivModLNode, DivModNode) \ + declare_c2_type(BoxLockNode, Node) \ + declare_c2_type(LoopNode, RegionNode) \ + declare_c2_type(CountedLoopNode, LoopNode) \ + declare_c2_type(CountedLoopEndNode, IfNode) \ + declare_c2_type(MachNode, Node) \ + declare_c2_type(MachIdealNode, MachNode) \ + declare_c2_type(MachTypeNode, MachNode) \ + declare_c2_type(MachBreakpointNode, MachIdealNode) \ + declare_c2_type(MachUEPNode, MachIdealNode) \ + declare_c2_type(MachPrologNode, MachIdealNode) \ + declare_c2_type(MachEpilogNode, MachIdealNode) \ + declare_c2_type(MachNopNode, MachIdealNode) \ + declare_c2_type(MachSpillCopyNode, MachIdealNode) \ + declare_c2_type(MachNullCheckNode, MachIdealNode) \ + declare_c2_type(MachProjNode, ProjNode) \ + declare_c2_type(MachIfNode, MachNode) \ + declare_c2_type(MachFastLockNode, MachNode) \ + declare_c2_type(MachReturnNode, MachNode) \ + declare_c2_type(MachSafePointNode, MachReturnNode) \ + declare_c2_type(MachCallNode, MachSafePointNode) \ + declare_c2_type(MachCallJavaNode, MachCallNode) \ + declare_c2_type(MachCallStaticJavaNode, MachCallJavaNode) \ + declare_c2_type(MachCallDynamicJavaNode, MachCallJavaNode) \ + declare_c2_type(MachCallRuntimeNode, MachCallNode) \ + declare_c2_type(MachHaltNode, MachReturnNode) \ + declare_c2_type(MachTempNode, MachNode) \ + declare_c2_type(MemNode, Node) \ + declare_c2_type(MergeMemNode, Node) \ + declare_c2_type(LoadNode, MemNode) \ + declare_c2_type(LoadBNode, LoadNode) \ + declare_c2_type(LoadUSNode, LoadNode) \ + declare_c2_type(LoadINode, LoadNode) \ + declare_c2_type(LoadRangeNode, LoadINode) \ + declare_c2_type(LoadLNode, LoadNode) \ + declare_c2_type(LoadL_unalignedNode, LoadLNode) \ + declare_c2_type(LoadFNode, LoadNode) \ + declare_c2_type(LoadDNode, LoadNode) \ + declare_c2_type(LoadD_unalignedNode, LoadDNode) \ + declare_c2_type(LoadPNode, LoadNode) \ + declare_c2_type(LoadNNode, LoadNode) \ + declare_c2_type(LoadKlassNode, LoadPNode) \ + declare_c2_type(LoadNKlassNode, LoadNNode) \ + declare_c2_type(LoadSNode, LoadNode) \ + declare_c2_type(StoreNode, MemNode) \ + declare_c2_type(StoreBNode, StoreNode) \ + declare_c2_type(StoreCNode, StoreNode) \ + declare_c2_type(StoreINode, StoreNode) \ + declare_c2_type(StoreLNode, StoreNode) \ + declare_c2_type(StoreFNode, StoreNode) \ + declare_c2_type(StoreDNode, StoreNode) \ + declare_c2_type(StorePNode, StoreNode) \ + declare_c2_type(StoreNNode, StoreNode) \ + declare_c2_type(StoreCMNode, StoreNode) \ + declare_c2_type(LoadPLockedNode, LoadPNode) \ + declare_c2_type(LoadLLockedNode, LoadLNode) \ + declare_c2_type(SCMemProjNode, ProjNode) \ + declare_c2_type(LoadStoreNode, Node) \ + declare_c2_type(StorePConditionalNode, LoadStoreNode) \ + declare_c2_type(StoreLConditionalNode, LoadStoreNode) \ + declare_c2_type(CompareAndSwapLNode, LoadStoreNode) \ + declare_c2_type(CompareAndSwapINode, LoadStoreNode) \ + declare_c2_type(CompareAndSwapPNode, LoadStoreNode) \ + declare_c2_type(CompareAndSwapNNode, LoadStoreNode) \ + declare_c2_type(PrefetchReadNode, Node) \ + declare_c2_type(PrefetchWriteNode, Node) \ + declare_c2_type(MulNode, Node) \ + declare_c2_type(MulINode, MulNode) \ + declare_c2_type(MulLNode, MulNode) \ + declare_c2_type(MulFNode, MulNode) \ + declare_c2_type(MulDNode, MulNode) \ + declare_c2_type(MulHiLNode, Node) \ + declare_c2_type(AndINode, MulINode) \ + declare_c2_type(AndLNode, MulLNode) \ + declare_c2_type(LShiftINode, Node) \ + declare_c2_type(LShiftLNode, Node) \ + declare_c2_type(RShiftINode, Node) \ + declare_c2_type(RShiftLNode, Node) \ + declare_c2_type(URShiftINode, Node) \ + declare_c2_type(URShiftLNode, Node) \ + declare_c2_type(MultiNode, Node) \ + declare_c2_type(ProjNode, Node) \ + declare_c2_type(TypeNode, Node) \ + declare_c2_type(NodeHash, StackObj) \ + declare_c2_type(RootNode, LoopNode) \ + declare_c2_type(HaltNode, Node) \ + declare_c2_type(SubNode, Node) \ + declare_c2_type(SubINode, SubNode) \ + declare_c2_type(SubLNode, SubNode) \ + declare_c2_type(SubFPNode, SubNode) \ + declare_c2_type(SubFNode, SubFPNode) \ + declare_c2_type(SubDNode, SubFPNode) \ + declare_c2_type(CmpNode, SubNode) \ + declare_c2_type(CmpINode, CmpNode) \ + declare_c2_type(CmpUNode, CmpNode) \ + declare_c2_type(CmpPNode, CmpNode) \ + declare_c2_type(CmpNNode, CmpNode) \ + declare_c2_type(CmpLNode, CmpNode) \ + declare_c2_type(CmpL3Node, CmpLNode) \ + declare_c2_type(CmpFNode, CmpNode) \ + declare_c2_type(CmpF3Node, CmpFNode) \ + declare_c2_type(CmpDNode, CmpNode) \ + declare_c2_type(CmpD3Node, CmpDNode) \ + declare_c2_type(BoolNode, Node) \ + declare_c2_type(AbsNode, Node) \ + declare_c2_type(AbsINode, AbsNode) \ + declare_c2_type(AbsFNode, AbsNode) \ + declare_c2_type(AbsDNode, AbsNode) \ + declare_c2_type(CmpLTMaskNode, Node) \ + declare_c2_type(NegNode, Node) \ + declare_c2_type(NegFNode, NegNode) \ + declare_c2_type(NegDNode, NegNode) \ + declare_c2_type(CosDNode, Node) \ + declare_c2_type(SinDNode, Node) \ + declare_c2_type(TanDNode, Node) \ + declare_c2_type(AtanDNode, Node) \ + declare_c2_type(SqrtDNode, Node) \ + declare_c2_type(ExpDNode, Node) \ + declare_c2_type(LogDNode, Node) \ + declare_c2_type(Log10DNode, Node) \ + declare_c2_type(PowDNode, Node) \ + declare_c2_type(ReverseBytesINode, Node) \ + declare_c2_type(ReverseBytesLNode, Node) \ + declare_c2_type(VectorNode, Node) \ + declare_c2_type(AddVBNode, VectorNode) \ + declare_c2_type(AddVCNode, VectorNode) \ + declare_c2_type(AddVSNode, VectorNode) \ + declare_c2_type(AddVINode, VectorNode) \ + declare_c2_type(AddVLNode, VectorNode) \ + declare_c2_type(AddVFNode, VectorNode) \ + declare_c2_type(AddVDNode, VectorNode) \ + declare_c2_type(SubVBNode, VectorNode) \ + declare_c2_type(SubVCNode, VectorNode) \ + declare_c2_type(SubVSNode, VectorNode) \ + declare_c2_type(SubVINode, VectorNode) \ + declare_c2_type(SubVLNode, VectorNode) \ + declare_c2_type(SubVFNode, VectorNode) \ + declare_c2_type(SubVDNode, VectorNode) \ + declare_c2_type(MulVFNode, VectorNode) \ + declare_c2_type(MulVDNode, VectorNode) \ + declare_c2_type(DivVFNode, VectorNode) \ + declare_c2_type(DivVDNode, VectorNode) \ + declare_c2_type(LShiftVBNode, VectorNode) \ + declare_c2_type(LShiftVCNode, VectorNode) \ + declare_c2_type(LShiftVSNode, VectorNode) \ + declare_c2_type(LShiftVINode, VectorNode) \ + declare_c2_type(URShiftVBNode, VectorNode) \ + declare_c2_type(URShiftVCNode, VectorNode) \ + declare_c2_type(URShiftVSNode, VectorNode) \ + declare_c2_type(URShiftVINode, VectorNode) \ + declare_c2_type(AndVNode, VectorNode) \ + declare_c2_type(OrVNode, VectorNode) \ + declare_c2_type(XorVNode, VectorNode) \ + declare_c2_type(VectorLoadNode, LoadNode) \ + declare_c2_type(Load16BNode, VectorLoadNode) \ + declare_c2_type(Load8BNode, VectorLoadNode) \ + declare_c2_type(Load4BNode, VectorLoadNode) \ + declare_c2_type(Load8CNode, VectorLoadNode) \ + declare_c2_type(Load4CNode, VectorLoadNode) \ + declare_c2_type(Load2CNode, VectorLoadNode) \ + declare_c2_type(Load8SNode, VectorLoadNode) \ + declare_c2_type(Load4SNode, VectorLoadNode) \ + declare_c2_type(Load2SNode, VectorLoadNode) \ + declare_c2_type(Load4INode, VectorLoadNode) \ + declare_c2_type(Load2INode, VectorLoadNode) \ + declare_c2_type(Load2LNode, VectorLoadNode) \ + declare_c2_type(Load4FNode, VectorLoadNode) \ + declare_c2_type(Load2FNode, VectorLoadNode) \ + declare_c2_type(Load2DNode, VectorLoadNode) \ + declare_c2_type(VectorStoreNode, StoreNode) \ + declare_c2_type(Store16BNode, VectorStoreNode) \ + declare_c2_type(Store8BNode, VectorStoreNode) \ + declare_c2_type(Store4BNode, VectorStoreNode) \ + declare_c2_type(Store8CNode, VectorStoreNode) \ + declare_c2_type(Store4CNode, VectorStoreNode) \ + declare_c2_type(Store2CNode, VectorStoreNode) \ + declare_c2_type(Store4INode, VectorStoreNode) \ + declare_c2_type(Store2INode, VectorStoreNode) \ + declare_c2_type(Store2LNode, VectorStoreNode) \ + declare_c2_type(Store4FNode, VectorStoreNode) \ + declare_c2_type(Store2FNode, VectorStoreNode) \ + declare_c2_type(Store2DNode, VectorStoreNode) \ + declare_c2_type(Replicate16BNode, VectorNode) \ + declare_c2_type(Replicate8BNode, VectorNode) \ + declare_c2_type(Replicate4BNode, VectorNode) \ + declare_c2_type(Replicate8CNode, VectorNode) \ + declare_c2_type(Replicate4CNode, VectorNode) \ + declare_c2_type(Replicate2CNode, VectorNode) \ + declare_c2_type(Replicate8SNode, VectorNode) \ + declare_c2_type(Replicate4SNode, VectorNode) \ + declare_c2_type(Replicate2SNode, VectorNode) \ + declare_c2_type(Replicate4INode, VectorNode) \ + declare_c2_type(Replicate2INode, VectorNode) \ + declare_c2_type(Replicate2LNode, VectorNode) \ + declare_c2_type(Replicate4FNode, VectorNode) \ + declare_c2_type(Replicate2FNode, VectorNode) \ + declare_c2_type(Replicate2DNode, VectorNode) \ + declare_c2_type(PackNode, VectorNode) \ + declare_c2_type(PackBNode, PackNode) \ + declare_c2_type(PackCNode, PackNode) \ + declare_c2_type(PackSNode, PackNode) \ + declare_c2_type(PackINode, PackNode) \ + declare_c2_type(PackLNode, PackNode) \ + declare_c2_type(PackFNode, PackNode) \ + declare_c2_type(PackDNode, PackNode) \ + declare_c2_type(Pack2x1BNode, PackNode) \ + declare_c2_type(Pack2x2BNode, PackNode) \ + declare_c2_type(ExtractNode, Node) \ + declare_c2_type(ExtractBNode, ExtractNode) \ + declare_c2_type(ExtractCNode, ExtractNode) \ + declare_c2_type(ExtractSNode, ExtractNode) \ + declare_c2_type(ExtractINode, ExtractNode) \ + declare_c2_type(ExtractLNode, ExtractNode) \ + declare_c2_type(ExtractFNode, ExtractNode) \ + declare_c2_type(ExtractDNode, ExtractNode) \ \ /*********************/ \ /* Adapter Blob Entries */ \ @@ -1402,6 +2026,32 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(AdapterHandlerEntry) \ declare_toplevel_type(AdapterHandlerEntry*) \ \ + /*********************/ \ + /* CI */ \ + /*********************/ \ + declare_toplevel_type(ciEnv) \ + declare_toplevel_type(ciObjectFactory) \ + declare_toplevel_type(ciConstant) \ + declare_toplevel_type(ciField) \ + declare_toplevel_type(void*) \ + declare_toplevel_type(ciObject) \ + declare_type(ciMethod, ciObject) \ + declare_type(ciMethodData, ciObject) \ + declare_type(ciType, ciObject) \ + declare_type(ciInstance, ciObject) \ + declare_toplevel_type(ciSymbol) \ + declare_type(ciKlass, ciType) \ + declare_type(ciInstanceKlass, ciKlass) \ + declare_type(ciArrayKlass, ciKlass) \ + declare_type(ciTypeArrayKlass, ciArrayKlass) \ + declare_type(ciObjArrayKlass, ciArrayKlass) \ + declare_type(ciMethodKlass, ciKlass) \ + declare_type(ciKlassKlass, ciKlass) \ + declare_type(ciInstanceKlassKlass, ciKlassKlass) \ + declare_type(ciArrayKlassKlass, ciKlassKlass) \ + declare_type(ciTypeArrayKlassKlass, ciArrayKlassKlass) \ + declare_type(ciObjArrayKlassKlass, ciArrayKlassKlass) \ + \ /********************/ \ /* -XX flags */ \ /********************/ \ @@ -1410,6 +2060,12 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(Flag*) \ \ /********************/ \ + /* JVMTI */ \ + /********************/ \ + \ + declare_toplevel_type(JvmtiExport) \ + \ + /********************/ \ /* JDK/VM version */ \ /********************/ \ \ @@ -1435,19 +2091,24 @@ static inline uint64_t cast_uint64_t(size_t x) declare_integer_type(Location::Type) \ declare_integer_type(Location::Where) \ declare_integer_type(PermGen::Name) \ + declare_integer_type(FlagValueOrigin) \ + COMPILER2_PRESENT(declare_integer_type(OptoReg::Name)) \ \ declare_integer_type(AccessFlags) /* FIXME: wrong type (not integer) */\ declare_toplevel_type(address) /* FIXME: should this be an integer type? */\ + declare_integer_type(BasicType) /* FIXME: wrong type (not integer) */\ declare_toplevel_type(BreakpointInfo) \ declare_toplevel_type(BreakpointInfo*) \ declare_toplevel_type(CodeBlob*) \ declare_toplevel_type(CompressedWriteStream*) \ declare_toplevel_type(ConstantPoolCacheEntry) \ declare_toplevel_type(elapsedTimer) \ + declare_toplevel_type(frame) \ declare_toplevel_type(intptr_t*) \ declare_unsigned_integer_type(InvocationCounter) /* FIXME: wrong type (not integer) */ \ declare_toplevel_type(JavaThread*) \ declare_toplevel_type(java_lang_Class) \ + declare_integer_type(JavaThread::AsyncRequests) \ declare_toplevel_type(jbyte*) \ declare_toplevel_type(jbyte**) \ declare_toplevel_type(jint*) \ @@ -1460,6 +2121,7 @@ static inline uint64_t cast_uint64_t(size_t x) declare_toplevel_type(jmethodID*) \ declare_toplevel_type(Mutex*) \ declare_toplevel_type(nmethod*) \ + COMPILER2_PRESENT(declare_unsigned_integer_type(node_idx_t)) \ declare_toplevel_type(ObjectMonitor*) \ declare_toplevel_type(oop*) \ declare_toplevel_type(OopMap**) \ @@ -1470,7 +2132,10 @@ static inline uint64_t cast_uint64_t(size_t x) declare_integer_type(ReferenceType) \ declare_toplevel_type(StubQueue*) \ declare_toplevel_type(Thread*) \ - declare_toplevel_type(Universe) + declare_toplevel_type(Universe) \ + declare_toplevel_type(vframeArray) \ + declare_toplevel_type(vframeArrayElement) + /* NOTE that we do not use the last_entry() macro here; it is used */ /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must be */ @@ -1775,6 +2440,27 @@ static inline uint64_t cast_uint64_t(size_t x) declare_constant(Location::on_stack) \ declare_constant(Location::in_register) \ \ + declare_constant(Deoptimization::Reason_many) \ + declare_constant(Deoptimization::Reason_none) \ + declare_constant(Deoptimization::Reason_null_check) \ + declare_constant(Deoptimization::Reason_null_assert) \ + declare_constant(Deoptimization::Reason_range_check) \ + declare_constant(Deoptimization::Reason_class_check) \ + declare_constant(Deoptimization::Reason_array_check) \ + declare_constant(Deoptimization::Reason_intrinsic) \ + declare_constant(Deoptimization::Reason_bimorphic) \ + declare_constant(Deoptimization::Reason_unloaded) \ + declare_constant(Deoptimization::Reason_uninitialized) \ + declare_constant(Deoptimization::Reason_unreached) \ + declare_constant(Deoptimization::Reason_unhandled) \ + declare_constant(Deoptimization::Reason_constraint) \ + declare_constant(Deoptimization::Reason_div0_check) \ + declare_constant(Deoptimization::Reason_age) \ + declare_constant(Deoptimization::Reason_predicate) \ + declare_constant(Deoptimization::Reason_loop_limit_check) \ + declare_constant(Deoptimization::Reason_LIMIT) \ + declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \ + \ /*********************/ \ /* Matcher (C2 only) */ \ /*********************/ \ @@ -2478,12 +3164,14 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool { VMTypeEntry* types = origtypes; while (types->typeName != NULL) { - if (!strcmp(typeName, types->typeName)) { + if (strcmp(typeName, types->typeName) == 0) { + // Found it return 1; } ++types; } } + // Search for the base type by peeling off const and * size_t len = strlen(typeName); if (typeName[len-1] == '*') { char * s = new char[len]; diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index 52540f31f65..f4ad5dd1c89 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -58,6 +58,8 @@ class JavaCallArguments; // include hierachy reasons). class ThreadShadow: public CHeapObj { + friend class VMStructs; + protected: oop _pending_exception; // Thread has gc actions. const char* _exception_file; // file information for exception (debugging only) diff --git a/hotspot/src/share/vm/utilities/growableArray.hpp b/hotspot/src/share/vm/utilities/growableArray.hpp index 9ee96394152..34972be8d4a 100644 --- a/hotspot/src/share/vm/utilities/growableArray.hpp +++ b/hotspot/src/share/vm/utilities/growableArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,6 +77,8 @@ extern "C" { } class GenericGrowableArray : public ResourceObj { + friend class VMStructs; + protected: int _len; // current length int _max; // maximum length @@ -136,6 +138,8 @@ class GenericGrowableArray : public ResourceObj { }; template class GrowableArray : public GenericGrowableArray { + friend class VMStructs; + private: E* _data; // data array From 95832db2e529961a8046c3653d4cc074399f76f8 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Tue, 20 Sep 2011 09:59:59 -0400 Subject: [PATCH 050/214] 7059019: G1: add G1 support to the SA Extend the SA to recognize the G1CollectedHeap and implement any code that's needed by our serviceability tools (jmap, jinfo, jstack, etc.) that depend on the SA. Reviewed-by: never, poonam, johnc --- hotspot/agent/make/Makefile | 6 +- .../gc_implementation/g1/G1CollectedHeap.java | 107 ++++++++++++++++++ .../gc_implementation/g1/HeapRegion.java | 66 +++++++++++ .../gc_implementation/g1/HeapRegionSeq.java | 102 +++++++++++++++++ .../gc_interface/CollectedHeapName.java | 3 +- .../sun/jvm/hotspot/memory/Universe.java | 4 +- .../sun/jvm/hotspot/oops/ObjectHeap.java | 27 +++-- .../sun/jvm/hotspot/tools/HeapSummary.java | 74 ++++++++---- hotspot/make/sa.files | 3 +- .../vm/gc_implementation/g1/heapRegionSeq.hpp | 1 + .../vm/gc_implementation/g1/vmStructs_g1.hpp | 54 +++++++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 15 +++ 12 files changed, 427 insertions(+), 35 deletions(-) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java create mode 100644 hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp diff --git a/hotspot/agent/make/Makefile b/hotspot/agent/make/Makefile index fc845ffd09a..c38c7864203 100644 --- a/hotspot/agent/make/Makefile +++ b/hotspot/agent/make/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,7 @@ sun.jvm.hotspot.debugger.windbg.ia64 \ sun.jvm.hotspot.debugger.windbg.x86 \ sun.jvm.hotspot.debugger.x86 \ sun.jvm.hotspot.gc_implementation \ +sun.jvm.hotspot.gc_implementation.g1 \ sun.jvm.hotspot.gc_implementation.parallelScavenge \ sun.jvm.hotspot.gc_implementation.shared \ sun.jvm.hotspot.gc_interface \ @@ -167,6 +168,9 @@ sun/jvm/hotspot/debugger/windbg/*.java \ sun/jvm/hotspot/debugger/windbg/ia64/*.java \ sun/jvm/hotspot/debugger/windbg/x86/*.java \ sun/jvm/hotspot/debugger/x86/*.java \ +sun/jvm/hotspot/gc_implementation/g1/*.java \ +sun/jvm/hotspot/gc_implementation/parallelScavenge/*.java \ +sun/jvm/hotspot/gc_implementation/shared/*.java \ sun/jvm/hotspot/interpreter/*.java \ sun/jvm/hotspot/jdi/*.java \ sun/jvm/hotspot/livejvm/*.java \ diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java new file mode 100644 index 00000000000..dfdd51099fa --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Iterator; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.gc_interface.CollectedHeapName; +import sun.jvm.hotspot.memory.MemRegion; +import sun.jvm.hotspot.memory.SharedHeap; +import sun.jvm.hotspot.memory.SpaceClosure; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for G1CollectedHeap. + +public class G1CollectedHeap extends SharedHeap { + // HeapRegionSeq _seq; + static private long hrsFieldOffset; + // MemRegion _g1_committed; + static private long g1CommittedFieldOffset; + // size_t _summary_bytes_used; + static private CIntegerField summaryBytesUsedField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("G1CollectedHeap"); + + hrsFieldOffset = type.getField("_hrs").getOffset(); + g1CommittedFieldOffset = type.getField("_g1_committed").getOffset(); + summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used"); + } + + public long capacity() { + Address g1CommittedAddr = addr.addOffsetTo(g1CommittedFieldOffset); + MemRegion g1_committed = new MemRegion(g1CommittedAddr); + return g1_committed.byteSize(); + } + + public long used() { + return summaryBytesUsedField.getValue(addr); + } + + public long n_regions() { + return hrs().length(); + } + + private HeapRegionSeq hrs() { + Address hrsAddr = addr.addOffsetTo(hrsFieldOffset); + return (HeapRegionSeq) VMObjectFactory.newObject(HeapRegionSeq.class, + hrsAddr); + } + + private Iterator heapRegionIterator() { + return hrs().heapRegionIterator(); + } + + public void heapRegionIterate(SpaceClosure scl) { + Iterator iter = heapRegionIterator(); + while (iter.hasNext()) { + HeapRegion hr = iter.next(); + scl.doSpace(hr); + } + } + + public CollectedHeapName kind() { + return CollectedHeapName.G1_COLLECTED_HEAP; + } + + public G1CollectedHeap(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java new file mode 100644 index 00000000000..4aa7620f730 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.memory.ContiguousSpace; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for HeapRegion. Currently we don't actually include +// any of its fields but only iterate over it (which we get "for free" +// as HeapRegion ultimately inherits from ContiguousSpace). + +public class HeapRegion extends ContiguousSpace { + // static int GrainBytes; + static private CIntegerField grainBytesField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("HeapRegion"); + + grainBytesField = type.getCIntegerField("GrainBytes"); + } + + static public long grainBytes() { + return grainBytesField.getValue(); + } + + public HeapRegion(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java new file mode 100644 index 00000000000..d0da28bdd8a --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Iterator; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for HeapRegionSeq. It's essentially an index -> HeapRegion map. + +public class HeapRegionSeq extends VMObject { + // HeapRegion** _regions; + static private AddressField regionsField; + // size_t _length; + static private CIntegerField lengthField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("HeapRegionSeq"); + + regionsField = type.getAddressField("_regions"); + lengthField = type.getCIntegerField("_length"); + } + + private HeapRegion at(long index) { + Address arrayAddr = regionsField.getValue(addr); + // Offset of &_region[index] + long offset = index * VM.getVM().getAddressSize(); + Address regionAddr = arrayAddr.getAddressAt(offset); + return (HeapRegion) VMObjectFactory.newObject(HeapRegion.class, + regionAddr); + } + + public long length() { + return lengthField.getValue(addr); + } + + private class HeapRegionIterator implements Iterator { + private long index; + private long length; + + @Override + public boolean hasNext() { return index < length; } + + @Override + public HeapRegion next() { return at(index++); } + + @Override + public void remove() { /* not supported */ } + + HeapRegionIterator(Address addr) { + index = 0; + length = length(); + } + } + + public Iterator heapRegionIterator() { + return new HeapRegionIterator(addr); + } + + public HeapRegionSeq(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_interface/CollectedHeapName.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_interface/CollectedHeapName.java index 1561a25fcdd..2e57740135a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_interface/CollectedHeapName.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_interface/CollectedHeapName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ public class CollectedHeapName { public static final CollectedHeapName ABSTRACT = new CollectedHeapName("abstract"); public static final CollectedHeapName SHARED_HEAP = new CollectedHeapName("SharedHeap"); public static final CollectedHeapName GEN_COLLECTED_HEAP = new CollectedHeapName("GenCollectedHeap"); + public static final CollectedHeapName G1_COLLECTED_HEAP = new CollectedHeapName("G1CollectedHeap"); public static final CollectedHeapName PARALLEL_SCAVENGE_HEAP = new CollectedHeapName("ParallelScavengeHeap"); public String toString() { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java index c25f7c7ff78..41f45a56c21 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.gc_interface.*; +import sun.jvm.hotspot.gc_implementation.g1.G1CollectedHeap; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; @@ -72,6 +73,7 @@ public class Universe { heapConstructor = new VirtualConstructor(db); heapConstructor.addMapping("GenCollectedHeap", GenCollectedHeap.class); heapConstructor.addMapping("ParallelScavengeHeap", ParallelScavengeHeap.class); + heapConstructor.addMapping("G1CollectedHeap", G1CollectedHeap.class); mainThreadGroupField = type.getOopField("_main_thread_group"); systemThreadGroupField = type.getOopField("_system_thread_group"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java index 749c49d1b91..961e16753a2 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @@ -33,6 +33,7 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.gc_interface.*; +import sun.jvm.hotspot.gc_implementation.g1.*; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; @@ -514,9 +515,16 @@ public class ObjectHeap { private void addPermGenLiveRegions(List output, CollectedHeap heap) { LiveRegionsCollector lrc = new LiveRegionsCollector(output); - if (heap instanceof GenCollectedHeap) { - GenCollectedHeap genHeap = (GenCollectedHeap) heap; - Generation gen = genHeap.permGen(); + if (heap instanceof SharedHeap) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(heap instanceof GenCollectedHeap || + heap instanceof G1CollectedHeap, + "Expecting GenCollectedHeap or G1CollectedHeap, " + + "but got " + heap.getClass().getName()); + } + // Handles both GenCollectedHeap and G1CollectedHeap + SharedHeap sharedHeap = (SharedHeap) heap; + Generation gen = sharedHeap.permGen(); gen.spaceIterate(lrc, true); } else if (heap instanceof ParallelScavengeHeap) { ParallelScavengeHeap psh = (ParallelScavengeHeap) heap; @@ -524,8 +532,9 @@ public class ObjectHeap { addLiveRegions(permGen.objectSpace().getLiveRegions(), output); } else { if (Assert.ASSERTS_ENABLED) { - Assert.that(false, "Expecting GenCollectedHeap or ParallelScavengeHeap, but got " + - heap.getClass().getName()); + Assert.that(false, + "Expecting SharedHeap or ParallelScavengeHeap, " + + "but got " + heap.getClass().getName()); } } } @@ -588,10 +597,14 @@ public class ObjectHeap { addLiveRegions(youngGen.fromSpace().getLiveRegions(), liveRegions); PSOldGen oldGen = psh.oldGen(); addLiveRegions(oldGen.objectSpace().getLiveRegions(), liveRegions); + } else if (heap instanceof G1CollectedHeap) { + G1CollectedHeap g1h = (G1CollectedHeap) heap; + g1h.heapRegionIterate(lrc); } else { if (Assert.ASSERTS_ENABLED) { - Assert.that(false, "Expecting GenCollectedHeap or ParallelScavengeHeap, but got " + - heap.getClass().getName()); + Assert.that(false, "Expecting GenCollectedHeap, G1CollectedHeap, " + + "or ParallelScavengeHeap, but got " + + heap.getClass().getName()); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index 3e2cfa31810..3be7f3da0f4 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,11 @@ package sun.jvm.hotspot.tools; import java.util.*; import sun.jvm.hotspot.gc_interface.*; +import sun.jvm.hotspot.gc_implementation.g1.*; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.gc_implementation.shared.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.tools.*; public class HeapSummary extends Tool { @@ -70,32 +70,50 @@ public class HeapSummary extends Tool { System.out.println(); System.out.println("Heap Usage:"); - if (heap instanceof GenCollectedHeap) { - GenCollectedHeap genHeap = (GenCollectedHeap) heap; - for (int n = 0; n < genHeap.nGens(); n++) { - Generation gen = genHeap.getGen(n); - if (gen instanceof sun.jvm.hotspot.memory.DefNewGeneration) { - System.out.println("New Generation (Eden + 1 Survivor Space):"); - printGen(gen); + if (heap instanceof SharedHeap) { + SharedHeap sharedHeap = (SharedHeap) heap; + if (sharedHeap instanceof GenCollectedHeap) { + GenCollectedHeap genHeap = (GenCollectedHeap) sharedHeap; + for (int n = 0; n < genHeap.nGens(); n++) { + Generation gen = genHeap.getGen(n); + if (gen instanceof sun.jvm.hotspot.memory.DefNewGeneration) { + System.out.println("New Generation (Eden + 1 Survivor Space):"); + printGen(gen); - ContiguousSpace eden = ((DefNewGeneration)gen).eden(); - System.out.println("Eden Space:"); - printSpace(eden); + ContiguousSpace eden = ((DefNewGeneration)gen).eden(); + System.out.println("Eden Space:"); + printSpace(eden); - ContiguousSpace from = ((DefNewGeneration)gen).from(); - System.out.println("From Space:"); - printSpace(from); + ContiguousSpace from = ((DefNewGeneration)gen).from(); + System.out.println("From Space:"); + printSpace(from); - ContiguousSpace to = ((DefNewGeneration)gen).to(); - System.out.println("To Space:"); - printSpace(to); - } else { - System.out.println(gen.name() + ":"); - printGen(gen); + ContiguousSpace to = ((DefNewGeneration)gen).to(); + System.out.println("To Space:"); + printSpace(to); + } else { + System.out.println(gen.name() + ":"); + printGen(gen); + } } + } else if (sharedHeap instanceof G1CollectedHeap) { + G1CollectedHeap g1h = (G1CollectedHeap) sharedHeap; + + System.out.println("Garbage-First (G1) Heap"); + long capacityBytes = g1h.capacity(); + long usedBytes = g1h.used(); + long freeBytes = capacityBytes - usedBytes; + printValMB("region size = ", HeapRegion.grainBytes()); + printValue("regions = ", g1h.n_regions()); + printValMB("capacity = ", capacityBytes); + printValMB("used = ", usedBytes); + printValMB("free = ", freeBytes); + System.out.println(alignment + (double) usedBytes * 100.0 / capacityBytes + "% used"); + } else { + throw new RuntimeException("unknown SharedHeap type : " + heap.getClass()); } - // Perm generation - Generation permGen = genHeap.permGen(); + // Perm generation shared by the above + Generation permGen = sharedHeap.permGen(); System.out.println("Perm Generation:"); printGen(permGen); } else if (heap instanceof ParallelScavengeHeap) { @@ -119,7 +137,7 @@ public class HeapSummary extends Tool { printValMB("free = ", permFree); System.out.println(alignment + (double)permGen.used() * 100.0 / permGen.capacity() + "% used"); } else { - throw new RuntimeException("unknown heap type : " + heap.getClass()); + throw new RuntimeException("unknown CollectedHeap type : " + heap.getClass()); } } @@ -151,6 +169,14 @@ public class HeapSummary extends Tool { return; } + l = getFlagValue("UseG1GC", flagMap); + if (l == 1L) { + System.out.print("Garbage-First (G1) GC "); + l = getFlagValue("ParallelGCThreads", flagMap); + System.out.println("with " + l + " thread(s)"); + return; + } + System.out.println("Mark Sweep Compact GC"); } diff --git a/hotspot/make/sa.files b/hotspot/make/sa.files index 92984320268..da4c669f3a6 100644 --- a/hotspot/make/sa.files +++ b/hotspot/make/sa.files @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -79,6 +79,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/amd64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/ia64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/x86/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/g1/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/parallelScavenge/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/shared/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_interface/*.java \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp index c47b64891d1..3df8d738bdc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp @@ -56,6 +56,7 @@ class FreeRegionList; // and maintain that: _length <= _allocated_length <= _max_length class HeapRegionSeq: public CHeapObj { + friend class VMStructs; // The array that holds the HeapRegions. HeapRegion** _regions; diff --git a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp new file mode 100644 index 00000000000..f85c76cee7b --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP + +#include "gc_implementation/g1/heapRegion.hpp" +#include "gc_implementation/g1/heapRegionSeq.inline.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" + +#define VM_STRUCTS_G1(nonstatic_field, static_field) \ + \ + static_field(HeapRegion, GrainBytes, int) \ + \ + nonstatic_field(HeapRegionSeq, _regions, HeapRegion**) \ + nonstatic_field(HeapRegionSeq, _length, size_t) \ + \ + nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \ + nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ + nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \ + + +#define VM_TYPES_G1(declare_type, declare_toplevel_type) \ + \ + declare_type(G1CollectedHeap, SharedHeap) \ + \ + declare_type(HeapRegion, ContiguousSpace) \ + declare_toplevel_type(HeapRegionSeq) \ + \ + declare_toplevel_type(G1CollectedHeap*) \ + declare_toplevel_type(HeapRegion*) \ + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 101d6f92fcd..2c1246145df 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -173,6 +173,7 @@ #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp" +#include "gc_implementation/g1/vmStructs_g1.hpp" #endif #ifdef COMPILER2 #include "opto/addnode.hpp" @@ -2855,6 +2856,9 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ GENERATE_STATIC_VM_STRUCT_ENTRY) + + VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + GENERATE_STATIC_VM_STRUCT_ENTRY) #endif // SERIALGC VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ @@ -2898,6 +2902,9 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_TOPLEVEL_VM_TYPE_ENTRY) VM_TYPES_PARNEW(GENERATE_VM_TYPE_ENTRY) + + VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY, + GENERATE_TOPLEVEL_VM_TYPE_ENTRY) #endif // SERIALGC VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, @@ -2997,6 +3004,9 @@ VMStructs::init() { VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); + + VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY, + CHECK_STATIC_VM_STRUCT_ENTRY); #endif // SERIALGC VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, @@ -3037,6 +3047,9 @@ VMStructs::init() { CHECK_SINGLE_ARG_VM_TYPE_NO_OP); VM_TYPES_PARNEW(CHECK_VM_TYPE_ENTRY) + + VM_TYPES_G1(CHECK_VM_TYPE_ENTRY, + CHECK_SINGLE_ARG_VM_TYPE_NO_OP); #endif // SERIALGC VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, @@ -3102,6 +3115,8 @@ VMStructs::init() { debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, \ ENSURE_FIELD_TYPE_PRESENT, \ ENSURE_FIELD_TYPE_PRESENT)); + debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, \ + ENSURE_FIELD_TYPE_PRESENT)); #endif // SERIALGC debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, \ ENSURE_FIELD_TYPE_PRESENT, \ From 3ae9021b5945675c93bf1796977011ece4cb8f74 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 20 Sep 2011 15:39:17 -0700 Subject: [PATCH 051/214] 7092412: G1: Some roots not marked during an initial mark that gets an evacuation failure As a result of the changes for 7080389, an evacuation failure during an initial mark pause may result in some root objects not being marked. Pass whether the caller is a root scanning closure into the evacuation failure handling code so that the thread that successfully forwards an object to itself also marks the object. Reviewed-by: ysr, brutisso, tonyp --- .../gc_implementation/g1/g1CollectedHeap.cpp | 38 ++++++++++++++++--- .../gc_implementation/g1/g1CollectedHeap.hpp | 3 +- .../vm/gc_implementation/g1/g1OopClosures.hpp | 3 +- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 9d628451002..146c28781f2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -3946,7 +3946,8 @@ void G1CollectedHeap::drain_evac_failure_scan_stack() { oop G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, - oop old) { + oop old, + bool should_mark_root) { assert(obj_in_cs(old), err_msg("obj: "PTR_FORMAT" should still be in the CSet", (HeapWord*) old)); @@ -3954,6 +3955,16 @@ G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop forward_ptr = old->forward_to_atomic(old); if (forward_ptr == NULL) { // Forward-to-self succeeded. + + // should_mark_root will be true when this routine is called + // from a root scanning closure during an initial mark pause. + // In this case the thread that succeeds in self-forwarding the + // object is also responsible for marking the object. + if (should_mark_root) { + assert(!oopDesc::is_null(old), "shouldn't be"); + _cm->grayRoot(old); + } + if (_evac_failure_closure != cl) { MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag); assert(!_drain_in_progress, @@ -4208,7 +4219,8 @@ template void G1ParCopyHelper::mark_object(T* p) { } } -oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) { +oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_root, + bool should_mark_copy) { size_t word_sz = old->size(); HeapRegion* from_region = _g1->heap_region_containing_raw(old); // +1 to make the -1 indexes valid... @@ -4228,7 +4240,7 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) { // This will either forward-to-self, or detect that someone else has // installed a forwarding pointer. OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); - return _g1->handle_evacuation_failure_par(cl, old); + return _g1->handle_evacuation_failure_par(cl, old, should_mark_root); } // We're going to allocate linearly, so might as well prefetch ahead. @@ -4330,11 +4342,26 @@ void G1ParCopyClosure // we also need to handle marking of roots in the // event of an evacuation failure. In the event of an // evacuation failure, the object is forwarded to itself - // and not copied so let's mark it here. + // and not copied. For root-scanning closures, the + // object would be marked after a successful self-forward + // but an object could be pointed to by both a root and non + // root location and be self-forwarded by a non-root-scanning + // closure. Therefore we also have to attempt to mark the + // self-forwarded root object here. if (do_mark_object && obj->forwardee() == obj) { mark_object(p); } } else { + // During an initial mark pause, objects that are pointed to + // by the roots need to be marked - even in the event of an + // evacuation failure. We pass the template parameter + // do_mark_object (which is true for root scanning closures + // during an initial mark pause) to copy_to_survivor_space + // which will pass it on to the evacuation failure handling + // code. The thread that successfully self-forwards a root + // object to itself is responsible for marking the object. + bool should_mark_root = do_mark_object; + // We need to mark the copied object if we're a root scanning // closure during an initial mark pause (i.e. do_mark_object // will be true), or the object is already marked and we need @@ -4343,7 +4370,8 @@ void G1ParCopyClosure _during_initial_mark || (_mark_in_progress && !_g1->is_obj_ill(obj)); - oop copy_oop = copy_to_survivor_space(obj, should_mark_copy); + oop copy_oop = copy_to_survivor_space(obj, should_mark_root, + should_mark_copy); oopDesc::encode_store_heap_oop(p, copy_oop); } // When scanning the RS, we only care about objs in CS. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 650e43887f6..6a361326f6d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -822,7 +822,8 @@ protected: void finalize_for_evac_failure(); // An attempt to evacuate "obj" has failed; take necessary steps. - oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); + oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj, + bool should_mark_root); void handle_evacuation_failure_common(oop obj, markOop m); // Instance of the concurrent mark is_alive closure for embedding diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index d3f1ce24c62..73d87a11c66 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -105,7 +105,8 @@ class G1ParCopyHelper : public G1ParClosureSuper { G1ParScanClosure *_scanner; protected: template void mark_object(T* p); - oop copy_to_survivor_space(oop obj, bool should_mark_copy); + oop copy_to_survivor_space(oop obj, bool should_mark_root, + bool should_mark_copy); public: G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, G1ParScanClosure *scanner) : From c5b2025c028684ab1dfde2dd66133f69ea9c45c5 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 21 Sep 2011 01:27:20 -0400 Subject: [PATCH 052/214] 7045232: G1: pool names are inconsistent with other collectors (don't have 'Space') Make sure the eden and survivor pools have "Space" in their name. Reviewed-by: jmasa, ysr --- hotspot/src/share/vm/services/g1MemoryPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/services/g1MemoryPool.cpp b/hotspot/src/share/vm/services/g1MemoryPool.cpp index ce64f0e3d13..a480c12b4dd 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.cpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.cpp @@ -73,7 +73,7 @@ size_t G1MemoryPoolSuper::old_space_used(G1CollectedHeap* g1h) { G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, - "G1 Eden", + "G1 Eden Space", eden_space_committed(g1h), /* init_size */ false /* support_usage_threshold */) { } @@ -88,7 +88,7 @@ MemoryUsage G1EdenPool::get_memory_usage() { G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, - "G1 Survivor", + "G1 Survivor Space", survivor_space_committed(g1h), /* init_size */ false /* support_usage_threshold */) { } From 2f83b52706e9eb37a2d3d5bc4bd73d65ff8531d7 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Wed, 21 Sep 2011 10:04:45 -0700 Subject: [PATCH 053/214] 7068215: G1: Print reference processing time during remark Displays the elapsed time taken to perform reference processing during remark as part of the PrintGCDetails output. Reviewed-by: ysr --- .../gc_implementation/g1/concurrentMark.cpp | 115 ++++++++++-------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 3679002b92f..183bd2b4490 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -2163,71 +2163,84 @@ void G1RefProcTaskExecutor::execute(EnqueueTask& enq_task) { void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { ResourceMark rm; HandleMark hm; - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - ReferenceProcessor* rp = g1h->ref_processor(); - // See the comment in G1CollectedHeap::ref_processing_init() - // about how reference processing currently works in G1. + G1CollectedHeap* g1h = G1CollectedHeap::heap(); - // Process weak references. - rp->setup_policy(clear_all_soft_refs); - assert(_markStack.isEmpty(), "mark stack should be empty"); + // Is alive closure. + G1CMIsAliveClosure g1_is_alive(g1h); - G1CMIsAliveClosure g1_is_alive(g1h); - G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); - G1CMDrainMarkingStackClosure - g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); - // We use the work gang from the G1CollectedHeap and we utilize all - // the worker threads. - int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; - active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); + // Inner scope to exclude the cleaning of the string and symbol + // tables from the displayed time. + { + bool verbose = PrintGC && PrintGCDetails; + if (verbose) { + gclog_or_tty->put(' '); + } + TraceTime t("GC ref-proc", verbose, false, gclog_or_tty); - G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), - g1h->workers(), active_workers); + ReferenceProcessor* rp = g1h->ref_processor(); + // See the comment in G1CollectedHeap::ref_processing_init() + // about how reference processing currently works in G1. - if (rp->processing_is_mt()) { - // Set the degree of MT here. If the discovery is done MT, there - // may have been a different number of threads doing the discovery - // and a different number of discovered lists may have Ref objects. - // That is OK as long as the Reference lists are balanced (see - // balance_all_queues() and balance_queues()). - rp->set_active_mt_degree(active_workers); + // Process weak references. + rp->setup_policy(clear_all_soft_refs); + assert(_markStack.isEmpty(), "mark stack should be empty"); - rp->process_discovered_references(&g1_is_alive, + G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); + G1CMDrainMarkingStackClosure + g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); + + // We use the work gang from the G1CollectedHeap and we utilize all + // the worker threads. + int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; + active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); + + G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), + g1h->workers(), active_workers); + + if (rp->processing_is_mt()) { + // Set the degree of MT here. If the discovery is done MT, there + // may have been a different number of threads doing the discovery + // and a different number of discovered lists may have Ref objects. + // That is OK as long as the Reference lists are balanced (see + // balance_all_queues() and balance_queues()). + rp->set_active_mt_degree(active_workers); + + rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, &g1_drain_mark_stack, &par_task_executor); - // The work routines of the parallel keep_alive and drain_marking_stack - // will set the has_overflown flag if we overflow the global marking - // stack. - } else { - rp->process_discovered_references(&g1_is_alive, - &g1_keep_alive, - &g1_drain_mark_stack, - NULL); + // The work routines of the parallel keep_alive and drain_marking_stack + // will set the has_overflown flag if we overflow the global marking + // stack. + } else { + rp->process_discovered_references(&g1_is_alive, + &g1_keep_alive, + &g1_drain_mark_stack, + NULL); + } + assert(_markStack.overflow() || _markStack.isEmpty(), + "mark stack should be empty (unless it overflowed)"); + if (_markStack.overflow()) { + // Should have been done already when we tried to push an + // entry on to the global mark stack. But let's do it again. + set_has_overflown(); + } + + if (rp->processing_is_mt()) { + assert(rp->num_q() == active_workers, "why not"); + rp->enqueue_discovered_references(&par_task_executor); + } else { + rp->enqueue_discovered_references(); + } + + rp->verify_no_references_recorded(); + assert(!rp->discovery_enabled(), "should have been disabled"); } - assert(_markStack.overflow() || _markStack.isEmpty(), - "mark stack should be empty (unless it overflowed)"); - if (_markStack.overflow()) { - // Should have been done already when we tried to push an - // entry on to the global mark stack. But let's do it again. - set_has_overflown(); - } - - if (rp->processing_is_mt()) { - assert(rp->num_q() == active_workers, "why not"); - rp->enqueue_discovered_references(&par_task_executor); - } else { - rp->enqueue_discovered_references(); - } - - rp->verify_no_references_recorded(); - assert(!rp->discovery_enabled(), "should have been disabled"); - // Now clean up stale oops in StringTable StringTable::unlink(&g1_is_alive); // Clean up unreferenced symbols in symbol table. From 0f7ff53cce849caf64e93f0fb2412bdebf6bdf1b Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 21 Sep 2011 13:36:37 -0400 Subject: [PATCH 054/214] 7091032: G1: assert failure when NewRatio is used The desired min / max heap sizes are miscalculated at initialization when NewRatio is used. The changeset also includes an additional small change to turn a print statement into a warning. Reviewed-by: johnc, jmasa, ysr, brutisso --- .../vm/gc_implementation/g1/g1CollectorPolicy.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index d43d080c7f4..92c47409a28 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -459,15 +459,16 @@ void G1CollectorPolicy::initialize_flags() { // ParallelScavengeHeap::initialize()). We might change this in the // future, but it's a good start. class G1YoungGenSizer : public TwoGenerationCollectorPolicy { +private: + size_t size_to_region_num(size_t byte_size) { + return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); + } public: G1YoungGenSizer() { initialize_flags(); initialize_size_info(); } - size_t size_to_region_num(size_t byte_size) { - return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); - } size_t min_young_region_num() { return size_to_region_num(_min_gen0_size); } @@ -501,11 +502,10 @@ void G1CollectorPolicy::init() { if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { - gclog_or_tty->print_cr("-XX:NewSize and -XX:MaxNewSize overrides -XX:NewRatio"); + warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { // Treat NewRatio as a fixed size that is only recalculated when the heap size changes - size_t heap_regions = sizer.size_to_region_num(_g1->n_regions()); - update_young_list_size_using_newratio(heap_regions); + update_young_list_size_using_newratio(_g1->n_regions()); _using_new_ratio_calculations = true; } } From 08bdb35a29be632ab8653cfc025f4a6a983446af Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Wed, 21 Sep 2011 15:24:07 -0700 Subject: [PATCH 055/214] 7092245: G1: Wrong format specifier in G1PrintRegionLivenessInfo header output Cast HeapRegion::GrainBytes to size_t in output statement. Reviewed-by: ysr, brutisso, pbk, tonyp --- .../share/vm/gc_implementation/g1/concurrentMark.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 183bd2b4490..61adccb1005 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -4566,7 +4566,7 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) G1PPRL_SUM_BYTE_FORMAT("region-size"), g1_committed.start(), g1_committed.end(), g1_reserved.start(), g1_reserved.end(), - HeapRegion::GrainBytes); + (size_t)HeapRegion::GrainBytes); _out->print_cr(G1PPRL_LINE_PREFIX); _out->print_cr(G1PPRL_LINE_PREFIX G1PPRL_TYPE_H_FORMAT @@ -4577,6 +4577,15 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) G1PPRL_DOUBLE_H_FORMAT, "type", "address-range", "used", "prev-live", "next-live", "gc-eff"); + _out->print_cr(G1PPRL_LINE_PREFIX + G1PPRL_TYPE_H_FORMAT + G1PPRL_ADDR_BASE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_DOUBLE_H_FORMAT, + "", "", + "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)"); } // It takes as a parameter a reference to one of the _hum_* fields, it From 70bb8e788e1b5760dd2dbc6bc50ef0e8428522a0 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Thu, 22 Sep 2011 07:18:51 -0400 Subject: [PATCH 056/214] 7092238: G1: Uninitialized field gc_efficiency in G1PrintRegionLivenessInfo output Reviewed-by: jcoomes, johnc --- hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index ec423143979..f199cd85f38 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -489,6 +489,7 @@ HeapRegion(size_t hrs_index, G1BlockOffsetSharedArray* sharedOffsetArray, _next_in_special_set(NULL), _orig_end(NULL), _claimed(InitialClaimValue), _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1), + _gc_efficiency(0.0), _young_type(NotYoung), _next_young_region(NULL), _next_dirty_cards_region(NULL), _next(NULL), _pending_removal(false), #ifdef ASSERT From 1b62d10b4b221938c3be8d360cb0fac8fd977d14 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 22 Sep 2011 10:57:37 -0700 Subject: [PATCH 057/214] 6484982: G1: process references during evacuation pauses G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate. Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp --- .../concurrentMarkSweepGeneration.cpp | 9 +- .../gc_implementation/g1/concurrentMark.cpp | 47 +- .../gc_implementation/g1/concurrentMark.hpp | 4 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 1224 ++++++++++++----- .../gc_implementation/g1/g1CollectedHeap.hpp | 115 +- .../g1/g1CollectorPolicy.cpp | 8 +- .../g1/g1CollectorPolicy.hpp | 10 + .../vm/gc_implementation/g1/g1MarkSweep.cpp | 8 +- .../vm/gc_implementation/g1/g1OopClosures.hpp | 86 +- .../vm/gc_implementation/g1/g1RemSet.cpp | 6 +- .../vm/gc_implementation/g1/heapRegion.cpp | 40 +- .../vm/gc_implementation/g1/heapRegion.hpp | 31 - .../vm/gc_implementation/g1/satbQueue.cpp | 16 +- .../parallelScavenge/psMarkSweep.cpp | 3 +- .../parallelScavenge/psParallelCompact.cpp | 3 +- .../parallelScavenge/psScavenge.cpp | 3 +- .../src/share/vm/memory/genCollectedHeap.cpp | 3 +- .../share/vm/memory/referenceProcessor.cpp | 234 +--- .../share/vm/memory/referenceProcessor.hpp | 222 ++- hotspot/src/share/vm/runtime/thread.cpp | 8 +- 20 files changed, 1448 insertions(+), 632 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index c5bd4ca295e..54bbb24b0a4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -2004,7 +2004,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); ref_processor()->set_enqueuing_is_done(false); - ref_processor()->enable_discovery(); + ref_processor()->enable_discovery(false /*verify_disabled*/, false /*check_no_refs*/); ref_processor()->setup_policy(clear_all_soft_refs); // If an asynchronous collection finishes, the _modUnionTable is // all clear. If we are assuming the collection from an asynchronous @@ -3490,8 +3490,8 @@ void CMSCollector::checkpointRootsInitial(bool asynch) { MutexLockerEx x(bitMapLock(), Mutex::_no_safepoint_check_flag); checkpointRootsInitialWork(asynch); - rp->verify_no_references_recorded(); - rp->enable_discovery(); // enable ("weak") refs discovery + // enable ("weak") refs discovery + rp->enable_discovery(true /*verify_disabled*/, true /*check_no_refs*/); _collectorState = Marking; } else { // (Weak) Refs discovery: this is controlled from genCollectedHeap::do_collection @@ -3503,7 +3503,8 @@ void CMSCollector::checkpointRootsInitial(bool asynch) { "ref discovery for this generation kind"); // already have locks checkpointRootsInitialWork(asynch); - rp->enable_discovery(); // now enable ("weak") refs discovery + // now enable ("weak") refs discovery + rp->enable_discovery(true /*verify_disabled*/, false /*verify_no_refs*/); _collectorState = Marking; } SpecializationStats::print(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 61adccb1005..d78db6e5d2d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -818,10 +818,10 @@ void ConcurrentMark::checkpointRootsInitialPost() { NoteStartOfMarkHRClosure startcl; g1h->heap_region_iterate(&startcl); - // Start weak-reference discovery. - ReferenceProcessor* rp = g1h->ref_processor(); - rp->verify_no_references_recorded(); - rp->enable_discovery(); // enable ("weak") refs discovery + // Start Concurrent Marking weak-reference discovery. + ReferenceProcessor* rp = g1h->ref_processor_cm(); + // enable ("weak") refs discovery + rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); @@ -1133,6 +1133,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { // world is stopped at this checkpoint assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped"); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If a full collection has happened, we shouldn't do this. @@ -1837,6 +1838,10 @@ void ConcurrentMark::cleanup() { size_t cleaned_up_bytes = start_used_bytes - g1h->used(); g1p->decrease_known_garbage_bytes(cleaned_up_bytes); + // Clean up will have freed any regions completely full of garbage. + // Update the soft reference policy with the new heap occupancy. + Universe::update_heap_info_at_gc(); + // We need to make this be a "collection" so any collection pause that // races with it goes around and waits for completeCleanup to finish. g1h->increment_total_collections(); @@ -2072,8 +2077,10 @@ class G1CMParDrainMarkingStackClosure: public VoidClosure { } }; -// Implementation of AbstractRefProcTaskExecutor for G1 -class G1RefProcTaskExecutor: public AbstractRefProcTaskExecutor { +// Implementation of AbstractRefProcTaskExecutor for parallel +// reference processing at the end of G1 concurrent marking + +class G1CMRefProcTaskExecutor: public AbstractRefProcTaskExecutor { private: G1CollectedHeap* _g1h; ConcurrentMark* _cm; @@ -2082,7 +2089,7 @@ private: int _active_workers; public: - G1RefProcTaskExecutor(G1CollectedHeap* g1h, + G1CMRefProcTaskExecutor(G1CollectedHeap* g1h, ConcurrentMark* cm, CMBitMap* bitmap, WorkGang* workers, @@ -2096,7 +2103,7 @@ public: virtual void execute(EnqueueTask& task); }; -class G1RefProcTaskProxy: public AbstractGangTask { +class G1CMRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; ProcessTask& _proc_task; G1CollectedHeap* _g1h; @@ -2104,7 +2111,7 @@ class G1RefProcTaskProxy: public AbstractGangTask { CMBitMap* _bitmap; public: - G1RefProcTaskProxy(ProcessTask& proc_task, + G1CMRefProcTaskProxy(ProcessTask& proc_task, G1CollectedHeap* g1h, ConcurrentMark* cm, CMBitMap* bitmap) : @@ -2122,10 +2129,10 @@ public: } }; -void G1RefProcTaskExecutor::execute(ProcessTask& proc_task) { +void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { assert(_workers != NULL, "Need parallel worker threads."); - G1RefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap); + G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap); // We need to reset the phase for each task execution so that // the termination protocol of CMTask::do_marking_step works. @@ -2135,12 +2142,12 @@ void G1RefProcTaskExecutor::execute(ProcessTask& proc_task) { _g1h->set_par_threads(0); } -class G1RefEnqueueTaskProxy: public AbstractGangTask { +class G1CMRefEnqueueTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; EnqueueTask& _enq_task; public: - G1RefEnqueueTaskProxy(EnqueueTask& enq_task) : + G1CMRefEnqueueTaskProxy(EnqueueTask& enq_task) : AbstractGangTask("Enqueue reference objects in parallel"), _enq_task(enq_task) { } @@ -2150,10 +2157,10 @@ public: } }; -void G1RefProcTaskExecutor::execute(EnqueueTask& enq_task) { +void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { assert(_workers != NULL, "Need parallel worker threads."); - G1RefEnqueueTaskProxy enq_task_proxy(enq_task); + G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task); _g1h->set_par_threads(_active_workers); _workers->run_task(&enq_task_proxy); @@ -2178,7 +2185,7 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { } TraceTime t("GC ref-proc", verbose, false, gclog_or_tty); - ReferenceProcessor* rp = g1h->ref_processor(); + ReferenceProcessor* rp = g1h->ref_processor_cm(); // See the comment in G1CollectedHeap::ref_processing_init() // about how reference processing currently works in G1. @@ -2196,8 +2203,8 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); - G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), - g1h->workers(), active_workers); + G1CMRefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), + g1h->workers(), active_workers); if (rp->processing_is_mt()) { // Set the degree of MT here. If the discovery is done MT, there @@ -2238,7 +2245,7 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { } rp->verify_no_references_recorded(); - assert(!rp->discovery_enabled(), "should have been disabled"); + assert(!rp->discovery_enabled(), "Post condition"); } // Now clean up stale oops in StringTable @@ -3342,7 +3349,7 @@ G1CMOopClosure::G1CMOopClosure(G1CollectedHeap* g1h, assert(_ref_processor == NULL, "should be initialized to NULL"); if (G1UseConcMarkReferenceProcessing) { - _ref_processor = g1h->ref_processor(); + _ref_processor = g1h->ref_processor_cm(); assert(_ref_processor != NULL, "should not be NULL"); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 0aca6421d5d..c724594f4af 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -366,8 +366,8 @@ class ConcurrentMark: public CHeapObj { friend class CMConcurrentMarkingTask; friend class G1ParNoteEndTask; friend class CalcLiveObjectsClosure; - friend class G1RefProcTaskProxy; - friend class G1RefProcTaskExecutor; + friend class G1CMRefProcTaskProxy; + friend class G1CMRefProcTaskExecutor; friend class G1CMParKeepAliveAndDrainClosure; friend class G1CMParDrainMarkingStackClosure; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 146c28781f2..66ca7442c5f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -42,6 +42,7 @@ #include "memory/gcLocker.inline.hpp" #include "memory/genOopClosures.inline.hpp" #include "memory/generationSpec.hpp" +#include "memory/referenceProcessor.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.pcgc.inline.hpp" #include "runtime/aprofiler.hpp" @@ -1244,15 +1245,11 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, COMPILER2_PRESENT(DerivedPointerTable::clear()); - // We want to discover references, but not process them yet. - // This mode is disabled in - // instanceRefKlass::process_discovered_references if the - // generation does some collection work, or - // instanceRefKlass::enqueue_discovered_references if the - // generation returns without doing any work. - ref_processor()->disable_discovery(); - ref_processor()->abandon_partial_discovery(); - ref_processor()->verify_no_references_recorded(); + // Disable discovery and empty the discovered lists + // for the CM ref processor. + ref_processor_cm()->disable_discovery(); + ref_processor_cm()->abandon_partial_discovery(); + ref_processor_cm()->verify_no_references_recorded(); // Abandon current iterations of concurrent marking and concurrent // refinement, if any are in progress. @@ -1280,31 +1277,33 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, empty_young_list(); g1_policy()->set_full_young_gcs(true); - // See the comment in G1CollectedHeap::ref_processing_init() about + // See the comments in g1CollectedHeap.hpp and + // G1CollectedHeap::ref_processing_init() about // how reference processing currently works in G1. - // Temporarily make reference _discovery_ single threaded (non-MT). - ReferenceProcessorMTDiscoveryMutator rp_disc_ser(ref_processor(), false); + // Temporarily make discovery by the STW ref processor single threaded (non-MT). + ReferenceProcessorMTDiscoveryMutator stw_rp_disc_ser(ref_processor_stw(), false); - // Temporarily make refs discovery atomic - ReferenceProcessorAtomicMutator rp_disc_atomic(ref_processor(), true); + // Temporarily clear the STW ref processor's _is_alive_non_header field. + ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL); - // Temporarily clear _is_alive_non_header - ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL); + ref_processor_stw()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + ref_processor_stw()->setup_policy(do_clear_all_soft_refs); - ref_processor()->enable_discovery(); - ref_processor()->setup_policy(do_clear_all_soft_refs); // Do collection work { HandleMark hm; // Discard invalid handles created during gc - G1MarkSweep::invoke_at_safepoint(ref_processor(), do_clear_all_soft_refs); + G1MarkSweep::invoke_at_safepoint(ref_processor_stw(), do_clear_all_soft_refs); } + assert(free_regions() == 0, "we should not have added any free regions"); rebuild_region_lists(); _summary_bytes_used = recalculate_used(); - ref_processor()->enqueue_discovered_references(); + // Enqueue any discovered reference objects that have + // not been removed from the discovered lists. + ref_processor_stw()->enqueue_discovered_references(); COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); @@ -1319,7 +1318,16 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, /* option */ VerifyOption_G1UsePrevMarking); } - NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); + + assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); + ref_processor_stw()->verify_no_references_recorded(); + + // Note: since we've just done a full GC, concurrent + // marking is no longer active. Therefore we need not + // re-enable reference discovery for the CM ref processor. + // That will be done at the start of the next marking cycle. + assert(!ref_processor_cm()->discovery_enabled(), "Postcondition"); + ref_processor_cm()->verify_no_references_recorded(); reset_gc_time_stamp(); // Since everything potentially moved, we will clear all remembered @@ -1772,8 +1780,10 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _g1_policy(policy_), _dirty_card_queue_set(false), _into_cset_dirty_card_queue_set(false), - _is_alive_closure(this), - _ref_processor(NULL), + _is_alive_closure_cm(this), + _is_alive_closure_stw(this), + _ref_processor_cm(NULL), + _ref_processor_stw(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), _objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL), @@ -2067,34 +2077,81 @@ jint G1CollectedHeap::initialize() { void G1CollectedHeap::ref_processing_init() { // Reference processing in G1 currently works as follows: // - // * There is only one reference processor instance that - // 'spans' the entire heap. It is created by the code - // below. - // * Reference discovery is not enabled during an incremental - // pause (see 6484982). - // * Discoverered refs are not enqueued nor are they processed - // during an incremental pause (see 6484982). - // * Reference discovery is enabled at initial marking. - // * Reference discovery is disabled and the discovered - // references processed etc during remarking. - // * Reference discovery is MT (see below). - // * Reference discovery requires a barrier (see below). - // * Reference processing is currently not MT (see 6608385). - // * A full GC enables (non-MT) reference discovery and - // processes any discovered references. + // * There are two reference processor instances. One is + // used to record and process discovered references + // during concurrent marking; the other is used to + // record and process references during STW pauses + // (both full and incremental). + // * Both ref processors need to 'span' the entire heap as + // the regions in the collection set may be dotted around. + // + // * For the concurrent marking ref processor: + // * Reference discovery is enabled at initial marking. + // * Reference discovery is disabled and the discovered + // references processed etc during remarking. + // * Reference discovery is MT (see below). + // * Reference discovery requires a barrier (see below). + // * Reference processing may or may not be MT + // (depending on the value of ParallelRefProcEnabled + // and ParallelGCThreads). + // * A full GC disables reference discovery by the CM + // ref processor and abandons any entries on it's + // discovered lists. + // + // * For the STW processor: + // * Non MT discovery is enabled at the start of a full GC. + // * Processing and enqueueing during a full GC is non-MT. + // * During a full GC, references are processed after marking. + // + // * Discovery (may or may not be MT) is enabled at the start + // of an incremental evacuation pause. + // * References are processed near the end of a STW evacuation pause. + // * For both types of GC: + // * Discovery is atomic - i.e. not concurrent. + // * Reference discovery will not need a barrier. SharedHeap::ref_processing_init(); MemRegion mr = reserved_region(); - _ref_processor = + + // Concurrent Mark ref processor + _ref_processor_cm = new ReferenceProcessor(mr, // span - ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing - (int) ParallelGCThreads, // degree of mt processing - ParallelGCThreads > 1 || ConcGCThreads > 1, // mt discovery - (int) MAX2(ParallelGCThreads, ConcGCThreads), // degree of mt discovery - false, // Reference discovery is not atomic - &_is_alive_closure, // is alive closure for efficiency - true); // Setting next fields of discovered - // lists requires a barrier. + ParallelRefProcEnabled && (ParallelGCThreads > 1), + // mt processing + (int) ParallelGCThreads, + // degree of mt processing + (ParallelGCThreads > 1) || (ConcGCThreads > 1), + // mt discovery + (int) MAX2(ParallelGCThreads, ConcGCThreads), + // degree of mt discovery + false, + // Reference discovery is not atomic + &_is_alive_closure_cm, + // is alive closure + // (for efficiency/performance) + true); + // Setting next fields of discovered + // lists requires a barrier. + + // STW ref processor + _ref_processor_stw = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), + // mt processing + MAX2((int)ParallelGCThreads, 1), + // degree of mt processing + (ParallelGCThreads > 1), + // mt discovery + MAX2((int)ParallelGCThreads, 1), + // degree of mt discovery + true, + // Reference discovery is atomic + &_is_alive_closure_stw, + // is alive closure + // (for efficiency/performance) + false); + // Setting next fields of discovered + // lists requires a barrier. } size_t G1CollectedHeap::capacity() const { @@ -3117,6 +3174,10 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "derived pointer present")); // always_do_update_barrier = true; + + // We have just completed a GC. Update the soft reference + // policy with the new heap occupancy + Universe::update_heap_info_at_gc(); } HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size, @@ -3354,231 +3415,242 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { COMPILER2_PRESENT(DerivedPointerTable::clear()); - // Please see comment in G1CollectedHeap::ref_processing_init() - // to see how reference processing currently works in G1. - // - // We want to turn off ref discovery, if necessary, and turn it back on - // on again later if we do. XXX Dubious: why is discovery disabled? - bool was_enabled = ref_processor()->discovery_enabled(); - if (was_enabled) ref_processor()->disable_discovery(); + // Please see comment in g1CollectedHeap.hpp and + // G1CollectedHeap::ref_processing_init() to see how + // reference processing currently works in G1. - // Forget the current alloc region (we might even choose it to be part - // of the collection set!). - release_mutator_alloc_region(); - - // We should call this after we retire the mutator alloc - // region(s) so that all the ALLOC / RETIRE events are generated - // before the start GC event. - _hr_printer.start_gc(false /* full */, (size_t) total_collections()); - - // The elapsed time induced by the start time below deliberately elides - // the possible verification above. - double start_time_sec = os::elapsedTime(); - size_t start_used_bytes = used(); - -#if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nBefore recording pause start.\nYoung_list:"); - _young_list->print(); - g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); -#endif // YOUNG_LIST_VERBOSE - - g1_policy()->record_collection_pause_start(start_time_sec, - start_used_bytes); - -#if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); - _young_list->print(); -#endif // YOUNG_LIST_VERBOSE - - if (g1_policy()->during_initial_mark_pause()) { - concurrent_mark()->checkpointRootsInitialPre(); - } - perm_gen()->save_marks(); - - // We must do this before any possible evacuation that should propagate - // marks. - if (mark_in_progress()) { - double start_time_sec = os::elapsedTime(); - - _cm->drainAllSATBBuffers(); - double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; - g1_policy()->record_satb_drain_time(finish_mark_ms); - } - // Record the number of elements currently on the mark stack, so we - // only iterate over these. (Since evacuation may add to the mark - // stack, doing more exposes race conditions.) If no mark is in - // progress, this will be zero. - _cm->set_oops_do_bound(); - - if (mark_in_progress()) { - concurrent_mark()->newCSet(); - } - -#if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nBefore choosing collection set.\nYoung_list:"); - _young_list->print(); - g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); -#endif // YOUNG_LIST_VERBOSE - - g1_policy()->choose_collection_set(target_pause_time_ms); - - if (_hr_printer.is_active()) { - HeapRegion* hr = g1_policy()->collection_set(); - while (hr != NULL) { - G1HRPrinter::RegionType type; - if (!hr->is_young()) { - type = G1HRPrinter::Old; - } else if (hr->is_survivor()) { - type = G1HRPrinter::Survivor; - } else { - type = G1HRPrinter::Eden; - } - _hr_printer.cset(hr); - hr = hr->next_in_collection_set(); - } - } - - // We have chosen the complete collection set. If marking is - // active then, we clear the region fields of any of the - // concurrent marking tasks whose region fields point into - // the collection set as these values will become stale. This - // will cause the owning marking threads to claim a new region - // when marking restarts. - if (mark_in_progress()) { - concurrent_mark()->reset_active_task_region_fields_in_cset(); - } - -#ifdef ASSERT - VerifyCSetClosure cl; - collection_set_iterate(&cl); -#endif // ASSERT - - setup_surviving_young_words(); - - // Initialize the GC alloc regions. - init_gc_alloc_regions(); - - // Actually do the work... - evacuate_collection_set(); - - free_collection_set(g1_policy()->collection_set()); - g1_policy()->clear_collection_set(); - - cleanup_surviving_young_words(); - - // Start a new incremental collection set for the next pause. - g1_policy()->start_incremental_cset_building(); - - // Clear the _cset_fast_test bitmap in anticipation of adding - // regions to the incremental collection set for the next - // evacuation pause. - clear_cset_fast_test(); - - _young_list->reset_sampled_info(); - - // Don't check the whole heap at this point as the - // GC alloc regions from this pause have been tagged - // as survivors and moved on to the survivor list. - // Survivor regions will fail the !is_young() check. - assert(check_young_list_empty(false /* check_heap */), - "young list should be empty"); - -#if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("Before recording survivors.\nYoung List:"); - _young_list->print(); -#endif // YOUNG_LIST_VERBOSE - - g1_policy()->record_survivor_regions(_young_list->survivor_length(), - _young_list->first_survivor_region(), - _young_list->last_survivor_region()); - - _young_list->reset_auxilary_lists(); - - if (evacuation_failed()) { - _summary_bytes_used = recalculate_used(); - } else { - // The "used" of the the collection set have already been subtracted - // when they were freed. Add in the bytes evacuated. - _summary_bytes_used += g1_policy()->bytes_copied_during_gc(); - } - - if (g1_policy()->during_initial_mark_pause()) { - concurrent_mark()->checkpointRootsInitialPost(); - set_marking_started(); - // CAUTION: after the doConcurrentMark() call below, - // the concurrent marking thread(s) could be running - // concurrently with us. Make sure that anything after - // this point does not assume that we are the only GC thread - // running. Note: of course, the actual marking work will - // not start until the safepoint itself is released in - // ConcurrentGCThread::safepoint_desynchronize(). - doConcurrentMark(); - } - - allocate_dummy_regions(); - -#if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nEnd of the pause.\nYoung_list:"); - _young_list->print(); - g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); -#endif // YOUNG_LIST_VERBOSE - - init_mutator_alloc_region(); + // Enable discovery in the STW reference processor + ref_processor_stw()->enable_discovery(true /*verify_disabled*/, + true /*verify_no_refs*/); { - size_t expand_bytes = g1_policy()->expansion_amount(); - if (expand_bytes > 0) { - size_t bytes_before = capacity(); - if (!expand(expand_bytes)) { - // We failed to expand the heap so let's verify that - // committed/uncommitted amount match the backing store - assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); - assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + // We want to temporarily turn off discovery by the + // CM ref processor, if necessary, and turn it back on + // on again later if we do. Using a scoped + // NoRefDiscovery object will do this. + NoRefDiscovery no_cm_discovery(ref_processor_cm()); + + // Forget the current alloc region (we might even choose it to be part + // of the collection set!). + release_mutator_alloc_region(); + + // We should call this after we retire the mutator alloc + // region(s) so that all the ALLOC / RETIRE events are generated + // before the start GC event. + _hr_printer.start_gc(false /* full */, (size_t) total_collections()); + + // The elapsed time induced by the start time below deliberately elides + // the possible verification above. + double start_time_sec = os::elapsedTime(); + size_t start_used_bytes = used(); + +#if YOUNG_LIST_VERBOSE + gclog_or_tty->print_cr("\nBefore recording pause start.\nYoung_list:"); + _young_list->print(); + g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); +#endif // YOUNG_LIST_VERBOSE + + g1_policy()->record_collection_pause_start(start_time_sec, + start_used_bytes); + +#if YOUNG_LIST_VERBOSE + gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); + _young_list->print(); +#endif // YOUNG_LIST_VERBOSE + + if (g1_policy()->during_initial_mark_pause()) { + concurrent_mark()->checkpointRootsInitialPre(); + } + perm_gen()->save_marks(); + + // We must do this before any possible evacuation that should propagate + // marks. + if (mark_in_progress()) { + double start_time_sec = os::elapsedTime(); + + _cm->drainAllSATBBuffers(); + double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; + g1_policy()->record_satb_drain_time(finish_mark_ms); + } + // Record the number of elements currently on the mark stack, so we + // only iterate over these. (Since evacuation may add to the mark + // stack, doing more exposes race conditions.) If no mark is in + // progress, this will be zero. + _cm->set_oops_do_bound(); + + if (mark_in_progress()) { + concurrent_mark()->newCSet(); + } + +#if YOUNG_LIST_VERBOSE + gclog_or_tty->print_cr("\nBefore choosing collection set.\nYoung_list:"); + _young_list->print(); + g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); +#endif // YOUNG_LIST_VERBOSE + + g1_policy()->choose_collection_set(target_pause_time_ms); + + if (_hr_printer.is_active()) { + HeapRegion* hr = g1_policy()->collection_set(); + while (hr != NULL) { + G1HRPrinter::RegionType type; + if (!hr->is_young()) { + type = G1HRPrinter::Old; + } else if (hr->is_survivor()) { + type = G1HRPrinter::Survivor; + } else { + type = G1HRPrinter::Eden; + } + _hr_printer.cset(hr); + hr = hr->next_in_collection_set(); } } + + // We have chosen the complete collection set. If marking is + // active then, we clear the region fields of any of the + // concurrent marking tasks whose region fields point into + // the collection set as these values will become stale. This + // will cause the owning marking threads to claim a new region + // when marking restarts. + if (mark_in_progress()) { + concurrent_mark()->reset_active_task_region_fields_in_cset(); + } + +#ifdef ASSERT + VerifyCSetClosure cl; + collection_set_iterate(&cl); +#endif // ASSERT + + setup_surviving_young_words(); + + // Initialize the GC alloc regions. + init_gc_alloc_regions(); + + // Actually do the work... + evacuate_collection_set(); + + free_collection_set(g1_policy()->collection_set()); + g1_policy()->clear_collection_set(); + + cleanup_surviving_young_words(); + + // Start a new incremental collection set for the next pause. + g1_policy()->start_incremental_cset_building(); + + // Clear the _cset_fast_test bitmap in anticipation of adding + // regions to the incremental collection set for the next + // evacuation pause. + clear_cset_fast_test(); + + _young_list->reset_sampled_info(); + + // Don't check the whole heap at this point as the + // GC alloc regions from this pause have been tagged + // as survivors and moved on to the survivor list. + // Survivor regions will fail the !is_young() check. + assert(check_young_list_empty(false /* check_heap */), + "young list should be empty"); + +#if YOUNG_LIST_VERBOSE + gclog_or_tty->print_cr("Before recording survivors.\nYoung List:"); + _young_list->print(); +#endif // YOUNG_LIST_VERBOSE + + g1_policy()->record_survivor_regions(_young_list->survivor_length(), + _young_list->first_survivor_region(), + _young_list->last_survivor_region()); + + _young_list->reset_auxilary_lists(); + + if (evacuation_failed()) { + _summary_bytes_used = recalculate_used(); + } else { + // The "used" of the the collection set have already been subtracted + // when they were freed. Add in the bytes evacuated. + _summary_bytes_used += g1_policy()->bytes_copied_during_gc(); + } + + if (g1_policy()->during_initial_mark_pause()) { + concurrent_mark()->checkpointRootsInitialPost(); + set_marking_started(); + // CAUTION: after the doConcurrentMark() call below, + // the concurrent marking thread(s) could be running + // concurrently with us. Make sure that anything after + // this point does not assume that we are the only GC thread + // running. Note: of course, the actual marking work will + // not start until the safepoint itself is released in + // ConcurrentGCThread::safepoint_desynchronize(). + doConcurrentMark(); + } + + allocate_dummy_regions(); + +#if YOUNG_LIST_VERBOSE + gclog_or_tty->print_cr("\nEnd of the pause.\nYoung_list:"); + _young_list->print(); + g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); +#endif // YOUNG_LIST_VERBOSE + + init_mutator_alloc_region(); + + { + size_t expand_bytes = g1_policy()->expansion_amount(); + if (expand_bytes > 0) { + size_t bytes_before = capacity(); + if (!expand(expand_bytes)) { + // We failed to expand the heap so let's verify that + // committed/uncommitted amount match the backing store + assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); + assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + } + } + } + + double end_time_sec = os::elapsedTime(); + double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; + g1_policy()->record_pause_time_ms(pause_time_ms); + g1_policy()->record_collection_pause_end(); + + MemoryService::track_memory_usage(); + + // In prepare_for_verify() below we'll need to scan the deferred + // update buffers to bring the RSets up-to-date if + // G1HRRSFlushLogBuffersOnVerify has been set. While scanning + // the update buffers we'll probably need to scan cards on the + // regions we just allocated to (i.e., the GC alloc + // regions). However, during the last GC we called + // set_saved_mark() on all the GC alloc regions, so card + // scanning might skip the [saved_mark_word()...top()] area of + // those regions (i.e., the area we allocated objects into + // during the last GC). But it shouldn't. Given that + // saved_mark_word() is conditional on whether the GC time stamp + // on the region is current or not, by incrementing the GC time + // stamp here we invalidate all the GC time stamps on all the + // regions and saved_mark_word() will simply return top() for + // all the regions. This is a nicer way of ensuring this rather + // than iterating over the regions and fixing them. In fact, the + // GC time stamp increment here also ensures that + // saved_mark_word() will return top() between pauses, i.e., + // during concurrent refinement. So we don't need the + // is_gc_active() check to decided which top to use when + // scanning cards (see CR 7039627). + increment_gc_time_stamp(); + + if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { + HandleMark hm; // Discard invalid handles created during verification + gclog_or_tty->print(" VerifyAfterGC:"); + prepare_for_verify(); + Universe::verify(/* allow dirty */ true, + /* silent */ false, + /* option */ VerifyOption_G1UsePrevMarking); + } + + assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); + ref_processor_stw()->verify_no_references_recorded(); + + // CM reference discovery will be re-enabled if necessary. } - double end_time_sec = os::elapsedTime(); - double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; - g1_policy()->record_pause_time_ms(pause_time_ms); - g1_policy()->record_collection_pause_end(); - - MemoryService::track_memory_usage(); - - // In prepare_for_verify() below we'll need to scan the deferred - // update buffers to bring the RSets up-to-date if - // G1HRRSFlushLogBuffersOnVerify has been set. While scanning - // the update buffers we'll probably need to scan cards on the - // regions we just allocated to (i.e., the GC alloc - // regions). However, during the last GC we called - // set_saved_mark() on all the GC alloc regions, so card - // scanning might skip the [saved_mark_word()...top()] area of - // those regions (i.e., the area we allocated objects into - // during the last GC). But it shouldn't. Given that - // saved_mark_word() is conditional on whether the GC time stamp - // on the region is current or not, by incrementing the GC time - // stamp here we invalidate all the GC time stamps on all the - // regions and saved_mark_word() will simply return top() for - // all the regions. This is a nicer way of ensuring this rather - // than iterating over the regions and fixing them. In fact, the - // GC time stamp increment here also ensures that - // saved_mark_word() will return top() between pauses, i.e., - // during concurrent refinement. So we don't need the - // is_gc_active() check to decided which top to use when - // scanning cards (see CR 7039627). - increment_gc_time_stamp(); - - if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyAfterGC:"); - prepare_for_verify(); - Universe::verify(/* allow dirty */ true, - /* silent */ false, - /* option */ VerifyOption_G1UsePrevMarking); - } - - if (was_enabled) ref_processor()->enable_discovery(); - { size_t expand_bytes = g1_policy()->expansion_amount(); if (expand_bytes > 0) { @@ -3728,34 +3800,6 @@ void G1CollectedHeap::finalize_for_evac_failure() { _evac_failure_scan_stack = NULL; } -// *** Sequential G1 Evacuation - -class G1IsAliveClosure: public BoolObjectClosure { - G1CollectedHeap* _g1; -public: - G1IsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} - void do_object(oop p) { assert(false, "Do not call."); } - bool do_object_b(oop p) { - // It is reachable if it is outside the collection set, or is inside - // and forwarded. - return !_g1->obj_in_cs(p) || p->is_forwarded(); - } -}; - -class G1KeepAliveClosure: public OopClosure { - G1CollectedHeap* _g1; -public: - G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} - void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } - void do_oop( oop* p) { - oop obj = *p; - if (_g1->obj_in_cs(obj)) { - assert( obj->is_forwarded(), "invariant" ); - *p = obj->forwardee(); - } - } -}; - class UpdateRSetDeferred : public OopsInHeapRegionClosure { private: G1CollectedHeap* _g1; @@ -4186,12 +4230,17 @@ bool G1ParScanThreadState::verify_task(StarTask ref) const { #endif // ASSERT void G1ParScanThreadState::trim_queue() { + assert(_evac_cl != NULL, "not set"); + assert(_evac_failure_cl != NULL, "not set"); + assert(_partial_scan_cl != NULL, "not set"); + StarTask ref; do { // Drain the overflow stack first, so other threads can steal. while (refs()->pop_overflow(ref)) { deal_with_reference(ref); } + while (refs()->pop_local(ref)) { deal_with_reference(ref); } @@ -4529,35 +4578,42 @@ public: ResourceMark rm; HandleMark hm; + ReferenceProcessor* rp = _g1h->ref_processor_stw(); + G1ParScanThreadState pss(_g1h, i); - G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); - G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss); - G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp); pss.set_evac_closure(&scan_evac_cl); pss.set_evac_failure_closure(&evac_failure_cl); pss.set_partial_scan_closure(&partial_scan_cl); - G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss); - G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss); - G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss); - G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss); + G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss, rp); + G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss, rp); - G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss); - G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); - G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss); + G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp); + G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss, rp); - OopsInHeapRegionClosure *scan_root_cl; - OopsInHeapRegionClosure *scan_perm_cl; + OopClosure* scan_root_cl = &only_scan_root_cl; + OopsInHeapRegionClosure* scan_perm_cl = &only_scan_perm_cl; if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. scan_root_cl = &scan_mark_root_cl; scan_perm_cl = &scan_mark_perm_cl; - } else { - scan_root_cl = &only_scan_root_cl; - scan_perm_cl = &only_scan_perm_cl; } + // The following closure is used to scan RSets looking for reference + // fields that point into the collection set. The actual field iteration + // is performed by a FilterIntoCSClosure, whose do_oop method calls the + // do_oop method of the following closure. + // Therefore we want to record the reference processor in the + // FilterIntoCSClosure. To do so we record the STW reference + // processor into the following closure and pass it to the + // FilterIntoCSClosure in HeapRegionDCTOC::walk_mem_region_with_cl. + G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss, rp); + pss.start_strong_roots(); _g1h->g1_process_strong_roots(/* not collecting perm */ false, SharedHeap::SO_AllClasses, @@ -4605,6 +4661,7 @@ g1_process_strong_roots(bool collecting_perm_gen, OopsInHeapRegionClosure* scan_rs, OopsInGenClosure* scan_perm, int worker_i) { + // First scan the strong roots, including the perm gen. double ext_roots_start = os::elapsedTime(); double closure_app_time_sec = 0.0; @@ -4623,12 +4680,13 @@ g1_process_strong_roots(bool collecting_perm_gen, &eager_scan_code_roots, &buf_scan_perm); - // Now the ref_processor roots. + // Now the CM ref_processor roots. if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) { - // We need to treat the discovered reference lists as roots and - // keep entries (which are added by the marking threads) on them - // live until they can be processed at the end of marking. - ref_processor()->weak_oops_do(&buf_scan_non_heap_roots); + // We need to treat the discovered reference lists of the + // concurrent mark ref processor as roots and keep entries + // (which are added by the marking threads) on them live + // until they can be processed at the end of marking. + ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); } // Finish up any enqueued closure apps (attributed as object copy time). @@ -4669,6 +4727,524 @@ G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure, SharedHeap::process_weak_roots(root_closure, &roots_in_blobs, non_root_closure); } +// Weak Reference Processing support + +// An always "is_alive" closure that is used to preserve referents. +// If the object is non-null then it's alive. Used in the preservation +// of referent objects that are pointed to by reference objects +// discovered by the CM ref processor. +class G1AlwaysAliveClosure: public BoolObjectClosure { + G1CollectedHeap* _g1; +public: + G1AlwaysAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} + void do_object(oop p) { assert(false, "Do not call."); } + bool do_object_b(oop p) { + if (p != NULL) { + return true; + } + return false; + } +}; + +bool G1STWIsAliveClosure::do_object_b(oop p) { + // An object is reachable if it is outside the collection set, + // or is inside and copied. + return !_g1->obj_in_cs(p) || p->is_forwarded(); +} + +// Non Copying Keep Alive closure +class G1KeepAliveClosure: public OopClosure { + G1CollectedHeap* _g1; +public: + G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} + void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } + void do_oop( oop* p) { + oop obj = *p; + + if (_g1->obj_in_cs(obj)) { + assert( obj->is_forwarded(), "invariant" ); + *p = obj->forwardee(); + } + } +}; + +// Copying Keep Alive closure - can be called from both +// serial and parallel code as long as different worker +// threads utilize different G1ParScanThreadState instances +// and different queues. + +class G1CopyingKeepAliveClosure: public OopClosure { + G1CollectedHeap* _g1h; + OopClosure* _copy_non_heap_obj_cl; + OopsInHeapRegionClosure* _copy_perm_obj_cl; + G1ParScanThreadState* _par_scan_state; + +public: + G1CopyingKeepAliveClosure(G1CollectedHeap* g1h, + OopClosure* non_heap_obj_cl, + OopsInHeapRegionClosure* perm_obj_cl, + G1ParScanThreadState* pss): + _g1h(g1h), + _copy_non_heap_obj_cl(non_heap_obj_cl), + _copy_perm_obj_cl(perm_obj_cl), + _par_scan_state(pss) + {} + + virtual void do_oop(narrowOop* p) { do_oop_work(p); } + virtual void do_oop( oop* p) { do_oop_work(p); } + + template void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop(p); + + if (_g1h->obj_in_cs(obj)) { + // If the referent object has been forwarded (either copied + // to a new location or to itself in the event of an + // evacuation failure) then we need to update the reference + // field and, if both reference and referent are in the G1 + // heap, update the RSet for the referent. + // + // If the referent has not been forwarded then we have to keep + // it alive by policy. Therefore we have copy the referent. + // + // If the reference field is in the G1 heap then we can push + // on the PSS queue. When the queue is drained (after each + // phase of reference processing) the object and it's followers + // will be copied, the reference field set to point to the + // new location, and the RSet updated. Otherwise we need to + // use the the non-heap or perm closures directly to copy + // the refernt object and update the pointer, while avoiding + // updating the RSet. + + if (_g1h->is_in_g1_reserved(p)) { + _par_scan_state->push_on_queue(p); + } else { + // The reference field is not in the G1 heap. + if (_g1h->perm_gen()->is_in(p)) { + _copy_perm_obj_cl->do_oop(p); + } else { + _copy_non_heap_obj_cl->do_oop(p); + } + } + } + } +}; + +// Serial drain queue closure. Called as the 'complete_gc' +// closure for each discovered list in some of the +// reference processing phases. + +class G1STWDrainQueueClosure: public VoidClosure { +protected: + G1CollectedHeap* _g1h; + G1ParScanThreadState* _par_scan_state; + + G1ParScanThreadState* par_scan_state() { return _par_scan_state; } + +public: + G1STWDrainQueueClosure(G1CollectedHeap* g1h, G1ParScanThreadState* pss) : + _g1h(g1h), + _par_scan_state(pss) + { } + + void do_void() { + G1ParScanThreadState* const pss = par_scan_state(); + pss->trim_queue(); + } +}; + +// Parallel Reference Processing closures + +// Implementation of AbstractRefProcTaskExecutor for parallel reference +// processing during G1 evacuation pauses. + +class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor { +private: + G1CollectedHeap* _g1h; + RefToScanQueueSet* _queues; + WorkGang* _workers; + int _active_workers; + +public: + G1STWRefProcTaskExecutor(G1CollectedHeap* g1h, + WorkGang* workers, + RefToScanQueueSet *task_queues, + int n_workers) : + _g1h(g1h), + _queues(task_queues), + _workers(workers), + _active_workers(n_workers) + { + assert(n_workers > 0, "shouldn't call this otherwise"); + } + + // Executes the given task using concurrent marking worker threads. + virtual void execute(ProcessTask& task); + virtual void execute(EnqueueTask& task); +}; + +// Gang task for possibly parallel reference processing + +class G1STWRefProcTaskProxy: public AbstractGangTask { + typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; + ProcessTask& _proc_task; + G1CollectedHeap* _g1h; + RefToScanQueueSet *_task_queues; + ParallelTaskTerminator* _terminator; + +public: + G1STWRefProcTaskProxy(ProcessTask& proc_task, + G1CollectedHeap* g1h, + RefToScanQueueSet *task_queues, + ParallelTaskTerminator* terminator) : + AbstractGangTask("Process reference objects in parallel"), + _proc_task(proc_task), + _g1h(g1h), + _task_queues(task_queues), + _terminator(terminator) + {} + + virtual void work(int i) { + // The reference processing task executed by a single worker. + ResourceMark rm; + HandleMark hm; + + G1STWIsAliveClosure is_alive(_g1h); + + G1ParScanThreadState pss(_g1h, i); + + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, NULL); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, NULL); + + pss.set_evac_closure(&scan_evac_cl); + pss.set_evac_failure_closure(&evac_failure_cl); + pss.set_partial_scan_closure(&partial_scan_cl); + + G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, &pss, NULL); + G1ParScanPermClosure only_copy_perm_cl(_g1h, &pss, NULL); + + G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, &pss, NULL); + G1ParScanAndMarkPermClosure copy_mark_perm_cl(_g1h, &pss, NULL); + + OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl; + OopsInHeapRegionClosure* copy_perm_cl = &only_copy_perm_cl; + + if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. + copy_non_heap_cl = ©_mark_non_heap_cl; + copy_perm_cl = ©_mark_perm_cl; + } + + // Keep alive closure. + G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, copy_perm_cl, &pss); + + // Complete GC closure + G1ParEvacuateFollowersClosure drain_queue(_g1h, &pss, _task_queues, _terminator); + + // Call the reference processing task's work routine. + _proc_task.work(i, is_alive, keep_alive, drain_queue); + + // Note we cannot assert that the refs array is empty here as not all + // of the processing tasks (specifically phase2 - pp2_work) execute + // the complete_gc closure (which ordinarily would drain the queue) so + // the queue may not be empty. + } +}; + +// Driver routine for parallel reference processing. +// Creates an instance of the ref processing gang +// task and has the worker threads execute it. +void G1STWRefProcTaskExecutor::execute(ProcessTask& proc_task) { + assert(_workers != NULL, "Need parallel worker threads."); + + ParallelTaskTerminator terminator(_active_workers, _queues); + G1STWRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _queues, &terminator); + + _g1h->set_par_threads(_active_workers); + _workers->run_task(&proc_task_proxy); + _g1h->set_par_threads(0); +} + +// Gang task for parallel reference enqueueing. + +class G1STWRefEnqueueTaskProxy: public AbstractGangTask { + typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; + EnqueueTask& _enq_task; + +public: + G1STWRefEnqueueTaskProxy(EnqueueTask& enq_task) : + AbstractGangTask("Enqueue reference objects in parallel"), + _enq_task(enq_task) + { } + + virtual void work(int i) { + _enq_task.work(i); + } +}; + +// Driver routine for parallel reference enqueing. +// Creates an instance of the ref enqueueing gang +// task and has the worker threads execute it. + +void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) { + assert(_workers != NULL, "Need parallel worker threads."); + + G1STWRefEnqueueTaskProxy enq_task_proxy(enq_task); + + _g1h->set_par_threads(_active_workers); + _workers->run_task(&enq_task_proxy); + _g1h->set_par_threads(0); +} + +// End of weak reference support closures + +// Abstract task used to preserve (i.e. copy) any referent objects +// that are in the collection set and are pointed to by reference +// objects discovered by the CM ref processor. + +class G1ParPreserveCMReferentsTask: public AbstractGangTask { +protected: + G1CollectedHeap* _g1h; + RefToScanQueueSet *_queues; + ParallelTaskTerminator _terminator; + int _n_workers; + +public: + G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h,int workers, RefToScanQueueSet *task_queues) : + AbstractGangTask("ParPreserveCMReferents"), + _g1h(g1h), + _queues(task_queues), + _terminator(workers, _queues), + _n_workers(workers) + { } + + void work(int i) { + ResourceMark rm; + HandleMark hm; + + G1ParScanThreadState pss(_g1h, i); + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, NULL); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, NULL); + + pss.set_evac_closure(&scan_evac_cl); + pss.set_evac_failure_closure(&evac_failure_cl); + pss.set_partial_scan_closure(&partial_scan_cl); + + assert(pss.refs()->is_empty(), "both queue and overflow should be empty"); + + + G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, &pss, NULL); + G1ParScanPermClosure only_copy_perm_cl(_g1h, &pss, NULL); + + G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, &pss, NULL); + G1ParScanAndMarkPermClosure copy_mark_perm_cl(_g1h, &pss, NULL); + + OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl; + OopsInHeapRegionClosure* copy_perm_cl = &only_copy_perm_cl; + + if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. + copy_non_heap_cl = ©_mark_non_heap_cl; + copy_perm_cl = ©_mark_perm_cl; + } + + // Is alive closure + G1AlwaysAliveClosure always_alive(_g1h); + + // Copying keep alive closure. Applied to referent objects that need + // to be copied. + G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, copy_perm_cl, &pss); + + ReferenceProcessor* rp = _g1h->ref_processor_cm(); + + int limit = ReferenceProcessor::number_of_subclasses_of_ref() * rp->max_num_q(); + int stride = MIN2(MAX2(_n_workers, 1), limit); + + // limit is set using max_num_q() - which was set using ParallelGCThreads. + // So this must be true - but assert just in case someone decides to + // change the worker ids. + assert(0 <= i && i < limit, "sanity"); + assert(!rp->discovery_is_atomic(), "check this code"); + + // Select discovered lists [i, i+stride, i+2*stride,...,limit) + for (int idx = i; idx < limit; idx += stride) { + DiscoveredList& ref_list = rp->discovered_soft_refs()[idx]; + + DiscoveredListIterator iter(ref_list, &keep_alive, &always_alive); + while (iter.has_next()) { + // Since discovery is not atomic for the CM ref processor, we + // can see some null referent objects. + iter.load_ptrs(DEBUG_ONLY(true)); + oop ref = iter.obj(); + + // This will filter nulls. + if (iter.is_referent_alive()) { + iter.make_referent_alive(); + } + iter.move_to_next(); + } + } + + // Drain the queue - which may cause stealing + G1ParEvacuateFollowersClosure drain_queue(_g1h, &pss, _queues, &_terminator); + drain_queue.do_void(); + // Allocation buffers were retired at the end of G1ParEvacuateFollowersClosure + assert(pss.refs()->is_empty(), "should be"); + } +}; + +// Weak Reference processing during an evacuation pause (part 1). +void G1CollectedHeap::process_discovered_references() { + double ref_proc_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(rp->discovery_enabled(), "should have been enabled"); + + // Any reference objects, in the collection set, that were 'discovered' + // by the CM ref processor should have already been copied (either by + // applying the external root copy closure to the discovered lists, or + // by following an RSet entry). + // + // But some of the referents, that are in the collection set, that these + // reference objects point to may not have been copied: the STW ref + // processor would have seen that the reference object had already + // been 'discovered' and would have skipped discovering the reference, + // but would not have treated the reference object as a regular oop. + // As a reult the copy closure would not have been applied to the + // referent object. + // + // We need to explicitly copy these referent objects - the references + // will be processed at the end of remarking. + // + // We also need to do this copying before we process the reference + // objects discovered by the STW ref processor in case one of these + // referents points to another object which is also referenced by an + // object discovered by the STW ref processor. + + int n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? + workers()->total_workers() : 1); + + set_par_threads(n_workers); + G1ParPreserveCMReferentsTask keep_cm_referents(this, n_workers, _task_queues); + + if (G1CollectedHeap::use_parallel_gc_threads()) { + workers()->run_task(&keep_cm_referents); + } else { + keep_cm_referents.work(0); + } + + set_par_threads(0); + + // Closure to test whether a referent is alive. + G1STWIsAliveClosure is_alive(this); + + // Even when parallel reference processing is enabled, the processing + // of JNI refs is serial and performed serially by the current thread + // rather than by a worker. The following PSS will be used for processing + // JNI refs. + + // Use only a single queue for this PSS. + G1ParScanThreadState pss(this, 0); + + // We do not embed a reference processor in the copying/scanning + // closures while we're actually processing the discovered + // reference objects. + G1ParScanHeapEvacClosure scan_evac_cl(this, &pss, NULL); + G1ParScanHeapEvacFailureClosure evac_failure_cl(this, &pss, NULL); + G1ParScanPartialArrayClosure partial_scan_cl(this, &pss, NULL); + + pss.set_evac_closure(&scan_evac_cl); + pss.set_evac_failure_closure(&evac_failure_cl); + pss.set_partial_scan_closure(&partial_scan_cl); + + assert(pss.refs()->is_empty(), "pre-condition"); + + G1ParScanExtRootClosure only_copy_non_heap_cl(this, &pss, NULL); + G1ParScanPermClosure only_copy_perm_cl(this, &pss, NULL); + + G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(this, &pss, NULL); + G1ParScanAndMarkPermClosure copy_mark_perm_cl(this, &pss, NULL); + + OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl; + OopsInHeapRegionClosure* copy_perm_cl = &only_copy_perm_cl; + + if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. + copy_non_heap_cl = ©_mark_non_heap_cl; + copy_perm_cl = ©_mark_perm_cl; + } + + // Keep alive closure. + G1CopyingKeepAliveClosure keep_alive(this, copy_non_heap_cl, copy_perm_cl, &pss); + + // Serial Complete GC closure + G1STWDrainQueueClosure drain_queue(this, &pss); + + // Setup the soft refs policy... + rp->setup_policy(false); + + if (!rp->processing_is_mt()) { + // Serial reference processing... + rp->process_discovered_references(&is_alive, + &keep_alive, + &drain_queue, + NULL); + } else { + // Parallel reference processing + int active_workers = (ParallelGCThreads > 0 ? workers()->total_workers() : 1); + assert(rp->num_q() == active_workers, "sanity"); + assert(active_workers <= rp->max_num_q(), "sanity"); + + G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, active_workers); + rp->process_discovered_references(&is_alive, &keep_alive, &drain_queue, &par_task_executor); + } + + // We have completed copying any necessary live referent objects + // (that were not copied during the actual pause) so we can + // retire any active alloc buffers + pss.retire_alloc_buffers(); + assert(pss.refs()->is_empty(), "both queue and overflow should be empty"); + + double ref_proc_time = os::elapsedTime() - ref_proc_start; + g1_policy()->record_ref_proc_time(ref_proc_time * 1000.0); +} + +// Weak Reference processing during an evacuation pause (part 2). +void G1CollectedHeap::enqueue_discovered_references() { + double ref_enq_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(!rp->discovery_enabled(), "should have been disabled as part of processing"); + + // Now enqueue any remaining on the discovered lists on to + // the pending list. + if (!rp->processing_is_mt()) { + // Serial reference processing... + rp->enqueue_discovered_references(); + } else { + // Parallel reference enqueuing + + int active_workers = (ParallelGCThreads > 0 ? workers()->total_workers() : 1); + assert(rp->num_q() == active_workers, "sanity"); + assert(active_workers <= rp->max_num_q(), "sanity"); + + G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, active_workers); + rp->enqueue_discovered_references(&par_task_executor); + } + + rp->verify_no_references_recorded(); + assert(!rp->discovery_enabled(), "should have been disabled"); + + // FIXME + // CM's reference processing also cleans up the string and symbol tables. + // Should we do that here also? We could, but it is a serial operation + // and could signicantly increase the pause time. + + double ref_enq_time = os::elapsedTime() - ref_enq_start; + g1_policy()->record_ref_enq_time(ref_enq_time * 1000.0); +} + void G1CollectedHeap::evacuate_collection_set() { set_evacuation_failed(false); @@ -4686,6 +5262,7 @@ void G1CollectedHeap::evacuate_collection_set() { assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); double start_par = os::elapsedTime(); + if (G1CollectedHeap::use_parallel_gc_threads()) { // The individual threads will set their evac-failure closures. StrongRootsScope srs(this); @@ -4700,15 +5277,23 @@ void G1CollectedHeap::evacuate_collection_set() { g1_policy()->record_par_time(par_time); set_par_threads(0); + // Process any discovered reference objects - we have + // to do this _before_ we retire the GC alloc regions + // as we may have to copy some 'reachable' referent + // objects (and their reachable sub-graphs) that were + // not copied during the pause. + process_discovered_references(); + // Weak root processing. // Note: when JSR 292 is enabled and code blobs can contain // non-perm oops then we will need to process the code blobs // here too. { - G1IsAliveClosure is_alive(this); + G1STWIsAliveClosure is_alive(this); G1KeepAliveClosure keep_alive(this); JNIHandles::weak_oops_do(&is_alive, &keep_alive); } + release_gc_alloc_regions(); g1_rem_set()->cleanup_after_oops_into_collection_set_do(); @@ -4730,6 +5315,15 @@ void G1CollectedHeap::evacuate_collection_set() { } } + // Enqueue any remaining references remaining on the STW + // reference processor's discovered lists. We need to do + // this after the card table is cleaned (and verified) as + // the act of enqueuing entries on to the pending list + // will log these updates (and dirty their associated + // cards). We need these updates logged to update any + // RSets. + enqueue_discovered_references(); + if (G1DeferredRSUpdate) { RedirtyLoggedCardTableEntryFastClosure redirty; dirty_card_queue_set().set_closure(&redirty); @@ -4930,7 +5524,7 @@ void G1CollectedHeap::cleanUpCardTable() { } double elapsed = os::elapsedTime() - start; - g1_policy()->record_clear_ct_time( elapsed * 1000.0); + g1_policy()->record_clear_ct_time(elapsed * 1000.0); #ifndef PRODUCT if (G1VerifyCTCleanup || VerifyAfterGC) { G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 6a361326f6d..9dcf1a82556 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -155,6 +155,19 @@ public: : G1AllocRegion("Mutator Alloc Region", false /* bot_updates */) { } }; +// The G1 STW is alive closure. +// An instance is embedded into the G1CH and used as the +// (optional) _is_alive_non_header closure in the STW +// reference processor. It is also extensively used during +// refence processing during STW evacuation pauses. +class G1STWIsAliveClosure: public BoolObjectClosure { + G1CollectedHeap* _g1; +public: + G1STWIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} + void do_object(oop p) { assert(false, "Do not call."); } + bool do_object_b(oop p); +}; + class SurvivorGCAllocRegion : public G1AllocRegion { protected: virtual HeapRegion* allocate_new_region(size_t word_size, bool force); @@ -174,6 +187,7 @@ public: }; class RefineCardTableEntryClosure; + class G1CollectedHeap : public SharedHeap { friend class VM_G1CollectForAllocation; friend class VM_GenCollectForPermanentAllocation; @@ -573,6 +587,14 @@ protected: // allocated block, or else "NULL". HeapWord* expand_and_allocate(size_t word_size); + // Process any reference objects discovered during + // an incremental evacuation pause. + void process_discovered_references(); + + // Enqueue any remaining discovered references + // after processing. + void enqueue_discovered_references(); + public: G1MonitoringSupport* g1mm() { return _g1mm; } @@ -826,14 +848,83 @@ protected: bool should_mark_root); void handle_evacuation_failure_common(oop obj, markOop m); - // Instance of the concurrent mark is_alive closure for embedding - // into the reference processor as the is_alive_non_header. This - // prevents unnecessary additions to the discovered lists during - // concurrent discovery. - G1CMIsAliveClosure _is_alive_closure; + // ("Weak") Reference processing support. + // + // G1 has 2 instances of the referece processor class. One + // (_ref_processor_cm) handles reference object discovery + // and subsequent processing during concurrent marking cycles. + // + // The other (_ref_processor_stw) handles reference object + // discovery and processing during full GCs and incremental + // evacuation pauses. + // + // During an incremental pause, reference discovery will be + // temporarily disabled for _ref_processor_cm and will be + // enabled for _ref_processor_stw. At the end of the evacuation + // pause references discovered by _ref_processor_stw will be + // processed and discovery will be disabled. The previous + // setting for reference object discovery for _ref_processor_cm + // will be re-instated. + // + // At the start of marking: + // * Discovery by the CM ref processor is verified to be inactive + // and it's discovered lists are empty. + // * Discovery by the CM ref processor is then enabled. + // + // At the end of marking: + // * Any references on the CM ref processor's discovered + // lists are processed (possibly MT). + // + // At the start of full GC we: + // * Disable discovery by the CM ref processor and + // empty CM ref processor's discovered lists + // (without processing any entries). + // * Verify that the STW ref processor is inactive and it's + // discovered lists are empty. + // * Temporarily set STW ref processor discovery as single threaded. + // * Temporarily clear the STW ref processor's _is_alive_non_header + // field. + // * Finally enable discovery by the STW ref processor. + // + // The STW ref processor is used to record any discovered + // references during the full GC. + // + // At the end of a full GC we: + // * Enqueue any reference objects discovered by the STW ref processor + // that have non-live referents. This has the side-effect of + // making the STW ref processor inactive by disabling discovery. + // * Verify that the CM ref processor is still inactive + // and no references have been placed on it's discovered + // lists (also checked as a precondition during initial marking). - // ("Weak") Reference processing support - ReferenceProcessor* _ref_processor; + // The (stw) reference processor... + ReferenceProcessor* _ref_processor_stw; + + // During reference object discovery, the _is_alive_non_header + // closure (if non-null) is applied to the referent object to + // determine whether the referent is live. If so then the + // reference object does not need to be 'discovered' and can + // be treated as a regular oop. This has the benefit of reducing + // the number of 'discovered' reference objects that need to + // be processed. + // + // Instance of the is_alive closure for embedding into the + // STW reference processor as the _is_alive_non_header field. + // Supplying a value for the _is_alive_non_header field is + // optional but doing so prevents unnecessary additions to + // the discovered lists during reference discovery. + G1STWIsAliveClosure _is_alive_closure_stw; + + // The (concurrent marking) reference processor... + ReferenceProcessor* _ref_processor_cm; + + // Instance of the concurrent mark is_alive closure for embedding + // into the Concurrent Marking reference processor as the + // _is_alive_non_header field. Supplying a value for the + // _is_alive_non_header field is optional but doing so prevents + // unnecessary additions to the discovered lists during reference + // discovery. + G1CMIsAliveClosure _is_alive_closure_cm; enum G1H_process_strong_roots_tasks { G1H_PS_mark_stack_oops_do, @@ -874,6 +965,7 @@ public: // specified by the policy object. jint initialize(); + // Initialize weak reference processing. virtual void ref_processing_init(); void set_par_threads(int t) { @@ -925,8 +1017,13 @@ public: // The shared block offset table array. G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; } - // Reference Processing accessor - ReferenceProcessor* ref_processor() { return _ref_processor; } + // Reference Processing accessors + + // The STW reference processor.... + ReferenceProcessor* ref_processor_stw() const { return _ref_processor_stw; } + + // The Concurent Marking reference processor... + ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; } virtual size_t capacity() const; virtual size_t used() const; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 92c47409a28..24f96aef85c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -152,8 +152,12 @@ G1CollectorPolicy::G1CollectorPolicy() : _summary(new Summary()), -#ifndef PRODUCT _cur_clear_ct_time_ms(0.0), + + _cur_ref_proc_time_ms(0.0), + _cur_ref_enq_time_ms(0.0), + +#ifndef PRODUCT _min_clear_cc_time_ms(-1.0), _max_clear_cc_time_ms(-1.0), _cur_clear_cc_time_ms(0.0), @@ -1479,6 +1483,8 @@ void G1CollectorPolicy::record_collection_pause_end() { #endif print_stats(1, "Other", other_time_ms); print_stats(2, "Choose CSet", _recorded_young_cset_choice_time_ms); + print_stats(2, "Ref Proc", _cur_ref_proc_time_ms); + print_stats(2, "Ref Enq", _cur_ref_enq_time_ms); for (int i = 0; i < _aux_num; ++i) { if (_cur_aux_times_set[i]) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 9dc7349fa47..2c315729e34 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -119,6 +119,8 @@ protected: double _cur_satb_drain_time_ms; double _cur_clear_ct_time_ms; bool _satb_drain_time_set; + double _cur_ref_proc_time_ms; + double _cur_ref_enq_time_ms; #ifndef PRODUCT // Card Table Count Cache stats @@ -986,6 +988,14 @@ public: _cur_aux_times_ms[i] += ms; } + void record_ref_proc_time(double ms) { + _cur_ref_proc_time_ms = ms; + } + + void record_ref_enq_time(double ms) { + _cur_ref_enq_time_ms = ms; + } + #ifndef PRODUCT void record_cc_clear_time(double ms) { if (_min_clear_cc_time_ms < 0.0 || ms <= _min_clear_cc_time_ms) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp index 1ed4f993d12..84bbadbb951 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp @@ -62,6 +62,8 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, // hook up weak ref data so it can be used during Mark-Sweep assert(GenMarkSweep::ref_processor() == NULL, "no stomping"); assert(rp != NULL, "should be non-NULL"); + assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Precondition"); + GenMarkSweep::_ref_processor = rp; rp->setup_policy(clear_all_softrefs); @@ -139,6 +141,8 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, // Process reference objects found during marking ReferenceProcessor* rp = GenMarkSweep::ref_processor(); + assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Sanity"); + rp->setup_policy(clear_all_softrefs); rp->process_discovered_references(&GenMarkSweep::is_alive, &GenMarkSweep::keep_alive, @@ -166,7 +170,6 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, GenMarkSweep::follow_mdo_weak_refs(); assert(GenMarkSweep::_marking_stack.is_empty(), "just drained"); - // Visit interned string tables and delete unmarked oops StringTable::unlink(&GenMarkSweep::is_alive); // Clean up unreferenced symbols in symbol table. @@ -346,7 +349,8 @@ void G1MarkSweep::mark_sweep_phase3() { NULL, // do not touch code cache here &GenMarkSweep::adjust_pointer_closure); - g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure); + assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity"); + g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure); // Now adjust pointers in remaining weak roots. (All of which should // have been cleared if they pointed to non-surviving objects.) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 73d87a11c66..84e67725f90 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -34,6 +34,7 @@ class CMBitMap; class CMMarkStack; class G1ParScanThreadState; class CMTask; +class ReferenceProcessor; // A class that scans oops in a given heap region (much as OopsInGenClosure // scans oops in a generation.) @@ -59,8 +60,15 @@ public: class G1ParPushHeapRSClosure : public G1ParClosureSuper { public: - G1ParPushHeapRSClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - G1ParClosureSuper(g1, par_scan_state) { } + G1ParPushHeapRSClosure(G1CollectedHeap* g1, + G1ParScanThreadState* par_scan_state, + ReferenceProcessor* rp) : + G1ParClosureSuper(g1, par_scan_state) + { + assert(_ref_processor == NULL, "sanity"); + _ref_processor = rp; + } + template void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -68,8 +76,13 @@ public: class G1ParScanClosure : public G1ParClosureSuper { public: - G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - G1ParClosureSuper(g1, par_scan_state) { } + G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) : + G1ParClosureSuper(g1, par_scan_state) + { + assert(_ref_processor == NULL, "sanity"); + _ref_processor = rp; + } + template void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -92,9 +105,18 @@ template inline oop clear_partial_array_mask(T* ref) { class G1ParScanPartialArrayClosure : public G1ParClosureSuper { G1ParScanClosure _scanner; + public: - G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state) { } + G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) : + G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state, rp) + { + assert(_ref_processor == NULL, "sanity"); + } + + G1ParScanClosure* scanner() { + return &_scanner; + } + template void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -117,10 +139,20 @@ template class G1ParCopyClosure : public G1ParCopyHelper { G1ParScanClosure _scanner; + template void do_oop_work(T* p); + public: - G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { } + G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, + ReferenceProcessor* rp) : + _scanner(g1, par_scan_state, rp), + G1ParCopyHelper(g1, par_scan_state, &_scanner) + { + assert(_ref_processor == NULL, "sanity"); + } + + G1ParScanClosure* scanner() { return &_scanner; } + template void do_oop_nv(T* p) { do_oop_work(p); } @@ -130,21 +162,25 @@ public: typedef G1ParCopyClosure G1ParScanExtRootClosure; typedef G1ParCopyClosure G1ParScanPermClosure; -typedef G1ParCopyClosure G1ParScanHeapRSClosure; + typedef G1ParCopyClosure G1ParScanAndMarkExtRootClosure; typedef G1ParCopyClosure G1ParScanAndMarkPermClosure; -typedef G1ParCopyClosure G1ParScanAndMarkHeapRSClosure; -// This is the only case when we set skip_cset_test. Basically, this -// closure is (should?) only be called directly while we're draining -// the overflow and task queues. In that case we know that the -// reference in question points into the collection set, otherwise we -// would not have pushed it on the queue. The following is defined in -// g1_specialized_oop_closures.hpp. -// typedef G1ParCopyClosure G1ParScanHeapEvacClosure; -// We need a separate closure to handle references during evacuation -// failure processing, as we cannot asume that the reference already -// points into the collection set (like G1ParScanHeapEvacClosure does). +// The following closure types are no longer used but are retained +// for historical reasons: +// typedef G1ParCopyClosure G1ParScanHeapRSClosure; +// typedef G1ParCopyClosure G1ParScanAndMarkHeapRSClosure; + +// The following closure type is defined in g1_specialized_oop_closures.hpp: +// +// typedef G1ParCopyClosure G1ParScanHeapEvacClosure; + +// We use a separate closure to handle references during evacuation +// failure processing. +// We could have used another instance of G1ParScanHeapEvacClosure +// (since that closure no longer assumes that the references it +// handles point into the collection set). + typedef G1ParCopyClosure G1ParScanHeapEvacFailureClosure; class FilterIntoCSClosure: public OopClosure { @@ -153,9 +189,15 @@ class FilterIntoCSClosure: public OopClosure { DirtyCardToOopClosure* _dcto_cl; public: FilterIntoCSClosure( DirtyCardToOopClosure* dcto_cl, - G1CollectedHeap* g1, OopClosure* oc) : + G1CollectedHeap* g1, + OopClosure* oc, + ReferenceProcessor* rp) : _dcto_cl(dcto_cl), _g1(g1), _oc(oc) - {} + { + assert(_ref_processor == NULL, "sanity"); + _ref_processor = rp; + } + template void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 568bb64f505..04a3bf5e5fa 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -234,6 +234,7 @@ void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) { HeapRegion *startRegion = calculateStartRegion(worker_i); ScanRSClosure scanRScl(oc, worker_i); + _g1->collection_set_iterate_from(startRegion, &scanRScl); scanRScl.set_try_claimed(); _g1->collection_set_iterate_from(startRegion, &scanRScl); @@ -283,6 +284,7 @@ void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) { double start = os::elapsedTime(); // Apply the given closure to all remaining log entries. RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); + _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i); // Now there should be no dirty cards. @@ -466,7 +468,7 @@ public: MemRegion scanRegion(start, end); UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set()); - FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl); + FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl, NULL /* rp */); FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl); // We can pass false as the "filter_young" parameter here as: @@ -642,7 +644,7 @@ bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, update_rs_oop_cl.set_from(r); TriggerClosure trigger_cl; - FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl); + FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl, NULL /* rp */); InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl); Mux2Closure mux(&invoke_cl, &update_rs_oop_cl); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index f199cd85f38..36636152e39 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -45,7 +45,7 @@ HeapRegionDCTOC::HeapRegionDCTOC(G1CollectedHeap* g1, FilterKind fk) : ContiguousSpaceDCTOC(hr, cl, precision, NULL), _hr(hr), _fk(fk), _g1(g1) -{} +{ } FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r, OopClosure* oc) : @@ -214,8 +214,37 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, int oop_size; OopClosure* cl2 = cl; - FilterIntoCSClosure intoCSFilt(this, g1h, cl); + + // If we are scanning the remembered sets looking for refs + // into the collection set during an evacuation pause then + // we will want to 'discover' reference objects that point + // to referents in the collection set. + // + // Unfortunately it is an instance of FilterIntoCSClosure + // that is iterated over the reference fields of oops in + // mr (and not the G1ParPushHeapRSClosure - which is the + // cl parameter). + // If we set the _ref_processor field in the FilterIntoCSClosure + // instance, all the reference objects that are walked + // (regardless of whether their referent object's are in + // the cset) will be 'discovered'. + // + // The G1STWIsAlive closure considers a referent object that + // is outside the cset as alive. The G1CopyingKeepAliveClosure + // skips referents that are not in the cset. + // + // Therefore reference objects in mr with a referent that is + // outside the cset should be OK. + + ReferenceProcessor* rp = _cl->_ref_processor; + if (rp != NULL) { + assert(rp == _g1->ref_processor_stw(), "should be stw"); + assert(_fk == IntoCSFilterKind, "should be looking for refs into CS"); + } + + FilterIntoCSClosure intoCSFilt(this, g1h, cl, rp); FilterOutOfRegionClosure outOfRegionFilt(_hr, cl); + switch (_fk) { case IntoCSFilterKind: cl2 = &intoCSFilt; break; case OutOfRegionFilterKind: cl2 = &outOfRegionFilt; break; @@ -239,16 +268,19 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, case NoFilterKind: bottom = walk_mem_region_loop(cl, g1h, _hr, bottom, top); break; + case IntoCSFilterKind: { - FilterIntoCSClosure filt(this, g1h, cl); + FilterIntoCSClosure filt(this, g1h, cl, rp); bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); break; } + case OutOfRegionFilterKind: { FilterOutOfRegionClosure filt(_hr, cl); bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); break; } + default: ShouldNotReachHere(); } @@ -483,7 +515,7 @@ HeapRegion:: HeapRegion(size_t hrs_index, G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr, bool is_zeroed) : G1OffsetTableContigSpace(sharedOffsetArray, mr, is_zeroed), - _next_fk(HeapRegionDCTOC::NoFilterKind), _hrs_index(hrs_index), + _hrs_index(hrs_index), _humongous_type(NotHumongous), _humongous_start_region(NULL), _in_collection_set(false), _next_in_special_set(NULL), _orig_end(NULL), diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 774987dd8af..f2edf01b9f6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -118,7 +118,6 @@ public: FilterKind fk); }; - // The complicating factor is that BlockOffsetTable diverged // significantly, and we need functionality that is only in the G1 version. // So I copied that code, which led to an alternate G1 version of @@ -223,10 +222,6 @@ class HeapRegion: public G1OffsetTableContigSpace { ContinuesHumongous }; - // The next filter kind that should be used for a "new_dcto_cl" call with - // the "traditional" signature. - HeapRegionDCTOC::FilterKind _next_fk; - // Requires that the region "mr" be dense with objects, and begin and end // with an object. void oops_in_mr_iterate(MemRegion mr, OopClosure* cl); @@ -573,40 +568,14 @@ class HeapRegion: public G1OffsetTableContigSpace { // allocated in the current region before the last call to "save_mark". void oop_before_save_marks_iterate(OopClosure* cl); - // This call determines the "filter kind" argument that will be used for - // the next call to "new_dcto_cl" on this region with the "traditional" - // signature (i.e., the call below.) The default, in the absence of a - // preceding call to this method, is "NoFilterKind", and a call to this - // method is necessary for each such call, or else it reverts to the - // default. - // (This is really ugly, but all other methods I could think of changed a - // lot of main-line code for G1.) - void set_next_filter_kind(HeapRegionDCTOC::FilterKind nfk) { - _next_fk = nfk; - } - DirtyCardToOopClosure* new_dcto_closure(OopClosure* cl, CardTableModRefBS::PrecisionStyle precision, HeapRegionDCTOC::FilterKind fk); -#if WHASSUP - DirtyCardToOopClosure* - new_dcto_closure(OopClosure* cl, - CardTableModRefBS::PrecisionStyle precision, - HeapWord* boundary) { - assert(boundary == NULL, "This arg doesn't make sense here."); - DirtyCardToOopClosure* res = new_dcto_closure(cl, precision, _next_fk); - _next_fk = HeapRegionDCTOC::NoFilterKind; - return res; - } -#endif - - // // Note the start or end of marking. This tells the heap region // that the collector is about to start or has finished (concurrently) // marking the heap. - // // Note the start of a marking phase. Record the // start of the unmarked area of the region here. diff --git a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp index 5a7a7b694e8..ea0c19a89a8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp @@ -29,6 +29,7 @@ #include "memory/sharedHeap.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.hpp" +#include "runtime/vmThread.hpp" // This method removes entries from an SATB buffer that will not be // useful to the concurrent marking threads. An entry is removed if it @@ -252,9 +253,18 @@ void SATBMarkQueueSet::par_iterate_closure_all_threads(int worker) { t->satb_mark_queue().apply_closure(_par_closures[worker]); } } - // We'll have worker 0 do this one. - if (worker == 0) { - shared_satb_queue()->apply_closure(_par_closures[0]); + + // We also need to claim the VMThread so that its parity is updated + // otherwise the next call to Thread::possibly_parallel_oops_do inside + // a StrongRootsScope might skip the VMThread because it has a stale + // parity that matches the parity set by the StrongRootsScope + // + // Whichever worker succeeds in claiming the VMThread gets to do + // the shared queue. + + VMThread* vmt = VMThread::vm_thread(); + if (vmt->claim_oops_do(true, parity)) { + shared_satb_queue()->apply_closure(_par_closures[worker]); } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index 3d7e0ba4c2d..f2965e67406 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -198,10 +198,9 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { allocate_stacks(); - NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); COMPILER2_PRESENT(DerivedPointerTable::clear()); - ref_processor()->enable_discovery(); + ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); ref_processor()->setup_policy(clear_all_softrefs); mark_sweep_phase1(clear_all_softrefs); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 55cb34350b2..a62059c68e8 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -2069,10 +2069,9 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { CodeCache::gc_prologue(); Threads::gc_prologue(); - NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); COMPILER2_PRESENT(DerivedPointerTable::clear()); - ref_processor()->enable_discovery(); + ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); ref_processor()->setup_policy(maximum_heap_compaction); bool marked_for_unloading = false; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index b2234676f1e..1094d1708e8 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -350,10 +350,9 @@ bool PSScavenge::invoke_no_policy() { } save_to_space_top_before_gc(); - NOT_PRODUCT(reference_processor()->verify_no_references_recorded()); COMPILER2_PRESENT(DerivedPointerTable::clear()); - reference_processor()->enable_discovery(); + reference_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); reference_processor()->setup_policy(false); // We track how much was promoted to the next generation for diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index f233cbc7b59..d6a54e17e56 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -599,8 +599,7 @@ void GenCollectedHeap::do_collection(bool full, // atomic wrt other collectors in this configuration, we // are guaranteed to have empty discovered ref lists. if (rp->discovery_is_atomic()) { - rp->verify_no_references_recorded(); - rp->enable_discovery(); + rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); rp->setup_policy(do_clear_all_soft_refs); } else { // collect() below will enable discovery as appropriate diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 9b593ef3f75..27a1ff41b12 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -35,42 +35,8 @@ ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; -const int subclasses_of_ref = REF_PHANTOM - REF_OTHER; bool ReferenceProcessor::_pending_list_uses_discovered_field = false; -// List of discovered references. -class DiscoveredList { -public: - DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } - oop head() const { - return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : - _oop_head; - } - HeapWord* adr_head() { - return UseCompressedOops ? (HeapWord*)&_compressed_head : - (HeapWord*)&_oop_head; - } - void set_head(oop o) { - if (UseCompressedOops) { - // Must compress the head ptr. - _compressed_head = oopDesc::encode_heap_oop(o); - } else { - _oop_head = o; - } - } - bool empty() const { return head() == NULL; } - size_t length() { return _len; } - void set_length(size_t len) { _len = len; } - void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } - void dec_length(size_t dec) { _len -= dec; } -private: - // Set value depending on UseCompressedOops. This could be a template class - // but then we have to fix all the instantiations and declarations that use this class. - oop _oop_head; - narrowOop _compressed_head; - size_t _len; -}; - void referenceProcessor_init() { ReferenceProcessor::init_statics(); } @@ -112,7 +78,8 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, _discovery_is_mt = mt_discovery; _num_q = MAX2(1, mt_processing_degree); _max_num_q = MAX2(_num_q, mt_discovery_degree); - _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref); + _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, + _max_num_q * number_of_subclasses_of_ref()); if (_discoveredSoftRefs == NULL) { vm_exit_during_initialization("Could not allocated RefProc Array"); } @@ -120,7 +87,7 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; // Initialized all entries to NULL - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { _discoveredSoftRefs[i].set_head(NULL); _discoveredSoftRefs[i].set_length(0); } @@ -134,19 +101,15 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, #ifndef PRODUCT void ReferenceProcessor::verify_no_references_recorded() { guarantee(!_discovering_refs, "Discovering refs?"); - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - guarantee(_discoveredSoftRefs[i].empty(), + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + guarantee(_discoveredSoftRefs[i].is_empty(), "Found non-empty discovered list"); } } #endif void ReferenceProcessor::weak_oops_do(OopClosure* f) { - // Should this instead be - // for (int i = 0; i < subclasses_of_ref; i++_ { - // for (int j = 0; j < _num_q; j++) { - // int index = i * _max_num_q + j; - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { if (UseCompressedOops) { f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head()); } else { @@ -404,7 +367,7 @@ public: // allocated and are indexed into. assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); for (int j = 0; - j < subclasses_of_ref; + j < ReferenceProcessor::number_of_subclasses_of_ref(); j++, index += _n_queues) { _ref_processor.enqueue_discovered_reflist( _refs_lists[index], _pending_list_addr); @@ -424,7 +387,7 @@ void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr task_executor->execute(tsk); } else { // Serial code: call the parent class's implementation - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); _discoveredSoftRefs[i].set_head(NULL); _discoveredSoftRefs[i].set_length(0); @@ -432,119 +395,7 @@ void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr } } -// Iterator for the list of discovered references. -class DiscoveredListIterator { -public: - inline DiscoveredListIterator(DiscoveredList& refs_list, - OopClosure* keep_alive, - BoolObjectClosure* is_alive); - - // End Of List. - inline bool has_next() const { return _ref != NULL; } - - // Get oop to the Reference object. - inline oop obj() const { return _ref; } - - // Get oop to the referent object. - inline oop referent() const { return _referent; } - - // Returns true if referent is alive. - inline bool is_referent_alive() const; - - // Loads data for the current reference. - // The "allow_null_referent" argument tells us to allow for the possibility - // of a NULL referent in the discovered Reference object. This typically - // happens in the case of concurrent collectors that may have done the - // discovery concurrently, or interleaved, with mutator execution. - inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); - - // Move to the next discovered reference. - inline void next(); - - // Remove the current reference from the list - inline void remove(); - - // Make the Reference object active again. - inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); } - - // Make the referent alive. - inline void make_referent_alive() { - if (UseCompressedOops) { - _keep_alive->do_oop((narrowOop*)_referent_addr); - } else { - _keep_alive->do_oop((oop*)_referent_addr); - } - } - - // Update the discovered field. - inline void update_discovered() { - // First _prev_next ref actually points into DiscoveredList (gross). - if (UseCompressedOops) { - if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { - _keep_alive->do_oop((narrowOop*)_prev_next); - } - } else { - if (!oopDesc::is_null(*(oop*)_prev_next)) { - _keep_alive->do_oop((oop*)_prev_next); - } - } - } - - // NULL out referent pointer. - inline void clear_referent() { oop_store_raw(_referent_addr, NULL); } - - // Statistics - NOT_PRODUCT( - inline size_t processed() const { return _processed; } - inline size_t removed() const { return _removed; } - ) - - inline void move_to_next(); - -private: - DiscoveredList& _refs_list; - HeapWord* _prev_next; - oop _prev; - oop _ref; - HeapWord* _discovered_addr; - oop _next; - HeapWord* _referent_addr; - oop _referent; - OopClosure* _keep_alive; - BoolObjectClosure* _is_alive; - DEBUG_ONLY( - oop _first_seen; // cyclic linked list check - ) - NOT_PRODUCT( - size_t _processed; - size_t _removed; - ) -}; - -inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, - OopClosure* keep_alive, - BoolObjectClosure* is_alive) - : _refs_list(refs_list), - _prev_next(refs_list.adr_head()), - _prev(NULL), - _ref(refs_list.head()), -#ifdef ASSERT - _first_seen(refs_list.head()), -#endif -#ifndef PRODUCT - _processed(0), - _removed(0), -#endif - _next(NULL), - _keep_alive(keep_alive), - _is_alive(is_alive) -{ } - -inline bool DiscoveredListIterator::is_referent_alive() const { - return _is_alive->do_object_b(_referent); -} - -inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { +void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref); oop discovered = java_lang_ref_Reference::discovered(_ref); assert(_discovered_addr && discovered->is_oop_or_null(), @@ -560,13 +411,7 @@ inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referen "bad referent"); } -inline void DiscoveredListIterator::next() { - _prev_next = _discovered_addr; - _prev = _ref; - move_to_next(); -} - -inline void DiscoveredListIterator::remove() { +void DiscoveredListIterator::remove() { assert(_ref->is_oop(), "Dropping a bad reference"); oop_store_raw(_discovered_addr, NULL); @@ -592,15 +437,29 @@ inline void DiscoveredListIterator::remove() { _refs_list.dec_length(1); } -inline void DiscoveredListIterator::move_to_next() { - if (_ref == _next) { - // End of the list. - _ref = NULL; +// Make the Reference object active again. +void DiscoveredListIterator::make_active() { + // For G1 we don't want to use set_next - it + // will dirty the card for the next field of + // the reference object and will fail + // CT verification. + if (UseG1GC) { + BarrierSet* bs = oopDesc::bs(); + HeapWord* next_addr = java_lang_ref_Reference::next_addr(_ref); + + if (UseCompressedOops) { + bs->write_ref_field_pre((narrowOop*)next_addr, NULL); + } else { + bs->write_ref_field_pre((oop*)next_addr, NULL); + } + java_lang_ref_Reference::set_next_raw(_ref, NULL); } else { - _ref = _next; + java_lang_ref_Reference::set_next(_ref, NULL); } - assert(_ref != _first_seen, "cyclic ref_list found"); - NOT_PRODUCT(_processed++); +} + +void DiscoveredListIterator::clear_referent() { + oop_store_raw(_referent_addr, NULL); } // NOTE: process_phase*() are largely similar, and at a high level @@ -786,10 +645,9 @@ ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { void ReferenceProcessor::abandon_partial_discovery() { // loop over the lists - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { - gclog_or_tty->print_cr("\nAbandoning %s discovered list", - list_name(i)); + gclog_or_tty->print_cr("\nAbandoning %s discovered list", list_name(i)); } abandon_partial_discovered_list(_discoveredSoftRefs[i]); } @@ -858,6 +716,14 @@ private: bool _clear_referent; }; +void ReferenceProcessor::set_discovered(oop ref, oop value) { + if (_discovered_list_needs_barrier) { + java_lang_ref_Reference::set_discovered(ref, value); + } else { + java_lang_ref_Reference::set_discovered_raw(ref, value); + } +} + // Balances reference queues. // Move entries from all queues[0, 1, ..., _max_num_q-1] to // queues[0, 1, ..., _num_q-1] because only the first _num_q @@ -915,9 +781,9 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) // Add the chain to the to list. if (ref_lists[to_idx].head() == NULL) { // to list is empty. Make a loop at the end. - java_lang_ref_Reference::set_discovered(move_tail, move_tail); + set_discovered(move_tail, move_tail); } else { - java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); + set_discovered(move_tail, ref_lists[to_idx].head()); } ref_lists[to_idx].set_head(move_head); ref_lists[to_idx].inc_length(refs_to_move); @@ -1038,11 +904,7 @@ ReferenceProcessor::process_discovered_reflist( void ReferenceProcessor::clean_up_discovered_references() { // loop over the lists - // Should this instead be - // for (int i = 0; i < subclasses_of_ref; i++_ { - // for (int j = 0; j < _num_q; j++) { - // int index = i * _max_num_q + j; - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { gclog_or_tty->print_cr( "\nScrubbing %s discovered list of Null referents", @@ -1260,6 +1122,8 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { } } + ResourceMark rm; // Needed for tracing. + HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj); const oop discovered = java_lang_ref_Reference::discovered(obj); assert(discovered->is_oop_or_null(), "bad discovered field"); @@ -1472,7 +1336,9 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, } const char* ReferenceProcessor::list_name(int i) { - assert(i >= 0 && i <= _max_num_q * subclasses_of_ref, "Out of bounds index"); + assert(i >= 0 && i <= _max_num_q * number_of_subclasses_of_ref(), + "Out of bounds index"); + int j = i / _max_num_q; switch (j) { case 0: return "SoftRef"; @@ -1493,7 +1359,7 @@ void ReferenceProcessor::verify_ok_to_handle_reflists() { #ifndef PRODUCT void ReferenceProcessor::clear_discovered_references() { guarantee(!_discovering_refs, "Discovering refs?"); - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { clear_discovered_references(_discoveredSoftRefs[i]); } } diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index 8178f60ea7b..63ed31ddd2a 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -48,18 +48,175 @@ // forward references class ReferencePolicy; class AbstractRefProcTaskExecutor; -class DiscoveredList; + +// List of discovered references. +class DiscoveredList { +public: + DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } + oop head() const { + return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : + _oop_head; + } + HeapWord* adr_head() { + return UseCompressedOops ? (HeapWord*)&_compressed_head : + (HeapWord*)&_oop_head; + } + void set_head(oop o) { + if (UseCompressedOops) { + // Must compress the head ptr. + _compressed_head = oopDesc::encode_heap_oop(o); + } else { + _oop_head = o; + } + } + bool is_empty() const { return head() == NULL; } + size_t length() { return _len; } + void set_length(size_t len) { _len = len; } + void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } + void dec_length(size_t dec) { _len -= dec; } +private: + // Set value depending on UseCompressedOops. This could be a template class + // but then we have to fix all the instantiations and declarations that use this class. + oop _oop_head; + narrowOop _compressed_head; + size_t _len; +}; + +// Iterator for the list of discovered references. +class DiscoveredListIterator { +private: + DiscoveredList& _refs_list; + HeapWord* _prev_next; + oop _prev; + oop _ref; + HeapWord* _discovered_addr; + oop _next; + HeapWord* _referent_addr; + oop _referent; + OopClosure* _keep_alive; + BoolObjectClosure* _is_alive; + + DEBUG_ONLY( + oop _first_seen; // cyclic linked list check + ) + + NOT_PRODUCT( + size_t _processed; + size_t _removed; + ) + +public: + inline DiscoveredListIterator(DiscoveredList& refs_list, + OopClosure* keep_alive, + BoolObjectClosure* is_alive): + _refs_list(refs_list), + _prev_next(refs_list.adr_head()), + _prev(NULL), + _ref(refs_list.head()), +#ifdef ASSERT + _first_seen(refs_list.head()), +#endif +#ifndef PRODUCT + _processed(0), + _removed(0), +#endif + _next(NULL), + _keep_alive(keep_alive), + _is_alive(is_alive) +{ } + + // End Of List. + inline bool has_next() const { return _ref != NULL; } + + // Get oop to the Reference object. + inline oop obj() const { return _ref; } + + // Get oop to the referent object. + inline oop referent() const { return _referent; } + + // Returns true if referent is alive. + inline bool is_referent_alive() const { + return _is_alive->do_object_b(_referent); + } + + // Loads data for the current reference. + // The "allow_null_referent" argument tells us to allow for the possibility + // of a NULL referent in the discovered Reference object. This typically + // happens in the case of concurrent collectors that may have done the + // discovery concurrently, or interleaved, with mutator execution. + void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); + + // Move to the next discovered reference. + inline void next() { + _prev_next = _discovered_addr; + _prev = _ref; + move_to_next(); + } + + // Remove the current reference from the list + void remove(); + + // Make the Reference object active again. + void make_active(); + + // Make the referent alive. + inline void make_referent_alive() { + if (UseCompressedOops) { + _keep_alive->do_oop((narrowOop*)_referent_addr); + } else { + _keep_alive->do_oop((oop*)_referent_addr); + } + } + + // Update the discovered field. + inline void update_discovered() { + // First _prev_next ref actually points into DiscoveredList (gross). + if (UseCompressedOops) { + if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { + _keep_alive->do_oop((narrowOop*)_prev_next); + } + } else { + if (!oopDesc::is_null(*(oop*)_prev_next)) { + _keep_alive->do_oop((oop*)_prev_next); + } + } + } + + // NULL out referent pointer. + void clear_referent(); + + // Statistics + NOT_PRODUCT( + inline size_t processed() const { return _processed; } + inline size_t removed() const { return _removed; } + ) + + inline void move_to_next() { + if (_ref == _next) { + // End of the list. + _ref = NULL; + } else { + _ref = _next; + } + assert(_ref != _first_seen, "cyclic ref_list found"); + NOT_PRODUCT(_processed++); + } + +}; class ReferenceProcessor : public CHeapObj { protected: // Compatibility with pre-4965777 JDK's static bool _pending_list_uses_discovered_field; - MemRegion _span; // (right-open) interval of heap - // subject to wkref discovery - bool _discovering_refs; // true when discovery enabled - bool _discovery_is_atomic; // if discovery is atomic wrt - // other collectors in configuration - bool _discovery_is_mt; // true if reference discovery is MT. + + MemRegion _span; // (right-open) interval of heap + // subject to wkref discovery + + bool _discovering_refs; // true when discovery enabled + bool _discovery_is_atomic; // if discovery is atomic wrt + // other collectors in configuration + bool _discovery_is_mt; // true if reference discovery is MT. + // If true, setting "next" field of a discovered refs list requires // write barrier(s). (Must be true if used in a collector in which // elements of a discovered list may be moved during discovery: for @@ -67,18 +224,19 @@ class ReferenceProcessor : public CHeapObj { // long-term concurrent marking phase that does weak reference // discovery.) bool _discovered_list_needs_barrier; - BarrierSet* _bs; // Cached copy of BarrierSet. - bool _enqueuing_is_done; // true if all weak references enqueued - bool _processing_is_mt; // true during phases when - // reference processing is MT. - int _next_id; // round-robin mod _num_q counter in - // support of work distribution - // For collectors that do not keep GC marking information + BarrierSet* _bs; // Cached copy of BarrierSet. + bool _enqueuing_is_done; // true if all weak references enqueued + bool _processing_is_mt; // true during phases when + // reference processing is MT. + int _next_id; // round-robin mod _num_q counter in + // support of work distribution + + // For collectors that do not keep GC liveness information // in the object header, this field holds a closure that // helps the reference processor determine the reachability - // of an oop (the field is currently initialized to NULL for - // all collectors but the CMS collector). + // of an oop. It is currently initialized to NULL for all + // collectors except for CMS and G1. BoolObjectClosure* _is_alive_non_header; // Soft ref clearing policies @@ -102,10 +260,13 @@ class ReferenceProcessor : public CHeapObj { DiscoveredList* _discoveredPhantomRefs; public: - int num_q() { return _num_q; } - int max_num_q() { return _max_num_q; } - void set_active_mt_degree(int v) { _num_q = v; } - DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } + static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); } + + int num_q() { return _num_q; } + int max_num_q() { return _max_num_q; } + void set_active_mt_degree(int v) { _num_q = v; } + DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } + ReferencePolicy* setup_policy(bool always_clear) { _current_soft_ref_policy = always_clear ? _always_clear_soft_ref_policy : _default_soft_ref_policy; @@ -205,6 +366,11 @@ class ReferenceProcessor : public CHeapObj { void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); protected: + // Set the 'discovered' field of the given reference to + // the given value - emitting barriers depending upon + // the value of _discovered_list_needs_barrier. + void set_discovered(oop ref, oop value); + // "Preclean" the given discovered reference list // by removing references with strongly reachable referents. // Currently used in support of CMS only. @@ -290,7 +456,19 @@ class ReferenceProcessor : public CHeapObj { void set_span(MemRegion span) { _span = span; } // start and stop weak ref discovery - void enable_discovery() { _discovering_refs = true; } + void enable_discovery(bool verify_disabled, bool check_no_refs) { +#ifdef ASSERT + // Verify that we're not currently discovering refs + assert(!verify_disabled || !_discovering_refs, "nested call?"); + + if (check_no_refs) { + // Verify that the discovered lists are empty + verify_no_references_recorded(); + } +#endif // ASSERT + _discovering_refs = true; + } + void disable_discovery() { _discovering_refs = false; } bool discovery_enabled() { return _discovering_refs; } @@ -365,7 +543,7 @@ class NoRefDiscovery: StackObj { ~NoRefDiscovery() { if (_was_discovering_refs) { - _rp->enable_discovery(); + _rp->enable_discovery(true /*verify_disabled*/, false /*check_no_refs*/); } } }; diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 5b5138e8350..8b7059c8389 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -749,8 +749,9 @@ bool Thread::claim_oops_do_par_case(int strong_roots_parity) { jint thread_parity = _oops_do_parity; if (thread_parity != strong_roots_parity) { jint res = Atomic::cmpxchg(strong_roots_parity, &_oops_do_parity, thread_parity); - if (res == thread_parity) return true; - else { + if (res == thread_parity) { + return true; + } else { guarantee(res == strong_roots_parity, "Or else what?"); assert(SharedHeap::heap()->n_par_threads() > 0, "Should only fail when parallel."); @@ -3905,8 +3906,9 @@ void Threads::possibly_parallel_oops_do(OopClosure* f, CodeBlobClosure* cf) { } } VMThread* vmt = VMThread::vm_thread(); - if (vmt->claim_oops_do(is_par, cp)) + if (vmt->claim_oops_do(is_par, cp)) { vmt->oops_do(f, cf); + } } #ifndef SERIALGC From 55c503aea2d0ffe9e7b479124a9b7a84a950d793 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Fri, 23 Sep 2011 16:07:49 -0400 Subject: [PATCH 058/214] 7075646: G1: fix inconsistencies in the monitoring data Fixed a few inconsistencies in the monitoring data, in particular when reported from jstat. Reviewed-by: jmasa, brutisso, johnc --- .../gc_implementation/g1/g1CollectedHeap.cpp | 17 +- .../gc_implementation/g1/g1CollectedHeap.hpp | 5 +- .../g1/g1CollectorPolicy.hpp | 4 + .../g1/g1MonitoringSupport.cpp | 235 +++++++++++----- .../g1/g1MonitoringSupport.hpp | 256 +++++++++++------- .../vm/gc_implementation/g1/heapRegion.hpp | 5 + .../shared/generationCounters.cpp | 45 ++- .../shared/generationCounters.hpp | 23 +- .../src/share/vm/services/g1MemoryPool.cpp | 56 +--- .../src/share/vm/services/g1MemoryPool.hpp | 41 +-- 10 files changed, 419 insertions(+), 268 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 66ca7442c5f..b71f058a82f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -816,6 +816,11 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) { result = humongous_obj_allocate_initialize_regions(first, num_regions, word_size); assert(result != NULL, "it should always return a valid result"); + + // A successful humongous object allocation changes the used space + // information of the old generation so we need to recalculate the + // sizes and update the jstat counters here. + g1mm()->update_sizes(); } verify_region_sets_optional(); @@ -1422,7 +1427,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, if (PrintHeapAtGC) { Universe::print_heap_after_gc(); } - g1mm()->update_counters(); + g1mm()->update_sizes(); post_full_gc_dump(); return true; @@ -1790,6 +1795,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _evac_failure_scan_stack(NULL) , _mark_in_progress(false), _cg1r(NULL), _summary_bytes_used(0), + _g1mm(NULL), _refine_cte_cl(NULL), _full_collection(false), _free_list("Master Free List"), @@ -2069,7 +2075,7 @@ jint G1CollectedHeap::initialize() { // Do create of the monitoring and management support so that // values in the heap have been properly initialized. - _g1mm = new G1MonitoringSupport(this, &_g1_storage); + _g1mm = new G1MonitoringSupport(this); return JNI_OK; } @@ -3702,7 +3708,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { if (PrintHeapAtGC) { Universe::print_heap_after_gc(); } - g1mm()->update_counters(); + g1mm()->update_sizes(); if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) && @@ -5815,7 +5821,6 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, g1_policy()->update_region_num(true /* next_is_young */); set_region_short_lived_locked(new_alloc_region); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Eden, young_list_full); - g1mm()->update_eden_counters(); return new_alloc_region; } } @@ -5830,6 +5835,10 @@ void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region, g1_policy()->add_region_to_incremental_cset_lhs(alloc_region); _summary_bytes_used += allocated_bytes; _hr_printer.retire(alloc_region); + // We update the eden sizes here, when the region is retired, + // instead of when it's allocated, since this is the point that its + // used space has been recored in _summary_bytes_used. + g1mm()->update_eden_size(); } HeapRegion* MutatorAllocRegion::allocate_new_region(size_t word_size, diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 9dcf1a82556..76bf194a9c7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -597,7 +597,10 @@ protected: public: - G1MonitoringSupport* g1mm() { return _g1mm; } + G1MonitoringSupport* g1mm() { + assert(_g1mm != NULL, "should have been initialized"); + return _g1mm; + } // Expand the garbage-first heap by at least the given size (in bytes!). // Returns true if the heap was expanded by the requested amount; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 2c315729e34..4e613951831 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -1149,6 +1149,10 @@ public: return young_list_length < young_list_max_length; } + size_t young_list_max_length() { + return _young_list_max_length; + } + void update_region_num(bool young); bool full_young_gcs() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp index aab16dba661..d22dc7a3564 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp @@ -27,19 +27,69 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" -G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h, - VirtualSpace* g1_storage_addr) : +G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm, + const char* name, + int ordinal, int spaces, + size_t min_capacity, + size_t max_capacity, + size_t curr_capacity) + : GenerationCounters(name, ordinal, spaces, min_capacity, + max_capacity, curr_capacity), _g1mm(g1mm) { } + +// We pad the capacity three times given that the young generation +// contains three spaces (eden and two survivors). +G1YoungGenerationCounters::G1YoungGenerationCounters(G1MonitoringSupport* g1mm, + const char* name) + : G1GenerationCounters(g1mm, name, 0 /* ordinal */, 3 /* spaces */, + G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */, + G1MonitoringSupport::pad_capacity(g1mm->young_gen_max(), 3), + G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) { + update_all(); +} + +G1OldGenerationCounters::G1OldGenerationCounters(G1MonitoringSupport* g1mm, + const char* name) + : G1GenerationCounters(g1mm, name, 1 /* ordinal */, 1 /* spaces */, + G1MonitoringSupport::pad_capacity(0) /* min_capacity */, + G1MonitoringSupport::pad_capacity(g1mm->old_gen_max()), + G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) { + update_all(); +} + +void G1YoungGenerationCounters::update_all() { + size_t committed = + G1MonitoringSupport::pad_capacity(_g1mm->young_gen_committed(), 3); + _current_size->set_value(committed); +} + +void G1OldGenerationCounters::update_all() { + size_t committed = + G1MonitoringSupport::pad_capacity(_g1mm->old_gen_committed()); + _current_size->set_value(committed); +} + +G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : _g1h(g1h), _incremental_collection_counters(NULL), _full_collection_counters(NULL), - _non_young_collection_counters(NULL), + _old_collection_counters(NULL), _old_space_counters(NULL), _young_collection_counters(NULL), _eden_counters(NULL), _from_counters(NULL), _to_counters(NULL), - _g1_storage_addr(g1_storage_addr) -{ + + _overall_reserved(0), + _overall_committed(0), _overall_used(0), + _young_region_num(0), + _young_gen_committed(0), + _eden_committed(0), _eden_used(0), + _survivor_committed(0), _survivor_used(0), + _old_committed(0), _old_used(0) { + + _overall_reserved = g1h->max_capacity(); + recalculate_sizes(); + // Counters for GC collections // // name "collector.0". In a generational collector this would be the @@ -69,110 +119,147 @@ G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h, // generational GC terms. The "1, 1" parameters are for // the n-th generation (=1) with 1 space. // Counters are created from minCapacity, maxCapacity, and capacity - _non_young_collection_counters = - new GenerationCounters("whole heap", 1, 1, _g1_storage_addr); + _old_collection_counters = new G1OldGenerationCounters(this, "old"); // name "generation.1.space.0" // Counters are created from maxCapacity, capacity, initCapacity, // and used. - _old_space_counters = new HSpaceCounters("space", 0, - _g1h->max_capacity(), _g1h->capacity(), _non_young_collection_counters); + _old_space_counters = new HSpaceCounters("space", 0 /* ordinal */, + pad_capacity(overall_reserved()) /* max_capacity */, + pad_capacity(old_space_committed()) /* init_capacity */, + _old_collection_counters); // Young collection set // name "generation.0". This is logically the young generation. // The "0, 3" are paremeters for the n-th genertaion (=0) with 3 spaces. - // See _non_young_collection_counters for additional counters - _young_collection_counters = new GenerationCounters("young", 0, 3, NULL); + // See _old_collection_counters for additional counters + _young_collection_counters = new G1YoungGenerationCounters(this, "young"); - // Replace "max_heap_byte_size() with maximum young gen size for - // g1Collectedheap // name "generation.0.space.0" // See _old_space_counters for additional counters - _eden_counters = new HSpaceCounters("eden", 0, - _g1h->max_capacity(), eden_space_committed(), + _eden_counters = new HSpaceCounters("eden", 0 /* ordinal */, + pad_capacity(overall_reserved()) /* max_capacity */, + pad_capacity(eden_space_committed()) /* init_capacity */, _young_collection_counters); // name "generation.0.space.1" // See _old_space_counters for additional counters // Set the arguments to indicate that this survivor space is not used. - _from_counters = new HSpaceCounters("s0", 1, (long) 0, (long) 0, + _from_counters = new HSpaceCounters("s0", 1 /* ordinal */, + pad_capacity(0) /* max_capacity */, + pad_capacity(0) /* init_capacity */, _young_collection_counters); + // Given that this survivor space is not used, we update it here + // once to reflect that its used space is 0 so that we don't have to + // worry about updating it again later. + _from_counters->update_used(0); // name "generation.0.space.2" // See _old_space_counters for additional counters - _to_counters = new HSpaceCounters("s1", 2, - _g1h->max_capacity(), - survivor_space_committed(), + _to_counters = new HSpaceCounters("s1", 2 /* ordinal */, + pad_capacity(overall_reserved()) /* max_capacity */, + pad_capacity(survivor_space_committed()) /* init_capacity */, _young_collection_counters); } -size_t G1MonitoringSupport::overall_committed() { - return g1h()->capacity(); +void G1MonitoringSupport::recalculate_sizes() { + G1CollectedHeap* g1 = g1h(); + + // Recalculate all the sizes from scratch. We assume that this is + // called at a point where no concurrent updates to the various + // values we read here are possible (i.e., at a STW phase at the end + // of a GC). + + size_t young_list_length = g1->young_list()->length(); + size_t survivor_list_length = g1->g1_policy()->recorded_survivor_regions(); + assert(young_list_length >= survivor_list_length, "invariant"); + size_t eden_list_length = young_list_length - survivor_list_length; + // Max length includes any potential extensions to the young gen + // we'll do when the GC locker is active. + size_t young_list_max_length = g1->g1_policy()->young_list_max_length(); + assert(young_list_max_length >= survivor_list_length, "invariant"); + size_t eden_list_max_length = young_list_max_length - survivor_list_length; + + _overall_used = g1->used_unlocked(); + _eden_used = eden_list_length * HeapRegion::GrainBytes; + _survivor_used = survivor_list_length * HeapRegion::GrainBytes; + _young_region_num = young_list_length; + _old_used = subtract_up_to_zero(_overall_used, _eden_used + _survivor_used); + + // First calculate the committed sizes that can be calculated independently. + _survivor_committed = _survivor_used; + _old_committed = HeapRegion::align_up_to_region_byte_size(_old_used); + + // Next, start with the overall committed size. + _overall_committed = g1->capacity(); + size_t committed = _overall_committed; + + // Remove the committed size we have calculated so far (for the + // survivor and old space). + assert(committed >= (_survivor_committed + _old_committed), "sanity"); + committed -= _survivor_committed + _old_committed; + + // Next, calculate and remove the committed size for the eden. + _eden_committed = eden_list_max_length * HeapRegion::GrainBytes; + // Somewhat defensive: be robust in case there are inaccuracies in + // the calculations + _eden_committed = MIN2(_eden_committed, committed); + committed -= _eden_committed; + + // Finally, give the rest to the old space... + _old_committed += committed; + // ..and calculate the young gen committed. + _young_gen_committed = _eden_committed + _survivor_committed; + + assert(_overall_committed == + (_eden_committed + _survivor_committed + _old_committed), + "the committed sizes should add up"); + // Somewhat defensive: cap the eden used size to make sure it + // never exceeds the committed size. + _eden_used = MIN2(_eden_used, _eden_committed); + // _survivor_committed and _old_committed are calculated in terms of + // the corresponding _*_used value, so the next two conditions + // should hold. + assert(_survivor_used <= _survivor_committed, "post-condition"); + assert(_old_used <= _old_committed, "post-condition"); } -size_t G1MonitoringSupport::overall_used() { - return g1h()->used_unlocked(); +void G1MonitoringSupport::recalculate_eden_size() { + G1CollectedHeap* g1 = g1h(); + + // When a new eden region is allocated, only the eden_used size is + // affected (since we have recalculated everything else at the last GC). + + size_t young_region_num = g1h()->young_list()->length(); + if (young_region_num > _young_region_num) { + size_t diff = young_region_num - _young_region_num; + _eden_used += diff * HeapRegion::GrainBytes; + // Somewhat defensive: cap the eden used size to make sure it + // never exceeds the committed size. + _eden_used = MIN2(_eden_used, _eden_committed); + _young_region_num = young_region_num; + } } -size_t G1MonitoringSupport::eden_space_committed() { - return MAX2(eden_space_used(), (size_t) HeapRegion::GrainBytes); -} - -size_t G1MonitoringSupport::eden_space_used() { - size_t young_list_length = g1h()->young_list()->length(); - size_t eden_used = young_list_length * HeapRegion::GrainBytes; - size_t survivor_used = survivor_space_used(); - eden_used = subtract_up_to_zero(eden_used, survivor_used); - return eden_used; -} - -size_t G1MonitoringSupport::survivor_space_committed() { - return MAX2(survivor_space_used(), - (size_t) HeapRegion::GrainBytes); -} - -size_t G1MonitoringSupport::survivor_space_used() { - size_t survivor_num = g1h()->g1_policy()->recorded_survivor_regions(); - size_t survivor_used = survivor_num * HeapRegion::GrainBytes; - return survivor_used; -} - -size_t G1MonitoringSupport::old_space_committed() { - size_t committed = overall_committed(); - size_t eden_committed = eden_space_committed(); - size_t survivor_committed = survivor_space_committed(); - committed = subtract_up_to_zero(committed, eden_committed); - committed = subtract_up_to_zero(committed, survivor_committed); - committed = MAX2(committed, (size_t) HeapRegion::GrainBytes); - return committed; -} - -// See the comment near the top of g1MonitoringSupport.hpp for -// an explanation of these calculations for "used" and "capacity". -size_t G1MonitoringSupport::old_space_used() { - size_t used = overall_used(); - size_t eden_used = eden_space_used(); - size_t survivor_used = survivor_space_used(); - used = subtract_up_to_zero(used, eden_used); - used = subtract_up_to_zero(used, survivor_used); - return used; -} - -void G1MonitoringSupport::update_counters() { +void G1MonitoringSupport::update_sizes() { + recalculate_sizes(); if (UsePerfData) { - eden_counters()->update_capacity(eden_space_committed()); + eden_counters()->update_capacity(pad_capacity(eden_space_committed())); eden_counters()->update_used(eden_space_used()); - to_counters()->update_capacity(survivor_space_committed()); + // only the to survivor space (s1) is active, so we don't need to + // update the counteres for the from survivor space (s0) + to_counters()->update_capacity(pad_capacity(survivor_space_committed())); to_counters()->update_used(survivor_space_used()); - old_space_counters()->update_capacity(old_space_committed()); + old_space_counters()->update_capacity(pad_capacity(old_space_committed())); old_space_counters()->update_used(old_space_used()); - non_young_collection_counters()->update_all(); + old_collection_counters()->update_all(); + young_collection_counters()->update_all(); } } -void G1MonitoringSupport::update_eden_counters() { +void G1MonitoringSupport::update_eden_size() { + recalculate_eden_size(); if (UsePerfData) { - eden_counters()->update_capacity(eden_space_committed()); eden_counters()->update_used(eden_space_used()); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp index 61de266fe5f..aa142916b94 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp @@ -28,101 +28,93 @@ #include "gc_implementation/shared/hSpaceCounters.hpp" class G1CollectedHeap; -class G1SpaceMonitoringSupport; -// Class for monitoring logical spaces in G1. -// G1 defines a set of regions as a young -// collection (analogous to a young generation). -// The young collection is a logical generation -// with no fixed chunk (see space.hpp) reflecting -// the address space for the generation. In addition -// to the young collection there is its complement -// the non-young collection that is simply the regions -// not in the young collection. The non-young collection -// is treated here as a logical old generation only -// because the monitoring tools expect a generational -// heap. The monitoring tools expect that a Space -// (see space.hpp) exists that describe the -// address space of young collection and non-young -// collection and such a view is provided here. +// Class for monitoring logical spaces in G1. It provides data for +// both G1's jstat counters as well as G1's memory pools. // -// This class provides interfaces to access -// the value of variables for the young collection -// that include the "capacity" and "used" of the -// young collection along with constant values -// for the minimum and maximum capacities for -// the logical spaces. Similarly for the non-young -// collection. +// G1 splits the heap into heap regions and each heap region belongs +// to one of the following categories: // -// Also provided are counters for G1 concurrent collections -// and stop-the-world full heap collecitons. +// * eden : regions that have been allocated since the last GC +// * survivors : regions with objects that survived the last few GCs +// * old : long-lived non-humongous regions +// * humongous : humongous regions +// * free : free regions // -// Below is a description of how "used" and "capactiy" -// (or committed) is calculated for the logical spaces. +// The combination of eden and survivor regions form the equivalent of +// the young generation in the other GCs. The combination of old and +// humongous regions form the equivalent of the old generation in the +// other GCs. Free regions do not have a good equivalent in the other +// GCs given that they can be allocated as any of the other region types. // -// 1) The used space calculation for a pool is not necessarily -// independent of the others. We can easily get from G1 the overall -// used space in the entire heap, the number of regions in the young -// generation (includes both eden and survivors), and the number of -// survivor regions. So, from that we calculate: +// The monitoring tools expect the heap to contain a number of +// generations (young, old, perm) and each generation to contain a +// number of spaces (young: eden, survivors, old). Given that G1 does +// not maintain those spaces physically (e.g., the set of +// non-contiguous eden regions can be considered as a "logical" +// space), we'll provide the illusion that those generations and +// spaces exist. In reality, each generation and space refers to a set +// of heap regions that are potentially non-contiguous. // -// survivor_used = survivor_num * region_size -// eden_used = young_region_num * region_size - survivor_used -// old_gen_used = overall_used - eden_used - survivor_used +// This class provides interfaces to access the min, current, and max +// capacity and current occupancy for each of G1's logical spaces and +// generations we expose to the monitoring tools. Also provided are +// counters for G1 concurrent collections and stop-the-world full heap +// collections. // -// Note that survivor_used and eden_used are upper bounds. To get the -// actual value we would have to iterate over the regions and add up -// ->used(). But that'd be expensive. So, we'll accept some lack of -// accuracy for those two. But, we have to be careful when calculating -// old_gen_used, in case we subtract from overall_used more then the -// actual number and our result goes negative. +// Below is a description of how the various sizes are calculated. // -// 2) Calculating the used space is straightforward, as described -// above. However, how do we calculate the committed space, given that -// we allocate space for the eden, survivor, and old gen out of the -// same pool of regions? One way to do this is to use the used value -// as also the committed value for the eden and survivor spaces and -// then calculate the old gen committed space as follows: +// * Current Capacity // -// old_gen_committed = overall_committed - eden_committed - survivor_committed +// - heap_capacity = current heap capacity (e.g., current committed size) +// - young_gen_capacity = current max young gen target capacity +// (i.e., young gen target capacity + max allowed expansion capacity) +// - survivor_capacity = current survivor region capacity +// - eden_capacity = young_gen_capacity - survivor_capacity +// - old_capacity = heap_capacity - young_gen_capacity // -// Maybe a better way to do that would be to calculate used for eden -// and survivor as a sum of ->used() over their regions and then -// calculate committed as region_num * region_size (i.e., what we use -// to calculate the used space now). This is something to consider -// in the future. +// What we do in the above is to distribute the free regions among +// eden_capacity and old_capacity. // -// 3) Another decision that is again not straightforward is what is -// the max size that each memory pool can grow to. One way to do this -// would be to use the committed size for the max for the eden and -// survivors and calculate the old gen max as follows (basically, it's -// a similar pattern to what we use for the committed space, as -// described above): +// * Occupancy // -// old_gen_max = overall_max - eden_max - survivor_max +// - young_gen_used = current young region capacity +// - survivor_used = survivor_capacity +// - eden_used = young_gen_used - survivor_used +// - old_used = overall_used - young_gen_used // -// Unfortunately, the above makes the max of each pool fluctuate over -// time and, even though this is allowed according to the spec, it -// broke several assumptions in the M&M framework (there were cases -// where used would reach a value greater than max). So, for max we -// use -1, which means "undefined" according to the spec. +// Unfortunately, we currently only keep track of the number of +// currently allocated young and survivor regions + the overall used +// bytes in the heap, so the above can be a little inaccurate. // -// 4) Now, there is a very subtle issue with all the above. The -// framework will call get_memory_usage() on the three pools -// asynchronously. As a result, each call might get a different value -// for, say, survivor_num which will yield inconsistent values for -// eden_used, survivor_used, and old_gen_used (as survivor_num is used -// in the calculation of all three). This would normally be -// ok. However, it's possible that this might cause the sum of -// eden_used, survivor_used, and old_gen_used to go over the max heap -// size and this seems to sometimes cause JConsole (and maybe other -// clients) to get confused. There's not a really an easy / clean -// solution to this problem, due to the asynchrounous nature of the -// framework. +// * Min Capacity +// +// We set this to 0 for all spaces. We could consider setting the old +// min capacity to the min capacity of the heap (see 7078465). +// +// * Max Capacity +// +// For jstat, we set the max capacity of all spaces to heap_capacity, +// given that we don't always have a reasonably upper bound on how big +// each space can grow. For the memory pools, we actually make the max +// capacity undefined. We could consider setting the old max capacity +// to the max capacity of the heap (see 7078465). +// +// If we had more accurate occupancy / capacity information per +// region set the above calculations would be greatly simplified and +// be made more accurate. +// +// We update all the above synchronously and we store the results in +// fields so that we just read said fields when needed. A subtle point +// is that all the above sizes need to be recalculated when the old +// gen changes capacity (after a GC or after a humongous allocation) +// but only the eden occupancy changes when a new eden region is +// allocated. So, in the latter case we have minimal recalcuation to +// do which is important as we want to keep the eden region allocation +// path as low-overhead as possible. class G1MonitoringSupport : public CHeapObj { G1CollectedHeap* _g1h; - VirtualSpace* _g1_storage_addr; // jstat performance counters // incremental collections both fully and partially young @@ -133,9 +125,9 @@ class G1MonitoringSupport : public CHeapObj { // _from_counters, and _to_counters are associated with // this "generational" counter. GenerationCounters* _young_collection_counters; - // non-young collection set counters. The _old_space_counters + // old collection set counters. The _old_space_counters // below are associated with this "generational" counter. - GenerationCounters* _non_young_collection_counters; + GenerationCounters* _old_collection_counters; // Counters for the capacity and used for // the whole heap HSpaceCounters* _old_space_counters; @@ -145,6 +137,27 @@ class G1MonitoringSupport : public CHeapObj { HSpaceCounters* _from_counters; HSpaceCounters* _to_counters; + // When it's appropriate to recalculate the various sizes (at the + // end of a GC, when a new eden region is allocated, etc.) we store + // them here so that we can easily report them when needed and not + // have to recalculate them every time. + + size_t _overall_reserved; + size_t _overall_committed; + size_t _overall_used; + + size_t _young_region_num; + size_t _young_gen_committed; + size_t _eden_committed; + size_t _eden_used; + size_t _survivor_committed; + size_t _survivor_used; + + size_t _old_committed; + size_t _old_used; + + G1CollectedHeap* g1h() { return _g1h; } + // It returns x - y if x > y, 0 otherwise. // As described in the comment above, some of the inputs to the // calculations we have to do are obtained concurrently and hence @@ -160,15 +173,35 @@ class G1MonitoringSupport : public CHeapObj { } } + // Recalculate all the sizes. + void recalculate_sizes(); + // Recalculate only what's necessary when a new eden region is allocated. + void recalculate_eden_size(); + public: - G1MonitoringSupport(G1CollectedHeap* g1h, VirtualSpace* g1_storage_addr); + G1MonitoringSupport(G1CollectedHeap* g1h); - G1CollectedHeap* g1h() { return _g1h; } - VirtualSpace* g1_storage_addr() { return _g1_storage_addr; } + // Unfortunately, the jstat tool assumes that no space has 0 + // capacity. In our case, given that each space is logical, it's + // possible that no regions will be allocated to it, hence to have 0 + // capacity (e.g., if there are no survivor regions, the survivor + // space has 0 capacity). The way we deal with this is to always pad + // each capacity value we report to jstat by a very small amount to + // make sure that it's never zero. Given that we sometimes have to + // report a capacity of a generation that contains several spaces + // (e.g., young gen includes one eden, two survivor spaces), the + // mult parameter is provided in order to adding the appropriate + // padding multiple times so that the capacities add up correctly. + static size_t pad_capacity(size_t size_bytes, size_t mult = 1) { + return size_bytes + MinObjAlignmentInBytes * mult; + } - // Performance Counter accessors - void update_counters(); - void update_eden_counters(); + // Recalculate all the sizes from scratch and update all the jstat + // counters accordingly. + void update_sizes(); + // Recalculate only what's necessary when a new eden region is + // allocated and update any jstat counters that need to be updated. + void update_eden_size(); CollectorCounters* incremental_collection_counters() { return _incremental_collection_counters; @@ -176,8 +209,11 @@ class G1MonitoringSupport : public CHeapObj { CollectorCounters* full_collection_counters() { return _full_collection_counters; } - GenerationCounters* non_young_collection_counters() { - return _non_young_collection_counters; + GenerationCounters* young_collection_counters() { + return _young_collection_counters; + } + GenerationCounters* old_collection_counters() { + return _old_collection_counters; } HSpaceCounters* old_space_counters() { return _old_space_counters; } HSpaceCounters* eden_counters() { return _eden_counters; } @@ -187,17 +223,45 @@ class G1MonitoringSupport : public CHeapObj { // Monitoring support used by // MemoryService // jstat counters - size_t overall_committed(); - size_t overall_used(); - size_t eden_space_committed(); - size_t eden_space_used(); + size_t overall_reserved() { return _overall_reserved; } + size_t overall_committed() { return _overall_committed; } + size_t overall_used() { return _overall_used; } - size_t survivor_space_committed(); - size_t survivor_space_used(); + size_t young_gen_committed() { return _young_gen_committed; } + size_t young_gen_max() { return overall_reserved(); } + size_t eden_space_committed() { return _eden_committed; } + size_t eden_space_used() { return _eden_used; } + size_t survivor_space_committed() { return _survivor_committed; } + size_t survivor_space_used() { return _survivor_used; } - size_t old_space_committed(); - size_t old_space_used(); + size_t old_gen_committed() { return old_space_committed(); } + size_t old_gen_max() { return overall_reserved(); } + size_t old_space_committed() { return _old_committed; } + size_t old_space_used() { return _old_used; } +}; + +class G1GenerationCounters: public GenerationCounters { +protected: + G1MonitoringSupport* _g1mm; + +public: + G1GenerationCounters(G1MonitoringSupport* g1mm, + const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity); +}; + +class G1YoungGenerationCounters: public G1GenerationCounters { +public: + G1YoungGenerationCounters(G1MonitoringSupport* g1mm, const char* name); + virtual void update_all(); +}; + +class G1OldGenerationCounters: public G1GenerationCounters { +public: + G1OldGenerationCounters(G1MonitoringSupport* g1mm, const char* name); + virtual void update_all(); }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index f2edf01b9f6..2a30331529d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -357,6 +357,11 @@ class HeapRegion: public G1OffsetTableContigSpace { static int GrainWords; static int CardsPerRegion; + static size_t align_up_to_region_byte_size(size_t sz) { + return (sz + (size_t) GrainBytes - 1) & + ~((1 << (size_t) LogOfHRGrainBytes) - 1); + } + // It sets up the heap region size (GrainBytes / GrainWords), as // well as other related fields that are based on the heap region // size (LogOfHRGrainBytes / LogOfHRGrainWords / diff --git a/hotspot/src/share/vm/gc_implementation/shared/generationCounters.cpp b/hotspot/src/share/vm/gc_implementation/shared/generationCounters.cpp index f07f486e895..68ab6ffc17e 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/generationCounters.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/generationCounters.cpp @@ -26,14 +26,10 @@ #include "gc_implementation/shared/generationCounters.hpp" #include "memory/resourceArea.hpp" - -GenerationCounters::GenerationCounters(const char* name, - int ordinal, int spaces, - VirtualSpace* v): - _virtual_space(v) { - +void GenerationCounters::initialize(const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity) { if (UsePerfData) { - EXCEPTION_MARK; ResourceMark rm; @@ -51,18 +47,37 @@ GenerationCounters::GenerationCounters(const char* name, cname = PerfDataManager::counter_name(_name_space, "minCapacity"); PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - _virtual_space == NULL ? 0 : - _virtual_space->committed_size(), CHECK); + min_capacity, CHECK); cname = PerfDataManager::counter_name(_name_space, "maxCapacity"); PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - _virtual_space == NULL ? 0 : - _virtual_space->reserved_size(), CHECK); + max_capacity, CHECK); cname = PerfDataManager::counter_name(_name_space, "capacity"); - _current_size = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, - _virtual_space == NULL ? 0 : - _virtual_space->committed_size(), CHECK); + _current_size = + PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, + curr_capacity, CHECK); } } + +GenerationCounters::GenerationCounters(const char* name, + int ordinal, int spaces, + VirtualSpace* v) + : _virtual_space(v) { + assert(v != NULL, "don't call this constructor if v == NULL"); + initialize(name, ordinal, spaces, + v->committed_size(), v->reserved_size(), v->committed_size()); +} + +GenerationCounters::GenerationCounters(const char* name, + int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity) + : _virtual_space(NULL) { + initialize(name, ordinal, spaces, min_capacity, max_capacity, curr_capacity); +} + +void GenerationCounters::update_all() { + assert(_virtual_space != NULL, "otherwise, override this method"); + _current_size->set_value(_virtual_space->committed_size()); +} diff --git a/hotspot/src/share/vm/gc_implementation/shared/generationCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/generationCounters.hpp index 21f76918c17..f399b955819 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/generationCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/generationCounters.hpp @@ -34,6 +34,11 @@ class GenerationCounters: public CHeapObj { friend class VMStructs; +private: + void initialize(const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity); + protected: PerfVariable* _current_size; VirtualSpace* _virtual_space; @@ -48,11 +53,18 @@ class GenerationCounters: public CHeapObj { char* _name_space; // This constructor is only meant for use with the PSGenerationCounters - // constructor. The need for such an constructor should be eliminated + // constructor. The need for such an constructor should be eliminated // when VirtualSpace and PSVirtualSpace are unified. - GenerationCounters() : _name_space(NULL), _current_size(NULL), _virtual_space(NULL) {} - public: + GenerationCounters() + : _name_space(NULL), _current_size(NULL), _virtual_space(NULL) {} + // This constructor is used for subclasses that do not have a space + // associated with them (e.g, in G1). + GenerationCounters(const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity); + + public: GenerationCounters(const char* name, int ordinal, int spaces, VirtualSpace* v); @@ -60,10 +72,7 @@ class GenerationCounters: public CHeapObj { if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); } - virtual void update_all() { - _current_size->set_value(_virtual_space == NULL ? 0 : - _virtual_space->committed_size()); - } + virtual void update_all(); const char* name_space() const { return _name_space; } diff --git a/hotspot/src/share/vm/services/g1MemoryPool.cpp b/hotspot/src/share/vm/services/g1MemoryPool.cpp index a480c12b4dd..c621ecc7951 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.cpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.cpp @@ -32,56 +32,28 @@ G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, size_t init_size, + size_t max_size, bool support_usage_threshold) : - _g1h(g1h), CollectedMemoryPool(name, - MemoryPool::Heap, - init_size, - undefined_max(), - support_usage_threshold) { + _g1mm(g1h->g1mm()), CollectedMemoryPool(name, + MemoryPool::Heap, + init_size, + max_size, + support_usage_threshold) { assert(UseG1GC, "sanity"); } -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::eden_space_committed(G1CollectedHeap* g1h) { - return MAX2(eden_space_used(g1h), (size_t) HeapRegion::GrainBytes); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::eden_space_used(G1CollectedHeap* g1h) { - return g1h->g1mm()->eden_space_used(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::survivor_space_committed(G1CollectedHeap* g1h) { - return g1h->g1mm()->survivor_space_committed(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::survivor_space_used(G1CollectedHeap* g1h) { - return g1h->g1mm()->survivor_space_used(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::old_space_committed(G1CollectedHeap* g1h) { - return g1h->g1mm()->old_space_committed(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::old_space_used(G1CollectedHeap* g1h) { - return g1h->g1mm()->old_space_used(); -} - G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, "G1 Eden Space", - eden_space_committed(g1h), /* init_size */ + g1h->g1mm()->eden_space_committed(), /* init_size */ + _undefined_max, false /* support_usage_threshold */) { } MemoryUsage G1EdenPool::get_memory_usage() { size_t initial_sz = initial_size(); size_t max_sz = max_size(); size_t used = used_in_bytes(); - size_t committed = eden_space_committed(_g1h); + size_t committed = _g1mm->eden_space_committed(); return MemoryUsage(initial_sz, used, committed, max_sz); } @@ -89,14 +61,15 @@ MemoryUsage G1EdenPool::get_memory_usage() { G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, "G1 Survivor Space", - survivor_space_committed(g1h), /* init_size */ + g1h->g1mm()->survivor_space_committed(), /* init_size */ + _undefined_max, false /* support_usage_threshold */) { } MemoryUsage G1SurvivorPool::get_memory_usage() { size_t initial_sz = initial_size(); size_t max_sz = max_size(); size_t used = used_in_bytes(); - size_t committed = survivor_space_committed(_g1h); + size_t committed = _g1mm->survivor_space_committed(); return MemoryUsage(initial_sz, used, committed, max_sz); } @@ -104,14 +77,15 @@ MemoryUsage G1SurvivorPool::get_memory_usage() { G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, "G1 Old Gen", - old_space_committed(g1h), /* init_size */ + g1h->g1mm()->old_space_committed(), /* init_size */ + _undefined_max, true /* support_usage_threshold */) { } MemoryUsage G1OldGenPool::get_memory_usage() { size_t initial_sz = initial_size(); size_t max_sz = max_size(); size_t used = used_in_bytes(); - size_t committed = old_space_committed(_g1h); + size_t committed = _g1mm->old_space_committed(); return MemoryUsage(initial_sz, used, committed, max_sz); } diff --git a/hotspot/src/share/vm/services/g1MemoryPool.hpp b/hotspot/src/share/vm/services/g1MemoryPool.hpp index 958a0885b98..ce93d0e5a31 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.hpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.hpp @@ -26,12 +26,11 @@ #define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP #ifndef SERIALGC +#include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" #endif -class G1CollectedHeap; - // This file contains the three classes that represent the memory // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and // G1OldGenPool. In G1, unlike our other GCs, we do not have a @@ -50,37 +49,19 @@ class G1CollectedHeap; // on this model. // - // This class is shared by the three G1 memory pool classes -// (G1EdenPool, G1SurvivorPool, G1OldGenPool). Given that the way we -// calculate used / committed bytes for these three pools is related -// (see comment above), we put the calculations in this class so that -// we can easily share them among the subclasses. +// (G1EdenPool, G1SurvivorPool, G1OldGenPool). class G1MemoryPoolSuper : public CollectedMemoryPool { protected: - G1CollectedHeap* _g1h; + const static size_t _undefined_max = (size_t) -1; + G1MonitoringSupport* _g1mm; // Would only be called from subclasses. G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, size_t init_size, + size_t max_size, bool support_usage_threshold); - - // The reason why all the code is in static methods is so that it - // can be safely called from the constructors of the subclasses. - - static size_t undefined_max() { - return (size_t) -1; - } - - static size_t eden_space_committed(G1CollectedHeap* g1h); - static size_t eden_space_used(G1CollectedHeap* g1h); - - static size_t survivor_space_committed(G1CollectedHeap* g1h); - static size_t survivor_space_used(G1CollectedHeap* g1h); - - static size_t old_space_committed(G1CollectedHeap* g1h); - static size_t old_space_used(G1CollectedHeap* g1h); }; // Memory pool that represents the G1 eden. @@ -89,10 +70,10 @@ public: G1EdenPool(G1CollectedHeap* g1h); size_t used_in_bytes() { - return eden_space_used(_g1h); + return _g1mm->eden_space_used(); } size_t max_size() const { - return undefined_max(); + return _undefined_max; } MemoryUsage get_memory_usage(); }; @@ -103,10 +84,10 @@ public: G1SurvivorPool(G1CollectedHeap* g1h); size_t used_in_bytes() { - return survivor_space_used(_g1h); + return _g1mm->survivor_space_used(); } size_t max_size() const { - return undefined_max(); + return _undefined_max; } MemoryUsage get_memory_usage(); }; @@ -117,10 +98,10 @@ public: G1OldGenPool(G1CollectedHeap* g1h); size_t used_in_bytes() { - return old_space_used(_g1h); + return _g1mm->old_space_used(); } size_t max_size() const { - return undefined_max(); + return _undefined_max; } MemoryUsage get_memory_usage(); }; From cc177fd51592dd4e4142cfeb5c173d02bbef6199 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 26 Sep 2011 10:14:30 +0200 Subject: [PATCH 059/214] 7091366: re-enable quicksort tests Added extern "C" to make it build with JDK6 compilers Reviewed-by: jwilhelm, kvn --- hotspot/src/share/vm/utilities/quickSort.cpp | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/utilities/quickSort.cpp b/hotspot/src/share/vm/utilities/quickSort.cpp index b377d9a3c0d..947b420e7a9 100644 --- a/hotspot/src/share/vm/utilities/quickSort.cpp +++ b/hotspot/src/share/vm/utilities/quickSort.cpp @@ -54,16 +54,18 @@ static int test_even_odd_comparator(int a, int b) { return 1; } -static int test_stdlib_comparator(const void* a, const void* b) { - int ai = *(int*)a; - int bi = *(int*)b; - if (ai == bi) { - return 0; +extern "C" { + static int test_stdlib_comparator(const void* a, const void* b) { + int ai = *(int*)a; + int bi = *(int*)b; + if (ai == bi) { + return 0; + } + if (ai < bi) { + return -1; + } + return 1; } - if (ai < bi) { - return -1; - } - return 1; } void QuickSort::print_array(const char* prefix, int* array, int length) { @@ -92,7 +94,6 @@ bool QuickSort::sort_and_compare(int* arrayToSort, int* expectedResult, int leng } bool QuickSort::test_quick_sort() { -#if 0 tty->print_cr("test_quick_sort\n"); { int* test_array = NULL; @@ -213,7 +214,6 @@ bool QuickSort::test_quick_sort() { delete[] test_array; delete[] expected_array; } -#endif return true; } From bbfe9c6e250f9aea0b5c8287ca54cfed29416ac2 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Wed, 28 Sep 2011 10:36:31 -0700 Subject: [PATCH 060/214] 7086533: G1: assert(!_g1->is_obj_dead(obj)): We should not be preserving dead objs: g1CollectedHeap.cpp:3835 Some objects may not be marked in the event of an evacuation failure in a partially young GC, during a marking cycle. Avoid this situation by not allowing partially young GCs during a marking cycle. Reviewed-by: tonyp, ysr, brutisso --- .../gc_implementation/g1/g1CollectedHeap.cpp | 8 +++++++ .../g1/g1CollectorPolicy.cpp | 23 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index b71f058a82f..801af4c0a46 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -3365,6 +3365,14 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { // for the duration of this pause. g1_policy()->decide_on_conc_mark_initiation(); + // We do not allow initial-mark to be piggy-backed on a + // partially-young GC. + assert(!g1_policy()->during_initial_mark_pause() || + g1_policy()->full_young_gcs(), "sanity"); + + // We also do not allow partially-young GCs during marking. + assert(!mark_in_progress() || g1_policy()->full_young_gcs(), "sanity"); + char verbose_str[128]; sprintf(verbose_str, "GC pause "); if (g1_policy()->full_young_gcs()) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 24f96aef85c..ee3fc6ecac9 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1525,11 +1525,17 @@ void G1CollectorPolicy::record_collection_pause_end() { } if (_last_full_young_gc) { - ergo_verbose2(ErgoPartiallyYoungGCs, - "start partially-young GCs", - ergo_format_byte_perc("known garbage"), - _known_garbage_bytes, _known_garbage_ratio * 100.0); - set_full_young_gcs(false); + if (!last_pause_included_initial_mark) { + ergo_verbose2(ErgoPartiallyYoungGCs, + "start partially-young GCs", + ergo_format_byte_perc("known garbage"), + _known_garbage_bytes, _known_garbage_ratio * 100.0); + set_full_young_gcs(false); + } else { + ergo_verbose0(ErgoPartiallyYoungGCs, + "do not start partially-young GCs", + ergo_format_reason("concurrent cycle is about to start")); + } _last_full_young_gc = false; } @@ -2491,6 +2497,13 @@ G1CollectorPolicy::decide_on_conc_mark_initiation() { // initiate a new cycle. set_during_initial_mark_pause(); + // We do not allow non-full young GCs during marking. + if (!full_young_gcs()) { + set_full_young_gcs(true); + ergo_verbose0(ErgoPartiallyYoungGCs, + "end partially-young GCs", + ergo_format_reason("concurrent cycle is about to start")); + } // And we can now clear initiate_conc_mark_if_possible() as // we've already acted on it. From 02e989445467c4cdebcfa5c1bd2f50efdc810068 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Mon, 3 Oct 2011 12:49:53 -0700 Subject: [PATCH 061/214] 7097053: G1: assert(da ? referent->is_oop() : referent->is_oop_or_null()) failed: referenceProcessor.cpp:1054 During remembered set scanning, the reference processor could discover a reference object whose referent was in the process of being copied and so may not be completely initialized. Do not perform reference discovery during remembered set scanning. Reviewed-by: tonyp, ysr --- .../gc_implementation/g1/g1CollectedHeap.cpp | 10 +---- .../vm/gc_implementation/g1/g1OopClosures.hpp | 18 ++------- .../vm/gc_implementation/g1/g1RemSet.cpp | 4 +- .../vm/gc_implementation/g1/heapRegion.cpp | 37 +++---------------- 4 files changed, 12 insertions(+), 57 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 801af4c0a46..1550dbcf0c8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -4618,15 +4618,7 @@ public: scan_perm_cl = &scan_mark_perm_cl; } - // The following closure is used to scan RSets looking for reference - // fields that point into the collection set. The actual field iteration - // is performed by a FilterIntoCSClosure, whose do_oop method calls the - // do_oop method of the following closure. - // Therefore we want to record the reference processor in the - // FilterIntoCSClosure. To do so we record the STW reference - // processor into the following closure and pass it to the - // FilterIntoCSClosure in HeapRegionDCTOC::walk_mem_region_with_cl. - G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss, rp); + G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss); pss.start_strong_roots(); _g1h->g1_process_strong_roots(/* not collecting perm */ false, diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 84e67725f90..ace59ead402 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -61,13 +61,8 @@ public: class G1ParPushHeapRSClosure : public G1ParClosureSuper { public: G1ParPushHeapRSClosure(G1CollectedHeap* g1, - G1ParScanThreadState* par_scan_state, - ReferenceProcessor* rp) : - G1ParClosureSuper(g1, par_scan_state) - { - assert(_ref_processor == NULL, "sanity"); - _ref_processor = rp; - } + G1ParScanThreadState* par_scan_state): + G1ParClosureSuper(g1, par_scan_state) { } template void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } @@ -190,13 +185,8 @@ class FilterIntoCSClosure: public OopClosure { public: FilterIntoCSClosure( DirtyCardToOopClosure* dcto_cl, G1CollectedHeap* g1, - OopClosure* oc, - ReferenceProcessor* rp) : - _dcto_cl(dcto_cl), _g1(g1), _oc(oc) - { - assert(_ref_processor == NULL, "sanity"); - _ref_processor = rp; - } + OopClosure* oc) : + _dcto_cl(dcto_cl), _g1(g1), _oc(oc) { } template void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 04a3bf5e5fa..1e6373cf709 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -468,7 +468,7 @@ public: MemRegion scanRegion(start, end); UpdateRSetImmediate update_rs_cl(_g1->g1_rem_set()); - FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl, NULL /* rp */); + FilterIntoCSClosure update_rs_cset_oop_cl(NULL, _g1, &update_rs_cl); FilterOutOfRegionClosure filter_then_update_rs_cset_oop_cl(r, &update_rs_cset_oop_cl); // We can pass false as the "filter_young" parameter here as: @@ -644,7 +644,7 @@ bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, update_rs_oop_cl.set_from(r); TriggerClosure trigger_cl; - FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl, NULL /* rp */); + FilterIntoCSClosure into_cs_cl(NULL, _g1, &trigger_cl); InvokeIfNotTriggeredClosure invoke_cl(&trigger_cl, &into_cs_cl); Mux2Closure mux(&invoke_cl, &update_rs_oop_cl); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 36636152e39..069ce3c3dbb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -210,44 +210,17 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, HeapWord* top, OopClosure* cl) { G1CollectedHeap* g1h = _g1; - int oop_size; + OopClosure* cl2 = NULL; - OopClosure* cl2 = cl; - - // If we are scanning the remembered sets looking for refs - // into the collection set during an evacuation pause then - // we will want to 'discover' reference objects that point - // to referents in the collection set. - // - // Unfortunately it is an instance of FilterIntoCSClosure - // that is iterated over the reference fields of oops in - // mr (and not the G1ParPushHeapRSClosure - which is the - // cl parameter). - // If we set the _ref_processor field in the FilterIntoCSClosure - // instance, all the reference objects that are walked - // (regardless of whether their referent object's are in - // the cset) will be 'discovered'. - // - // The G1STWIsAlive closure considers a referent object that - // is outside the cset as alive. The G1CopyingKeepAliveClosure - // skips referents that are not in the cset. - // - // Therefore reference objects in mr with a referent that is - // outside the cset should be OK. - - ReferenceProcessor* rp = _cl->_ref_processor; - if (rp != NULL) { - assert(rp == _g1->ref_processor_stw(), "should be stw"); - assert(_fk == IntoCSFilterKind, "should be looking for refs into CS"); - } - - FilterIntoCSClosure intoCSFilt(this, g1h, cl, rp); + FilterIntoCSClosure intoCSFilt(this, g1h, cl); FilterOutOfRegionClosure outOfRegionFilt(_hr, cl); switch (_fk) { + case NoFilterKind: cl2 = cl; break; case IntoCSFilterKind: cl2 = &intoCSFilt; break; case OutOfRegionFilterKind: cl2 = &outOfRegionFilt; break; + default: ShouldNotReachHere(); } // Start filtering what we add to the remembered set. If the object is @@ -270,7 +243,7 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, break; case IntoCSFilterKind: { - FilterIntoCSClosure filt(this, g1h, cl, rp); + FilterIntoCSClosure filt(this, g1h, cl); bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); break; } From 75685a273aa1045992f912f1cbb292fa19289e36 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Mon, 3 Oct 2011 19:04:14 -0400 Subject: [PATCH 062/214] 7097048: G1: extend the G1 SA changes to print per-heap space information Reviewed-by: brutisso, johnc --- .../gc_implementation/g1/G1CollectedHeap.java | 9 ++ .../g1/G1MonitoringSupport.java | 99 +++++++++++++++++++ .../sun/jvm/hotspot/tools/HeapSummary.java | 27 ++--- .../g1/g1MonitoringSupport.hpp | 2 + .../vm/gc_implementation/g1/vmStructs_g1.hpp | 11 +++ 5 files changed, 137 insertions(+), 11 deletions(-) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java index dfdd51099fa..502d8e4ad14 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java @@ -35,6 +35,7 @@ import sun.jvm.hotspot.memory.SharedHeap; import sun.jvm.hotspot.memory.SpaceClosure; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; import sun.jvm.hotspot.types.CIntegerField; import sun.jvm.hotspot.types.Type; import sun.jvm.hotspot.types.TypeDataBase; @@ -48,6 +49,8 @@ public class G1CollectedHeap extends SharedHeap { static private long g1CommittedFieldOffset; // size_t _summary_bytes_used; static private CIntegerField summaryBytesUsedField; + // G1MonitoringSupport* _g1mm + static private AddressField g1mmField; static { VM.registerVMInitializedObserver(new Observer() { @@ -63,6 +66,7 @@ public class G1CollectedHeap extends SharedHeap { hrsFieldOffset = type.getField("_hrs").getOffset(); g1CommittedFieldOffset = type.getField("_g1_committed").getOffset(); summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used"); + g1mmField = type.getAddressField("_g1mm"); } public long capacity() { @@ -85,6 +89,11 @@ public class G1CollectedHeap extends SharedHeap { hrsAddr); } + public G1MonitoringSupport g1mm() { + Address g1mmAddr = g1mmField.getValue(addr); + return (G1MonitoringSupport) VMObjectFactory.newObject(G1MonitoringSupport.class, g1mmAddr); + } + private Iterator heapRegionIterator() { return hrs().heapRegionIterator(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java new file mode 100644 index 00000000000..7b03aed9c9c --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for G1MonitoringSupport. + +public class G1MonitoringSupport extends VMObject { + // size_t _eden_committed; + static private CIntegerField edenCommittedField; + // size_t _eden_used; + static private CIntegerField edenUsedField; + // size_t _survivor_committed; + static private CIntegerField survivorCommittedField; + // size_t _survivor_used; + static private CIntegerField survivorUsedField; + // size_t _old_committed; + static private CIntegerField oldCommittedField; + // size_t _old_used; + static private CIntegerField oldUsedField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("G1MonitoringSupport"); + + edenCommittedField = type.getCIntegerField("_eden_committed"); + edenUsedField = type.getCIntegerField("_eden_used"); + survivorCommittedField = type.getCIntegerField("_survivor_committed"); + survivorUsedField = type.getCIntegerField("_survivor_used"); + oldCommittedField = type.getCIntegerField("_old_committed"); + oldUsedField = type.getCIntegerField("_old_used"); + } + + public long edenCommitted() { + return edenCommittedField.getValue(addr); + } + + public long edenUsed() { + return edenUsedField.getValue(addr); + } + + public long survivorCommitted() { + return survivorCommittedField.getValue(addr); + } + + public long survivorUsed() { + return survivorUsedField.getValue(addr); + } + + public long oldCommitted() { + return oldCommittedField.getValue(addr); + } + + public long oldUsed() { + return oldUsedField.getValue(addr); + } + + public G1MonitoringSupport(Address addr) { + super(addr); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index 3be7f3da0f4..bbeab88a741 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -98,17 +98,12 @@ public class HeapSummary extends Tool { } } else if (sharedHeap instanceof G1CollectedHeap) { G1CollectedHeap g1h = (G1CollectedHeap) sharedHeap; - - System.out.println("Garbage-First (G1) Heap"); - long capacityBytes = g1h.capacity(); - long usedBytes = g1h.used(); - long freeBytes = capacityBytes - usedBytes; - printValMB("region size = ", HeapRegion.grainBytes()); - printValue("regions = ", g1h.n_regions()); - printValMB("capacity = ", capacityBytes); - printValMB("used = ", usedBytes); - printValMB("free = ", freeBytes); - System.out.println(alignment + (double) usedBytes * 100.0 / capacityBytes + "% used"); + G1MonitoringSupport g1mm = g1h.g1mm(); + System.out.println("G1 Young Generation"); + printG1Space("Eden Space:", g1mm.edenUsed(), g1mm.edenCommitted()); + printG1Space("From Space:", g1mm.survivorUsed(), g1mm.survivorCommitted()); + printG1Space("To Space:", 0, 0); + printG1Space("G1 Old Generation", g1mm.oldUsed(), g1mm.oldCommitted()); } else { throw new RuntimeException("unknown SharedHeap type : " + heap.getClass()); } @@ -217,6 +212,16 @@ public class HeapSummary extends Tool { System.out.println(alignment + (double)space.used() * 100.0 / space.capacity() + "% used"); } + private void printG1Space(String spaceName, long used, long capacity) { + long free = capacity - used; + System.out.println(spaceName); + printValMB("capacity = ", capacity); + printValMB("used = ", used); + printValMB("free = ", free); + double occPerc = (capacity > 0) ? (double) used * 100.0 / capacity : 0.0; + System.out.println(alignment + occPerc + "% used"); + } + private static final double FACTOR = 1024*1024; private void printValMB(String title, long value) { if (value < 0) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp index aa142916b94..3d124cefbab 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp @@ -114,6 +114,8 @@ class G1CollectedHeap; // path as low-overhead as possible. class G1MonitoringSupport : public CHeapObj { + friend class VMStructs; + G1CollectedHeap* _g1h; // jstat performance counters diff --git a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp index f85c76cee7b..1243a58a3d0 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp @@ -39,6 +39,14 @@ nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \ nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \ + nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \ + \ + nonstatic_field(G1MonitoringSupport, _eden_committed, size_t) \ + nonstatic_field(G1MonitoringSupport, _eden_used, size_t) \ + nonstatic_field(G1MonitoringSupport, _survivor_committed, size_t) \ + nonstatic_field(G1MonitoringSupport, _survivor_used, size_t) \ + nonstatic_field(G1MonitoringSupport, _old_committed, size_t) \ + nonstatic_field(G1MonitoringSupport, _old_used, size_t) \ #define VM_TYPES_G1(declare_type, declare_toplevel_type) \ @@ -47,8 +55,11 @@ \ declare_type(HeapRegion, ContiguousSpace) \ declare_toplevel_type(HeapRegionSeq) \ + declare_toplevel_type(G1MonitoringSupport) \ \ declare_toplevel_type(G1CollectedHeap*) \ declare_toplevel_type(HeapRegion*) \ + declare_toplevel_type(G1MonitoringSupport*) \ + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP From a4523cfc7ff58e2ccbbfff9615f0282434230186 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 12 Sep 2011 16:09:50 +0200 Subject: [PATCH 063/214] 7021322: assert(object_end <= top()) failed: Object crosses promotion LAB boundary Pass the same object size value to both allocate and unallocate_object Reviewed-by: ysr, brutisso --- .../parallelScavenge/psPromotionLAB.cpp | 12 +++++------- .../parallelScavenge/psPromotionLAB.hpp | 2 +- .../parallelScavenge/psPromotionManager.cpp | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp index 3569ed7b63d..fc05b2e95d8 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp @@ -102,17 +102,15 @@ void PSPromotionLAB::flush() { _state = flushed; } -bool PSPromotionLAB::unallocate_object(oop obj) { +bool PSPromotionLAB::unallocate_object(HeapWord* obj, size_t obj_size) { assert(Universe::heap()->is_in(obj), "Object outside heap"); if (contains(obj)) { - HeapWord* object_end = (HeapWord*)obj + obj->size(); - assert(object_end <= top(), "Object crosses promotion LAB boundary"); + HeapWord* object_end = obj + obj_size; + assert(object_end == top(), "Not matching last allocation"); - if (object_end == top()) { - set_top((HeapWord*)obj); - return true; - } + set_top(obj); + return true; } return false; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp index bed0c0cdeeb..fd6a7bf561b 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp @@ -73,7 +73,7 @@ class PSPromotionLAB : public CHeapObj { bool is_flushed() { return _state == flushed; } - bool unallocate_object(oop obj); + bool unallocate_object(HeapWord* obj, size_t obj_size); // Returns a subregion containing all objects in this space. MemRegion used_region() { return MemRegion(bottom(), top()); } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp index ad58a90fcd8..255bb8ee8c7 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp @@ -380,10 +380,10 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { // deallocate it, so we have to test. If the deallocation fails, // overwrite with a filler object. if (new_obj_is_tenured) { - if (!_old_lab.unallocate_object(new_obj)) { + if (!_old_lab.unallocate_object((HeapWord*) new_obj, new_obj_size)) { CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size); } - } else if (!_young_lab.unallocate_object(new_obj)) { + } else if (!_young_lab.unallocate_object((HeapWord*) new_obj, new_obj_size)) { CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size); } From 1f8f1f79be978643b54fa05d2615f9c696bb6f42 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Mon, 12 Sep 2011 13:51:40 -0700 Subject: [PATCH 064/214] 7089709: type "jushort" not found Reviewed-by: kvn, twisti --- hotspot/src/share/vm/runtime/vmStructs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 69b3ab653f8..101d6f92fcd 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1341,6 +1341,7 @@ static inline uint64_t cast_uint64_t(size_t x) declare_unsigned_integer_type(unsigned int) \ declare_unsigned_integer_type(uint) \ declare_unsigned_integer_type(unsigned short) \ + declare_unsigned_integer_type(jushort) \ declare_unsigned_integer_type(unsigned long) \ /* The compiler thinks this is a different type than */ \ /* unsigned short on Win32 */ \ @@ -3216,7 +3217,7 @@ static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool if (!isRecurse) { tty->print_cr("type \"%s\" not found", typeName); } - return 2; + return 0; } From 81d33c472719b4f89f6f50201f80bec16e5a184d Mon Sep 17 00:00:00 2001 From: Sean Coffey Date: Tue, 13 Sep 2011 11:21:51 +0100 Subject: [PATCH 065/214] 7082769: FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor be closed when still in use Reviewed-by: alanb --- .../classes/java/io/FileInputStream.java | 25 +- .../classes/java/io/FileOutputStream.java | 26 +- .../classes/java/io/RandomAccessFile.java | 13 +- .../java/io/etc/FileDescriptorSharing.java | 336 ++++++++++++++++++ 4 files changed, 351 insertions(+), 49 deletions(-) create mode 100644 jdk/test/java/io/etc/FileDescriptorSharing.java diff --git a/jdk/src/share/classes/java/io/FileInputStream.java b/jdk/src/share/classes/java/io/FileInputStream.java index 3aec50810fb..9dc19557e54 100644 --- a/jdk/src/share/classes/java/io/FileInputStream.java +++ b/jdk/src/share/classes/java/io/FileInputStream.java @@ -56,16 +56,6 @@ class FileInputStream extends InputStream private final Object closeLock = new Object(); private volatile boolean closed = false; - private static final ThreadLocal runningFinalize = - new ThreadLocal<>(); - - private static boolean isRunningFinalize() { - Boolean val; - if ((val = runningFinalize.get()) != null) - return val.booleanValue(); - return false; - } - /** * Creates a FileInputStream by * opening a connection to an actual file, @@ -319,10 +309,10 @@ class FileInputStream extends InputStream int useCount = fd.decrementAndGetUseCount(); /* - * If FileDescriptor is still in use by another stream, the finalizer + * If FileDescriptor is still in use by another stream, we * will not close it. */ - if ((useCount <= 0) || !isRunningFinalize()) { + if (useCount <= 0) { close0(); } } @@ -391,18 +381,7 @@ class FileInputStream extends InputStream */ protected void finalize() throws IOException { if ((fd != null) && (fd != FileDescriptor.in)) { - - /* - * Finalizer should not release the FileDescriptor if another - * stream is still using it. If the user directly invokes - * close() then the FileDescriptor is also released. - */ - runningFinalize.set(Boolean.TRUE); - try { close(); - } finally { - runningFinalize.set(Boolean.FALSE); - } } } } diff --git a/jdk/src/share/classes/java/io/FileOutputStream.java b/jdk/src/share/classes/java/io/FileOutputStream.java index 6f1a77633c4..4a8a724ba15 100644 --- a/jdk/src/share/classes/java/io/FileOutputStream.java +++ b/jdk/src/share/classes/java/io/FileOutputStream.java @@ -63,21 +63,12 @@ class FileOutputStream extends OutputStream private final boolean append; /** - * The associated channel, initalized lazily. + * The associated channel, initialized lazily. */ private FileChannel channel; private final Object closeLock = new Object(); private volatile boolean closed = false; - private static final ThreadLocal runningFinalize = - new ThreadLocal<>(); - - private static boolean isRunningFinalize() { - Boolean val; - if ((val = runningFinalize.get()) != null) - return val.booleanValue(); - return false; - } /** * Creates a file output stream to write to the file with the @@ -355,10 +346,10 @@ class FileOutputStream extends OutputStream int useCount = fd.decrementAndGetUseCount(); /* - * If FileDescriptor is still in use by another stream, the finalizer + * If FileDescriptor is still in use by another stream, we * will not close it. */ - if ((useCount <= 0) || !isRunningFinalize()) { + if (useCount <= 0) { close0(); } } @@ -424,18 +415,7 @@ class FileOutputStream extends OutputStream if (fd == FileDescriptor.out || fd == FileDescriptor.err) { flush(); } else { - - /* - * Finalizer should not release the FileDescriptor if another - * stream is still using it. If the user directly invokes - * close() then the FileDescriptor is also released. - */ - runningFinalize.set(Boolean.TRUE); - try { close(); - } finally { - runningFinalize.set(Boolean.FALSE); - } } } } diff --git a/jdk/src/share/classes/java/io/RandomAccessFile.java b/jdk/src/share/classes/java/io/RandomAccessFile.java index 2c16791f4b8..a2863c59a08 100644 --- a/jdk/src/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/share/classes/java/io/RandomAccessFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -590,8 +590,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * Decrement FD use count associated with this stream. * The count got incremented by FileDescriptor during its construction. */ - fd.decrementAndGetUseCount(); - close0(); + int useCount = fd.decrementAndGetUseCount(); + + /* + * If FileDescriptor is still in use by another stream, we + * will not close it. + */ + if (useCount <= 0) { + close0(); + } } // diff --git a/jdk/test/java/io/etc/FileDescriptorSharing.java b/jdk/test/java/io/etc/FileDescriptorSharing.java new file mode 100644 index 00000000000..d46f61a5282 --- /dev/null +++ b/jdk/test/java/io/etc/FileDescriptorSharing.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6322678 7082769 + * @summary FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor + * to be closed while still in use. + * @run main/othervm FileDescriptorSharing + */ + +import java.io.*; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.util.concurrent.CountDownLatch; + +public class FileDescriptorSharing { + + final static int numFiles = 10; + volatile static boolean fail; + + public static void main(String[] args) throws Exception { + TestFinalizer(); + TestMultipleFD(); + TestIsValid(); + MultiThreadedFD(); + } + + /** + * We shouldn't discard a file descriptor until all streams have + * finished with it + */ + private static void TestFinalizer() throws Exception { + FileDescriptor fd = null; + File tempFile = new File("TestFinalizer1.txt"); + tempFile.deleteOnExit(); + try (Writer writer = new FileWriter(tempFile)) { + for (int i=0; i<5; i++) { + writer.write("test file content test file content"); + } + } + + FileInputStream fis1 = new FileInputStream(tempFile); + fd = fis1.getFD(); + // Create a new FIS based on the existing FD (so the two FIS's share the same native fd) + try (FileInputStream fis2 = new FileInputStream(fd)) { + // allow fis1 to be gc'ed + fis1 = null; + int ret = 0; + while(ret >= 0) { + // encourage gc + System.gc(); + // read from fis2 - when fis1 is gc'ed and finalizer is run, read will fail + System.out.print("."); + ret = fis2.read(); + } + } + + // variation of above. Use RandomAccessFile to obtain a filedescriptor + File testFinalizerFile = new File("TestFinalizer"); + RandomAccessFile raf = new RandomAccessFile(testFinalizerFile, "rw"); + raf.writeBytes("test file content test file content"); + raf.seek(0L); + fd = raf.getFD(); + try (FileInputStream fis3 = new FileInputStream(fd)) { + // allow raf to be gc'ed + raf = null; + int ret = 0; + while (ret >= 0) { + // encourage gc + System.gc(); + /* + * read from fis3 - when raf is gc'ed and finalizer is run, + * fd should still be valid. + */ + System.out.print("."); + ret = fis3.read(); + } + if(!fd.valid()) { + throw new RuntimeException("TestFinalizer() : FileDescriptor should be valid"); + } + } finally { + testFinalizerFile.delete(); + } + } + + /** + * Exercise FileDispatcher close()/preClose() + */ + private static void TestMultipleFD() throws Exception { + RandomAccessFile raf = null; + FileOutputStream fos = null; + FileInputStream fis = null; + FileChannel fc = null; + FileLock fileLock = null; + + File test1 = new File("test1"); + try { + raf = new RandomAccessFile(test1, "rw"); + fos = new FileOutputStream(raf.getFD()); + fis = new FileInputStream(raf.getFD()); + fc = raf.getChannel(); + fileLock = fc.lock(); + raf.setLength(0L); + fos.flush(); + fos.write("TEST".getBytes()); + } finally { + if (fileLock != null) fileLock.release(); + if (fis != null) fis.close(); + if (fos != null) fos.close(); + if (raf != null) raf.close(); + test1.delete(); + } + + /* + * Close out in different order to ensure FD is not + * closed out too early + */ + File test2 = new File("test2"); + try { + raf = new RandomAccessFile(test2, "rw"); + fos = new FileOutputStream(raf.getFD()); + fis = new FileInputStream(raf.getFD()); + fc = raf.getChannel(); + fileLock = fc.lock(); + raf.setLength(0L); + fos.flush(); + fos.write("TEST".getBytes()); + } finally { + if (fileLock != null) fileLock.release(); + if (raf != null) raf.close(); + if (fos != null) fos.close(); + if (fis != null) fis.close(); + test2.delete(); + } + + // one more time, fos first this time + File test3 = new File("test3"); + try { + raf = new RandomAccessFile(test3, "rw"); + fos = new FileOutputStream(raf.getFD()); + fis = new FileInputStream(raf.getFD()); + fc = raf.getChannel(); + fileLock = fc.lock(); + raf.setLength(0L); + fos.flush(); + fos.write("TEST".getBytes()); + } finally { + if (fileLock != null) fileLock.release(); + if (fos != null) fos.close(); + if (raf != null) raf.close(); + if (fis != null) fis.close(); + test3.delete(); + } + } + + /** + * Similar to TestMultipleFD() but this time we + * just get and use FileDescriptor.valid() for testing. + */ + private static void TestIsValid() throws Exception { + FileDescriptor fd = null; + RandomAccessFile raf = null; + FileOutputStream fos = null; + FileInputStream fis = null; + FileChannel fc = null; + + File test1 = new File("test1"); + try { + raf = new RandomAccessFile(test1, "rw"); + fd = raf.getFD(); + fos = new FileOutputStream(fd); + fis = new FileInputStream(fd); + } finally { + try { + if (fis != null) fis.close(); + if (fos != null) fos.close(); + if (!fd.valid()) { + throw new RuntimeException("FileDescriptor should be valid"); + } + if (raf != null) raf.close(); + if (fd.valid()) { + throw new RuntimeException("close() called and FileDescriptor still valid"); + } + } finally { + if (raf != null) raf.close(); + test1.delete(); + } + } + + /* + * Close out in different order to ensure FD is not + * closed out too early + */ + File test2 = new File("test2"); + try { + raf = new RandomAccessFile(test2, "rw"); + fd = raf.getFD(); + fos = new FileOutputStream(fd); + fis = new FileInputStream(fd); + } finally { + try { + if (raf != null) raf.close(); + if (fos != null) fos.close(); + if (!fd.valid()) { + throw new RuntimeException("FileDescriptor should be valid"); + } + if (fis != null) fis.close(); + if (fd.valid()) { + throw new RuntimeException("close() called and FileDescriptor still valid"); + } + } finally { + test2.delete(); + } + } + + // one more time, fos first this time + File test3 = new File("test3"); + try { + raf = new RandomAccessFile(test3, "rw"); + fd = raf.getFD(); + fos = new FileOutputStream(fd); + fis = new FileInputStream(fd); + } finally { + try { + if (fos != null) fos.close(); + if (raf != null) raf.close(); + if (!fd.valid()) { + throw new RuntimeException("FileDescriptor should be valid"); + } + if (fis != null) fis.close(); + if (fd.valid()) { + throw new RuntimeException("close() called and FileDescriptor still valid"); + } + } finally { + test3.delete(); + } + } + } + + /** + * Test concurrent access to the same fd.useCount field + */ + private static void MultiThreadedFD() throws Exception { + RandomAccessFile raf = null; + FileDescriptor fd = null; + int numThreads = 2; + CountDownLatch done = new CountDownLatch(numThreads); + OpenClose[] fileOpenClose = new OpenClose[numThreads]; + File MultipleThreadedFD = new File("MultipleThreadedFD"); + try { + raf = new RandomAccessFile(MultipleThreadedFD, "rw"); + fd = raf.getFD(); + for(int count=0;count Date: Tue, 13 Sep 2011 14:14:57 +0100 Subject: [PATCH 066/214] 7086595: Error message bug: name of initializer is 'null' Implementation of MethodSymbol.location() should take into account static/instance initializers Reviewed-by: jjg --- .../com/sun/tools/javac/code/Kinds.java | 8 +++- .../com/sun/tools/javac/code/Printer.java | 2 +- .../com/sun/tools/javac/code/Symbol.java | 10 ++++- .../com/sun/tools/javac/comp/Check.java | 11 +++++- .../tools/javac/resources/compiler.properties | 14 ++++++- .../javac/util/RichDiagnosticFormatter.java | 2 +- .../test/tools/javac/7086595/T7086595.java | 32 ++++++++++++++++ .../test/tools/javac/7086595/T7086595.out | 11 ++++++ .../javac/Diagnostics/6860795/T6860795.out | 2 +- langtools/test/tools/javac/LocalClasses_2.out | 2 +- .../tools/javac/NestedInnerClassNames.out | 32 ++++++++-------- .../tools/javac/TryWithResources/BadTwr.out | 6 +-- .../DuplicateResourceDecl.out | 2 +- .../diags/examples/AlreadyDefinedClinit.java | 31 ++++++++++++++++ .../diags/examples/KindnameInstanceInit.java | 37 +++++++++++++++++++ .../diags/examples/KindnameStaticInit.java | 37 +++++++++++++++++++ .../javac/generics/6910550/T6910550d.out | 2 +- 17 files changed, 210 insertions(+), 31 deletions(-) create mode 100644 langtools/test/tools/javac/7086595/T7086595.java create mode 100644 langtools/test/tools/javac/7086595/T7086595.out create mode 100644 langtools/test/tools/javac/diags/examples/AlreadyDefinedClinit.java create mode 100644 langtools/test/tools/javac/diags/examples/KindnameInstanceInit.java create mode 100644 langtools/test/tools/javac/diags/examples/KindnameStaticInit.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java index 7156513a5d5..9f9273e3eb5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java @@ -103,6 +103,8 @@ public class Kinds { VAL("kindname.value"), METHOD("kindname.method"), CLASS("kindname.class"), + STATIC_INIT("kindname.static.init"), + INSTANCE_INIT("kindname.instance.init"), PACKAGE("kindname.package"); private String name; @@ -170,9 +172,11 @@ public class Kinds { return KindName.CONSTRUCTOR; case METHOD: - case STATIC_INIT: - case INSTANCE_INIT: return KindName.METHOD; + case STATIC_INIT: + return KindName.STATIC_INIT; + case INSTANCE_INIT: + return KindName.INSTANCE_INIT; default: if (sym.kind == VAL) diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java index 7f63aa4c44c..59aa924385d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java @@ -311,7 +311,7 @@ public abstract class Printer implements Type.Visitor, Symbol.Vi @Override public String visitMethodSymbol(MethodSymbol s, Locale locale) { - if ((s.flags() & BLOCK) != 0) { + if (s.isStaticOrInstanceInit()) { return s.owner.name.toString(); } else { String ms = (s.name == s.name.table.names.init) diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 05c9f6bb074..69473bd5d4f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -149,7 +149,8 @@ public abstract class Symbol implements Element { * the default package; otherwise, the owner symbol is returned */ public Symbol location() { - if (owner.name == null || (owner.name.isEmpty() && owner.kind != PCK && owner.kind != TYP)) { + if (owner.name == null || (owner.name.isEmpty() && + (owner.flags() & BLOCK) == 0 && owner.kind != PCK && owner.kind != TYP)) { return null; } return owner; @@ -1299,10 +1300,17 @@ public abstract class Symbol implements Element { return ElementKind.CONSTRUCTOR; else if (name == name.table.names.clinit) return ElementKind.STATIC_INIT; + else if ((flags() & BLOCK) != 0) + return isStatic() ? ElementKind.STATIC_INIT : ElementKind.INSTANCE_INIT; else return ElementKind.METHOD; } + public boolean isStaticOrInstanceInit() { + return getKind() == ElementKind.STATIC_INIT || + getKind() == ElementKind.INSTANCE_INIT; + } + public Attribute getDefaultValue() { return defaultValue; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index aa5f7c25b2f..15c331ff519 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -306,7 +306,16 @@ public class Check { */ void duplicateError(DiagnosticPosition pos, Symbol sym) { if (!sym.type.isErroneous()) { - log.error(pos, "already.defined", sym, sym.location()); + Symbol location = sym.location(); + if (location.kind == MTH && + ((MethodSymbol)location).isStaticOrInstanceInit()) { + log.error(pos, "already.defined.in.clinit", kindName(sym), sym, + kindName(sym.location()), kindName(sym.location().enclClass()), + sym.location().enclClass()); + } else { + log.error(pos, "already.defined", kindName(sym), sym, + kindName(sym.location()), sym.location()); + } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index eea800fa3c9..2587e0353a2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -68,9 +68,13 @@ compiler.err.abstract.meth.cant.have.body=\ compiler.err.already.annotated=\ {0} {1} has already been annotated -# 0: symbol, 1: symbol +# 0: symbol kind, 1: symbol, 2: symbol kind, 3: symbol compiler.err.already.defined=\ - {0} is already defined in {1} + {0} {1} is already defined in {2} {3} + +# 0: symbol kind, 1: symbol, 2: symbol kind, 3: symbol kind, 4: symbol +compiler.err.already.defined.in.clinit=\ + {0} {1} is already defined in {2} of {3} {4} # 0: string compiler.err.already.defined.single.import=\ @@ -1753,6 +1757,12 @@ compiler.misc.kindname.class=\ compiler.misc.kindname.package=\ package +compiler.misc.kindname.static.init=\ + static initializer + +compiler.misc.kindname.instance.init=\ + instance initializer + ##### compiler.misc.no.args=\ diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java index 44badbf5c64..24861c2a20f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java @@ -412,7 +412,7 @@ public class RichDiagnosticFormatter extends @Override public String visitMethodSymbol(MethodSymbol s, Locale locale) { String ownerName = visit(s.owner, locale); - if ((s.flags() & BLOCK) != 0) { + if (s.isStaticOrInstanceInit()) { return ownerName; } else { String ms = (s.name == s.name.table.names.init) diff --git a/langtools/test/tools/javac/7086595/T7086595.java b/langtools/test/tools/javac/7086595/T7086595.java new file mode 100644 index 00000000000..83ab4f93558 --- /dev/null +++ b/langtools/test/tools/javac/7086595/T7086595.java @@ -0,0 +1,32 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7086595 + * @summary Error message bug: name of initializer is 'null' + * @compile/fail/ref=T7086595.out -XDrawDiagnostics T7086595.java + */ + +class T7086595 { + + String s = "x"; + String s = nonExistent; + + int foo() { + String s = "x"; + String s = nonExistent; + } + + static int bar() { + String s = "x"; + String s = nonExistent; + } + + { + String s = "x"; + String s = nonExistent; + } + + static { + String s = "x"; + String s = nonExistent; + } +} diff --git a/langtools/test/tools/javac/7086595/T7086595.out b/langtools/test/tools/javac/7086595/T7086595.out new file mode 100644 index 00000000000..9e53aea4c79 --- /dev/null +++ b/langtools/test/tools/javac/7086595/T7086595.out @@ -0,0 +1,11 @@ +T7086595.java:11:12: compiler.err.already.defined: kindname.variable, s, kindname.class, T7086595 +T7086595.java:11:16: compiler.err.cant.resolve.location: kindname.variable, nonExistent, , , (compiler.misc.location: kindname.class, T7086595, null) +T7086595.java:15:16: compiler.err.already.defined: kindname.variable, s, kindname.method, foo() +T7086595.java:15:20: compiler.err.cant.resolve.location: kindname.variable, nonExistent, , , (compiler.misc.location: kindname.class, T7086595, null) +T7086595.java:20:16: compiler.err.already.defined: kindname.variable, s, kindname.method, bar() +T7086595.java:20:20: compiler.err.cant.resolve.location: kindname.variable, nonExistent, , , (compiler.misc.location: kindname.class, T7086595, null) +T7086595.java:25:16: compiler.err.already.defined.in.clinit: kindname.variable, s, kindname.instance.init, kindname.class, T7086595 +T7086595.java:25:20: compiler.err.cant.resolve.location: kindname.variable, nonExistent, , , (compiler.misc.location: kindname.class, T7086595, null) +T7086595.java:30:16: compiler.err.already.defined.in.clinit: kindname.variable, s, kindname.static.init, kindname.class, T7086595 +T7086595.java:30:20: compiler.err.cant.resolve.location: kindname.variable, nonExistent, , , (compiler.misc.location: kindname.class, T7086595, null) +10 errors diff --git a/langtools/test/tools/javac/Diagnostics/6860795/T6860795.out b/langtools/test/tools/javac/Diagnostics/6860795/T6860795.out index c0ba0f19676..cc50d8f433c 100644 --- a/langtools/test/tools/javac/Diagnostics/6860795/T6860795.out +++ b/langtools/test/tools/javac/Diagnostics/6860795/T6860795.out @@ -1,2 +1,2 @@ -T6860795.java:10:27: compiler.err.already.defined: x, foo +T6860795.java:10:27: compiler.err.already.defined: kindname.variable, x, kindname.method, foo 1 error diff --git a/langtools/test/tools/javac/LocalClasses_2.out b/langtools/test/tools/javac/LocalClasses_2.out index 5391308409d..1ef052792c8 100644 --- a/langtools/test/tools/javac/LocalClasses_2.out +++ b/langtools/test/tools/javac/LocalClasses_2.out @@ -1,2 +1,2 @@ -LocalClasses_2.java:15:13: compiler.err.already.defined: Local, foo() +LocalClasses_2.java:15:13: compiler.err.already.defined: kindname.class, Local, kindname.method, foo() 1 error diff --git a/langtools/test/tools/javac/NestedInnerClassNames.out b/langtools/test/tools/javac/NestedInnerClassNames.out index b4f171b834c..2038a29791e 100644 --- a/langtools/test/tools/javac/NestedInnerClassNames.out +++ b/langtools/test/tools/javac/NestedInnerClassNames.out @@ -1,18 +1,18 @@ -NestedInnerClassNames.java:16:5: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package -NestedInnerClassNames.java:23:9: compiler.err.already.defined: NestedInnerClassNames.foo, NestedInnerClassNames -NestedInnerClassNames.java:34:9: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package -NestedInnerClassNames.java:45:9: compiler.err.already.defined: NestedInnerClassNames.baz, NestedInnerClassNames -NestedInnerClassNames.java:46:13: compiler.err.already.defined: NestedInnerClassNames.baz.baz, NestedInnerClassNames.baz -NestedInnerClassNames.java:59:9: compiler.err.already.defined: NestedInnerClassNames.foo$bar, NestedInnerClassNames -NestedInnerClassNames.java:76:13: compiler.err.already.defined: NestedInnerClassNames.$bar, NestedInnerClassNames -NestedInnerClassNames.java:90:13: compiler.err.already.defined: NestedInnerClassNames.bar$bar.bar, NestedInnerClassNames.bar$bar +NestedInnerClassNames.java:16:5: compiler.err.already.defined: kindname.class, NestedInnerClassNames, kindname.package, compiler.misc.unnamed.package +NestedInnerClassNames.java:23:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames.foo, kindname.class, NestedInnerClassNames +NestedInnerClassNames.java:34:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames, kindname.package, compiler.misc.unnamed.package +NestedInnerClassNames.java:45:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames.baz, kindname.class, NestedInnerClassNames +NestedInnerClassNames.java:46:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames.baz.baz, kindname.class, NestedInnerClassNames.baz +NestedInnerClassNames.java:59:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames.foo$bar, kindname.class, NestedInnerClassNames +NestedInnerClassNames.java:76:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames.$bar, kindname.class, NestedInnerClassNames +NestedInnerClassNames.java:90:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames.bar$bar.bar, kindname.class, NestedInnerClassNames.bar$bar NestedInnerClassNames.java:109:5: compiler.err.duplicate.class: NestedInnerClassNames.foo.foo -NestedInnerClassNames.java:19:9: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package -NestedInnerClassNames.java:28:13: compiler.err.already.defined: foo, m2() -NestedInnerClassNames.java:40:13: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package -NestedInnerClassNames.java:52:13: compiler.err.already.defined: baz, m4() -NestedInnerClassNames.java:53:17: compiler.err.already.defined: baz.baz, baz -NestedInnerClassNames.java:67:13: compiler.err.already.defined: foo$bar, m5() -NestedInnerClassNames.java:83:17: compiler.err.already.defined: $bar, m6() -NestedInnerClassNames.java:97:17: compiler.err.already.defined: bar$bar.bar, bar$bar +NestedInnerClassNames.java:19:9: compiler.err.already.defined: kindname.class, NestedInnerClassNames, kindname.package, compiler.misc.unnamed.package +NestedInnerClassNames.java:28:13: compiler.err.already.defined: kindname.class, foo, kindname.method, m2() +NestedInnerClassNames.java:40:13: compiler.err.already.defined: kindname.class, NestedInnerClassNames, kindname.package, compiler.misc.unnamed.package +NestedInnerClassNames.java:52:13: compiler.err.already.defined: kindname.class, baz, kindname.method, m4() +NestedInnerClassNames.java:53:17: compiler.err.already.defined: kindname.class, baz.baz, kindname.class, baz +NestedInnerClassNames.java:67:13: compiler.err.already.defined: kindname.class, foo$bar, kindname.method, m5() +NestedInnerClassNames.java:83:17: compiler.err.already.defined: kindname.class, $bar, kindname.method, m6() +NestedInnerClassNames.java:97:17: compiler.err.already.defined: kindname.class, bar$bar.bar, kindname.class, bar$bar 17 errors diff --git a/langtools/test/tools/javac/TryWithResources/BadTwr.out b/langtools/test/tools/javac/TryWithResources/BadTwr.out index aad91d6e35b..6b0b3a9a51b 100644 --- a/langtools/test/tools/javac/TryWithResources/BadTwr.out +++ b/langtools/test/tools/javac/TryWithResources/BadTwr.out @@ -1,5 +1,5 @@ -BadTwr.java:13:46: compiler.err.already.defined: r1, main(java.lang.String...) -BadTwr.java:18:20: compiler.err.already.defined: args, main(java.lang.String...) +BadTwr.java:13:46: compiler.err.already.defined: kindname.variable, r1, kindname.method, main(java.lang.String...) +BadTwr.java:18:20: compiler.err.already.defined: kindname.variable, args, kindname.method, main(java.lang.String...) BadTwr.java:21:13: compiler.err.cant.assign.val.to.final.var: thatsIt -BadTwr.java:26:24: compiler.err.already.defined: name, main(java.lang.String...) +BadTwr.java:26:24: compiler.err.already.defined: kindname.variable, name, kindname.method, main(java.lang.String...) 4 errors diff --git a/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out index e0056add017..c6406eb7768 100644 --- a/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out @@ -1,2 +1,2 @@ -DuplicateResourceDecl.java:12:56: compiler.err.already.defined: c, main(java.lang.String[]) +DuplicateResourceDecl.java:12:56: compiler.err.already.defined: kindname.variable, c, kindname.method, main(java.lang.String[]) 1 error diff --git a/langtools/test/tools/javac/diags/examples/AlreadyDefinedClinit.java b/langtools/test/tools/javac/diags/examples/AlreadyDefinedClinit.java new file mode 100644 index 00000000000..caa32c745c3 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/AlreadyDefinedClinit.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.already.defined.in.clinit + +class AlreadyDefinedClinit { + static { + int i; + int i; + } +} diff --git a/langtools/test/tools/javac/diags/examples/KindnameInstanceInit.java b/langtools/test/tools/javac/diags/examples/KindnameInstanceInit.java new file mode 100644 index 00000000000..f03c5a8d951 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/KindnameInstanceInit.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.already.defined.in.clinit +// key: compiler.misc.kindname.instance.init +// key: compiler.misc.kindname.class +// key: compiler.misc.kindname.variable +// key: compiler.misc.count.error +// key: compiler.err.error +// run: backdoor + +class KindnameInstanceInit { + { + int i; + int i; + } +} diff --git a/langtools/test/tools/javac/diags/examples/KindnameStaticInit.java b/langtools/test/tools/javac/diags/examples/KindnameStaticInit.java new file mode 100644 index 00000000000..047a370fcdc --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/KindnameStaticInit.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.already.defined.in.clinit +// key: compiler.misc.kindname.static.init +// key: compiler.misc.kindname.class +// key: compiler.misc.kindname.variable +// key: compiler.misc.count.error +// key: compiler.err.error +// run: backdoor + +class KindnameStaticInit { + static { + int i; + int i; + } +} diff --git a/langtools/test/tools/javac/generics/6910550/T6910550d.out b/langtools/test/tools/javac/generics/6910550/T6910550d.out index 676a967804f..c884fe41432 100644 --- a/langtools/test/tools/javac/generics/6910550/T6910550d.out +++ b/langtools/test/tools/javac/generics/6910550/T6910550d.out @@ -1,2 +1,2 @@ -T6910550d.java:12:14: compiler.err.already.defined: m(X), T6910550d +T6910550d.java:12:14: compiler.err.already.defined: kindname.method, m(X), kindname.class, T6910550d 1 error From 0208d38b3c0a6546b09469da99c433a25b4a4166 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Tue, 13 Sep 2011 14:15:22 +0100 Subject: [PATCH 067/214] 7003595: IncompatibleClassChangeError with unreferenced local class with subclass Compiler omits unreferenced local inner classes from the InnerClasses attribute Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symbol.java | 5 + .../com/sun/tools/javac/comp/Lower.java | 8 + .../com/sun/tools/javac/jvm/ClassWriter.java | 11 +- .../test/tools/javac/7003595/T7003595.java | 233 ++++++++++++++++++ .../test/tools/javac/7003595/T7003595b.java | 36 +++ 5 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/7003595/T7003595.java create mode 100644 langtools/test/tools/javac/7003595/T7003595b.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 69473bd5d4f..4903886d536 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -726,6 +726,11 @@ public abstract class Symbol implements Element { */ public JavaFileObject classfile; + /** the list of translated local classes (used for generating + * InnerClasses attribute) + */ + public List trans_local; + /** the constant pool of the class */ public Pool pool; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 6906c12fba3..6c687fb7c4d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2271,6 +2271,14 @@ public class Lower extends TreeTranslator { tree.extending = translate(tree.extending); tree.implementing = translate(tree.implementing); + if (currentClass.isLocal()) { + ClassSymbol encl = currentClass.owner.enclClass(); + if (encl.trans_local == null) { + encl.trans_local = List.nil(); + } + encl.trans_local = encl.trans_local.prepend(currentClass); + } + // Recursively translate members, taking into account that new members // might be created during the translation and prepended to the member // list `tree.defs'. diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 909ea65f749..819740ba120 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -863,10 +863,10 @@ public class ClassWriter extends ClassFile { } if (c.type.tag != CLASS) return; // arrays if (pool != null && // pool might be null if called from xClassName - c.owner.kind != PCK && + c.owner.enclClass() != null && (innerClasses == null || !innerClasses.contains(c))) { // log.errWriter.println("enter inner " + c);//DEBUG - if (c.owner.kind == TYP) enterInner((ClassSymbol)c.owner); + enterInner(c.owner.enclClass()); pool.put(c); pool.put(c.name); if (innerClasses == null) { @@ -1505,6 +1505,13 @@ public class ClassWriter extends ClassFile { default : Assert.error(); } } + + if (c.trans_local != null) { + for (ClassSymbol local : c.trans_local) { + enterInner(local); + } + } + databuf.appendChar(fieldsCount); writeFields(c.members().elems); databuf.appendChar(methodsCount); diff --git a/langtools/test/tools/javac/7003595/T7003595.java b/langtools/test/tools/javac/7003595/T7003595.java new file mode 100644 index 00000000000..6d86b786857 --- /dev/null +++ b/langtools/test/tools/javac/7003595/T7003595.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7003595 + * @summary IncompatibleClassChangeError with unreferenced local class with subclass + */ + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.ConstantPool.*; +import com.sun.tools.javac.api.JavacTool; + +import java.io.File; +import java.net.URI; +import java.util.Arrays; +import java.util.ArrayList; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + + +public class T7003595 { + + /** global decls ***/ + + // Create a single file manager and reuse it for each compile to save time. + static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); + + //statistics + static int checkCount = 0; + + enum ClassKind { + NESTED("static class #N { #B }", "$", true), + INNER("class #N { #B }", "$", false), + LOCAL_REF("void test() { class #N { #B }; new #N(); }", "$1", false), + LOCAL_NOREF("void test() { class #N { #B }; }", "$1", false), + ANON("void test() { new Object() { #B }; }", "$1", false), + NONE("", "", false); + + String memberInnerStr; + String sep; + boolean staticAllowed; + + private ClassKind(String memberInnerStr, String sep, boolean staticAllowed) { + this.memberInnerStr = memberInnerStr; + this.sep = sep; + this.staticAllowed = staticAllowed; + } + + String getSource(String className, String outerName, String nested) { + return memberInnerStr.replaceAll("#O", outerName). + replaceAll("#N", className).replaceAll("#B", nested); + } + + static String getClassfileName(String[] names, ClassKind[] outerKinds, int pos) { + System.out.println(" pos = " + pos + " kind = " + outerKinds[pos] + " sep = " + outerKinds[pos].sep); + String name = outerKinds[pos] != ANON ? + names[pos] : ""; + if (pos == 0) { + return "Test" + outerKinds[pos].sep + name; + } else { + String outerStr = getClassfileName(names, outerKinds, pos - 1); + return outerStr + outerKinds[pos].sep + name; + } + } + + boolean isAllowed(ClassKind nestedKind) { + return nestedKind != NESTED || + staticAllowed; + } + } + + enum LocalInnerClass { + LOCAL_REF("class L {}; new L();", "Test$1L"), + LOCAL_NOREF("class L {};", "Test$1L"), + ANON("new Object() {};", "Test$1"), + NONE("", ""); + + String localInnerStr; + String canonicalInnerStr; + + private LocalInnerClass(String localInnerStr, String canonicalInnerStr) { + this.localInnerStr = localInnerStr; + this.canonicalInnerStr = canonicalInnerStr; + } + } + + public static void main(String... args) throws Exception { + for (ClassKind ck1 : ClassKind.values()) { + String cname1 = "C1"; + for (ClassKind ck2 : ClassKind.values()) { + if (!ck1.isAllowed(ck2)) continue; + String cname2 = "C2"; + for (ClassKind ck3 : ClassKind.values()) { + if (!ck2.isAllowed(ck3)) continue; + String cname3 = "C3"; + new T7003595(new ClassKind[] {ck1, ck2, ck3}, new String[] { cname1, cname2, cname3 }).compileAndCheck(); + } + } + } + + System.out.println("Total checks made: " + checkCount); + } + + /** instance decls **/ + + ClassKind[] cks; + String[] cnames; + + T7003595(ClassKind[] cks, String[] cnames) { + this.cks = cks; + this.cnames = cnames; + } + + void compileAndCheck() throws Exception { + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(); + JavacTask ct = (JavacTask)tool.getTask(null, fm, null, + null, null, Arrays.asList(source)); + ct.call(); + verifyBytecode(source); + } + + void verifyBytecode(JavaSource source) { + for (int i = 0; i < 3 ; i ++) { + if (cks[i] == ClassKind.NONE) break; + checkCount++; + String filename = cks[i].getClassfileName(cnames, cks, i); + File compiledTest = new File(filename + ".class"); + try { + ClassFile cf = ClassFile.read(compiledTest); + if (cf == null) { + throw new Error("Classfile not found: " + filename); + } + + InnerClasses_attribute innerClasses = (InnerClasses_attribute)cf.getAttribute(Attribute.InnerClasses); + + ArrayList foundInnerSig = new ArrayList<>(); + if (innerClasses != null) { + for (InnerClasses_attribute.Info info : innerClasses.classes) { + String foundSig = info.getInnerClassInfo(cf.constant_pool).getName(); + foundInnerSig.add(foundSig); + } + } + + ArrayList expectedInnerSig = new ArrayList<>(); + //add inner class (if any) + if (i < 2 && cks[i + 1] != ClassKind.NONE) { + expectedInnerSig.add(cks[i + 1].getClassfileName(cnames, cks, i + 1)); + } + //add inner classes + for (int j = 0 ; j != i + 1 && j < 3; j++) { + expectedInnerSig.add(cks[j].getClassfileName(cnames, cks, j)); + } + + if (expectedInnerSig.size() != foundInnerSig.size()) { + throw new Error("InnerClasses attribute for " + cnames[i] + " has wrong size\n" + + "expected " + expectedInnerSig.size() + "\n" + + "found " + innerClasses.number_of_classes + "\n" + + source); + } + + for (String foundSig : foundInnerSig) { + if (!expectedInnerSig.contains(foundSig)) { + throw new Error("InnerClasses attribute for " + cnames[i] + " has unexpected signature: " + + foundSig + "\n" + source + "\n" + expectedInnerSig); + } + } + + for (String expectedSig : expectedInnerSig) { + if (!foundInnerSig.contains(expectedSig)) { + throw new Error("InnerClasses attribute for " + cnames[i] + " does not contain expected signature: " + + expectedSig + "\n" + source); + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Error("error reading " + compiledTest +": " + e); + } + } + } + + class JavaSource extends SimpleJavaFileObject { + + static final String source_template = "class Test { #C }"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + String c3 = cks[2].getSource(cnames[2], cnames[1], ""); + String c2 = cks[1].getSource(cnames[1], cnames[0], c3); + String c1 = cks[0].getSource(cnames[0], "Test", c2); + source = source_template.replace("#C", c1); + } + + @Override + public String toString() { + return source; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } +} diff --git a/langtools/test/tools/javac/7003595/T7003595b.java b/langtools/test/tools/javac/7003595/T7003595b.java new file mode 100644 index 00000000000..0e0eb2ecc57 --- /dev/null +++ b/langtools/test/tools/javac/7003595/T7003595b.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7003595 + * @summary IncompatibleClassChangeError with unreferenced local class with subclass + */ + +public class T7003595b { + public static void main(String... args) throws Exception { + class A {} + class B extends A {} + B.class.getSuperclass().getDeclaringClass(); + } +} From 08619c2e9c99e5ea8c9fa5e65ef0057c618720a3 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Tue, 13 Sep 2011 14:15:39 +0100 Subject: [PATCH 068/214] 7086601: Error message bug: cause for method mismatch is 'null' Inference error during lub() does not set 'cause' for method resolution diagnostic Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Infer.java | 21 +- .../tools/javac/resources/compiler.properties | 4 + .../examples/IncompatibleUpperBounds.java | 38 ++++ .../generics/inference/7086601/T7086601a.java | 34 +++ .../generics/inference/7086601/T7086601a.out | 5 + .../generics/inference/7086601/T7086601b.java | 199 ++++++++++++++++++ 6 files changed, 289 insertions(+), 12 deletions(-) create mode 100644 langtools/test/tools/javac/diags/examples/IncompatibleUpperBounds.java create mode 100644 langtools/test/tools/javac/generics/inference/7086601/T7086601a.java create mode 100644 langtools/test/tools/javac/generics/inference/7086601/T7086601a.out create mode 100644 langtools/test/tools/javac/generics/inference/7086601/T7086601b.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index 2938f9945fe..3c9ed3af15d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -269,21 +269,18 @@ public class Infer { // VGJ: sort of inlined maximizeInst() below. Adding // bounds can cause lobounds that are above hibounds. List hibounds = Type.filter(that.hibounds, errorFilter); - if (hibounds.isEmpty()) - return; Type hb = null; - if (hibounds.tail.isEmpty()) + if (hibounds.isEmpty()) + hb = syms.objectType; + else if (hibounds.tail.isEmpty()) hb = hibounds.head; - else for (List bs = hibounds; - bs.nonEmpty() && hb == null; - bs = bs.tail) { - if (isSubClass(bs.head, hibounds)) - hb = types.fromUnknownFun.apply(bs.head); - } + else + hb = types.glb(hibounds); if (hb == null || - !types.isSubtypeUnchecked(hb, hibounds, warn) || - !types.isSubtypeUnchecked(that.inst, hb, warn)) - throw ambiguousNoInstanceException; + hb.isErroneous()) + throw ambiguousNoInstanceException + .setMessage("incompatible.upper.bounds", + that.qtype, hibounds); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 2587e0353a2..4fc3d208503 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1602,6 +1602,10 @@ compiler.misc.no.unique.maximal.instance.exists=\ compiler.misc.no.unique.minimal.instance.exists=\ no unique minimal instance exists for type variable {0} with lower bounds {1} +# 0: type, 1: list of type +compiler.misc.incompatible.upper.bounds=\ + inference variable {0} has incompatible upper bounds {1} + # 0: list of type, 1: type, 2: type compiler.misc.infer.no.conforming.instance.exists=\ no instance(s) of type variable(s) {0} exist so that {1} conforms to {2} diff --git a/langtools/test/tools/javac/diags/examples/IncompatibleUpperBounds.java b/langtools/test/tools/javac/diags/examples/IncompatibleUpperBounds.java new file mode 100644 index 00000000000..bc15256657c --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/IncompatibleUpperBounds.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//key: compiler.err.cant.apply.symbols +//key: compiler.misc.inapplicable.method +//key: compiler.misc.arg.length.mismatch +//key: compiler.misc.incompatible.upper.bounds + +import java.util.List; + +class IncompatibleUpperBounds { + void m(List s1, List s2) { } + void m(Object o) {} + + void test(List li, List ls) { + m(li, ls); + } +} diff --git a/langtools/test/tools/javac/generics/inference/7086601/T7086601a.java b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.java new file mode 100644 index 00000000000..5243d82eee7 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.java @@ -0,0 +1,34 @@ +/** + * @test /nodynamiccopyright/ + * @bug 7086601 + * @summary Error message bug: cause for method mismatch is 'null' + * @compile/fail/ref=T7086601a.out -XDrawDiagnostics T7086601a.java + */ + +class T7086601 { + static void m1(Iterable s1, Iterable s2) { } + static void m1(Object o) {} + + static void m2(Iterable s1, Iterable s2, Iterable s3) { } + static void m2(Object o) {} + + @SafeVarargs + static void m3(Iterable... ss) { } + static void m3(Object o) {} + + static void test1(Iterable is, Iterable ii) { + m1(is, ii); + } + + static void test2(Iterable is, Iterable ii, Iterable id) { + m2(is, ii, id); + } + + static void test3(Iterable is, Iterable ii) { + m3(is, ii); + } + + static void test4(Iterable is, Iterable ii, Iterable id) { + m3(is, ii, id); + } +} diff --git a/langtools/test/tools/javac/generics/inference/7086601/T7086601a.out b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.out new file mode 100644 index 00000000000..8b2cdb27431 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.out @@ -0,0 +1,5 @@ +T7086601a.java:20:9: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m1(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m1(java.lang.Iterable,java.lang.Iterable), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String))} +T7086601a.java:24:9: compiler.err.cant.apply.symbols: kindname.method, m2, java.lang.Iterable,java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m2(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m2(java.lang.Iterable,java.lang.Iterable,java.lang.Iterable), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String))} +T7086601a.java:28:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Iterable...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String))} +T7086601a.java:32:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable,java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Iterable...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String))} +4 errors diff --git a/langtools/test/tools/javac/generics/inference/7086601/T7086601b.java b/langtools/test/tools/javac/generics/inference/7086601/T7086601b.java new file mode 100644 index 00000000000..0eceb7fe6a5 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601b.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7086601 + * @summary Error message bug: cause for method mismatch is 'null' + */ + +import com.sun.source.util.JavacTask; +import java.net.URI; +import java.util.Arrays; +import java.util.ArrayList; +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + + +public class T7086601b { + + static int checkCount = 0; + + enum TypeKind { + STRING("String", false), + INTEGER("Integer", false), + NUMBER("Number", false), + SERIALIZABLE("java.io.Serializable", true), + CLONEABLE("Cloneable", true), + X("X", false), + Y("Y", false), + Z("Z", false); + + String typeStr; + boolean isInterface; + + private TypeKind(String typeStr, boolean isInterface) { + this.typeStr = typeStr; + this.isInterface = isInterface; + } + + boolean isSubtypeof(TypeKind other) { + return (this == INTEGER && other == NUMBER || + this == Z && other == Y || + this == other); + } + } + + enum MethodCallKind { + ARITY_ONE("m(a1);", 1), + ARITY_TWO("m(a1, a2);", 2), + ARITY_THREE("m(a1, a2, a3);", 3); + + String invokeString; + int arity; + + private MethodCallKind(String invokeString, int arity) { + this.invokeString = invokeString; + this.arity = arity; + } + } + + public static void main(String... args) throws Exception { + + //create default shared JavaCompiler - reused across multiple compilations + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + for (TypeKind a1 : TypeKind.values()) { + for (TypeKind a2 : TypeKind.values()) { + for (TypeKind a3 : TypeKind.values()) { + for (MethodCallKind mck : MethodCallKind.values()) { + new T7086601b(a1, a2, a3, mck).run(comp, fm); + } + } + } + } + System.out.println("Total check executed: " + checkCount); + } + + TypeKind a1; + TypeKind a2; + TypeKind a3; + MethodCallKind mck; + JavaSource source; + DiagnosticChecker diagChecker; + + T7086601b(TypeKind a1, TypeKind a2, TypeKind a3, MethodCallKind mck) { + this.a1 = a1; + this.a2 = a2; + this.a3 = a3; + this.mck = mck; + this.source = new JavaSource(); + this.diagChecker = new DiagnosticChecker(); + } + + class JavaSource extends SimpleJavaFileObject { + + final String bodyTemplate = "import java.util.List;\n"+ + "class Test {\n" + + " void m(List l1) { }\n" + + " void m(List l1, List l2) { }\n" + + " void m(List l1, List l2, List l3) { }\n" + + " void test(List<#A1> a1, List<#A2> a2, List<#A3> a3) { #MC } }"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = bodyTemplate.replace("#A1", a1.typeStr) + .replace("#A2", a2.typeStr).replace("#A3", a3.typeStr) + .replace("#MC", mck.invokeString); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { + JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, + null, null, Arrays.asList(source)); + try { + ct.analyze(); + } catch (Throwable ex) { + throw new AssertionError("Error thron when compiling the following code:\n" + source.getCharContent(true)); + } + check(); + } + + void check() { + checkCount++; + + boolean errorExpected = false; + + if (mck.arity > 1) { + TypeKind[] argtypes = { a1, a2, a3 }; + ArrayList classes = new ArrayList<>(); + for (int i = 0 ; i < mck.arity ; i ++ ) { + if (!argtypes[i].isInterface) { + classes.add(argtypes[i]); + } + } + boolean glb_exists = true; + for (TypeKind arg_i : classes) { + glb_exists = true; + for (TypeKind arg_j : classes) { + if (!arg_i.isSubtypeof(arg_j)) { + glb_exists = false; + break; + } + } + if (glb_exists) break; + } + errorExpected = !glb_exists; + } + + if (errorExpected != diagChecker.errorFound) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nFound error: " + diagChecker.errorFound + + "\nExpected error: " + errorExpected); + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener { + + boolean errorFound; + + public void report(Diagnostic diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +} From 7d850203b954371d90b77a9711c3f90a11b5735e Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Tue, 13 Sep 2011 12:40:14 -0400 Subject: [PATCH 069/214] 7089625: G1: policy for how many old regions to add to the CSet (when young gen is fixed) is broken When refactoring the code for a previous fix, a condition was not correctly negated which prevents the G1 policy from adding the correct number of old regions to the CSet when the young gen size is fixed. The changeset also fixes a small syntactical issue in g1ErgoVerbose.hpp which is causing compiler warnings. Reviewed-by: brutisso, ysr --- .../src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp | 4 ++-- hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 306eec115c8..d43d080c7f4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -3042,10 +3042,10 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set( should_continue = false; } } else { - if (_collection_set_size < _young_list_fixed_length) { + if (_collection_set_size >= _young_list_fixed_length) { ergo_verbose2(ErgoCSetConstruction, "stop adding old regions to CSet", - ergo_format_reason("CSet length lower than target") + ergo_format_reason("CSet length reached target") ergo_format_region("CSet") ergo_format_region("young target"), _collection_set_size, _young_list_fixed_length); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp index 1fe9f9bdede..c170a49b85a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp @@ -58,7 +58,7 @@ typedef enum { // ErgoLow is 0 so that we don't have to explicitly or a heuristic // id with ErgoLow to keep its use simpler. ErgoLow = 0, - ErgoHigh = 1 << ErgoLevelShift, + ErgoHigh = 1 << ErgoLevelShift } ErgoLevel; // The available heuristics. From e756c96259dfddcaeb2240a8f551ce5be1c47f13 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 13 Sep 2011 11:46:51 -0700 Subject: [PATCH 070/214] 7089632: assert(machtmp->outcnt() == 1) failed: expected for a MachTemp Replace assert with check to delete MachTemp nodes only when they are really dead. Reviewed-by: never --- hotspot/src/share/vm/opto/postaloc.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/opto/postaloc.cpp b/hotspot/src/share/vm/opto/postaloc.cpp index f2605b0cb46..603264acc76 100644 --- a/hotspot/src/share/vm/opto/postaloc.cpp +++ b/hotspot/src/share/vm/opto/postaloc.cpp @@ -100,10 +100,13 @@ int PhaseChaitin::yank_if_dead( Node *old, Block *current_block, Node_List *valu Node *tmp = NULL; for (uint i = 1; i < old->req(); i++) { if (old->in(i)->is_MachTemp()) { + // handle TEMP inputs Node* machtmp = old->in(i); - assert(machtmp->outcnt() == 1, "expected for a MachTemp"); - blk_adjust += yank(machtmp, current_block, value, regnd); - machtmp->disconnect_inputs(NULL); + if (machtmp->outcnt() == 1) { + assert(machtmp->unique_out() == old, "sanity"); + blk_adjust += yank(machtmp, current_block, value, regnd); + machtmp->disconnect_inputs(NULL); + } } else { assert(tmp == NULL, "can't handle more non MachTemp inputs"); tmp = old->in(i); From 12a0dac949bd84176d0c1e6ea916161170d01086 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 13 Sep 2011 16:37:09 -0700 Subject: [PATCH 071/214] 7090297: Remove com.sun.tools.javac.Launcher from tools.jar Reviewed-by: jjg --- .../classes/com/sun/tools/javac/Launcher.java | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 langtools/src/share/classes/com/sun/tools/javac/Launcher.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/Launcher.java b/langtools/src/share/classes/com/sun/tools/javac/Launcher.java deleted file mode 100644 index 8c17804ea86..00000000000 --- a/langtools/src/share/classes/com/sun/tools/javac/Launcher.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac; - -import java.io.File; -import java.util.prefs.Preferences; -import javax.swing.JFileChooser; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; - - -/** - * Unsupported entry point for starting javac from an IDE. - * - *

Note: this class is not available in the JDK. It is not - * compiled by default and will not be in tools.jar. It is designed - * to be useful when editing the compiler sources in an IDE (as part - * of a project). Simply ensure that this class is added to - * the project and make it the main class of the project.

- * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

- * - * @author Peter von der Ahé - * @since 1.6 - */ -class Launcher { - public static void main(String... args) { - JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); - JFileChooser fileChooser; - Preferences prefs = Preferences.userNodeForPackage(Launcher.class); - if (args.length > 0) - fileChooser = new JFileChooser(args[0]); - else { - String fileName = prefs.get("recent.file", null); - fileChooser = new JFileChooser(); - if (fileName != null) { - fileChooser = new JFileChooser(); - fileChooser.setSelectedFile(new File(fileName)); - } - } - if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { - String fileName = fileChooser.getSelectedFile().getPath(); - prefs.put("recent.file", fileName); - javac.run(System.in, null, null, "-d", "/tmp", fileName); - } - } -} From 9b101c8ba6ae57b8ff42324912e71c6eb9a1f249 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 13 Sep 2011 16:58:35 -0700 Subject: [PATCH 072/214] 7090069: Java launcher hangs in infinite loop on windows when UseNUMA[Interleaving] is specified Fix _numa_used_node_list array size specification Reviewed-by: kvn, johnc, jmasa, ysr --- hotspot/src/os/windows/vm/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index d9cfca01038..9de05fa96a8 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2644,7 +2644,7 @@ public: ULONG highest_node_number; if (!os::Kernel32Dll::GetNumaHighestNodeNumber(&highest_node_number)) return false; free_node_list(); - _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number); + _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number + 1); for (unsigned int i = 0; i <= highest_node_number; i++) { ULONGLONG proc_mask_numa_node; if (!os::Kernel32Dll::GetNumaNodeProcessorMask(i, &proc_mask_numa_node)) return false; From f99084037a1c3a13d23a735e31f1efc7c4a747e2 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 13 Sep 2011 20:28:00 -0700 Subject: [PATCH 073/214] 7090259: Fix hotspot sources to build with old compilers Fixed warnings which prevent building VM with old compilers. Reviewed-by: never --- hotspot/make/solaris/makefiles/sparcWorks.make | 3 +++ hotspot/src/share/vm/classfile/javaClasses.cpp | 2 +- hotspot/src/share/vm/oops/instanceRefKlass.cpp | 10 +++++----- hotspot/src/share/vm/oops/methodOop.cpp | 15 +++++++++++---- hotspot/src/share/vm/opto/block.cpp | 2 +- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make index 18a892e91d8..8ee34787955 100644 --- a/hotspot/make/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -148,6 +148,9 @@ endif # -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +# Compiler warnings are treated as errors +CFLAGS_WARN = -xwe + ################################################ # Begin current (>=5.9) Forte compiler options # ################################################# diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index b7455b81b91..e7aa74490ae 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2701,7 +2701,7 @@ void java_lang_invoke_CallSite::compute_offsets() { instanceKlass* ik = instanceKlass::cast(k); methodOop m_normal = ik->lookup_method(vmSymbols::setTargetNormal_name(), vmSymbols::setTarget_signature()); methodOop m_volatile = ik->lookup_method(vmSymbols::setTargetVolatile_name(), vmSymbols::setTarget_signature()); - guarantee(m_normal && m_volatile, "must exist"); + guarantee(m_normal != NULL && m_volatile != NULL, "must exist"); m_normal->set_not_compilable_quietly(); m_volatile->set_not_compilable_quietly(); } diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index b3c3d161824..71a7a1fcff3 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -45,7 +45,7 @@ #endif template -static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { +void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); T heap_oop = oopDesc::load_heap_oop(referent_addr); debug_only( @@ -99,7 +99,7 @@ static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { oop discovered = java_lang_ref_Reference::discovered(obj); assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", - obj)); + (oopDesc*)obj)); #endif } // treat next as normal oop. next is a link in the reference queue. @@ -179,7 +179,7 @@ void specialized_oop_follow_contents(instanceRefKlass* ref, oop discovered = java_lang_ref_Reference::discovered(obj); assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", - obj)); + (oopDesc*)obj)); #endif } PSParallelCompact::mark_and_push(cm, next_addr); @@ -285,7 +285,7 @@ int instanceRefKlass::oop_adjust_pointers(oop obj) { T disc_oop = oopDesc::load_heap_oop(disc_addr); \ assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop), \ err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL" \ - "discovered field", obj)); \ + "discovered field", (oopDesc*)obj)); \ ) \ } \ /* treat next as normal oop */ \ @@ -403,7 +403,7 @@ void specialized_oop_push_contents(instanceRefKlass *ref, oop discovered = java_lang_ref_Reference::discovered(obj); assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", - obj)); + (oopDesc*)obj)); #endif } diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 0f03ae43c66..879ec0152ef 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -1268,12 +1268,19 @@ static void reorder_based_on_method_index(objArrayOop methods, // Comparer for sorting an object array containing // methodOops. -template -static int method_comparator(T a, T b) { +// Used non-template method_comparator methods since +// Visual Studio 2003 compiler generates incorrect +// optimized code for it. +static int method_comparator_narrowOop(narrowOop a, narrowOop b) { methodOop m = (methodOop)oopDesc::decode_heap_oop_not_null(a); methodOop n = (methodOop)oopDesc::decode_heap_oop_not_null(b); return m->name()->fast_compare(n->name()); } +static int method_comparator_oop(oop a, oop b) { + methodOop m = (methodOop)a; + methodOop n = (methodOop)b; + return m->name()->fast_compare(n->name()); +} // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array void methodOopDesc::sort_methods(objArrayOop methods, @@ -1299,9 +1306,9 @@ void methodOopDesc::sort_methods(objArrayOop methods, { No_Safepoint_Verifier nsv; if (UseCompressedOops) { - QuickSort::sort((narrowOop*)(methods->base()), length, method_comparator, idempotent); + QuickSort::sort((narrowOop*)(methods->base()), length, method_comparator_narrowOop, idempotent); } else { - QuickSort::sort((oop*)(methods->base()), length, method_comparator, idempotent); + QuickSort::sort((oop*)(methods->base()), length, method_comparator_oop, idempotent); } if (UseConcMarkSweepGC) { // For CMS we need to dirty the cards for the array diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index 3cbc5e7db1f..02ef7f90781 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -1107,7 +1107,7 @@ static int edge_order(CFGEdge **e0, CFGEdge **e1) { //------------------------------trace_frequency_order-------------------------- // Comparison function for edges -static int trace_frequency_order(const void *p0, const void *p1) { +extern "C" int trace_frequency_order(const void *p0, const void *p1) { Trace *tr0 = *(Trace **) p0; Trace *tr1 = *(Trace **) p1; Block *b0 = tr0->first_block(); From fcc31d97412196b241d2082c8290632de9596144 Mon Sep 17 00:00:00 2001 From: Bertrand Delsart Date: Wed, 14 Sep 2011 10:40:13 +0200 Subject: [PATCH 074/214] 7057978: improve robustness of c1 ARM back-end wrt non encodable constants ARM only, avoid assertion failures for huge constants generated by C1 shared code Reviewed-by: never, vladidan --- hotspot/src/share/vm/c1/c1_LIR.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index f6e10ec6fdf..44f2b62a7bd 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -142,7 +142,8 @@ void LIR_Address::verify() const { #endif #ifdef ARM assert(disp() == 0 || index()->is_illegal(), "can't have both"); - assert(-4096 < disp() && disp() < 4096, "architecture constraint"); + // Note: offsets higher than 4096 must not be rejected here. They can + // be handled by the back-end or will be rejected if not. #endif #ifdef _LP64 assert(base()->is_cpu_register(), "wrong base operand"); From bc855ff2e0d2365c6c48065ce377f97bc28f8fe1 Mon Sep 17 00:00:00 2001 From: Bertrand Delsart Date: Wed, 14 Sep 2011 16:28:39 +0200 Subject: [PATCH 075/214] 7077806: ARM: java.lang.InternalError: bound subword value does not fit into the subword type Shared fix necessary for ARM/PPC Reviewed-by: twisti, roland --- hotspot/src/share/vm/prims/methodHandles.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 216a6ede210..f1c44ba7b4d 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -515,11 +515,12 @@ class MethodHandles: AllStatic { } // Here is the transformation the i2i adapter must perform: static int truncate_subword_from_vminfo(jint value, int vminfo) { - jint tem = value << vminfo; + int shift = vminfo & ~CONV_VMINFO_SIGN_FLAG; + jint tem = value << shift; if ((vminfo & CONV_VMINFO_SIGN_FLAG) != 0) { - return (jint)tem >> vminfo; + return (jint)tem >> shift; } else { - return (juint)tem >> vminfo; + return (juint)tem >> shift; } } From 16a24a909d8b9aaaa9f0f67bcbeda56b36ede10d Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 14 Sep 2011 08:33:34 -0700 Subject: [PATCH 076/214] 6915797: Remove sun.tools.jar.JarImageSource that is not used 7090178: Move java.util.XMLUtils to another package to avoid split package Reviewed-by: alanb, sherman --- jdk/make/java/java/FILES_java.gmk | 1 - jdk/make/sun/Makefile | 2 +- jdk/make/sun/util/Makefile | 40 +++++++++ .../share/classes/java/util/Properties.java | 57 ++++++++++++ .../classes/sun/tools/jar/JarImageSource.java | 88 ------------------- .../{java/util => sun/util/xml}/XMLUtils.java | 9 +- 6 files changed, 103 insertions(+), 94 deletions(-) create mode 100644 jdk/make/sun/util/Makefile delete mode 100644 jdk/src/share/classes/sun/tools/jar/JarImageSource.java rename jdk/src/share/classes/{java/util => sun/util/xml}/XMLUtils.java (97%) diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 58c763a3fe5..7aae0877000 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -208,7 +208,6 @@ JAVA_JAVA_java = \ java/util/Observable.java \ java/util/Observer.java \ java/util/Properties.java \ - java/util/XMLUtils.java \ java/util/InvalidPropertiesFormatException.java \ java/util/PropertyPermission.java \ java/util/PropertyResourceBundle.java \ diff --git a/jdk/make/sun/Makefile b/jdk/make/sun/Makefile index 4c19f4ecbc0..c3a8f189170 100644 --- a/jdk/make/sun/Makefile +++ b/jdk/make/sun/Makefile @@ -68,7 +68,7 @@ else endif # nio need to be compiled before awt to have all charsets ready -SUBDIRS = jar security javazic misc net nio text launcher +SUBDIRS = jar security javazic misc net nio text util launcher ifdef BUILD_HEADLESS_ONLY DISPLAY_LIBS = awt $(HEADLESS_SUBDIR) diff --git a/jdk/make/sun/util/Makefile b/jdk/make/sun/util/Makefile new file mode 100644 index 00000000000..70d90757b7c --- /dev/null +++ b/jdk/make/sun/util/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +BUILDDIR = ../.. +PACKAGE = sun.util +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +AUTO_FILES_JAVA_DIRS = sun/util/xml + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk + diff --git a/jdk/src/share/classes/java/util/Properties.java b/jdk/src/share/classes/java/util/Properties.java index d27e60871f3..1cd19a0e40e 100644 --- a/jdk/src/share/classes/java/util/Properties.java +++ b/jdk/src/share/classes/java/util/Properties.java @@ -34,6 +34,7 @@ import java.io.Reader; import java.io.Writer; import java.io.OutputStreamWriter; import java.io.BufferedWriter; +import java.lang.reflect.*; /** * The Properties class represents a persistent set of @@ -1111,4 +1112,60 @@ class Properties extends Hashtable { private static final char[] hexDigit = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; + + + private static class XMLUtils { + private static Method load = null; + private static Method save = null; + static { + try { + // reference sun.util.xml.Utils reflectively + // to allow the Properties class be compiled in + // the absence of XML + Class c = Class.forName("sun.util.xml.XMLUtils", true, null); + load = c.getMethod("load", Properties.class, InputStream.class); + save = c.getMethod("save", Properties.class, OutputStream.class, + String.class, String.class); + } catch (ClassNotFoundException cnf) { + throw new AssertionError(cnf); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + } + + static void invoke(Method m, Object... args) throws IOException { + try { + m.invoke(null, args); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) + throw (RuntimeException)t; + + if (t instanceof IOException) { + throw (IOException)t; + } else { + throw new AssertionError(t); + } + } + } + + static void load(Properties props, InputStream in) + throws IOException, InvalidPropertiesFormatException + { + if (load == null) + throw new InternalError("sun.util.xml.XMLUtils not found"); + invoke(load, props, in); + } + + static void save(Properties props, OutputStream os, String comment, + String encoding) + throws IOException + { + if (save == null) + throw new InternalError("sun.util.xml.XMLUtils not found"); + invoke(save, props, os, comment, encoding); + } + } } diff --git a/jdk/src/share/classes/sun/tools/jar/JarImageSource.java b/jdk/src/share/classes/sun/tools/jar/JarImageSource.java deleted file mode 100644 index 254eebd284a..00000000000 --- a/jdk/src/share/classes/sun/tools/jar/JarImageSource.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package sun.tools.jar; - -import sun.awt.image.URLImageSource; -import sun.awt.image.ImageDecoder; -import java.net.URL; -import java.net.JarURLConnection; -import java.util.jar.JarFile; -import java.util.jar.JarEntry; -import java.io.InputStream; -import java.io.IOException; - - -public class JarImageSource extends URLImageSource { - String mimeType; - String entryName = null; - URL url; - - /** - * Create an image source from a Jar entry URL with the specified - * mime type. - */ - public JarImageSource(URL u, String type) { - super(u); - url = u; - mimeType = type; - } - - /** - * Create an image source from a Jar file/entry URL - * with the specified entry name and mime type. - */ - public JarImageSource(URL u, String name, String type) { - this(u, type); - this.entryName = name; - } - - protected ImageDecoder getDecoder() { - InputStream is = null; - try { - JarURLConnection c = (JarURLConnection)url.openConnection(); - JarFile f = c.getJarFile(); - JarEntry e = c.getJarEntry(); - - if (entryName != null && e == null) { - e = f.getJarEntry(entryName); - } - if (e == null || (e != null && entryName != null - && (!(entryName.equals(e.getName()))))) { - return null; - } - is = f.getInputStream(e); - } catch (IOException e) { - return null; - } - - ImageDecoder id = decoderForType(is, mimeType); - if (id == null) { - id = getDecoder(is); - } - return id; - } -} diff --git a/jdk/src/share/classes/java/util/XMLUtils.java b/jdk/src/share/classes/sun/util/xml/XMLUtils.java similarity index 97% rename from jdk/src/share/classes/java/util/XMLUtils.java rename to jdk/src/share/classes/sun/util/xml/XMLUtils.java index 1666c631cac..ab7ca851396 100644 --- a/jdk/src/share/classes/java/util/XMLUtils.java +++ b/jdk/src/share/classes/sun/util/xml/XMLUtils.java @@ -23,9 +23,10 @@ * questions. */ -package java.util; +package sun.util.xml; import java.io.*; +import java.util.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import org.w3c.dom.*; @@ -42,7 +43,7 @@ import javax.xml.transform.stream.*; * @author Michael McCloskey * @since 1.3 */ -class XMLUtils { +public class XMLUtils { // XML loading and saving methods for Properties @@ -66,7 +67,7 @@ class XMLUtils { */ private static final String EXTERNAL_XML_VERSION = "1.0"; - static void load(Properties props, InputStream in) + public static void load(Properties props, InputStream in) throws IOException, InvalidPropertiesFormatException { Document doc = null; @@ -120,7 +121,7 @@ class XMLUtils { } } - static void save(Properties props, OutputStream os, String comment, + public static void save(Properties props, OutputStream os, String comment, String encoding) throws IOException { From 30d2b45bd8010d5c01ad942beb4c9e2f2853f531 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 14 Sep 2011 11:32:11 -0700 Subject: [PATCH 077/214] 6879143: java.math.BigInteger misses the xxxValueExact methods Reviewed-by: alanb --- .../share/classes/java/math/BigInteger.java | 82 ++++++++ .../java/math/BigInteger/TestValueExact.java | 194 ++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 jdk/test/java/math/BigInteger/TestValueExact.java diff --git a/jdk/src/share/classes/java/math/BigInteger.java b/jdk/src/share/classes/java/math/BigInteger.java index 748a6c2f2b0..a4988deaa40 100644 --- a/jdk/src/share/classes/java/math/BigInteger.java +++ b/jdk/src/share/classes/java/math/BigInteger.java @@ -2919,6 +2919,7 @@ public class BigInteger extends Number implements Comparable { * result with the opposite sign. * * @return this BigInteger converted to an {@code int}. + * @see #intValueExact() */ public int intValue() { int result = 0; @@ -2939,6 +2940,7 @@ public class BigInteger extends Number implements Comparable { * result with the opposite sign. * * @return this BigInteger converted to a {@code long}. + * @see #longValueExact() */ public long longValue() { long result = 0; @@ -3382,4 +3384,84 @@ public class BigInteger extends Number implements Comparable { } return result; } + + /** + * Converts this {@code BigInteger} to a {@code long}, checking + * for lost information. If the value of this {@code BigInteger} + * is out of the range of the {@code long} type, then an + * {@code ArithmeticException} is thrown. + * + * @return this {@code BigInteger} converted to a {@code long}. + * @throws ArithmeticException if the value of {@code this} will + * not exactly fit in a {@code long}. + * @see BigInteger#longValue + * @since 1.8 + */ + public long longValueExact() { + if (mag.length <= 2 && bitLength() <= 63) + return longValue(); + else + throw new ArithmeticException("BigInteger out of long range"); + } + + /** + * Converts this {@code BigInteger} to an {@code int}, checking + * for lost information. If the value of this {@code BigInteger} + * is out of the range of the {@code int} type, then an + * {@code ArithmeticException} is thrown. + * + * @return this {@code BigInteger} converted to an {@code int}. + * @throws ArithmeticException if the value of {@code this} will + * not exactly fit in a {@code int}. + * @see BigInteger#intValue + * @since 1.8 + */ + public int intValueExact() { + if (mag.length <= 1 && bitLength() <= 31) + return intValue(); + else + throw new ArithmeticException("BigInteger out of int range"); + } + + /** + * Converts this {@code BigInteger} to a {@code short}, checking + * for lost information. If the value of this {@code BigInteger} + * is out of the range of the {@code short} type, then an + * {@code ArithmeticException} is thrown. + * + * @return this {@code BigInteger} converted to a {@code short}. + * @throws ArithmeticException if the value of {@code this} will + * not exactly fit in a {@code short}. + * @see BigInteger#shortValue + * @since 1.8 + */ + public short shortValueExact() { + if (mag.length <= 1 && bitLength() <= 31) { + int value = intValue(); + if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) + return shortValue(); + } + throw new ArithmeticException("BigInteger out of short range"); + } + + /** + * Converts this {@code BigInteger} to a {@code byte}, checking + * for lost information. If the value of this {@code BigInteger} + * is out of the range of the {@code byte} type, then an + * {@code ArithmeticException} is thrown. + * + * @return this {@code BigInteger} converted to a {@code byte}. + * @throws ArithmeticException if the value of {@code this} will + * not exactly fit in a {@code byte}. + * @see BigInteger#byteValue + * @since 1.8 + */ + public byte byteValueExact() { + if (mag.length <= 1 && bitLength() <= 31) { + int value = intValue(); + if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) + return byteValue(); + } + throw new ArithmeticException("BigInteger out of byte range"); + } } diff --git a/jdk/test/java/math/BigInteger/TestValueExact.java b/jdk/test/java/math/BigInteger/TestValueExact.java new file mode 100644 index 00000000000..63ee1583527 --- /dev/null +++ b/jdk/test/java/math/BigInteger/TestValueExact.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6371401 + * @summary Tests of fooValueExact methods + * @author Joseph D. Darcy + */ +import java.math.BigInteger; + +public class TestValueExact { + public static void main(String... args) { + int errors = 0; + + errors += testLongValueExact(); + errors += testIntValueExact(); + errors += testShortValueExact(); + errors += testByteValueExact(); + + if (errors > 0) + throw new RuntimeException(); + } + + private static int testLongValueExact() { + int errors = 0; + BigInteger[] inRange = { + BigInteger.valueOf(Long.MIN_VALUE), + BigInteger.ZERO, + BigInteger.valueOf(Long.MAX_VALUE) + }; + + BigInteger[] outOfRange = { + BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE), + BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE) + }; + + for (BigInteger bi : inRange) { + if (bi.longValueExact() != bi.longValue()) { + System.err.println("Mismatching int conversion for " + bi); + errors++; + } + } + + for (BigInteger bi : outOfRange) { + try { + long value = bi.longValueExact(); + System.err.println("Failed to get expected exception on " + + bi + " got " + value); + errors++; + } catch(ArithmeticException ae) { + ; // Expected + } + } + return errors; + } + + private static int testIntValueExact() { + int errors = 0; + BigInteger[] inRange = { + BigInteger.valueOf(Integer.MIN_VALUE), + BigInteger.ZERO, + BigInteger.ONE, + BigInteger.TEN, + BigInteger.valueOf(Integer.MAX_VALUE) + }; + + BigInteger[] outOfRange = { + BigInteger.valueOf((long)Integer.MIN_VALUE - 1), + BigInteger.valueOf((long)Integer.MAX_VALUE + 1) + }; + + for (BigInteger bi : inRange) { + if (bi.intValueExact() != bi.intValue()) { + System.err.println("Mismatching int conversion for " + bi); + errors++; + } + } + + for (BigInteger bi : outOfRange) { + try { + int value = bi.intValueExact(); + System.err.println("Failed to get expected exception on " + + bi + " got " + value); + errors++; + } catch(ArithmeticException ae) { + ; // Expected + } + } + return errors; + } + + private static int testShortValueExact() { + int errors = 0; + BigInteger[] inRange = { + BigInteger.valueOf(Short.MIN_VALUE), + BigInteger.ZERO, + BigInteger.ONE, + BigInteger.TEN, + BigInteger.valueOf(Short.MAX_VALUE) + }; + + BigInteger[] outOfRange = { + BigInteger.valueOf((long)Integer.MIN_VALUE - 1), + BigInteger.valueOf((long)Integer.MIN_VALUE), + BigInteger.valueOf( (int)Short.MIN_VALUE - 1), + BigInteger.valueOf( (int)Short.MAX_VALUE + 1), + BigInteger.valueOf((long)Integer.MAX_VALUE), + BigInteger.valueOf((long)Integer.MAX_VALUE + 1) + }; + + for (BigInteger bi : inRange) { + if (bi.shortValueExact() != bi.shortValue()) { + System.err.println("Mismatching short conversion for " + bi); + errors++; + } + } + + for (BigInteger bi : outOfRange) { + try { + int value = bi.shortValueExact(); + System.err.println("Failed to get expected exception on " + + bi + " got " + value); + errors++; + } catch(ArithmeticException ae) { + ; // Expected + } + } + return errors; + } + + private static int testByteValueExact() { + int errors = 0; + BigInteger[] inRange = { + BigInteger.valueOf(Byte.MIN_VALUE), + BigInteger.valueOf(0), + BigInteger.ONE, + BigInteger.TEN, + BigInteger.valueOf(Byte.MAX_VALUE) + }; + + BigInteger[] outOfRange = { + BigInteger.valueOf((long)Integer.MIN_VALUE - 1), + BigInteger.valueOf((long)Integer.MIN_VALUE), + BigInteger.valueOf( (int)Short.MIN_VALUE - 1), + BigInteger.valueOf( (int)Short.MIN_VALUE), + BigInteger.valueOf( (int)Byte.MIN_VALUE - 1), + BigInteger.valueOf( (int)Byte.MAX_VALUE + 1), + BigInteger.valueOf( (int)Short.MAX_VALUE + 1), + BigInteger.valueOf( (int)Short.MAX_VALUE), + BigInteger.valueOf((long)Integer.MAX_VALUE), + BigInteger.valueOf((long)Integer.MAX_VALUE + 1) + }; + + for (BigInteger bi : inRange) { + if (bi.byteValueExact() != bi.byteValue()) { + System.err.println("Mismatching byte conversion for " + bi); + errors++; + } + } + + for (BigInteger bi : outOfRange) { + try { + int value = bi.byteValueExact(); + System.err.println("Failed to get expected exception on " + + bi + " got " + value); + errors++; + } catch(ArithmeticException ae) { + ; // Expected + } + } + return errors; + } +} From 1ec8f70fdd40a0f3fe4e7586c90336021b41da48 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 14 Sep 2011 12:07:50 -0700 Subject: [PATCH 078/214] 7080267: Call to toString() from an ExpressionStatementTree doesn't take in consideration the ";" at the end Reviewed-by: mcimadamore --- .../com/sun/tools/javac/tree/JCTree.java | 15 ++ .../test/tools/javac/tree/TestToString.java | 159 ++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 langtools/test/tools/javac/tree/TestToString.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index bade408c04c..90376fb929b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -538,6 +538,21 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { super.setPos(pos); return this; } + + /** Convert a statement tree to a pretty-printed string. */ + @Override + public String toString() { + StringWriter s = new StringWriter(); + try { + new Pretty(s, false).printStat(this); + } + catch (IOException e) { + // should never happen, because StringWriter is defined + // never to throw any IOExceptions + throw new AssertionError(e); + } + return s.toString(); + } } public static abstract class JCExpression extends JCTree implements ExpressionTree { diff --git a/langtools/test/tools/javac/tree/TestToString.java b/langtools/test/tools/javac/tree/TestToString.java new file mode 100644 index 00000000000..d5644bcb6e2 --- /dev/null +++ b/langtools/test/tools/javac/tree/TestToString.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7080267 + * @summary Call to toString() from an ExpressionStatementTree doesn't take in + * consideration the ";" at the end + */ + +import com.sun.source.tree.BlockTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.StatementTree; +import com.sun.source.tree.Tree; +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import com.sun.tools.javac.api.JavacTool; + +public class TestToString { + String[] statements = { + "i = i + 1;", + "i++;", + "m();", + ";", + "if (i == 0) return;", + "while (i > 0) i--;", + "{ }", + "{ i++; }", + "class C { }" + }; + + public static void main(String... args) throws Exception { + new TestToString().run(); + } + + void run() throws Exception { + for (String s: statements) { + test(s); + } + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void test(String stmt) throws IOException { + System.err.println("Test: " + stmt); + List options = Collections.emptyList(); + List files = Arrays.asList(new JavaSource(stmt)); + JavacTask t = tool.getTask(null, fm, null, options, null, files); + checkEqual(scan(t.parse()), stmt); + } + + String scan(Iterable trees) { + class Scanner extends TreeScanner { + String scan(Iterable trees) { + StringBuilder sb = new StringBuilder(); + scan(trees, sb); + return sb.toString(); + } + @Override + public Void scan(Tree tree, StringBuilder sb) { + if (print && tree instanceof StatementTree) { + sb.append(PREFIX); + sb.append(tree); + sb.append(SUFFIX); + return null; + } else { + return super.scan(tree, sb); + } + } + @Override + public Void visitBlock(BlockTree tree, StringBuilder sb) { + print = true; + try { + return super.visitBlock(tree, sb); + } finally { + print = false; + } + } + boolean print = false; + } + return new Scanner().scan(trees); + } + + void checkEqual(String found, String expect) { + boolean match = (found == null) ? (expect == null) : + expect.equals(found + .replaceAll("^\\Q" + PREFIX + "\\E\\s*", "") + .replaceAll("\\s*\\Q" + SUFFIX + "\\E$", "") + .replaceAll("\\s+", " ")); + + if (!match) + error("Mismatch: expected: " + expect + " found: " + found); + } + + + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + static final String PREFIX = "#<"; + static final String SUFFIX = "#>"; + + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + int errors = 0; + + static class JavaSource extends SimpleJavaFileObject { + + String source = + "class Test {\n" + + " int i;\n" + + " void m() {\n" + + " #S\n" + + " }\n" + + "}"; + + public JavaSource(String stmt) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = source.replace("#S", stmt); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } +} From 2bbf6511565a68f803fbdde7800d38f46122e9ed Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 14 Sep 2011 12:14:30 -0700 Subject: [PATCH 079/214] 7090249: IllegalStateException from Trees.getScope when called from JSR 199 Reviewed-by: mcimadamore --- .../sun/tools/javac/api/JavacTaskImpl.java | 3 + .../com/sun/tools/javac/api/JavacTrees.java | 27 +++-- .../test/tools/javac/api/TestGetScope.java | 101 ++++++++++++++++++ 3 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 langtools/test/tools/javac/api/TestGetScope.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java index 7face094f16..9241a32ad0b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java @@ -274,6 +274,9 @@ public class JavacTaskImpl extends JavacTask { public Iterable enter(Iterable trees) throws IOException { + if (trees == null && notYetEntered != null && notYetEntered.isEmpty()) + return List.nil(); + prepareCompiler(); ListBuffer roots = null; diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java index b684d29ce64..7bd384bb5ac 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -65,6 +65,7 @@ import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.TreeCopier; import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.List; @@ -263,9 +264,10 @@ public class JavacTrees extends Trees { if (!(path.getLeaf() instanceof JCTree)) // implicit null-check throw new IllegalArgumentException(); - // if we're being invoked via from a JSR199 client, we need to make sure - // all the classes have been entered; if we're being invoked from JSR269, - // then the classes will already have been entered. + // if we're being invoked from a Tree API client via parse/enter/analyze, + // we need to make sure all the classes have been entered; + // if we're being invoked from JSR 199 or JSR 269, then the classes + // will already have been entered. if (javacTaskImpl != null) { try { javacTaskImpl.enter(null); @@ -313,10 +315,19 @@ public class JavacTrees extends Trees { break; case BLOCK: { // System.err.println("BLOCK: "); - if (method != null) - env = memberEnter.getMethodEnv(method, env); - JCTree body = copier.copy((JCTree)tree, (JCTree) path.getLeaf()); - env = attribStatToTree(body, env, copier.leafCopy); + if (method != null) { + try { + Assert.check(method.body == tree); + method.body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf()); + env = memberEnter.getMethodEnv(method, env); + env = attribStatToTree(method.body, env, copier.leafCopy); + } finally { + method.body = (JCBlock) tree; + } + } else { + JCBlock body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf()); + env = attribStatToTree(body, env, copier.leafCopy); + } return env; } default: @@ -329,7 +340,7 @@ public class JavacTrees extends Trees { } } } - return field != null ? memberEnter.getInitEnv(field, env) : env; + return (field != null) ? memberEnter.getInitEnv(field, env) : env; } private Env attribStatToTree(JCTree stat, Envenv, JCTree tree) { diff --git a/langtools/test/tools/javac/api/TestGetScope.java b/langtools/test/tools/javac/api/TestGetScope.java new file mode 100644 index 00000000000..40cf8c9cd3f --- /dev/null +++ b/langtools/test/tools/javac/api/TestGetScope.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7090249 + * @summary IllegalStateException from Trees.getScope when called from JSR 199 + */ + +import com.sun.source.tree.IdentifierTree; +import java.io.File; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import com.sun.source.util.Trees; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; + +@SupportedAnnotationTypes("*") +public class TestGetScope extends AbstractProcessor { + public static void main(String... args) { + new TestGetScope().run(); + } + + public void run() { + File srcDir = new File(System.getProperty("test.src")); + File thisFile = new File(srcDir, getClass().getName() + ".java"); + + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); + + List opts = Arrays.asList("-proc:only", "-doe"); + Iterable files = fm.getJavaFileObjects(thisFile); + JavacTask t = (JavacTask) c.getTask(null, fm, null, opts, null, files); + t.setProcessors(Collections.singleton(this)); + boolean ok = t.call(); + if (!ok) + throw new Error("compilation failed"); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + Trees trees = Trees.instance(processingEnv); + if (round++ == 0) { + for (Element e: roundEnv.getRootElements()) { + TreePath p = trees.getPath(e); + new Scanner().scan(p, trees); + } + } + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + int round; + + static class Scanner extends TreePathScanner { + @Override + public Void visitIdentifier(IdentifierTree t, Trees trees) { + System.err.println("visitIdentifier: " + t); + trees.getScope(getCurrentPath()); + return null; + } + } +} From 2c3a780b41a5577a45fc8469a3813dcff2bada57 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 14 Sep 2011 13:09:15 -0700 Subject: [PATCH 080/214] 7088500: there is no @since tag on SafeVarargs Reviewed-by: mduigou --- jdk/src/share/classes/java/lang/SafeVarargs.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/share/classes/java/lang/SafeVarargs.java b/jdk/src/share/classes/java/lang/SafeVarargs.java index 818ea21bafb..cb14134ffbe 100644 --- a/jdk/src/share/classes/java/lang/SafeVarargs.java +++ b/jdk/src/share/classes/java/lang/SafeVarargs.java @@ -82,6 +82,7 @@ import java.lang.annotation.*; * * * + * @since 1.7 * @jls 4.7 Reifiable Types * @jls 8.4.1 Formal Parameters */ From a300a41ea1905a50c79a03cf959250edc8ad8a26 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 14 Sep 2011 13:57:32 -0700 Subject: [PATCH 081/214] 7090654: nightly failures after 7086585 Reviewed-by: kvn --- .../sun/jvm/hotspot/oops/InstanceKlass.java | 32 ++++++++----------- .../classes/sun/jvm/hotspot/runtime/VM.java | 2 +- .../vm/prims/jvmtiClassFileReconstituter.cpp | 2 +- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index ebdd2633692..9ff98e2aaca 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -513,10 +513,9 @@ public class InstanceKlass extends Klass { void iterateStaticFieldsInternal(OopVisitor visitor) { TypeArray fields = getFields(); int length = getJavaFieldsCount(); - for (int index = 0; index < length; index += FIELD_SLOTS) { - short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); - short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); + for (int index = 0; index < length; index++) { + short accessFlags = getFieldAccessFlags(index); + FieldType type = new FieldType(getFieldSignature(index)); AccessFlags access = new AccessFlags(accessFlags); if (access.isStatic()) { visitField(visitor, type, index); @@ -545,11 +544,9 @@ public class InstanceKlass extends Klass { TypeArray fields = getFields(); int length = getJavaFieldsCount(); - for (int index = 0; index < length; index += FIELD_SLOTS) { - short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); - short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - - FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); + for (int index = 0; index < length; index++) { + short accessFlags = getFieldAccessFlags(index); + FieldType type = new FieldType(getFieldSignature(index)); AccessFlags access = new AccessFlags(accessFlags); if (!access.isStatic()) { visitField(visitor, type, index); @@ -562,11 +559,9 @@ public class InstanceKlass extends Klass { TypeArray fields = getFields(); int length = (int) fields.getLength(); ConstantPool cp = getConstants(); - for (int i = 0; i < length; i += FIELD_SLOTS) { - int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET); - int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET); - Symbol f_name = cp.getSymbolAt(nameIndex); - Symbol f_sig = cp.getSymbolAt(sigIndex); + for (int i = 0; i < length; i++) { + Symbol f_name = getFieldName(i); + Symbol f_sig = getFieldSignature(i); if (name.equals(f_name) && sig.equals(f_sig)) { return newField(i); } @@ -641,8 +636,8 @@ public class InstanceKlass extends Klass { /** Get field by its index in the fields array. Only designed for use in a debugging system. */ - public Field getFieldByIndex(int fieldArrayIndex) { - return newField(fieldArrayIndex); + public Field getFieldByIndex(int fieldIndex) { + return newField(fieldIndex); } @@ -657,7 +652,7 @@ public class InstanceKlass extends Klass { int length = getJavaFieldsCount(); List immediateFields = new ArrayList(length); - for (int index = 0; index < length; index += FIELD_SLOTS) { + for (int index = 0; index < length; index++) { immediateFields.add(getFieldByIndex(index)); } @@ -845,8 +840,7 @@ public class InstanceKlass extends Klass { // Creates new field from index in fields TypeArray private Field newField(int index) { TypeArray fields = getFields(); - short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); + FieldType type = new FieldType(getFieldSignature(index)); if (type.isOop()) { if (VM.getVM().isCompressedOopsEnabled()) { return new NarrowOopField(this, index); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 2d1b62bf914..5a96a8e52fd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -310,7 +310,7 @@ public class VM { usingServerCompiler = false; } else { // Determine whether C2 is present - if (type.getField("_interpreter_invocation_count", false, false) != null) { + if (db.lookupType("Matcher", false) != null) { usingServerCompiler = true; } else { usingClientCompiler = true; diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp index 8502ef26212..35ae7072035 100644 --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp @@ -58,7 +58,7 @@ void JvmtiClassFileReconstituter::write_field_infos() { // Compute the real number of Java fields int java_fields = ikh()->java_fields_count(); - write_u2(java_fields * FieldInfo::field_slots); + write_u2(java_fields); for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) { AccessFlags access_flags = fs.access_flags(); int name_index = fs.name_index(); From afaeb37bb51364a5c98b5136e3dde2f8e3c40a27 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 14 Sep 2011 15:49:54 -0700 Subject: [PATCH 082/214] 7090700: fix for 7080267 breaks two tests Reviewed-by: ksrini --- .../com/sun/tools/javac/tree/JCTree.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 90376fb929b..87f147f23cf 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -538,21 +538,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { super.setPos(pos); return this; } - - /** Convert a statement tree to a pretty-printed string. */ - @Override - public String toString() { - StringWriter s = new StringWriter(); - try { - new Pretty(s, false).printStat(this); - } - catch (IOException e) { - // should never happen, because StringWriter is defined - // never to throw any IOExceptions - throw new AssertionError(e); - } - return s.toString(); - } } public static abstract class JCExpression extends JCTree implements ExpressionTree { @@ -1191,6 +1176,21 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public int getTag() { return EXEC; } + + /** Convert a expression-statement tree to a pretty-printed string. */ + @Override + public String toString() { + StringWriter s = new StringWriter(); + try { + new Pretty(s, false).printStat(this); + } + catch (IOException e) { + // should never happen, because StringWriter is defined + // never to throw any IOExceptions + throw new AssertionError(e); + } + return s.toString(); + } } /** From 4589920917f69bb9471b8a7ed119a3a9edcd18dc Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 14 Sep 2011 18:26:57 -0700 Subject: [PATCH 083/214] 7068437: Regression: Filer.getResource(SOURCE_OUTPUT, ...) no longer works in JDK 7 w/o -s Reviewed-by: darcy --- .../tools/javac/processing/JavacFiler.java | 19 ++- langtools/test/tools/javac/file/T7068437.java | 136 ++++++++++++++++++ 2 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/file/T7068437.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java index 1f712e2d306..d023361098c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -455,9 +455,24 @@ public class JavacFiler implements Filer, Closeable { // TODO: Only support reading resources in selected output // locations? Only allow reading of non-source, non-class // files from the supported input locations? - FileObject fileObject = fileManager.getFileForInput(location, + + // In the following, getFileForInput is the "obvious" method + // to use, but it does not have the "obvious" semantics for + // SOURCE_OUTPUT and CLASS_OUTPUT. Conversely, getFileForOutput + // does not have the correct semantics for any "path" location + // with more than one component. So, for now, we use a hybrid + // invocation. + FileObject fileObject; + if (location.isOutputLocation()) { + fileObject = fileManager.getFileForOutput(location, + pkg.toString(), + relativeName.toString(), + null); + } else { + fileObject = fileManager.getFileForInput(location, pkg.toString(), relativeName.toString()); + } if (fileObject == null) { String name = (pkg.length() == 0) ? relativeName.toString() : (pkg + "/" + relativeName); diff --git a/langtools/test/tools/javac/file/T7068437.java b/langtools/test/tools/javac/file/T7068437.java new file mode 100644 index 00000000000..86ae51fe46e --- /dev/null +++ b/langtools/test/tools/javac/file/T7068437.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7068437 + * @summary Filer.getResource(SOURCE_OUTPUT, ...) no longer works in JDK 7 w/o -s + */ + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedOptions; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +public class T7068437 { + public static void main(String[] args) throws Exception { + new T7068437().run(); + } + + void run() throws Exception { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + System.err.println("using " + compiler.getClass() + + " from " + compiler.getClass().getProtectionDomain().getCodeSource()); + + CompilationTask task = compiler.getTask(null, null, null, + Collections.singleton("-proc:only"), + Collections.singleton("java.lang.Object"), + null); + task.setProcessors(Collections.singleton(new Proc())); + check("compilation", task.call()); + + task = compiler.getTask(null, null, null, + Arrays.asList("-proc:only", "-AexpectFile"), + Collections.singleton("java.lang.Object"), + null); + task.setProcessors(Collections.singleton(new Proc())); + check("compilation", task.call()); + } + + void check(String msg, boolean ok) { + System.err.println(msg + ": " + (ok ? "ok" : "failed")); + if (!ok) + throw new AssertionError(msg); + } + + @SupportedAnnotationTypes("*") + @SupportedOptions("expectFile") + private static class Proc extends AbstractProcessor { + int count; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver() || count++ > 0) { + return false; + } + + Filer filer = processingEnv.getFiler(); + Messager messager = processingEnv.getMessager(); + Map options = processingEnv.getOptions(); + System.err.println(options); + boolean expectFile = options.containsKey("expectFile"); + + System.err.println("running Proc: expectFile=" + expectFile); + + boolean found; + try { + messager.printMessage(Kind.NOTE, "found previous content of length " + + filer.getResource(StandardLocation.SOURCE_OUTPUT, "p", "C.java").getCharContent(false).length()); + found = true; + } catch (FileNotFoundException x) { + messager.printMessage(Kind.NOTE, "not previously there"); + found = false; + } catch (IOException x) { + messager.printMessage(Kind.ERROR, "while reading: " + x); + found = false; + } + + if (expectFile && !found) { + messager.printMessage(Kind.ERROR, "expected file but file not found"); + } + + try { + Writer w = filer.createSourceFile("p.C").openWriter(); + w.write("/* hello! */ package p; class C {}"); + w.close(); + messager.printMessage(Kind.NOTE, "wrote new content"); + } catch (IOException x) { + messager.printMessage(Kind.ERROR, "while writing: " + x); + } + + return true; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } +} From d9777d76bdaf3c26ff1fbb0340f18200e75b9128 Mon Sep 17 00:00:00 2001 From: Mala Bankal Date: Wed, 14 Sep 2011 21:43:42 -0700 Subject: [PATCH 084/214] 7049963: DISTINGUISHED NAMES FOR CERT ARE ESCAPED IN JROCKIT 1.6(NOT COMPATIBLE WITH JROC Reviewed-by: mullan --- jdk/src/share/classes/sun/security/x509/AVA.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/sun/security/x509/AVA.java b/jdk/src/share/classes/sun/security/x509/AVA.java index e1d49611c16..b07e565cfbd 100644 --- a/jdk/src/share/classes/sun/security/x509/AVA.java +++ b/jdk/src/share/classes/sun/security/x509/AVA.java @@ -1071,8 +1071,17 @@ public class AVA implements DerEncoder { * to need quoting, or at least escaping. So do leading or * trailing spaces, and multiple internal spaces. */ - for (int i = 0; i < valStr.length(); i++) { + int length = valStr.length(); + boolean alreadyQuoted = + (length > 1 && valStr.charAt(0) == '\"' + && valStr.charAt(length - 1) == '\"'); + + for (int i = 0; i < length; i++) { char c = valStr.charAt(i); + if (alreadyQuoted && (i == 0 || i == length - 1)) { + sbuffer.append(c); + continue; + } if (DerValue.isPrintableStringChar(c) || escapees.indexOf(c) >= 0) { @@ -1136,7 +1145,8 @@ public class AVA implements DerEncoder { } // Emit the string ... quote it if needed - if (quoteNeeded) { + // if string is already quoted, don't re-quote + if (!alreadyQuoted && quoteNeeded) { retval.append("\"" + sbuffer.toString() + "\""); } else { retval.append(sbuffer.toString()); From 3674ebe6e6c90b9c6d149fd3b2ac0d00302ec520 Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Thu, 15 Sep 2011 14:45:35 +0900 Subject: [PATCH 085/214] 7090844: Support a timezone whose offset is changed more than once in the future Reviewed-by: okutsu --- jdk/make/tools/src/build/tools/javazic/Mappings.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/make/tools/src/build/tools/javazic/Mappings.java b/jdk/make/tools/src/build/tools/javazic/Mappings.java index 954d3d5988f..5e5498a675c 100644 --- a/jdk/make/tools/src/build/tools/javazic/Mappings.java +++ b/jdk/make/tools/src/build/tools/javazic/Mappings.java @@ -76,8 +76,8 @@ class Mappings { // If the GMT offset of this Zone will change in some // future time, this Zone is added to the exclude list. boolean isExcluded = false; - if (zone.size() > 1) { - ZoneRec zrec = zone.get(zone.size()-2); + for (int i = 0; i < zone.size(); i++) { + ZoneRec zrec = zone.get(i); if ((zrec.getGmtOffset() != rawOffset) && (zrec.getUntilTime(0) > Time.getCurrentTime())) { if (excludeList == null) { @@ -85,6 +85,7 @@ class Mappings { } excludeList.add(zone.getName()); isExcluded = true; + break; } } From 0594a394983fff71184f77b5014436c1f08469fb Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Thu, 15 Sep 2011 15:02:05 +0900 Subject: [PATCH 086/214] 7090843: (tz) Support tzdata2011j Reviewed-by: okutsu --- jdk/make/sun/javazic/tzdata/VERSION | 2 +- jdk/make/sun/javazic/tzdata/africa | 13 +- jdk/make/sun/javazic/tzdata/antarctica | 12 -- jdk/make/sun/javazic/tzdata/asia | 4 + jdk/make/sun/javazic/tzdata/australasia | 72 +++++++++- jdk/make/sun/javazic/tzdata/europe | 68 +++++++--- jdk/make/sun/javazic/tzdata/iso3166.tab | 8 +- jdk/make/sun/javazic/tzdata/northamerica | 128 ++++++++++++++---- jdk/make/sun/javazic/tzdata/southamerica | 8 ++ jdk/make/sun/javazic/tzdata/zone.tab | 7 +- .../sun/util/resources/TimeZoneNames.java | 10 +- .../sun/util/resources/TimeZoneNames_de.java | 10 +- .../sun/util/resources/TimeZoneNames_es.java | 10 +- .../sun/util/resources/TimeZoneNames_fr.java | 10 +- .../sun/util/resources/TimeZoneNames_it.java | 10 +- .../sun/util/resources/TimeZoneNames_ja.java | 10 +- .../sun/util/resources/TimeZoneNames_ko.java | 10 +- .../util/resources/TimeZoneNames_pt_BR.java | 10 +- .../sun/util/resources/TimeZoneNames_sv.java | 10 +- .../util/resources/TimeZoneNames_zh_CN.java | 10 +- .../util/resources/TimeZoneNames_zh_TW.java | 10 +- 21 files changed, 323 insertions(+), 109 deletions(-) diff --git a/jdk/make/sun/javazic/tzdata/VERSION b/jdk/make/sun/javazic/tzdata/VERSION index c52096254ae..9ccfe4c299f 100644 --- a/jdk/make/sun/javazic/tzdata/VERSION +++ b/jdk/make/sun/javazic/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2011g +tzdata2011j diff --git a/jdk/make/sun/javazic/tzdata/africa b/jdk/make/sun/javazic/tzdata/africa index a43e73ce10b..6fb9d645000 100644 --- a/jdk/make/sun/javazic/tzdata/africa +++ b/jdk/make/sun/javazic/tzdata/africa @@ -80,7 +80,7 @@ # I invented the following abbreviations; corrections are welcome! # 2:00 WAST West Africa Summer Time # 2:30 BEAT British East Africa Time (no longer used) -# 2:44:45 BEAUT British East Africa Unified Time (no longer used) +# 2:45 BEAUT British East Africa Unified Time (no longer used) # 3:00 CAST Central Africa Summer Time (no longer used) # 3:00 SAST South Africa Summer Time (no longer used) # 3:00 EAT East Africa Time @@ -418,7 +418,7 @@ Zone Africa/Bissau -1:02:20 - LMT 1911 May 26 Zone Africa/Nairobi 2:27:16 - LMT 1928 Jul 3:00 - EAT 1930 2:30 - BEAT 1940 - 2:44:45 - BEAUT 1960 + 2:45 - BEAUT 1960 3:00 - EAT # Lesotho @@ -979,6 +979,11 @@ Zone Africa/Khartoum 2:10:08 - LMT 1931 2:00 Sudan CA%sT 2000 Jan 15 12:00 3:00 - EAT +# South Sudan +Zone Africa/Juba 2:06:24 - LMT 1931 + 2:00 Sudan CA%sT 2000 Jan 15 12:00 + 3:00 - EAT + # Swaziland # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Mbabane 2:04:24 - LMT 1903 Mar @@ -988,7 +993,7 @@ Zone Africa/Mbabane 2:04:24 - LMT 1903 Mar # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Dar_es_Salaam 2:37:08 - LMT 1931 3:00 - EAT 1948 - 2:44:45 - BEAUT 1961 + 2:45 - BEAUT 1961 3:00 - EAT # Togo @@ -1114,7 +1119,7 @@ Zone Africa/Tunis 0:40:44 - LMT 1881 May 12 Zone Africa/Kampala 2:09:40 - LMT 1928 Jul 3:00 - EAT 1930 2:30 - BEAT 1948 - 2:44:45 - BEAUT 1957 + 2:45 - BEAUT 1957 3:00 - EAT # Zambia diff --git a/jdk/make/sun/javazic/tzdata/antarctica b/jdk/make/sun/javazic/tzdata/antarctica index 17f44a8286a..2fa4232a60c 100644 --- a/jdk/make/sun/javazic/tzdata/antarctica +++ b/jdk/make/sun/javazic/tzdata/antarctica @@ -41,18 +41,6 @@ # I made up all time zone abbreviations mentioned here; corrections welcome! # FORMAT is `zzz' and GMTOFF is 0 for locations while uninhabited. -# These rules are stolen from the `europe' file. -# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -Rule RussAQ 1981 1984 - Apr 1 0:00 1:00 S -Rule RussAQ 1981 1983 - Oct 1 0:00 0 - -Rule RussAQ 1984 1991 - Sep lastSun 2:00s 0 - -Rule RussAQ 1985 1991 - Mar lastSun 2:00s 1:00 S -Rule RussAQ 1992 only - Mar lastSat 23:00 1:00 S -Rule RussAQ 1992 only - Sep lastSat 23:00 0 - -Rule RussAQ 1993 max - Mar lastSun 2:00s 1:00 S -Rule RussAQ 1993 1995 - Sep lastSun 2:00s 0 - -Rule RussAQ 1996 max - Oct lastSun 2:00s 0 - - # These rules are stolen from the `southamerica' file. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule ArgAQ 1964 1966 - Mar 1 0:00 0 - diff --git a/jdk/make/sun/javazic/tzdata/asia b/jdk/make/sun/javazic/tzdata/asia index d4d8ab1115e..36c52373004 100644 --- a/jdk/make/sun/javazic/tzdata/asia +++ b/jdk/make/sun/javazic/tzdata/asia @@ -99,6 +99,10 @@ Rule RussiaAsia 1993 max - Mar lastSun 2:00s 1:00 S Rule RussiaAsia 1993 1995 - Sep lastSun 2:00s 0 - Rule RussiaAsia 1996 max - Oct lastSun 2:00s 0 - +# From Arthur David Olson (2011-06-15): +# While Russia abandoned DST in 2011, Armenia may choose to +# follow Russia's "old" rules. + # Afghanistan # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Kabul 4:36:48 - LMT 1890 diff --git a/jdk/make/sun/javazic/tzdata/australasia b/jdk/make/sun/javazic/tzdata/australasia index 61d338f9683..0330fcd9234 100644 --- a/jdk/make/sun/javazic/tzdata/australasia +++ b/jdk/make/sun/javazic/tzdata/australasia @@ -521,7 +521,7 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf # -# From Raymond Hughes (2010-10-07): +# From Laupue Raymond Hughes (2010-10-07): # Please see # # http://www.mcil.gov.ws @@ -531,7 +531,7 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5 # to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks # backwards from 1:00am to 12:00am" -# From Raymond Hughes (2011-03-07) +# From Laupue Raymond Hughes (2011-03-07): # I believe this will be posted shortly on the website # # www.mcil.gov.ws @@ -551,12 +551,74 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5 # Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE, # INDUSTRY AND LABOUR 28th February 2011 +# From David Zuelke (2011-05-09): +# Subject: Samoa to move timezone from east to west of international date line +# +# +# http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963 +# + +# From Mark Sim-Smith (2011-08-17): +# I have been in contact with Leilani Tuala Warren from the Samoa Law +# Reform Commission, and she has sent me a copy of the Bill that she +# confirmed has been passed...Most of the sections are about maps rather +# than the time zone change, but I'll paste the relevant bits below. But +# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa +# changes from UTC-11 to UTC+13: +# +# International Date Line Bill 2011 +# +# AN ACT to provide for the change to standard time in Samoa and to make +# consequential amendments to the position of the International Date +# Line, and for related purposes. +# +# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament +# assembled as follows: +# +# 1. Short title and commencement-(1) This Act may be cited as the +# International Date Line Act 2011. (2) Except for section 5(3) this Act +# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3) +# Section 5(3) commences on the date of assent by the Head of State. +# +# [snip] +# +# 3. Interpretation - [snip] "Samoa standard time" in this Act and any +# other statute of Samoa which refers to 'Samoa standard time' means the +# time 13 hours in advance of Co-ordinated Universal Time. +# +# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa +# standard time shall be set at 13 hours in advance of Co-ordinated +# Universal Time for the whole of Samoa. (2) All references to Samoa's +# time zone and to Samoa standard time in Samoa in all legislation and +# instruments after the commencement of this Act shall be references to +# Samoa standard time as provided for in this Act. (3) Nothing in this +# Act affects the provisions of the Daylight Saving Act 2009, except that +# it defines Samoa standard time.... + +# From Laupue Raymond Hughes (2011-09-02): +# +# http://www.mcil.gov.ws/mcil_publications.html +# +# +# here is the official website publication for Samoa DST and dateline change +# +# DST +# Year End Time Start Time +# 2011 - - - - - - 24 September 3:00am to 4:00am +# 2012 01 April 4:00am to 3:00am - - - - - - +# +# Dateline Change skip Friday 30th Dec 2011 +# Thursday 29th December 2011 23:59:59 Hours +# Saturday 31st December 2011 00:00:00 Hours Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5 -11:26:56 - LMT 1911 -11:30 - SAMT 1950 # Samoa Time -11:00 - WST 2010 Sep 26 -11:00 1:00 WSDT 2011 Apr 2 4:00 - -11:00 - WST + -11:00 - WST 2011 Sep 24 3:00 + -11:00 1:00 WSDT 2011 Dec 30 + 13:00 1:00 WSDT 2012 Apr 1 4:00 + 13:00 - WST # Solomon Is # excludes Bougainville, for which see Papua New Guinea @@ -1228,7 +1290,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901 # Lord Howe Island Board (controlling authority for the Island) is # seeking the community's views on various options for summer time # arrangements on the Island, e.g. advance clocks by 1 full hour -# instead of only 30 minutes. Dependant on the wishes of residents +# instead of only 30 minutes. [Dependent] on the wishes of residents # the Board may approach the NSW government to change the existing # arrangements. The starting date for summer time on the Island will # however always coincide with the rest of NSW. @@ -1354,7 +1416,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901 # From Paul Eggert (1996-01-22): # Today's _Wall Street Journal_ (page 1) reports that Kiribati -# ``declared it the same day throught the country as of Jan. 1, 1995'' +# ``declared it the same day [throughout] the country as of Jan. 1, 1995'' # as part of the competition to be first into the 21st century. diff --git a/jdk/make/sun/javazic/tzdata/europe b/jdk/make/sun/javazic/tzdata/europe index 89bf6c5d3dc..5c6abc17424 100644 --- a/jdk/make/sun/javazic/tzdata/europe +++ b/jdk/make/sun/javazic/tzdata/europe @@ -587,6 +587,26 @@ Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S Rule Russia 1993 1995 - Sep lastSun 2:00s 0 - Rule Russia 1996 max - Oct lastSun 2:00s 0 - +# From Alexander Krivenyshev (2011-06-14): +# According to Kremlin press service, Russian President Dmitry Medvedev +# signed a federal law "On calculation of time" on June 9, 2011. +# According to the law Russia is abolishing daylight saving time. +# +# Medvedev signed a law "On the Calculation of Time" (in russian): +# +# http://bmockbe.ru/events/?ID=7583 +# +# +# Medvedev signed a law on the calculation of the time (in russian): +# +# http://www.regnum.ru/news/polit/1413906.html +# + +# From Arthur David Olson (2011-06-15): +# Take "abolishing daylight saving time" to mean that time is now considered +# to be standard. +# At least for now, keep the "old" Russia rules for the benefit of Belarus. + # These are for backward compatibility with older versions. # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -2035,7 +2055,8 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr 1:00 C-Eur CE%sT 1945 2:00 Poland CE%sT 1946 3:00 Russia MSK/MSD 1991 Mar 31 2:00s - 2:00 Russia EE%sT + 2:00 Russia EE%sT 2011 Mar 27 2:00s + 3:00 - KALT # # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Respublika Adygeya, Arkhangel'skaya oblast', @@ -2064,7 +2085,8 @@ Zone Europe/Moscow 2:30:20 - LMT 1880 2:00 - EET 1930 Jun 21 3:00 Russia MSK/MSD 1991 Mar 31 2:00s 2:00 Russia EE%sT 1992 Jan 19 2:00s - 3:00 Russia MSK/MSD + 3:00 Russia MSK/MSD 2011 Mar 27 2:00s + 4:00 - MSK # # Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast', # Volgogradskaya oblast'. Shanks & Pottenger say Kirov is still at +0400 @@ -2077,7 +2099,8 @@ Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3 4:00 Russia VOL%sT 1989 Mar 26 2:00s # Volgograd T 3:00 Russia VOL%sT 1991 Mar 31 2:00s 4:00 - VOLT 1992 Mar 29 2:00s - 3:00 Russia VOL%sT + 3:00 Russia VOL%sT 2011 Mar 27 2:00s + 4:00 - VOLT # # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Samarskaya oblast', Udmyrtskaya respublika @@ -2089,7 +2112,8 @@ Zone Europe/Samara 3:20:36 - LMT 1919 Jul 1 2:00 2:00 Russia KUY%sT 1991 Sep 29 2:00s 3:00 - KUYT 1991 Oct 20 3:00 4:00 Russia SAM%sT 2010 Mar 28 2:00s # Samara Time - 3:00 Russia SAM%sT + 3:00 Russia SAM%sT 2011 Mar 27 2:00s + 4:00 - SAMT # # From Oscar van Vlijmen (2001-08-25): [This region consists of] @@ -2102,7 +2126,8 @@ Zone Asia/Yekaterinburg 4:02:24 - LMT 1919 Jul 15 4:00 4:00 - SVET 1930 Jun 21 # Sverdlovsk Time 5:00 Russia SVE%sT 1991 Mar 31 2:00s 4:00 Russia SVE%sT 1992 Jan 19 2:00s - 5:00 Russia YEK%sT # Yekaterinburg Time + 5:00 Russia YEK%sT 2011 Mar 27 2:00s + 6:00 - YEKT # Yekaterinburg Time # # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Respublika Altaj, Altajskij kraj, Omskaya oblast'. @@ -2110,7 +2135,8 @@ Zone Asia/Omsk 4:53:36 - LMT 1919 Nov 14 5:00 - OMST 1930 Jun 21 # Omsk TIme 6:00 Russia OMS%sT 1991 Mar 31 2:00s 5:00 Russia OMS%sT 1992 Jan 19 2:00s - 6:00 Russia OMS%sT + 6:00 Russia OMS%sT 2011 Mar 27 2:00s + 7:00 - OMST # # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's # not clear when it switched from +7 to +6. @@ -2120,7 +2146,8 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00 7:00 Russia NOV%sT 1991 Mar 31 2:00s 6:00 Russia NOV%sT 1992 Jan 19 2:00s 7:00 Russia NOV%sT 1993 May 23 # say Shanks & P. - 6:00 Russia NOV%sT + 6:00 Russia NOV%sT 2011 Mar 27 2:00s + 7:00 - NOVT # From Alexander Krivenyshev (2009-10-13): # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on @@ -2153,7 +2180,8 @@ Zone Asia/Novokuznetsk 5:48:48 - NMT 1920 Jan 6 7:00 Russia KRA%sT 1991 Mar 31 2:00s 6:00 Russia KRA%sT 1992 Jan 19 2:00s 7:00 Russia KRA%sT 2010 Mar 28 2:00s - 6:00 Russia NOV%sT # Novosibirsk/Novokuznetsk Time + 6:00 Russia NOV%sT 2011 Mar 27 2:00s + 7:00 - NOVT # Novosibirsk/Novokuznetsk Time # # From Oscar van Vlijmen (2001-08-25): [This region consists of] @@ -2164,7 +2192,8 @@ Zone Asia/Krasnoyarsk 6:11:20 - LMT 1920 Jan 6 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time 7:00 Russia KRA%sT 1991 Mar 31 2:00s 6:00 Russia KRA%sT 1992 Jan 19 2:00s - 7:00 Russia KRA%sT + 7:00 Russia KRA%sT 2011 Mar 27 2:00s + 8:00 - KRAT # # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Respublika Buryatiya, Irkutskaya oblast', @@ -2174,7 +2203,8 @@ Zone Asia/Irkutsk 6:57:20 - LMT 1880 7:00 - IRKT 1930 Jun 21 # Irkutsk Time 8:00 Russia IRK%sT 1991 Mar 31 2:00s 7:00 Russia IRK%sT 1992 Jan 19 2:00s - 8:00 Russia IRK%sT + 8:00 Russia IRK%sT 2011 Mar 27 2:00s + 9:00 - IRKT # # From Oscar van Vlijmen (2003-10-18): [This region consists of] # Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast', @@ -2197,7 +2227,8 @@ Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15 8:00 - YAKT 1930 Jun 21 # Yakutsk Time 9:00 Russia YAK%sT 1991 Mar 31 2:00s 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT + 9:00 Russia YAK%sT 2011 Mar 27 2:00s + 10:00 - YAKT # # From Oscar van Vlijmen (2003-10-18): [This region consists of] # Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj, @@ -2210,7 +2241,8 @@ Zone Asia/Vladivostok 8:47:44 - LMT 1922 Nov 15 9:00 - VLAT 1930 Jun 21 # Vladivostok Time 10:00 Russia VLA%sT 1991 Mar 31 2:00s 9:00 Russia VLA%sST 1992 Jan 19 2:00s - 10:00 Russia VLA%sT + 10:00 Russia VLA%sT 2011 Mar 27 2:00s + 11:00 - VLAT # # Sakhalinskaya oblast'. # The Zone name should be Yuzhno-Sakhalinsk, but that's too long. @@ -2220,7 +2252,8 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 11:00 Russia SAK%sT 1991 Mar 31 2:00s # Sakhalin T. 10:00 Russia SAK%sT 1992 Jan 19 2:00s 11:00 Russia SAK%sT 1997 Mar lastSun 2:00s - 10:00 Russia SAK%sT + 10:00 Russia SAK%sT 2011 Mar 27 2:00s + 11:00 - SAKT # # From Oscar van Vlijmen (2003-10-18): [This region consists of] # Magadanskaya oblast', Respublika Sakha (Yakutiya). @@ -2233,7 +2266,8 @@ Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 10:00 - MAGT 1930 Jun 21 # Magadan Time 11:00 Russia MAG%sT 1991 Mar 31 2:00s 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT + 11:00 Russia MAG%sT 2011 Mar 27 2:00s + 12:00 - MAGT # # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Kamchatskaya oblast', Koryakskij avtonomnyj okrug. @@ -2244,7 +2278,8 @@ Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10 12:00 Russia PET%sT 1991 Mar 31 2:00s 11:00 Russia PET%sT 1992 Jan 19 2:00s 12:00 Russia PET%sT 2010 Mar 28 2:00s - 11:00 Russia PET%sT + 11:00 Russia PET%sT 2011 Mar 27 2:00s + 12:00 - PETT # # Chukotskij avtonomnyj okrug Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2 @@ -2253,7 +2288,8 @@ Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2 12:00 Russia ANA%sT 1991 Mar 31 2:00s 11:00 Russia ANA%sT 1992 Jan 19 2:00s 12:00 Russia ANA%sT 2010 Mar 28 2:00s - 11:00 Russia ANA%sT + 11:00 Russia ANA%sT 2011 Mar 27 2:00s + 12:00 - ANAT # Serbia # Zone NAME GMTOFF RULES FORMAT [UNTIL] diff --git a/jdk/make/sun/javazic/tzdata/iso3166.tab b/jdk/make/sun/javazic/tzdata/iso3166.tab index f582cad45eb..fee3f33911a 100644 --- a/jdk/make/sun/javazic/tzdata/iso3166.tab +++ b/jdk/make/sun/javazic/tzdata/iso3166.tab @@ -43,6 +43,9 @@ # # Lines beginning with `#' are comments. # +# From Arthur David Olson (2011-08-17): +# Resynchronized today with the ISO 3166 site (adding SS for South Sudan). +# #country- #code country name AD Andorra @@ -52,7 +55,6 @@ AG Antigua & Barbuda AI Anguilla AL Albania AM Armenia -AN Netherlands Antilles AO Angola AQ Antarctica AR Argentina @@ -75,6 +77,7 @@ BL St Barthelemy BM Bermuda BN Brunei BO Bolivia +BQ Bonaire Sint Eustatius & Saba BR Brazil BS Bahamas BT Bhutan @@ -97,6 +100,7 @@ CO Colombia CR Costa Rica CU Cuba CV Cape Verde +CW Curacao CX Christmas Island CY Cyprus CZ Czech Republic @@ -251,8 +255,10 @@ SM San Marino SN Senegal SO Somalia SR Suriname +SS South Sudan ST Sao Tome & Principe SV El Salvador +SX Sint Maarten SY Syria SZ Swaziland TC Turks & Caicos Is diff --git a/jdk/make/sun/javazic/tzdata/northamerica b/jdk/make/sun/javazic/tzdata/northamerica index 7111cb7048d..d31b7f0ad03 100644 --- a/jdk/make/sun/javazic/tzdata/northamerica +++ b/jdk/make/sun/javazic/tzdata/northamerica @@ -490,6 +490,10 @@ Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:07:02 # own time. I asked about daylight saving; they said it wasn't used. I # did not inquire about practices in the past. +# From Arthur David Olson (2011-08-17): +# For lack of better information, assume that Metlakatla's +# abandonment of use of daylight saving resulted from the 1983 vote. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone America/Juneau 15:02:19 - LMT 1867 Oct 18 -8:57:41 - LMT 1900 Aug 20 12:00 @@ -515,7 +519,7 @@ Zone America/Metlakatla 15:13:42 - LMT 1867 Oct 18 -8:00 US P%sT 1946 -8:00 - PST 1969 -8:00 US P%sT 1983 Oct 30 2:00 - -8:00 US MeST + -8:00 - MeST Zone America/Yakutat 14:41:05 - LMT 1867 Oct 18 -9:18:55 - LMT 1900 Aug 20 12:00 -9:00 - YST 1942 @@ -615,8 +619,8 @@ Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00 #Schmitt&Cox -10:30 - HST 1933 Apr 30 2:00 #Laws 1933 -10:30 1:00 HDT 1933 May 21 12:00 #Laws 1933+12 -10:30 - HST 1942 Feb 09 2:00 #Schmitt&Cox+2 - -10:30 1:00 HDT 1945 Sep 30 2:00 #Schmitt&Fox+2 - -10:30 US H%sT 1947 Jun 8 2:00 #Schmitt&Fox+2 + -10:30 1:00 HDT 1945 Sep 30 2:00 #Schmitt&Cox+2 + -10:30 - HST 1947 Jun 8 2:00 #Schmitt&Cox+2 -10:00 - HST # Now we turn to US areas that have diverged from the consensus since 1970. @@ -1185,12 +1189,39 @@ Rule StJohns 1960 1986 - Oct lastSun 2:00 0 S # From Paul Eggert (2000-10-02): # INMS (2000-09-12) says that, since 1988 at least, Newfoundland switches # at 00:01 local time. For now, assume it started in 1987. + +# From Michael Pelley (2011-08-05): +# The Government of Newfoundland and Labrador has pending changes to +# modify the hour for daylight savings time to come into effect in +# November 2011. This modification would change the time from 12:01AM to +# 2:00AM on the dates of the switches of Daylight Savings Time to/from +# Standard Time. +# +# As a matter of reference, in Canada provinces have the authority of +# setting time zone information. The legislation has passed our +# legislative body (The House of Assembly) and is awaiting the +# proclamation to come into effect. You may find this information at: +# +# http://www.assembly.nl.ca/legislation/sr/lists/Proclamation.htm +# +# and +# search within that web page for Standard Time (Amendment) Act. The Act +# may be found at: +# +# http://www.assembly.nl.ca/business/bills/Bill1106.htm +# +# ... +# MICHAEL PELLEY | Manager of Enterprise Architecture - Solution Delivery +# Office of the Chief Information Officer Executive Council Government of +# Newfoundland & Labrador P.O. Box 8700, 40 Higgins Line, St. John's NL +# A1B 4J6 + Rule StJohns 1987 only - Apr Sun>=1 0:01 1:00 D Rule StJohns 1987 2006 - Oct lastSun 0:01 0 S Rule StJohns 1988 only - Apr Sun>=1 0:01 2:00 DD Rule StJohns 1989 2006 - Apr Sun>=1 0:01 1:00 D -Rule StJohns 2007 max - Mar Sun>=8 0:01 1:00 D -Rule StJohns 2007 max - Nov Sun>=1 0:01 0 S +Rule StJohns 2007 2011 - Mar Sun>=8 0:01 1:00 D +Rule StJohns 2007 2010 - Nov Sun>=1 0:01 0 S # # St John's has an apostrophe, but Posix file names can't have apostrophes. # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -1200,7 +1231,8 @@ Zone America/St_Johns -3:30:52 - LMT 1884 -3:30:52 StJohns N%sT 1935 Mar 30 -3:30 StJohns N%sT 1942 May 11 -3:30 Canada N%sT 1946 - -3:30 StJohns N%sT + -3:30 StJohns N%sT 2011 Nov + -3:30 Canada N%sT # most of east Labrador @@ -1214,7 +1246,8 @@ Zone America/Goose_Bay -4:01:40 - LMT 1884 # Happy Valley-Goose Bay -3:30 StJohns N%sT 1942 May 11 -3:30 Canada N%sT 1946 -3:30 StJohns N%sT 1966 Mar 15 2:00 - -4:00 StJohns A%sT + -4:00 StJohns A%sT 2011 Nov + -4:00 Canada A%sT # west Labrador, Nova Scotia, Prince Edward I @@ -1946,20 +1979,69 @@ Zone America/Dawson_Creek -8:00:56 - LMT 1884 # daylight saving.... # http://www.nnsl.com/frames/newspapers/2006-11/nov13_06none.html -# From Chris Walton (2007-03-14): -# Today I phoned the "hamlet office" to find out what Resolute was doing with -# its clocks. +# From Chris Walton (2011-03-21): +# Back in 2007 I initiated the creation of a new "zone file" for Resolute +# Bay. Resolute Bay is a small community located about 900km north of +# the Arctic Circle. The zone file was required because Resolute Bay had +# decided to use UTC-5 instead of UTC-6 for the winter of 2006-2007. # -# The individual that answered the phone confirmed that the clocks did not -# move at the end of daylight saving on October 29/2006. He also told me that -# the clocks did not move this past weekend (March 11/2007).... - -# From Chris Walton (2008-11-13): -# ...the residents of Resolute believe that they are changing "time zones" -# twice a year. In winter months, local time is qualified with "Eastern -# Time" which is really "Eastern Standard Time (UTC-5)". In summer -# months, local time is qualified with "Central Time" which is really -# "Central Daylight Time (UTC-5)"... +# According to new information which I received last week, Resolute Bay +# went back to using UTC-6 in the winter of 2007-2008... +# +# On March 11/2007 most of Canada went onto daylight saving. On March +# 14/2007 I phoned the Resolute Bay hamlet office to do a "time check." I +# talked to somebody that was both knowledgeable and helpful. I was able +# to confirm that Resolute Bay was still operating on UTC-5. It was +# explained to me that Resolute Bay had been on the Eastern Time zone +# (EST) in the winter, and was now back on the Central Time zone (CDT). +# i.e. the time zone had changed twice in the last year but the clocks +# had not moved. The residents had to know which time zone they were in +# so they could follow the correct TV schedule... +# +# On Nov 02/2008 most of Canada went onto standard time. On Nov 03/2008 I +# phoned the Resolute Bay hamlet office...[D]ue to the challenging nature +# of the phone call, I decided to seek out an alternate source of +# information. I found an e-mail address for somebody by the name of +# Stephanie Adams whose job was listed as "Inns North Support Officer for +# Arctic Co-operatives." I was under the impression that Stephanie lived +# and worked in Resolute Bay... +# +# On March 14/2011 I phoned the hamlet office again. I was told that +# Resolute Bay had been using Central Standard Time over the winter of +# 2010-2011 and that the clocks had therefore been moved one hour ahead +# on March 13/2011. The person I talked to was aware that Resolute Bay +# had previously experimented with Eastern Standard Time but he could not +# tell me when the practice had stopped. +# +# On March 17/2011 I searched the Web to find an e-mail address of +# somebody that might be able to tell me exactly when Resolute Bay went +# off Eastern Standard Time. I stumbled on the name "Aziz Kheraj." Aziz +# used to be the mayor of Resolute Bay and he apparently owns half the +# businesses including "South Camp Inn." This website has some info on +# Aziz: +# +# http://www.uphere.ca/node/493 +# +# +# I sent Aziz an e-mail asking when Resolute Bay had stopped using +# Eastern Standard Time. +# +# Aziz responded quickly with this: "hi, The time was not changed for the +# 1 year only, the following year, the community went back to the old way +# of "spring ahead-fall behind" currently we are zulu plus 5 hrs and in +# the winter Zulu plus 6 hrs" +# +# This of course conflicted with everything I had ascertained in November 2008. +# +# I sent Aziz a copy of my 2008 e-mail exchange with Stephanie. Aziz +# responded with this: "Hi, Stephanie lives in Winnipeg. I live here, You +# may want to check with the weather office in Resolute Bay or do a +# search on the weather through Env. Canada. web site" +# +# If I had realized the Stephanie did not live in Resolute Bay I would +# never have contacted her. I now believe that all the information I +# obtained in November 2008 should be ignored... +# I apologize for reporting incorrect information in 2008. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule NT_YK 1918 only - Apr 14 2:00 1:00 D @@ -1987,14 +2069,12 @@ Zone America/Iqaluit 0 - zzz 1942 Aug # Frobisher Bay est. -6:00 Canada C%sT 2000 Oct 29 2:00 -5:00 Canada E%sT # aka Qausuittuq -# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -Rule Resolute 2006 max - Nov Sun>=1 2:00 0 ES -Rule Resolute 2007 max - Mar Sun>=8 2:00 0 CD Zone America/Resolute 0 - zzz 1947 Aug 31 # Resolute founded -6:00 NT_YK C%sT 2000 Oct 29 2:00 -5:00 - EST 2001 Apr 1 3:00 -6:00 Canada C%sT 2006 Oct 29 2:00 - -5:00 Resolute %sT + -5:00 - EST 2007 Mar 11 3:00 + -6:00 Canada C%sT # aka Kangiqiniq Zone America/Rankin_Inlet 0 - zzz 1957 # Rankin Inlet founded -6:00 NT_YK C%sT 2000 Oct 29 2:00 diff --git a/jdk/make/sun/javazic/tzdata/southamerica b/jdk/make/sun/javazic/tzdata/southamerica index 7717d12d17a..215d95defbc 100644 --- a/jdk/make/sun/javazic/tzdata/southamerica +++ b/jdk/make/sun/javazic/tzdata/southamerica @@ -1298,6 +1298,14 @@ Zone America/Curacao -4:35:44 - LMT 1912 Feb 12 # Willemstad -4:30 - ANT 1965 # Netherlands Antilles Time -4:00 - AST +# From Arthur David Olson (2011-06-15): +# At least for now, use links for places with new iso3166 codes. +# The name "Lower Prince's Quarter" is both longer than fourteen charaters +# and contains an apostrophe; use "Lower_Princes" below. + +Link America/Curacao America/Lower_Princes # Sint Maarten +Link America/Curacao America/Kralendijk # Bonaire, Sint Estatius and Saba + # Ecuador # # From Paul Eggert (2007-03-04): diff --git a/jdk/make/sun/javazic/tzdata/zone.tab b/jdk/make/sun/javazic/tzdata/zone.tab index 0b158ec2234..81ce7f5a56f 100644 --- a/jdk/make/sun/javazic/tzdata/zone.tab +++ b/jdk/make/sun/javazic/tzdata/zone.tab @@ -54,7 +54,6 @@ AG +1703-06148 America/Antigua AI +1812-06304 America/Anguilla AL +4120+01950 Europe/Tirane AM +4011+04430 Asia/Yerevan -AN +1211-06900 America/Curacao AO -0848+01314 Africa/Luanda AQ -7750+16636 Antarctica/McMurdo McMurdo Station, Ross Island AQ -9000+00000 Antarctica/South_Pole Amundsen-Scott Station, South Pole @@ -109,6 +108,7 @@ BL +1753-06251 America/St_Barthelemy BM +3217-06446 Atlantic/Bermuda BN +0456+11455 Asia/Brunei BO -1630-06809 America/La_Paz +BQ +120903-0681636 America/Kralendijk BR -0351-03225 America/Noronha Atlantic islands BR -0127-04829 America/Belem Amapa, E Para BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB) @@ -142,7 +142,7 @@ CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut -CA +744144-0944945 America/Resolute Eastern Standard Time - Resolute, Nunavut +CA +744144-0944945 America/Resolute Central Standard Time - Resolute, Nunavut CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario @@ -177,6 +177,7 @@ CO +0436-07405 America/Bogota CR +0956-08405 America/Costa_Rica CU +2308-08222 America/Havana CV +1455-02331 Atlantic/Cape_Verde +CW +1211-06900 America/Curacao CX -1025+10543 Indian/Christmas CY +3510+03322 Asia/Nicosia CZ +5005+01426 Europe/Prague @@ -382,8 +383,10 @@ SM +4355+01228 Europe/San_Marino SN +1440-01726 Africa/Dakar SO +0204+04522 Africa/Mogadishu SR +0550-05510 America/Paramaribo +SS +0451+03136 Africa/Juba ST +0020+00644 Africa/Sao_Tome SV +1342-08912 America/El_Salvador +SX +180305-0630250 America/Lower_Princes SY +3330+03618 Asia/Damascus SZ -2618+03106 Africa/Mbabane TC +2128-07108 America/Grand_Turk diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java index f39fae2f229..c4862dc75aa 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java @@ -159,8 +159,6 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}; - String RST[] = new String[] {"Eastern Standard Time", "EST", - "Central Daylight Time", "CDT"}; String SAST[] = new String[] {"South Africa Standard Time", "SAST", "South Africa Summer Time", "SAST"}; String SBT[] = new String[] {"Solomon Is. Time", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Bolivia Time", "BOT", "Bolivia Summer Time", "BOST"}}, {"America/Lima", new String[] {"Peru Time", "PET", "Peru Summer Time", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java index e74074f02cd..763f7f51fb1 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"Pazifische Normalzeit", "PST", "Pazifische Sommerzeit", "PDT"}; - String RST[] = new String[] {"\u00d6stliche Normalzeit", "EST", - "Zentrale Sommerzeit", "CDT"}; String SAST[] = new String[] {"S\u00fcdafrikanische Normalzeit", "SAST", "S\u00fcdafrikanische Sommerzeit", "SAST"}; String SBT[] = new String[] {"Salomoninseln Zeit", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Bolivianische Zeit", "BOT", "Bolivianische Sommerzeit", "BOST"}}, {"America/Lima", new String[] {"Peruanische Zeit", "PET", "Peruanische Sommerzeit", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java index 1a87c33ed56..1c09f1e585c 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"Hora est\u00e1ndar del Pac\u00edfico", "PST", "Hora de verano del Pac\u00edfico", "PDT"}; - String RST[] = new String[] {"Hora est\u00e1ndar Oriental", "EST", - "Hora de verano Central", "CDT"}; String SAST[] = new String[] {"Hora est\u00e1ndar de Sud\u00e1frica", "SAST", "Hora de verano de Sud\u00e1frica", "SAST"}; String SBT[] = new String[] {"Hora de las Islas Solomon", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Hora de Bolivia", "BOT", "Hora de verano de Bolivia", "BOST"}}, {"America/Lima", new String[] {"Hora de Per\u00fa", "PET", "Hora de verano de Per\u00fa", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java index 56701d6407e..fba1e827b0a 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"Heure normale du Pacifique", "PST", "Heure avanc\u00e9e du Pacifique", "PDT"} ; - String RST[] = new String[] {"Heure normale de l'Est", "EST", - "Heure avanc\u00e9e du Centre", "CDT"} ; String SAST[] = new String[] {"Heure normale d'Afrique du Sud", "SAST", "Heure d'\u00e9t\u00e9 d'Afrique du Sud", "SAST"} ; String SBT[] = new String[] {"Heure des \u00celes Salomon", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Heure de Bolivie", "BOT", "Heure d'\u00e9t\u00e9 de Bolivie", "BOST"}}, {"America/Lima", new String[] {"Heure du P\u00e9rou", "PET", "Heure d'\u00e9t\u00e9 du P\u00e9rou", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java index a02535fc00c..c2bb1d673f0 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"Ora solare della costa occidentale USA", "PST", "Ora legale della costa occidentale USA", "PDT"}; - String RST[] = new String[] {"Ora solare USA orientale", "EST", - "Ora legale USA centrale", "CDT"}; String SAST[] = new String[] {"Ora solare del Sudafrica", "SAST", "Ora estiva del Sudafrica", "SAST"}; String SBT[] = new String[] {"Ora delle Isole Salomone", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Ora della Bolivia", "BOT", "Ora estiva della Bolivia", "BOST"}}, {"America/Lima", new String[] {"Ora del Per\u00f9", "PET", "Ora estiva del Per\u00f9", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java index bb28e3c51e4..a0d9d7c863f 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6a19\u6e96\u6642", "PST", "\u592a\u5e73\u6d0b\u590f\u6642\u9593", "PDT"}; - String RST[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642", "EST", - "\u4e2d\u90e8\u590f\u6642\u9593", "CDT"}; String SAST[] = new String[] {"\u5357\u30a2\u30d5\u30ea\u30ab\u6a19\u6e96\u6642", "SAST", "\u5357\u30a2\u30d5\u30ea\u30ab\u590f\u6642\u9593", "SAST"}; String SBT[] = new String[] {"\u30bd\u30ed\u30e2\u30f3\u8af8\u5cf6\u6642\u9593", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"\u30dc\u30ea\u30d3\u30a2\u6642\u9593", "BOT", "\u30dc\u30ea\u30d3\u30a2\u590f\u6642\u9593", "BOST"}}, {"America/Lima", new String[] {"\u30da\u30eb\u30fc\u6642\u9593", "PET", "\u30da\u30eb\u30fc\u590f\u6642\u9593", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java index baaa5f057c6..2079655f736 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"\ud0dc\ud3c9\uc591 \ud45c\uc900\uc2dc", "PST", "\ud0dc\ud3c9\uc591 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PDT"}; - String RST[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc", "EST", - "\uc911\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT"}; String SAST[] = new String[] {"\ub0a8\uc544\ud504\ub9ac\uce74 \ud45c\uc900\uc2dc", "SAST", "\ub0a8\uc544\ud504\ub9ac\uce74 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SAST"}; String SBT[] = new String[] {"\uc194\ub85c\ubaac \uad70\ub3c4 \uc2dc\uac04", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"\ubcfc\ub9ac\ube44\uc544 \uc2dc\uac04", "BOT", "\ubcfc\ub9ac\ube44\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "BOST"}}, {"America/Lima", new String[] {"\ud398\ub8e8 \uc2dc\uac04", "PET", "\ud398\ub8e8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java index d7b485b2951..89191d0674f 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java @@ -157,8 +157,6 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o de Pohnpei", "PONST"}; String PST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o do Pac\u00edfico", "PST", "Hor\u00e1rio de luz natural do Pac\u00edfico", "PDT"}; - String RST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental", "EST", - "Hor\u00e1rio de luz natural central", "CDT"}; String SAST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o da \u00c1frica do Sul", "SAST", "Fuso hor\u00e1rio de ver\u00e3o da \u00c1frica do Sul", "SAST"}; String SBT[] = new String[] {"Fuso hor\u00e1rio das Ilhas Salom\u00e3o", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Fuso hor\u00e1rio da Bol\u00edvia", "BOT", "Fuso hor\u00e1rio de ver\u00e3o da Bol\u00edvia", "BOST"}}, {"America/Lima", new String[] {"Fuso hor\u00e1rio do Peru", "PET", "Fuso hor\u00e1rio de ver\u00e3o do Peru", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java index 0ddaa348326..007e5534a13 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"Stilla havet, normaltid", "PST", "Stilla havet, sommartid", "PDT"}; - String RST[] = new String[] {"Eastern, normaltid", "EST", - "Central sommartid", "CDT"}; String SAST[] = new String[] {"Sydafrika, normaltid", "SAST", "Sydafrika, sommartid", "SAST"}; String SBT[] = new String[] {"Salomon\u00f6arna, normaltid", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"Bolivia, normaltid", "BOT", "Bolivia, sommartid", "BOST"}}, {"America/Lima", new String[] {"Peru, normaltid", "PET", "Peru, sommartid", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java index 17f72a67b31..d7521372bbd 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4", "PST", "\u592a\u5e73\u6d0b\u590f\u4ee4\u65f6", "PDT"}; - String RST[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "EST", - "\u4e2d\u592e\u590f\u4ee4\u65f6", "CDT"}; String SAST[] = new String[] {"\u5357\u975e\u6807\u51c6\u65f6\u95f4", "SAST", "\u5357\u975e\u590f\u4ee4\u65f6", "SAST"}; String SBT[] = new String[] {"\u6240\u7f57\u95e8\u7fa4\u5c9b\u65f6\u95f4", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"\u73bb\u5229\u7ef4\u4e9a\u65f6\u95f4", "BOT", "\u73bb\u5229\u7ef4\u4e9a\u590f\u4ee4\u65f6", "BOST"}}, {"America/Lima", new String[] {"\u79d8\u9c81\u65f6\u95f4", "PET", "\u79d8\u9c81\u590f\u4ee4\u65f6", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -673,7 +674,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java index d7f1b10e2a4..9a7fbe9479a 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java @@ -159,8 +159,6 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "Pohnpei Summer Time", "PONST"}; String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6a19\u6e96\u6642\u9593", "PST", "\u592a\u5e73\u6d0b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PDT"}; - String RST[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593", "EST", - "\u4e2d\u592e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT"}; String SAST[] = new String[] {"\u5357\u975e\u6a19\u6e96\u6642\u9593", "SAST", "\u5357\u975e\u590f\u4ee4\u6642\u9593", "SAST"}; String SBT[] = new String[] {"\u6240\u7f85\u9580\u7fa4\u5cf6\u6642\u9593", "SBT", @@ -262,6 +260,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, + {"Africa/Juba", EAT}, {"Africa/Kampala", EAT}, {"Africa/Khartoum", EAT}, {"Africa/Kigali", CAT}, @@ -378,11 +377,13 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Kentucky/Louisville", EST}, {"America/Kentucky/Monticello", EST}, {"America/Knox_IN", CST}, + {"America/Kralendijk", AST}, {"America/La_Paz", new String[] {"\u73bb\u5229\u7dad\u4e9e\u6642\u9593", "BOT", "\u73bb\u5229\u7dad\u4e9e\u590f\u4ee4\u6642\u9593", "BOST"}}, {"America/Lima", new String[] {"\u7955\u9b6f\u6642\u9593", "PET", "\u7955\u9b6f\u590f\u4ee4\u6642\u9593", "PEST"}}, {"America/Louisville", EST}, + {"America/Lower_Princes", AST}, {"America/Maceio", BRT}, {"America/Managua", CST}, {"America/Manaus", AMT}, @@ -425,7 +426,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", RST}, + {"America/Resolute", CST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santa_Isabel", PST}, @@ -674,7 +675,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", EET}, + {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", + "Kaliningrad Summer Time", "KALST"}}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, From 782f6f887ef309ba4237ed0a9e32df4841ef2d4a Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Thu, 15 Sep 2011 16:43:25 +0400 Subject: [PATCH 087/214] 7090007: Missing style.css in nimbus/doc-files/properties.html Reviewed-by: alexp --- .../classes/javax/swing/plaf/nimbus/doc-files/properties.html | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html b/jdk/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html index 1e170c4d320..bedeffb5db7 100644 --- a/jdk/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html +++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/doc-files/properties.html @@ -1,6 +1,5 @@ -

Primary Colors

From f9cd96b19ba8ec54e17db197b7d09a99e5c131b0 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 15 Sep 2011 13:50:30 +0100 Subject: [PATCH 088/214] 7073491: -Dsun.net.maxDatagramSockets=1 does not work correctly with system.gc() Reviewed-by: ngmr --- .../share/classes/java/net/AbstractPlainDatagramSocketImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index a772b7c4c4a..ff0d2cd3584 100644 --- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -66,8 +66,8 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl * Creates a datagram socket */ protected synchronized void create() throws SocketException { - fd = new FileDescriptor(); ResourceManager.beforeUdpCreate(); + fd = new FileDescriptor(); try { datagramSocketCreate(); } catch (SocketException ioe) { From 86b01d99606169d5ca8739ec7b80cb935d3e789e Mon Sep 17 00:00:00 2001 From: John Coomes Date: Thu, 15 Sep 2011 20:30:12 -0700 Subject: [PATCH 089/214] 7091294: disable quicksort tests Reviewed-by: jmasa, ysr, kvn --- hotspot/src/share/vm/utilities/quickSort.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hotspot/src/share/vm/utilities/quickSort.cpp b/hotspot/src/share/vm/utilities/quickSort.cpp index cc41329bd24..b377d9a3c0d 100644 --- a/hotspot/src/share/vm/utilities/quickSort.cpp +++ b/hotspot/src/share/vm/utilities/quickSort.cpp @@ -92,6 +92,7 @@ bool QuickSort::sort_and_compare(int* arrayToSort, int* expectedResult, int leng } bool QuickSort::test_quick_sort() { +#if 0 tty->print_cr("test_quick_sort\n"); { int* test_array = NULL; @@ -212,6 +213,7 @@ bool QuickSort::test_quick_sort() { delete[] test_array; delete[] expected_array; } +#endif return true; } From 303c03e2ea773192d51425f816b091a1bff48f9b Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Thu, 15 Sep 2011 20:56:24 -0700 Subject: [PATCH 090/214] 7091255: Bump the hs22 build number to 06 Reviewed-by: johnc --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index ce2f28e8564..39b88ce51a0 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=22 HS_MINOR_VER=0 -HS_BUILD_NUMBER=05 +HS_BUILD_NUMBER=06 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 854ad24077c50e4f062c8855ff7ce17762af947c Mon Sep 17 00:00:00 2001 From: John Coomes Date: Thu, 15 Sep 2011 20:56:24 -0700 Subject: [PATCH 091/214] Added tag hs22-b06 for changeset 9de632dc424b --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 03779f9730e..42872376b78 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -184,3 +184,4 @@ dce7d24674f4d0bed00de24f00119057fdce7cfb jdk8-b05 3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03 ce9bde819dcba4a5d2822229d9183e69c74326ca hs22-b04 513a84dd0f8b56dc0836b4e0bdd5dd0a778fc634 hs22-b05 +650d15d8f37255d3b805aa00c5bd1c30984b203d hs22-b06 From bd420dc94eea12a8dccbbd3b0cc01f103e2e6d12 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 16 Sep 2011 14:16:11 +0100 Subject: [PATCH 092/214] 7086586: Inference producing null type argument Inference should fail in 15.12.2.7 when inference variables with 'nulltype' upper bounds are found Reviewed-by: dlsmith --- .../com/sun/tools/javac/code/Types.java | 7 ++- .../javac/Diagnostics/6862608/T6862608a.out | 2 +- .../generics/inference/6638712/T6638712a.out | 2 +- .../generics/inference/7086586/T7086586.java | 19 +++++++ .../generics/inference/7086586/T7086586.out | 5 ++ .../generics/inference/7086586/T7086586b.java | 54 +++++++++++++++++++ 6 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 langtools/test/tools/javac/generics/inference/7086586/T7086586.java create mode 100644 langtools/test/tools/javac/generics/inference/7086586/T7086586.out create mode 100644 langtools/test/tools/javac/generics/inference/7086586/T7086586b.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 475977c5bb6..55dc74d659a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -508,8 +508,13 @@ public class Types { @Override public Boolean visitUndetVar(UndetVar t, Type s) { //todo: test against origin needed? or replace with substitution? - if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN) + if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN) { return true; + } else if (s.tag == BOT) { + //if 's' is 'null' there's no instantiated type U for which + //U <: s (but 'null' itself, which is not a valid type) + return false; + } if (t.inst != null) return isSubtypeNoCapture(t.inst, s); // TODO: ", warn"? diff --git a/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.out b/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.out index b9f85252aaa..146bd51bdc5 100644 --- a/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.out +++ b/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.out @@ -1,3 +1,3 @@ -T6862608a.java:19:41: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, java.util.Comparator, java.util.Comparator)), java.util.Comparator, java.util.Comparator +T6862608a.java:19:33: compiler.err.cant.apply.symbol.1: kindname.method, compound, java.lang.Iterable>, java.util.List>, kindname.class, T6862608a, (compiler.misc.infer.no.conforming.assignment.exists: T, java.util.List>, java.lang.Iterable>) - compiler.misc.where.description.typevar: T,{(compiler.misc.where.typevar: T, java.lang.Object, kindname.method, compound(java.lang.Iterable>))} 1 error diff --git a/langtools/test/tools/javac/generics/inference/6638712/T6638712a.out b/langtools/test/tools/javac/generics/inference/6638712/T6638712a.out index c65e749bd55..04db2218b3d 100644 --- a/langtools/test/tools/javac/generics/inference/6638712/T6638712a.out +++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712a.out @@ -1,2 +1,2 @@ -T6638712a.java:16:41: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, java.util.Comparator, java.util.Comparator)), java.util.Comparator, java.util.Comparator +T6638712a.java:16:33: compiler.err.cant.apply.symbol.1: kindname.method, compound, java.lang.Iterable>, java.util.List>, kindname.class, T6638712a, (compiler.misc.infer.no.conforming.assignment.exists: T, java.util.List>, java.lang.Iterable>) 1 error diff --git a/langtools/test/tools/javac/generics/inference/7086586/T7086586.java b/langtools/test/tools/javac/generics/inference/7086586/T7086586.java new file mode 100644 index 00000000000..1045e5bf37f --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/7086586/T7086586.java @@ -0,0 +1,19 @@ +/** + * @test /nodynamiccopyright/ + * @bug 7086586 + * @summary Inference producing null type argument + * @compile/fail/ref=T7086586.out -XDrawDiagnostics T7086586.java + */ +import java.util.List; + +class T7086586 { + + List m(List dummy) { return null; } + + void test(List l) { + String s = m(l).get(0); + Number n = m(l).get(0); + Exception e = m(l).get(0); + m(l).nonExistentMethod(); + } +} diff --git a/langtools/test/tools/javac/generics/inference/7086586/T7086586.out b/langtools/test/tools/javac/generics/inference/7086586/T7086586.out new file mode 100644 index 00000000000..b6284a0312c --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/7086586/T7086586.out @@ -0,0 +1,5 @@ +T7086586.java:14:20: compiler.err.cant.apply.symbol.1: kindname.method, m, java.util.List, java.util.List, kindname.class, T7086586, (compiler.misc.infer.no.conforming.assignment.exists: T, java.util.List, java.util.List) +T7086586.java:15:20: compiler.err.cant.apply.symbol.1: kindname.method, m, java.util.List, java.util.List, kindname.class, T7086586, (compiler.misc.infer.no.conforming.assignment.exists: T, java.util.List, java.util.List) +T7086586.java:16:23: compiler.err.cant.apply.symbol.1: kindname.method, m, java.util.List, java.util.List, kindname.class, T7086586, (compiler.misc.infer.no.conforming.assignment.exists: T, java.util.List, java.util.List) +T7086586.java:17:9: compiler.err.cant.apply.symbol.1: kindname.method, m, java.util.List, java.util.List, kindname.class, T7086586, (compiler.misc.infer.no.conforming.assignment.exists: T, java.util.List, java.util.List) +4 errors diff --git a/langtools/test/tools/javac/generics/inference/7086586/T7086586b.java b/langtools/test/tools/javac/generics/inference/7086586/T7086586b.java new file mode 100644 index 00000000000..75dca61f58b --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/7086586/T7086586b.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7086586 + * + * @summary Inference producing null type argument + */ +import java.util.List; + +public class T7086586b { + + int assertionCount = 0; + + void assertTrue(boolean cond) { + if (!cond) { + throw new AssertionError(); + } + assertionCount++; + } + + void m(List dummy) { assertTrue(false); } + void m(Object dummy) { assertTrue(true); } + + void test(List l) { + m(l); + assertTrue(assertionCount == 1); + } + + public static void main(String[] args) { + new T7086586b().test(null); + } +} From 35806610982ead49cb90f2ead714171a134ab6cf Mon Sep 17 00:00:00 2001 From: Kurchi Subhra Hazra Date: Fri, 16 Sep 2011 12:09:04 -0700 Subject: [PATCH 093/214] 7090158: Networking Libraries don't build with javac -Werror Minor changes to networking java files to remove warnings Co-authored-by: Alexandre Boulgakov Reviewed-by: chegar, weijun, hawtin --- jdk/make/com/sun/net/httpserver/Makefile | 4 +- jdk/make/com/sun/net/ssl/Makefile | 3 ++ jdk/make/java/net/Makefile | 3 ++ jdk/make/javax/Makefile | 2 +- jdk/make/javax/others/Makefile | 1 - jdk/make/sun/net/Makefile | 4 +- jdk/make/sun/net/spi/Makefile | 2 + jdk/make/sun/net/spi/nameservice/dns/Makefile | 3 +- .../net/httpserver/BasicAuthenticator.java | 8 +-- .../com/sun/net/httpserver/Headers.java | 4 +- .../httpserver/spi/HttpServerProvider.java | 20 ++++---- .../classes/com/sun/net/ssl/SSLSecurity.java | 11 ++--- .../https/DelegateHttpsURLConnection.java | 6 +-- .../net/AbstractPlainDatagramSocketImpl.java | 4 +- .../classes/java/net/ContentHandler.java | 4 +- .../share/classes/java/net/CookieManager.java | 3 +- .../classes/java/net/DatagramSocket.java | 6 +-- .../classes/java/net/HttpURLConnection.java | 1 + .../share/classes/java/net/Inet4Address.java | 4 +- .../classes/java/net/Inet4AddressImpl.java | 6 +-- .../share/classes/java/net/Inet6Address.java | 6 +-- .../classes/java/net/Inet6AddressImpl.java | 6 +-- .../classes/java/net/MulticastSocket.java | 7 ++- jdk/src/share/classes/java/net/Proxy.java | 4 +- .../share/classes/java/net/ProxySelector.java | 4 +- jdk/src/share/classes/java/net/Socket.java | 9 ++-- .../classes/java/net/SocketPermission.java | 23 +++++---- jdk/src/share/classes/java/net/URL.java | 11 ++--- .../classes/java/net/URLClassLoader.java | 15 ++---- .../share/classes/java/net/URLConnection.java | 11 +++-- .../javax/net/ssl/SSLServerSocketFactory.java | 4 +- .../javax/net/ssl/SSLSocketFactory.java | 4 +- .../share/classes/sun/misc/REException.java | 3 ++ .../sun/net/TransferProtocolClient.java | 10 ++-- .../sun/net/ftp/FtpClientProvider.java | 15 +++--- .../classes/sun/net/httpserver/Request.java | 9 ++-- .../sun/net/httpserver/SSLStreams.java | 6 +-- .../sun/net/httpserver/ServerImpl.java | 6 +-- .../classes/sun/net/idn/UCharacterEnums.java | 43 ++++++++++++++++ .../spi/nameservice/dns/DNSNameService.java | 12 ++--- .../classes/sun/net/www/HeaderParser.java | 14 +++--- .../classes/sun/net/www/MessageHeader.java | 20 ++++---- .../share/classes/sun/net/www/MimeTable.java | 12 ++--- .../classes/sun/net/www/URLConnection.java | 9 +--- .../sun/net/www/content/image/gif.java | 7 +-- .../sun/net/www/content/image/jpeg.java | 7 +-- .../sun/net/www/content/image/png.java | 7 +-- .../sun/net/www/content/image/x_xbitmap.java | 4 +- .../sun/net/www/content/image/x_xpixmap.java | 4 +- .../sun/net/www/http/KeepAliveStream.java | 2 +- .../net/www/protocol/gopher/GopherClient.java | 2 +- .../net/www/protocol/http/AuthCacheImpl.java | 30 +++++------- .../protocol/http/AuthenticationHeader.java | 28 +++++------ .../www/protocol/http/HttpURLConnection.java | 49 ++++++++++--------- .../sun/net/www/protocol/http/Negotiator.java | 6 +-- .../AbstractDelegateHttpsURLConnection.java | 10 ++-- .../net/www/protocol/https/HttpsClient.java | 12 ++--- .../sun/net/www/protocol/mailto/Handler.java | 16 +++++- .../net/DefaultDatagramSocketImplFactory.java | 4 +- .../java/net/PlainDatagramSocketImpl.java | 4 +- .../net/dns/ResolverConfigurationImpl.java | 18 ++++--- .../net/DefaultDatagramSocketImplFactory.java | 4 +- .../net/DualStackPlainDatagramSocketImpl.java | 6 +-- .../net/TwoStacksPlainDatagramSocketImpl.java | 2 + .../net/dns/ResolverConfigurationImpl.java | 10 ++-- .../net/www/protocol/jar/JarFileFactory.java | 4 +- 66 files changed, 318 insertions(+), 280 deletions(-) diff --git a/jdk/make/com/sun/net/httpserver/Makefile b/jdk/make/com/sun/net/httpserver/Makefile index 5c0e85c8188..2d2e6b89b01 100644 --- a/jdk/make/com/sun/net/httpserver/Makefile +++ b/jdk/make/com/sun/net/httpserver/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ BUILDDIR = ../../../.. PACKAGE = com.sun.net.httpserver PRODUCT = sun +JAVAC_MAX_WARNINGS = true +JAVAC_WARNINGS_FATAL = true include $(BUILDDIR)/common/Defs.gmk # diff --git a/jdk/make/com/sun/net/ssl/Makefile b/jdk/make/com/sun/net/ssl/Makefile index 4ec297c2346..b5c291ec2e6 100644 --- a/jdk/make/com/sun/net/ssl/Makefile +++ b/jdk/make/com/sun/net/ssl/Makefile @@ -26,6 +26,9 @@ BUILDDIR = ../../../.. PACKAGE = com.sun.net.ssl PRODUCT = sun +JAVAC_LINT_OPTIONS=-Xlint:all,-deprecation +JAVAC_MAX_WARNINGS = true +JAVAC_WARNINGS_FATAL = true include $(BUILDDIR)/common/Defs.gmk # diff --git a/jdk/make/java/net/Makefile b/jdk/make/java/net/Makefile index e6429c6c209..83c885b34d8 100644 --- a/jdk/make/java/net/Makefile +++ b/jdk/make/java/net/Makefile @@ -27,6 +27,9 @@ BUILDDIR = ../.. PACKAGE = java.net LIBRARY = net PRODUCT = sun +JAVAC_MAX_WARNINGS = true +JAVAC_WARNINGS_FATAL = true +JAVAC_LINT_OPTIONS = -Xlint:all,-deprecation include $(BUILDDIR)/common/Defs.gmk # diff --git a/jdk/make/javax/Makefile b/jdk/make/javax/Makefile index a58a1b1eb5a..251628c8381 100644 --- a/jdk/make/javax/Makefile +++ b/jdk/make/javax/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/javax/others/Makefile b/jdk/make/javax/others/Makefile index c98d63ded35..1283dcea892 100644 --- a/jdk/make/javax/others/Makefile +++ b/jdk/make/javax/others/Makefile @@ -28,7 +28,6 @@ # BUILDDIR = ../.. -JAVAC_MAX_WARNINGS = true include $(BUILDDIR)/common/Defs.gmk # diff --git a/jdk/make/sun/net/Makefile b/jdk/make/sun/net/Makefile index 4a4278560c6..3e56798e2ee 100644 --- a/jdk/make/sun/net/Makefile +++ b/jdk/make/sun/net/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ BUILDDIR = ../.. PACKAGE = sun.net PRODUCT = sun +SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true +SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true include $(BUILDDIR)/common/Defs.gmk SUBDIRS = others spi diff --git a/jdk/make/sun/net/spi/Makefile b/jdk/make/sun/net/spi/Makefile index 1b2f8daffee..dc448cf2558 100644 --- a/jdk/make/sun/net/spi/Makefile +++ b/jdk/make/sun/net/spi/Makefile @@ -24,6 +24,8 @@ # BUILDDIR = ../../.. +SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true + include $(BUILDDIR)/common/Defs.gmk SUBDIRS_misc = nameservice diff --git a/jdk/make/sun/net/spi/nameservice/dns/Makefile b/jdk/make/sun/net/spi/nameservice/dns/Makefile index 13ed8e63e45..4c4ef34aa21 100644 --- a/jdk/make/sun/net/spi/nameservice/dns/Makefile +++ b/jdk/make/sun/net/spi/nameservice/dns/Makefile @@ -28,7 +28,8 @@ # BUILDDIR = ../../../../.. - +JAVAC_MAX_WARNINGS = true +JAVAC_WARNINGS_FATAL = true # dns should probably be its own module PACKAGE = sun.net.spi.nameservice.dns PRODUCT = sun diff --git a/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java b/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java index de749ff0440..781510a2cca 100644 --- a/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java +++ b/jdk/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,13 +54,13 @@ public abstract class BasicAuthenticator extends Authenticator { public Result authenticate (HttpExchange t) { - Headers rmap = (Headers) t.getRequestHeaders(); + Headers rmap = t.getRequestHeaders(); /* * look for auth token */ String auth = rmap.getFirst ("Authorization"); if (auth == null) { - Headers map = (Headers) t.getResponseHeaders(); + Headers map = t.getResponseHeaders(); map.set ("WWW-Authenticate", "Basic realm=" + "\""+realm+"\""); return new Authenticator.Retry (401); } @@ -83,7 +83,7 @@ public abstract class BasicAuthenticator extends Authenticator { } else { /* reject the request again with 401 */ - Headers map = (Headers) t.getResponseHeaders(); + Headers map = t.getResponseHeaders(); map.set ("WWW-Authenticate", "Basic realm=" + "\""+realm+"\""); return new Authenticator.Failure(401); } diff --git a/jdk/src/share/classes/com/sun/net/httpserver/Headers.java b/jdk/src/share/classes/com/sun/net/httpserver/Headers.java index 0d4172fd44e..afe3c217d41 100644 --- a/jdk/src/share/classes/com/sun/net/httpserver/Headers.java +++ b/jdk/src/share/classes/com/sun/net/httpserver/Headers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,7 @@ public class Headers implements Map> { * @return the first string value associated with the key */ public String getFirst (String key) { - List l = map.get(normalize((String)key)); + List l = map.get(normalize(key)); if (l == null) { return null; } diff --git a/jdk/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java b/jdk/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java index 53ba6488dcb..ec8b91c5f5d 100644 --- a/jdk/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java +++ b/jdk/src/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,29 +81,27 @@ public abstract class HttpServerProvider { if (cn == null) return false; try { - Class c = Class.forName(cn, true, + Class c = Class.forName(cn, true, ClassLoader.getSystemClassLoader()); provider = (HttpServerProvider)c.newInstance(); return true; - } catch (ClassNotFoundException x) { - throw new ServiceConfigurationError(x); - } catch (IllegalAccessException x) { - throw new ServiceConfigurationError(x); - } catch (InstantiationException x) { - throw new ServiceConfigurationError(x); - } catch (SecurityException x) { + } catch (ClassNotFoundException | + IllegalAccessException | + InstantiationException | + SecurityException x) { throw new ServiceConfigurationError(x); } } private static boolean loadProviderAsService() { - Iterator i = Service.providers(HttpServerProvider.class, + @SuppressWarnings("unchecked") + Iterator i = Service.providers(HttpServerProvider.class, ClassLoader.getSystemClassLoader()); for (;;) { try { if (!i.hasNext()) return false; - provider = (HttpServerProvider)i.next(); + provider = i.next(); return true; } catch (ServiceConfigurationError sce) { if (sce.getCause() instanceof SecurityException) { diff --git a/jdk/src/share/classes/com/sun/net/ssl/SSLSecurity.java b/jdk/src/share/classes/com/sun/net/ssl/SSLSecurity.java index ba80627cf8c..cac7298ab69 100644 --- a/jdk/src/share/classes/com/sun/net/ssl/SSLSecurity.java +++ b/jdk/src/share/classes/com/sun/net/ssl/SSLSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,7 +77,7 @@ final class SSLSecurity { { Provider provider = service.getProvider(); String className = service.getClassName(); - Class implClass; + Class implClass; try { ClassLoader cl = provider.getClass().getClassLoader(); if (cl == null) { @@ -133,8 +133,8 @@ final class SSLSecurity { * or someone has removed classes from the jsse.jar file. */ - Class typeClassJavax; - Class typeClassCom; + Class typeClassJavax; + Class typeClassCom; Object obj = null; /* @@ -237,7 +237,7 @@ final class SSLSecurity { /* * Checks whether one class is the superclass of another */ - private static boolean checkSuperclass(Class subclass, Class superclass) { + private static boolean checkSuperclass(Class subclass, Class superclass) { if ((subclass == null) || (superclass == null)) return false; @@ -276,7 +276,6 @@ final class SSLSecurity { * object. This also mean that anything going down into the SPI * needs to be wrapped, as well as anything coming back up. */ - final class SSLContextSpiWrapper extends SSLContextSpi { private javax.net.ssl.SSLContext theSSLContext; diff --git a/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java b/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java index 3dda0665ab6..2fcbc4e72a6 100644 --- a/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java +++ b/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java @@ -165,10 +165,10 @@ class VerifierWrapper implements javax.net.ssl.HostnameVerifier { private static String getServername(X509Certificate peerCert) { try { // compare to subjectAltNames if dnsName is present - Collection subjAltNames = peerCert.getSubjectAlternativeNames(); + Collection> subjAltNames = peerCert.getSubjectAlternativeNames(); if (subjAltNames != null) { - for (Iterator itr = subjAltNames.iterator(); itr.hasNext(); ) { - List next = (List)itr.next(); + for (Iterator> itr = subjAltNames.iterator(); itr.hasNext(); ) { + List next = itr.next(); if (((Integer)next.get(0)).intValue() == 2) { // compare dNSName with host in url String dnsName = ((String)next.get(1)); diff --git a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index ff0d2cd3584..0d03a40859c 100644 --- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -26,8 +26,6 @@ package java.net; import java.io.FileDescriptor; import java.io.IOException; -import java.io.InterruptedIOException; -import java.util.Enumeration; import sun.net.ResourceManager; /** @@ -153,11 +151,13 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl * Set the TTL (time-to-live) option. * @param TTL to be set. */ + @Deprecated protected abstract void setTTL(byte ttl) throws IOException; /** * Get the TTL (time-to-live) option. */ + @Deprecated protected abstract byte getTTL() throws IOException; /** diff --git a/jdk/src/share/classes/java/net/ContentHandler.java b/jdk/src/share/classes/java/net/ContentHandler.java index 9460f25a7ae..319e6199bf7 100644 --- a/jdk/src/share/classes/java/net/ContentHandler.java +++ b/jdk/src/share/classes/java/net/ContentHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ abstract public class ContentHandler { * @exception IOException if an I/O error occurs while reading the object. * @since 1.3 */ - public Object getContent(URLConnection urlc, Class[] classes) throws IOException { + public Object getContent(URLConnection urlc, Class[] classes) throws IOException { Object obj = getContent(urlc); for (int i = 0; i < classes.length; i++) { diff --git a/jdk/src/share/classes/java/net/CookieManager.java b/jdk/src/share/classes/java/net/CookieManager.java index 532999b57b7..b9de7191df3 100644 --- a/jdk/src/share/classes/java/net/CookieManager.java +++ b/jdk/src/share/classes/java/net/CookieManager.java @@ -249,7 +249,6 @@ public class CookieManager extends CookieHandler return Collections.unmodifiableMap(cookieMap); } - public void put(URI uri, Map> responseHeaders) throws IOException @@ -284,7 +283,7 @@ public class CookieManager extends CookieHandler cookies = HttpCookie.parse(headerValue); } catch (IllegalArgumentException e) { // Bogus header, make an empty list and log the error - cookies = java.util.Collections.EMPTY_LIST; + cookies = java.util.Collections.emptyList(); if (logger.isLoggable(PlatformLogger.SEVERE)) { logger.severe("Invalid cookie for " + uri + ": " + headerValue); } diff --git a/jdk/src/share/classes/java/net/DatagramSocket.java b/jdk/src/share/classes/java/net/DatagramSocket.java index 7166c5f93ea..5d73de6c0fc 100644 --- a/jdk/src/share/classes/java/net/DatagramSocket.java +++ b/jdk/src/share/classes/java/net/DatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ package java.net; -import java.io.FileDescriptor; import java.io.IOException; -import java.io.InterruptedIOException; import java.nio.channels.DatagramChannel; import java.security.AccessController; import java.security.PrivilegedExceptionAction; @@ -300,7 +298,7 @@ class DatagramSocket implements java.io.Closeable { } } - static Class implClass = null; + static Class implClass = null; void createImpl() throws SocketException { if (impl == null) { diff --git a/jdk/src/share/classes/java/net/HttpURLConnection.java b/jdk/src/share/classes/java/net/HttpURLConnection.java index f88e9ef1b20..d52c26789fa 100644 --- a/jdk/src/share/classes/java/net/HttpURLConnection.java +++ b/jdk/src/share/classes/java/net/HttpURLConnection.java @@ -535,6 +535,7 @@ abstract public class HttpURLConnection extends URLConnection { return responseMessage; } + @SuppressWarnings("deprecation") public long getHeaderFieldDate(String name, long Default) { String dateString = getHeaderField(name); try { diff --git a/jdk/src/share/classes/java/net/Inet4Address.java b/jdk/src/share/classes/java/net/Inet4Address.java index af8334640c3..190b56353ee 100644 --- a/jdk/src/share/classes/java/net/Inet4Address.java +++ b/jdk/src/share/classes/java/net/Inet4Address.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ package java.net; -import java.security.AccessController; import java.io.ObjectStreamException; -import sun.security.action.*; /** * This class represents an Internet Protocol version 4 (IPv4) address. diff --git a/jdk/src/share/classes/java/net/Inet4AddressImpl.java b/jdk/src/share/classes/java/net/Inet4AddressImpl.java index 86ff9d33260..367ca22b9aa 100644 --- a/jdk/src/share/classes/java/net/Inet4AddressImpl.java +++ b/jdk/src/share/classes/java/net/Inet4AddressImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,11 +59,11 @@ class Inet4AddressImpl implements InetAddressImpl { /* * Let's make sure we use an address of the proper family */ - java.util.Enumeration it = netif.getInetAddresses(); + java.util.Enumeration it = netif.getInetAddresses(); InetAddress inetaddr = null; while (!(inetaddr instanceof Inet4Address) && it.hasMoreElements()) - inetaddr = (InetAddress) it.nextElement(); + inetaddr = it.nextElement(); if (inetaddr instanceof Inet4Address) ifaddr = inetaddr.getAddress(); } diff --git a/jdk/src/share/classes/java/net/Inet6Address.java b/jdk/src/share/classes/java/net/Inet6Address.java index 4236ddc79c4..77e7cf80314 100644 --- a/jdk/src/share/classes/java/net/Inet6Address.java +++ b/jdk/src/share/classes/java/net/Inet6Address.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -383,9 +383,9 @@ class Inet6Address extends InetAddress { while (en.hasMoreElements()) { NetworkInterface ifc = en.nextElement(); if (ifc.getName().equals (ifname)) { - Enumeration addresses = ifc.getInetAddresses(); + Enumeration addresses = ifc.getInetAddresses(); while (addresses.hasMoreElements()) { - InetAddress addr = (InetAddress)addresses.nextElement(); + InetAddress addr = addresses.nextElement(); if (!(addr instanceof Inet6Address)) { continue; } diff --git a/jdk/src/share/classes/java/net/Inet6AddressImpl.java b/jdk/src/share/classes/java/net/Inet6AddressImpl.java index 3c2341064f1..663c77ebccc 100644 --- a/jdk/src/share/classes/java/net/Inet6AddressImpl.java +++ b/jdk/src/share/classes/java/net/Inet6AddressImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,10 +54,10 @@ class Inet6AddressImpl implements InetAddressImpl { * be either an IPv6 address or an IPv4 address (case of a dual * stack system). */ - java.util.Enumeration it = netif.getInetAddresses(); + java.util.Enumeration it = netif.getInetAddresses(); InetAddress inetaddr = null; while (it.hasMoreElements()) { - inetaddr = (InetAddress) it.nextElement(); + inetaddr = it.nextElement(); if (inetaddr.getClass().isInstance(addr)) { ifaddr = inetaddr.getAddress(); if (inetaddr instanceof Inet6Address) { diff --git a/jdk/src/share/classes/java/net/MulticastSocket.java b/jdk/src/share/classes/java/net/MulticastSocket.java index bb4760f1184..0171315530e 100644 --- a/jdk/src/share/classes/java/net/MulticastSocket.java +++ b/jdk/src/share/classes/java/net/MulticastSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.net; import java.io.IOException; -import java.io.InterruptedIOException; import java.util.Enumeration; /** @@ -500,9 +499,9 @@ class MulticastSocket extends DatagramSocket { */ try { NetworkInterface ni = NetworkInterface.getByInetAddress(ia); - Enumeration addrs = ni.getInetAddresses(); + Enumeration addrs = ni.getInetAddresses(); while (addrs.hasMoreElements()) { - InetAddress addr = (InetAddress)(addrs.nextElement()); + InetAddress addr = addrs.nextElement(); if (addr.equals(infAddress)) { return infAddress; } diff --git a/jdk/src/share/classes/java/net/Proxy.java b/jdk/src/share/classes/java/net/Proxy.java index 333067dea0f..4b8b6f148d5 100644 --- a/jdk/src/share/classes/java/net/Proxy.java +++ b/jdk/src/share/classes/java/net/Proxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,7 +73,7 @@ public class Proxy { // Creates the proxy that represents a DIRECT connection. private Proxy() { - type = type.DIRECT; + type = Type.DIRECT; sa = null; } diff --git a/jdk/src/share/classes/java/net/ProxySelector.java b/jdk/src/share/classes/java/net/ProxySelector.java index 9a62e138a2a..88f24a210ae 100644 --- a/jdk/src/share/classes/java/net/ProxySelector.java +++ b/jdk/src/share/classes/java/net/ProxySelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,7 +69,7 @@ public abstract class ProxySelector { static { try { - Class c = Class.forName("sun.net.spi.DefaultProxySelector"); + Class c = Class.forName("sun.net.spi.DefaultProxySelector"); if (c != null && ProxySelector.class.isAssignableFrom(c)) { theProxySelector = (ProxySelector) c.newInstance(); } diff --git a/jdk/src/share/classes/java/net/Socket.java b/jdk/src/share/classes/java/net/Socket.java index 91ec5862b34..22d4d6acd0a 100644 --- a/jdk/src/share/classes/java/net/Socket.java +++ b/jdk/src/share/classes/java/net/Socket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -459,13 +459,10 @@ class Socket implements java.io.Closeable { oldImpl = AccessController.doPrivileged (new PrivilegedAction() { public Boolean run() { - Class[] cl = new Class[2]; - cl[0] = SocketAddress.class; - cl[1] = Integer.TYPE; - Class clazz = impl.getClass(); + Class clazz = impl.getClass(); while (true) { try { - clazz.getDeclaredMethod("connect", cl); + clazz.getDeclaredMethod("connect", SocketAddress.class, int.class); return Boolean.FALSE; } catch (NoSuchMethodException e) { clazz = clazz.getSuperclass(); diff --git a/jdk/src/share/classes/java/net/SocketPermission.java b/jdk/src/share/classes/java/net/SocketPermission.java index a0fdbb8cc31..b20563bc9dc 100644 --- a/jdk/src/share/classes/java/net/SocketPermission.java +++ b/jdk/src/share/classes/java/net/SocketPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -467,6 +467,7 @@ implements java.io.Serializable * @param action the action string * @return the action mask */ + @SuppressWarnings("fallthrough") private static int getMask(String action) { if (action == null) { @@ -1231,7 +1232,7 @@ final class SocketPermissionCollection extends PermissionCollection implements Serializable { // Not serialized; see serialization section at end of class - private transient List perms; + private transient List perms; /** * Create an empty SocketPermissions object. @@ -1239,7 +1240,7 @@ implements Serializable */ public SocketPermissionCollection() { - perms = new ArrayList(); + perms = new ArrayList(); } /** @@ -1267,7 +1268,7 @@ implements Serializable // optimization to ensure perms most likely to be tested // show up early (4301064) synchronized (this) { - perms.add(0, permission); + perms.add(0, (SocketPermission)permission); } } @@ -1296,7 +1297,7 @@ implements Serializable int len = perms.size(); //System.out.println("implies "+np); for (int i = 0; i < len; i++) { - SocketPermission x = (SocketPermission) perms.get(i); + SocketPermission x = perms.get(i); //System.out.println(" trying "+x); if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { effective |= x.getMask(); @@ -1316,10 +1317,11 @@ implements Serializable * @return an enumeration of all the SocketPermission objects. */ - public Enumeration elements() { + @SuppressWarnings("unchecked") + public Enumeration elements() { // Convert Iterator into Enumeration synchronized (this) { - return Collections.enumeration(perms); + return Collections.enumeration((List)(List)perms); } } @@ -1353,7 +1355,7 @@ implements Serializable // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector(perms.size()); + Vector permissions = new Vector<>(perms.size()); synchronized (this) { permissions.addAll(perms); @@ -1375,8 +1377,9 @@ implements Serializable ObjectInputStream.GetField gfields = in.readFields(); // Get the one we want - Vector permissions = (Vector)gfields.get("permissions", null); - perms = new ArrayList(permissions.size()); + @SuppressWarnings("unchecked") + Vector permissions = (Vector)gfields.get("permissions", null); + perms = new ArrayList(permissions.size()); perms.addAll(permissions); } } diff --git a/jdk/src/share/classes/java/net/URL.java b/jdk/src/share/classes/java/net/URL.java index 06222c6f100..e7e9ddacc4c 100644 --- a/jdk/src/share/classes/java/net/URL.java +++ b/jdk/src/share/classes/java/net/URL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package java.net; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.util.Hashtable; import java.util.StringTokenizer; import sun.security.util.SecurityConstants; @@ -1113,7 +1112,7 @@ public final class URL implements java.io.Serializable { /** * A table of protocol handlers. */ - static Hashtable handlers = new Hashtable(); + static Hashtable handlers = new Hashtable<>(); private static Object streamHandlerLock = new Object(); /** @@ -1122,7 +1121,7 @@ public final class URL implements java.io.Serializable { */ static URLStreamHandler getURLStreamHandler(String protocol) { - URLStreamHandler handler = (URLStreamHandler)handlers.get(protocol); + URLStreamHandler handler = handlers.get(protocol); if (handler == null) { boolean checkedWithFactory = false; @@ -1160,7 +1159,7 @@ public final class URL implements java.io.Serializable { try { String clsName = packagePrefix + "." + protocol + ".Handler"; - Class cls = null; + Class cls = null; try { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { @@ -1185,7 +1184,7 @@ public final class URL implements java.io.Serializable { // Check again with hashtable just in case another // thread created a handler since we last checked - handler2 = (URLStreamHandler)handlers.get(protocol); + handler2 = handlers.get(protocol); if (handler2 != null) { return handler2; diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java index 4f28be634ff..fb0fe47cd2b 100644 --- a/jdk/src/share/classes/java/net/URLClassLoader.java +++ b/jdk/src/share/classes/java/net/URLClassLoader.java @@ -25,14 +25,7 @@ package java.net; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.ref.*; import java.io.*; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandlerFactory; -import java.util.Enumeration; import java.util.*; import java.util.jar.Manifest; import java.util.jar.JarFile; @@ -352,8 +345,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { { try { return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Class run() throws ClassNotFoundException { + new PrivilegedExceptionAction>() { + public Class run() throws ClassNotFoundException { String path = name.replace('.', '/').concat(".class"); Resource res = ucp.getResource(path, false); if (res != null) { @@ -406,7 +399,7 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * Resource. The resulting Class must be resolved before it can be * used. */ - private Class defineClass(String name, Resource res) throws IOException { + private Class defineClass(String name, Resource res) throws IOException { long t0 = System.nanoTime(); int i = name.lastIndexOf('.'); URL url = res.getCodeSourceURL(); @@ -774,7 +767,7 @@ final class FactoryURLClassLoader extends URLClassLoader { super(urls, acc); } - public final Class loadClass(String name, boolean resolve) + public final Class loadClass(String name, boolean resolve) throws ClassNotFoundException { // First check if we have permission to access the package. This diff --git a/jdk/src/share/classes/java/net/URLConnection.java b/jdk/src/share/classes/java/net/URLConnection.java index 976e8f66cea..cc747a8eef0 100644 --- a/jdk/src/share/classes/java/net/URLConnection.java +++ b/jdk/src/share/classes/java/net/URLConnection.java @@ -595,7 +595,7 @@ public abstract class URLConnection { * @since 1.4 */ public Map> getHeaderFields() { - return Collections.EMPTY_MAP; + return Collections.emptyMap(); } /** @@ -659,6 +659,7 @@ public abstract class URLConnection { * Default argument is returned if the field is * missing or malformed. */ + @SuppressWarnings("deprecation") public long getHeaderFieldDate(String name, long Default) { String value = getHeaderField(name); try { @@ -1153,7 +1154,7 @@ public abstract class URLConnection { throw new IllegalStateException("Already connected"); if (requests == null) - return Collections.EMPTY_MAP; + return Collections.emptyMap(); return requests.getHeaders(null); } @@ -1236,7 +1237,7 @@ public abstract class URLConnection { factory = fac; } - private static Hashtable handlers = new Hashtable(); + private static Hashtable handlers = new Hashtable<>(); /** * Gets the Content Handler appropriate for this connection. @@ -1250,7 +1251,7 @@ public abstract class URLConnection { if (contentType == null) throw new UnknownServiceException("no content-type"); try { - handler = (ContentHandler) handlers.get(contentType); + handler = handlers.get(contentType); if (handler != null) return handler; } catch(Exception e) { @@ -1316,7 +1317,7 @@ public abstract class URLConnection { try { String clsName = packagePrefix + "." + contentHandlerClassName; - Class cls = null; + Class cls = null; try { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { diff --git a/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java b/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java index dc32d14e559..24911295adf 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory if (clsName != null) { log("setting up default SSLServerSocketFactory"); try { - Class cls = null; + Class cls = null; try { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { diff --git a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java index f7d5e5b0a2f..c3d33c34f70 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,7 @@ public abstract class SSLSocketFactory extends SocketFactory if (clsName != null) { log("setting up default SSLSocketFactory"); try { - Class cls = null; + Class cls = null; try { cls = Class.forName(clsName); } catch (ClassNotFoundException e) { diff --git a/jdk/src/share/classes/sun/misc/REException.java b/jdk/src/share/classes/sun/misc/REException.java index 1799e82cd95..2b091cd6616 100644 --- a/jdk/src/share/classes/sun/misc/REException.java +++ b/jdk/src/share/classes/sun/misc/REException.java @@ -31,6 +31,9 @@ package sun.misc; */ public class REException extends Exception { + + private static final long serialVersionUID = 4656584872733646963L; + REException (String s) { super(s); } diff --git a/jdk/src/share/classes/sun/net/TransferProtocolClient.java b/jdk/src/share/classes/sun/net/TransferProtocolClient.java index 2b74b62e0f0..79f9e1358f8 100644 --- a/jdk/src/share/classes/sun/net/TransferProtocolClient.java +++ b/jdk/src/share/classes/sun/net/TransferProtocolClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,8 @@ package sun.net; -import java.lang.StringIndexOutOfBoundsException; import java.io.*; import java.util.Vector; -import sun.net.NetworkClient; /** * This class implements that basic intefaces of transfer protocols. @@ -44,7 +42,7 @@ public class TransferProtocolClient extends NetworkClient { /** Array of strings (usually 1 entry) for the last reply from the server. */ - protected Vector serverResponse = new Vector(1); + protected Vector serverResponse = new Vector<>(1); /** code for last reply */ protected int lastReplyCode; @@ -123,11 +121,11 @@ public class TransferProtocolClient extends NetworkClient { /** converts the server response into a string. */ public String getResponseString() { - return (String) serverResponse.elementAt(0); + return serverResponse.elementAt(0); } /** Returns all server response strings. */ - public Vector getResponseStrings() { + public Vector getResponseStrings() { return serverResponse; } diff --git a/jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java b/jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java index 71cd134fb17..7a09810718c 100644 --- a/jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java +++ b/jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,16 +67,13 @@ public abstract class FtpClientProvider { return false; } try { - Class c = Class.forName(cm, true, null); + Class c = Class.forName(cm, true, null); provider = (FtpClientProvider) c.newInstance(); return true; - } catch (ClassNotFoundException x) { - throw new ServiceConfigurationError(x.toString()); - } catch (IllegalAccessException x) { - throw new ServiceConfigurationError(x.toString()); - } catch (InstantiationException x) { - throw new ServiceConfigurationError(x.toString()); - } catch (SecurityException x) { + } catch (ClassNotFoundException | + IllegalAccessException | + InstantiationException | + SecurityException x) { throw new ServiceConfigurationError(x.toString()); } } diff --git a/jdk/src/share/classes/sun/net/httpserver/Request.java b/jdk/src/share/classes/sun/net/httpserver/Request.java index ee2db48240f..f0b56e1e815 100644 --- a/jdk/src/share/classes/sun/net/httpserver/Request.java +++ b/jdk/src/share/classes/sun/net/httpserver/Request.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,10 @@ package sun.net.httpserver; -import java.util.*; import java.nio.*; -import java.net.*; import java.io.*; import java.nio.channels.*; import com.sun.net.httpserver.*; -import com.sun.net.httpserver.spi.*; /** */ @@ -47,7 +44,6 @@ class Request { private OutputStream os; Request (InputStream rawInputStream, OutputStream rawout) throws IOException { - this.chan = chan; is = rawInputStream; os = rawout; do { @@ -121,7 +117,7 @@ class Request { } Headers hdrs = null; - + @SuppressWarnings("fallthrough") Headers headers () throws IOException { if (hdrs != null) { return hdrs; @@ -152,6 +148,7 @@ class Request { parseloop:{ while ((c = is.read()) >= 0) { switch (c) { + /*fallthrough*/ case ':': if (inKey && len > 0) keyend = len; diff --git a/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java b/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java index c6b87cd6729..6e362d07aa4 100644 --- a/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java +++ b/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,13 +29,10 @@ import java.net.*; import java.nio.*; import java.io.*; import java.nio.channels.*; -import java.util.*; -import java.util.concurrent.*; import java.util.concurrent.locks.*; import javax.net.ssl.*; import javax.net.ssl.SSLEngineResult.*; import com.sun.net.httpserver.*; -import com.sun.net.httpserver.spi.*; /** * given a non-blocking SocketChannel, it produces @@ -448,6 +445,7 @@ class SSLStreams { * on the wrapper methods being idempotent. eg. if wrapAndSend() * is called with no data to send then there must be no problem */ + @SuppressWarnings("fallthrough") void doHandshake (HandshakeStatus hs_status) throws IOException { try { handshaking.lock(); diff --git a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java index 5b53389d45f..cce9c136e8a 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -593,8 +593,8 @@ class ServerImpl implements TimeSource { rheaders.set ("Connection", "close"); } else if (chdr.equalsIgnoreCase ("keep-alive")) { rheaders.set ("Connection", "keep-alive"); - int idle=(int)ServerConfig.getIdleInterval()/1000; - int max=(int)ServerConfig.getMaxIdleConnections(); + int idle=(int)(ServerConfig.getIdleInterval()/1000); + int max=ServerConfig.getMaxIdleConnections(); String val = "timeout="+idle+", max="+max; rheaders.set ("Keep-Alive", val); } diff --git a/jdk/src/share/classes/sun/net/idn/UCharacterEnums.java b/jdk/src/share/classes/sun/net/idn/UCharacterEnums.java index 660d055a013..eef2fdda421 100644 --- a/jdk/src/share/classes/sun/net/idn/UCharacterEnums.java +++ b/jdk/src/share/classes/sun/net/idn/UCharacterEnums.java @@ -33,6 +33,22 @@ // - copy this file from icu4jsrc_3_2/src/com/ibm/icu/lang/UCharacterEnums.java // - move from package com.ibm.icu.lang to package sun.net.idn // +// 2011-09-06 Kurchi Subhra Hazra +// - Added @Deprecated tag to the following: +// - class UCharacterEnums +// - interfaces ECharacterCategory, ECharacterDirection +// - fields INITIAL_QUOTE_PUNCTUATION, FINAL_QUOTE_PUNCTUATION, +// DIRECTIONALITY_LEFT_TO_RIGHT, DIRECTIONALITY_RIGHT_TO_LEFT, +// DIRECTIONALITY_EUROPEAN_NUMBER, DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR +// DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR, DIRECTIONALITY_ARABIC_NUMBER, +// DIRECTIONALITY_COMMON_NUMBER_SEPARATOR, DIRECTIONALITY_PARAGRAPH_SEPARATOR, +// DIRECTIONALITY_SEGMENT_SEPARATOR, DIRECTIONALITY_WHITESPACE, +// DIRECTIONALITY_OTHER_NEUTRALS, DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING, +// DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE, DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC, +// DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING, DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE, +// DIRECTIONALITY_POP_DIRECTIONAL_FORMAT, DIRECTIONALITY_NON_SPACING_MARK, +// DIRECTIONALITY_BOUNDARY_NEUTRAL, DIRECTIONALITY_UNDEFINED +// package sun.net.idn; @@ -41,6 +57,8 @@ package sun.net.idn; * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + +@Deprecated class UCharacterEnums { /** This is just a namespace, it is not instantiatable. */ @@ -54,6 +72,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static interface ECharacterCategory { /** * Unassigned character type @@ -245,6 +264,7 @@ class UCharacterEnums { * @draft ICU 2.8 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final int INITIAL_QUOTE_PUNCTUATION = 28; /** @@ -261,6 +281,7 @@ class UCharacterEnums { * @draft ICU 2.8 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final int FINAL_QUOTE_PUNCTUATION = 29; /** @@ -279,6 +300,8 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + + @Deprecated public static interface ECharacterDirection { /** * Directional type L @@ -291,6 +314,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = (byte)LEFT_TO_RIGHT; /** @@ -304,6 +328,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = (byte)RIGHT_TO_LEFT; /** @@ -317,6 +342,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = (byte)EUROPEAN_NUMBER; /** @@ -330,6 +356,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = (byte)EUROPEAN_NUMBER_SEPARATOR; /** @@ -343,6 +370,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = (byte)EUROPEAN_NUMBER_TERMINATOR; /** @@ -356,6 +384,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_ARABIC_NUMBER = (byte)ARABIC_NUMBER; /** @@ -369,6 +398,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = (byte)COMMON_NUMBER_SEPARATOR; /** @@ -382,6 +412,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = (byte)BLOCK_SEPARATOR; /** @@ -395,6 +426,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = (byte)SEGMENT_SEPARATOR; /** @@ -408,6 +440,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_WHITESPACE = (byte)WHITE_SPACE_NEUTRAL; /** @@ -421,6 +454,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_OTHER_NEUTRALS = (byte)OTHER_NEUTRAL; /** @@ -434,6 +468,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = (byte)LEFT_TO_RIGHT_EMBEDDING; /** @@ -447,6 +482,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = (byte)LEFT_TO_RIGHT_OVERRIDE; /** @@ -460,6 +496,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = (byte)RIGHT_TO_LEFT_ARABIC; /** @@ -473,6 +510,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = (byte)RIGHT_TO_LEFT_EMBEDDING; /** @@ -486,6 +524,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = (byte)RIGHT_TO_LEFT_OVERRIDE; /** @@ -499,6 +538,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = (byte)POP_DIRECTIONAL_FORMAT; /** @@ -512,6 +552,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_NON_SPACING_MARK = (byte)DIR_NON_SPACING_MARK; /** @@ -525,6 +566,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = (byte)BOUNDARY_NEUTRAL; /** @@ -539,6 +581,7 @@ class UCharacterEnums { * @draft ICU 3.0 * @deprecated This is a draft API and might change in a future release of ICU. */ + @Deprecated public static final byte DIRECTIONALITY_UNDEFINED = -1; } } diff --git a/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java b/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java index 9142de0a3c0..5b11fe33e16 100644 --- a/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java +++ b/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,7 +140,7 @@ public final class DNSNameService implements NameService { // create new soft reference to our thread context // thrCtxt = new ThreadContext(dirCtxt, nsList); - contextRef.set(new SoftReference(thrCtxt)); + contextRef.set(new SoftReference(thrCtxt)); } return thrCtxt.dirContext(); @@ -193,7 +193,7 @@ public final class DNSNameService implements NameService { Attribute attr = ne.next(); String attrID = attr.getID(); - for (NamingEnumeration e = attr.getAll(); e.hasMoreElements();) { + for (NamingEnumeration e = attr.getAll(); e.hasMoreElements();) { String addr = (String)e.next(); // for canoncical name records do recursive lookup @@ -233,7 +233,7 @@ public final class DNSNameService implements NameService { String domain = AccessController.doPrivileged( new GetPropertyAction("sun.net.spi.nameservice.domain")); if (domain != null && domain.length() > 0) { - domainList = new LinkedList(); + domainList = new LinkedList(); domainList.add(domain); } @@ -282,7 +282,7 @@ public final class DNSNameService implements NameService { throw new Error(nx); } - ArrayList results = null; + ArrayList results = null; UnknownHostException uhe = null; // If host already contains a domain name then just look it up @@ -365,7 +365,7 @@ public final class DNSNameService implements NameService { InetAddress[] addrs = new InetAddress[results.size()]; int count = 0; for (int i=0; i { int index; boolean returnsValue; // or key @@ -202,7 +202,7 @@ public class HeaderParser { public boolean hasNext () { return index keys () { return new ParserIterator (false); } - public Iterator values () { + public Iterator values () { return new ParserIterator (true); } public String toString () { - Iterator k = keys(); + Iterator k = keys(); StringBuffer sbuf = new StringBuffer(); sbuf.append ("{size="+asize+" nkeys="+nkeys+" "); for (int i=0; k.hasNext(); i++) { - String key = (String)k.next(); + String key = k.next(); String val = findValue (i); if (val != null && "".equals (val)) { val = null; diff --git a/jdk/src/share/classes/sun/net/www/MessageHeader.java b/jdk/src/share/classes/sun/net/www/MessageHeader.java index 9f2ad57691c..dbb2cfc7c3a 100644 --- a/jdk/src/share/classes/sun/net/www/MessageHeader.java +++ b/jdk/src/share/classes/sun/net/www/MessageHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.util.Map; import java.util.HashMap; import java.util.List; import java.util.ArrayList; -import java.util.Set; import java.util.Iterator; import java.util.NoSuchElementException; @@ -199,7 +198,8 @@ class MessageHeader { return filterAndAddHeaders(excludeList, null); } - public synchronized Map> filterAndAddHeaders(String[] excludeList, Map> include) { + public synchronized Map> filterAndAddHeaders( + String[] excludeList, Map> include) { boolean skipIt = false; Map> m = new HashMap>(); for (int i = nkeys; --i >= 0;) { @@ -228,15 +228,13 @@ class MessageHeader { } if (include != null) { - Iterator entries = include.entrySet().iterator(); - while (entries.hasNext()) { - Map.Entry entry = (Map.Entry)entries.next(); - List l = (List)m.get(entry.getKey()); + for (Map.Entry> entry: include.entrySet()) { + List l = m.get(entry.getKey()); if (l == null) { - l = new ArrayList(); - m.put((String)entry.getKey(), l); + l = new ArrayList(); + m.put(entry.getKey(), l); } - l.add(entry.getValue()); + l.addAll(entry.getValue()); } } @@ -400,6 +398,7 @@ class MessageHeader { } /** Parse and merge a MIME header from an input stream. */ + @SuppressWarnings("fallthrough") public void mergeHeader(InputStream is) throws java.io.IOException { if (is == null) return; @@ -421,6 +420,7 @@ class MessageHeader { break; case '\t': c = ' '; + /*fall through*/ case ' ': inKey = false; break; diff --git a/jdk/src/share/classes/sun/net/www/MimeTable.java b/jdk/src/share/classes/sun/net/www/MimeTable.java index b8b70fdba91..cab244c7615 100644 --- a/jdk/src/share/classes/sun/net/www/MimeTable.java +++ b/jdk/src/share/classes/sun/net/www/MimeTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,6 @@ package sun.net.www; import java.io.*; -import java.util.Calendar; -import java.util.Date; -import java.text.SimpleDateFormat; -import java.net.URL; import java.net.FileNameMap; import java.util.Hashtable; import java.util.Enumeration; @@ -271,7 +267,7 @@ public class MimeTable implements FileNameMap { String tempFileTemplate = (String)entries.get("temp.file.template"); if (tempFileTemplate != null) { entries.remove("temp.file.template"); - this.tempFileTemplate = tempFileTemplate; + MimeTable.tempFileTemplate = tempFileTemplate; } // now, parse the mime-type spec's @@ -417,10 +413,10 @@ public class MimeTable implements FileNameMap { String user = System.getProperty("user.name"); if (user != null) { tag = "; customized for " + user; - properties.save(os, filePreamble + tag); + properties.store(os, filePreamble + tag); } else { - properties.save(os, filePreamble); + properties.store(os, filePreamble); } } catch (IOException e) { diff --git a/jdk/src/share/classes/sun/net/www/URLConnection.java b/jdk/src/share/classes/sun/net/www/URLConnection.java index 2760acc2081..c4959285d60 100644 --- a/jdk/src/share/classes/sun/net/www/URLConnection.java +++ b/jdk/src/share/classes/sun/net/www/URLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,7 @@ package sun.net.www; import java.net.URL; -import java.net.ContentHandler; import java.util.*; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.BufferedInputStream; -import java.net.UnknownServiceException; /** * A class to represent an active connection to an object @@ -99,7 +94,7 @@ abstract public class URLConnection extends java.net.URLConnection { public Map> getRequestProperties() { if (connected) throw new IllegalStateException("Already connected"); - return Collections.EMPTY_MAP; + return Collections.emptyMap(); } public String getHeaderField(String name) { diff --git a/jdk/src/share/classes/sun/net/www/content/image/gif.java b/jdk/src/share/classes/sun/net/www/content/image/gif.java index d388fad9720..adba0c16d5b 100644 --- a/jdk/src/share/classes/sun/net/www/content/image/gif.java +++ b/jdk/src/share/classes/sun/net/www/content/image/gif.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,8 @@ package sun.net.www.content.image; -import java.net.URL; -import java.net.URLConnection; import java.net.*; import sun.awt.image.*; -import java.io.InputStream; import java.io.IOException; import java.awt.Image; import java.awt.Toolkit; @@ -40,7 +37,7 @@ public class gif extends ContentHandler { return new URLImageSource(urlc); } - public Object getContent(URLConnection urlc, Class[] classes) throws IOException { + public Object getContent(URLConnection urlc, Class[] classes) throws IOException { for (int i = 0; i < classes.length; i++) { if (classes[i].isAssignableFrom(URLImageSource.class)) { return new URLImageSource(urlc); diff --git a/jdk/src/share/classes/sun/net/www/content/image/jpeg.java b/jdk/src/share/classes/sun/net/www/content/image/jpeg.java index 382d36347d4..8076954caeb 100644 --- a/jdk/src/share/classes/sun/net/www/content/image/jpeg.java +++ b/jdk/src/share/classes/sun/net/www/content/image/jpeg.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,8 @@ package sun.net.www.content.image; -import java.net.URL; -import java.net.URLConnection; import java.net.*; import sun.awt.image.*; -import java.io.InputStream; import java.io.IOException; import java.awt.Image; import java.awt.Toolkit; @@ -39,7 +36,7 @@ public class jpeg extends ContentHandler { return new URLImageSource(urlc); } - public Object getContent(URLConnection urlc, Class[] classes) throws IOException { + public Object getContent(URLConnection urlc, Class[] classes) throws IOException { for (int i = 0; i < classes.length; i++) { if (classes[i].isAssignableFrom(URLImageSource.class)) { return new URLImageSource(urlc); diff --git a/jdk/src/share/classes/sun/net/www/content/image/png.java b/jdk/src/share/classes/sun/net/www/content/image/png.java index 607402c87b4..88026de1e25 100644 --- a/jdk/src/share/classes/sun/net/www/content/image/png.java +++ b/jdk/src/share/classes/sun/net/www/content/image/png.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,7 @@ package sun.net.www.content.image; -import java.net.URL; -import java.net.URLConnection; import java.net.*; -import java.io.InputStream; import java.io.IOException; import sun.awt.image.*; import java.awt.Image; @@ -39,7 +36,7 @@ public class png extends ContentHandler { return new URLImageSource(urlc); } - public Object getContent(URLConnection urlc, Class[] classes) throws IOException { + public Object getContent(URLConnection urlc, Class[] classes) throws IOException { for (int i = 0; i < classes.length; i++) { if (classes[i].isAssignableFrom(URLImageSource.class)) { return new URLImageSource(urlc); diff --git a/jdk/src/share/classes/sun/net/www/content/image/x_xbitmap.java b/jdk/src/share/classes/sun/net/www/content/image/x_xbitmap.java index eea24fd2c1b..10e724622db 100644 --- a/jdk/src/share/classes/sun/net/www/content/image/x_xbitmap.java +++ b/jdk/src/share/classes/sun/net/www/content/image/x_xbitmap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ public class x_xbitmap extends ContentHandler { return new URLImageSource(urlc); } - public Object getContent(URLConnection urlc, Class[] classes) throws java.io.IOException { + public Object getContent(URLConnection urlc, Class[] classes) throws java.io.IOException { for (int i = 0; i < classes.length; i++) { if (classes[i].isAssignableFrom(URLImageSource.class)) { return new URLImageSource(urlc); diff --git a/jdk/src/share/classes/sun/net/www/content/image/x_xpixmap.java b/jdk/src/share/classes/sun/net/www/content/image/x_xpixmap.java index 31e83aad91e..3b3ed4006a2 100644 --- a/jdk/src/share/classes/sun/net/www/content/image/x_xpixmap.java +++ b/jdk/src/share/classes/sun/net/www/content/image/x_xpixmap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ public class x_xpixmap extends ContentHandler { return new URLImageSource(urlc); } - public Object getContent(URLConnection urlc, Class[] classes) throws java.io.IOException { + public Object getContent(URLConnection urlc, Class[] classes) throws java.io.IOException { for (int i = 0; i < classes.length; i++) { if (classes[i].isAssignableFrom(URLImageSource.class)) { return new URLImageSource(urlc); diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java index 5d7bb573aab..db9b7b03041 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java @@ -81,7 +81,7 @@ class KeepAliveStream extends MeteredStream implements Hurryable { // NOTE: Don't close super class try { if (expected > count) { - long nskip = (long) (expected - count); + long nskip = expected - count; if (nskip <= available()) { long n = 0; while (n < nskip) { diff --git a/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java b/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java index 41c6b8d2894..03470634a37 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java +++ b/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java @@ -281,7 +281,7 @@ public class GopherClient extends NetworkClient implements Runnable { ps.print("\n\n

"); ps.print(title); ps.print("

\n"); - DataInputStream ds = new DataInputStream(serverInput); + BufferedReader ds = new BufferedReader(new InputStreamReader(serverInput)); String s; while ((s = ds.readLine()) != null) { int len = s.length(); diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheImpl.java b/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheImpl.java index c2ebf429922..45a5a0eaf9b 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheImpl.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,8 @@ package sun.net.www.protocol.http; -import java.io.IOException; -import java.net.URL; -import java.util.Hashtable; import java.util.LinkedList; import java.util.ListIterator; -import java.util.Enumeration; import java.util.HashMap; /** @@ -38,13 +34,13 @@ import java.util.HashMap; */ public class AuthCacheImpl implements AuthCache { - HashMap hashtable; + HashMap> hashtable; public AuthCacheImpl () { - hashtable = new HashMap (); + hashtable = new HashMap>(); } - public void setMap (HashMap map) { + public void setMap (HashMap> map) { hashtable = map; } @@ -52,21 +48,21 @@ public class AuthCacheImpl implements AuthCache { // is the path field of AuthenticationInfo public synchronized void put (String pkey, AuthCacheValue value) { - LinkedList list = (LinkedList) hashtable.get (pkey); + LinkedList list = hashtable.get (pkey); String skey = value.getPath(); if (list == null) { - list = new LinkedList (); - hashtable.put (pkey, list); + list = new LinkedList(); + hashtable.put(pkey, list); } // Check if the path already exists or a super-set of it exists - ListIterator iter = list.listIterator(); + ListIterator iter = list.listIterator(); while (iter.hasNext()) { AuthenticationInfo inf = (AuthenticationInfo)iter.next(); if (inf.path == null || inf.path.startsWith (skey)) { iter.remove (); } } - iter.add (value); + iter.add(value); } // get a value from map checking both primary @@ -74,7 +70,7 @@ public class AuthCacheImpl implements AuthCache { public synchronized AuthCacheValue get (String pkey, String skey) { AuthenticationInfo result = null; - LinkedList list = (LinkedList) hashtable.get (pkey); + LinkedList list = hashtable.get (pkey); if (list == null || list.size() == 0) { return null; } @@ -82,7 +78,7 @@ public class AuthCacheImpl implements AuthCache { // list should contain only one element return (AuthenticationInfo)list.get (0); } - ListIterator iter = list.listIterator(); + ListIterator iter = list.listIterator(); while (iter.hasNext()) { AuthenticationInfo inf = (AuthenticationInfo)iter.next(); if (skey.startsWith (inf.path)) { @@ -93,7 +89,7 @@ public class AuthCacheImpl implements AuthCache { } public synchronized void remove (String pkey, AuthCacheValue entry) { - LinkedList list = (LinkedList) hashtable.get (pkey); + LinkedList list = hashtable.get (pkey); if (list == null) { return; } @@ -101,7 +97,7 @@ public class AuthCacheImpl implements AuthCache { list.clear(); return; } - ListIterator iter = list.listIterator (); + ListIterator iter = list.listIterator (); while (iter.hasNext()) { AuthenticationInfo inf = (AuthenticationInfo)iter.next(); if (entry.equals(inf)) { diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index eee2579d64f..390898292f0 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,7 +122,7 @@ public class AuthenticationHeader { this.dontUseNegotiate = dontUseNegotiate; rsp = response; this.hdrname = hdrname; - schemes = new HashMap(); + schemes = new HashMap(); parse(); } @@ -136,7 +136,7 @@ public class AuthenticationHeader { HeaderParser parser; } - HashMap schemes; + HashMap schemes; /* Iterate through each header line, and then within each line. * If multiple entries exist for a particular scheme (unlikely) @@ -144,11 +144,11 @@ public class AuthenticationHeader { * preferred scheme that we support will be used. */ private void parse () { - Iterator iter = rsp.multiValueIterator (hdrname); + Iterator iter = rsp.multiValueIterator(hdrname); while (iter.hasNext()) { - String raw = (String)iter.next(); - HeaderParser hp = new HeaderParser (raw); - Iterator keys = hp.keys(); + String raw = iter.next(); + HeaderParser hp = new HeaderParser(raw); + Iterator keys = hp.keys(); int i, lastSchemeIndex; for (i=0, lastSchemeIndex = -1; keys.hasNext(); i++) { keys.next(); @@ -164,7 +164,7 @@ public class AuthenticationHeader { if (i > lastSchemeIndex) { HeaderParser hpn = hp.subsequence (lastSchemeIndex, i); String scheme = hpn.findKey(0); - schemes.put (scheme, new SchemeMapValue (hpn, raw)); + schemes.put(scheme, new SchemeMapValue (hpn, raw)); } } @@ -172,10 +172,10 @@ public class AuthenticationHeader { * negotiate -> kerberos -> digest -> ntlm -> basic */ SchemeMapValue v = null; - if (authPref == null || (v=(SchemeMapValue)schemes.get (authPref)) == null) { + if (authPref == null || (v=schemes.get (authPref)) == null) { if(v == null && !dontUseNegotiate) { - SchemeMapValue tmp = (SchemeMapValue)schemes.get("negotiate"); + SchemeMapValue tmp = schemes.get("negotiate"); if(tmp != null) { if(hci == null || !NegotiateAuthentication.isSupported(new HttpCallerInfo(hci, "Negotiate"))) { tmp = null; @@ -185,7 +185,7 @@ public class AuthenticationHeader { } if(v == null && !dontUseNegotiate) { - SchemeMapValue tmp = (SchemeMapValue)schemes.get("kerberos"); + SchemeMapValue tmp = schemes.get("kerberos"); if(tmp != null) { // the Kerberos scheme is only observed in MS ISA Server. In // fact i think it's a Kerberos-mechnism-only Negotiate. @@ -205,9 +205,9 @@ public class AuthenticationHeader { } if(v == null) { - if ((v=(SchemeMapValue)schemes.get ("digest")) == null) { - if (((v=(SchemeMapValue)schemes.get("ntlm"))==null)) { - v = (SchemeMapValue)schemes.get ("basic"); + if ((v=schemes.get ("digest")) == null) { + if (((v=schemes.get("ntlm"))==null)) { + v = schemes.get ("basic"); } } } diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 4b297b8ba59..e14ce8d810d 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -25,6 +25,7 @@ package sun.net.www.protocol.http; +import java.util.Arrays; import java.net.URL; import java.net.URLConnection; import java.net.ProtocolException; @@ -229,9 +230,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { bufSize4ES = 4096; // use the default } - allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged( + allowRestrictedHeaders = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( - "sun.net.http.allowRestrictedHeaders"))).booleanValue(); + "sun.net.http.allowRestrictedHeaders")).booleanValue(); if (!allowRestrictedHeaders) { restrictedHeaderSet = new HashSet(restrictedHeaders.length); for (int i=0; i < restrictedHeaders.length; i++) { @@ -289,6 +290,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * REMIND: backwards compatibility with JDK 1.1. Should be * eliminated for JDK 2.0. */ + @Deprecated private static HttpAuthenticator defaultAuth; /* all the headers we send @@ -750,6 +752,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * @deprecated. Use java.net.Authenticator.setDefault() instead. */ + @Deprecated public static void setDefaultAuthenticator(HttpAuthenticator a) { defaultAuth = a; } @@ -830,8 +833,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { InetAddress a1 = InetAddress.getByName(h1); InetAddress a2 = InetAddress.getByName(h2); result[0] = a1.equals(a2); - } catch(UnknownHostException e) { - } catch(SecurityException e) { + } catch(UnknownHostException | SecurityException e) { } return null; } @@ -1336,9 +1338,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { // Read comments labeled "Failed Negotiate" for details. boolean dontUseNegotiate = false; - Iterator iter = responses.multiValueIterator("Proxy-Authenticate"); + Iterator iter = responses.multiValueIterator("Proxy-Authenticate"); while (iter.hasNext()) { - String value = ((String)iter.next()).trim(); + String value = iter.next().trim(); if (value.equalsIgnoreCase("Negotiate") || value.equalsIgnoreCase("Kerberos")) { if (!inNegotiateProxy) { @@ -1414,9 +1416,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { // Read comments labeled "Failed Negotiate" for details. boolean dontUseNegotiate = false; - Iterator iter = responses.multiValueIterator("WWW-Authenticate"); + Iterator iter = responses.multiValueIterator("WWW-Authenticate"); while (iter.hasNext()) { - String value = ((String)iter.next()).trim(); + String value = iter.next().trim(); if (value.equalsIgnoreCase("Negotiate") || value.equalsIgnoreCase("Kerberos")) { if (!inNegotiate) { @@ -1585,9 +1587,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { // HttpsURLConnection instance saved in // DelegateHttpsURLConnection uconn = (URLConnection)this.getClass().getField("httpsURLConnection").get(this); - } catch (IllegalAccessException iae) { - // ignored; use 'this' - } catch (NoSuchFieldException nsfe) { + } catch (IllegalAccessException | + NoSuchFieldException e) { // ignored; use 'this' } } @@ -1786,9 +1787,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { if (respCode == HTTP_PROXY_AUTH) { // Read comments labeled "Failed Negotiate" for details. boolean dontUseNegotiate = false; - Iterator iter = responses.multiValueIterator("Proxy-Authenticate"); + Iterator iter = responses.multiValueIterator("Proxy-Authenticate"); while (iter.hasNext()) { - String value = ((String)iter.next()).trim(); + String value = iter.next().trim(); if (value.equalsIgnoreCase("Negotiate") || value.equalsIgnoreCase("Kerberos")) { if (!inNegotiateProxy) { @@ -1938,6 +1939,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * Gets the authentication for an HTTP proxy, and applies it to * the connection. */ + @SuppressWarnings("fallthrough") private AuthenticationInfo getHttpProxyAuthentication (AuthenticationHeader authhdr) { /* get authorization from authenticator */ AuthenticationInfo ret = null; @@ -2004,13 +2006,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } break; case NTLM: - if (NTLMAuthenticationProxy.proxy.supported) { + if (NTLMAuthenticationProxy.supported) { /* tryTransparentNTLMProxy will always be true the first * time around, but verify that the platform supports it * otherwise don't try. */ if (tryTransparentNTLMProxy) { tryTransparentNTLMProxy = - NTLMAuthenticationProxy.proxy.supportsTransparentAuth; + NTLMAuthenticationProxy.supportsTransparentAuth; } a = null; if (tryTransparentNTLMProxy) { @@ -2043,6 +2045,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { break; case UNKNOWN: logger.finest("Unknown/Unsupported authentication scheme: " + scheme); + /*fall through*/ default: throw new AssertionError("should not reach here"); } @@ -2080,6 +2083,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * @param authHdr the AuthenticationHeader which tells what auth scheme is * prefered. */ + @SuppressWarnings("fallthrough") private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) { /* get authorization from authenticator */ AuthenticationInfo ret = null; @@ -2150,7 +2154,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } break; case NTLM: - if (NTLMAuthenticationProxy.proxy.supported) { + if (NTLMAuthenticationProxy.supported) { URL url1; try { url1 = new URL (url, "/"); /* truncate the path */ @@ -2163,13 +2167,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * otherwise don't try. */ if (tryTransparentNTLMServer) { tryTransparentNTLMServer = - NTLMAuthenticationProxy.proxy.supportsTransparentAuth; + NTLMAuthenticationProxy.supportsTransparentAuth; /* If the platform supports transparent authentication * then check if we are in a secure environment * whether, or not, we should try transparent authentication.*/ if (tryTransparentNTLMServer) { tryTransparentNTLMServer = - NTLMAuthenticationProxy.proxy.isTrustedSite(url); + NTLMAuthenticationProxy.isTrustedSite(url); } } a = null; @@ -2198,6 +2202,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { break; case UNKNOWN: logger.finest("Unknown/Unsupported authentication scheme: " + scheme); + /*fall through*/ default: throw new AssertionError("should not reach here"); } @@ -2745,14 +2750,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * The cookies in the requests message headers may have * been modified. Use the saved user cookies instead. */ - Map userCookiesMap = null; + Map> userCookiesMap = null; if (userCookies != null || userCookies2 != null) { - userCookiesMap = new HashMap(); + userCookiesMap = new HashMap<>(); if (userCookies != null) { - userCookiesMap.put("Cookie", userCookies); + userCookiesMap.put("Cookie", Arrays.asList(userCookies)); } if (userCookies2 != null) { - userCookiesMap.put("Cookie2", userCookies2); + userCookiesMap.put("Cookie2", Arrays.asList(userCookies2)); } } return requests.filterAndAddHeaders(EXCLUDE_HEADERS2, userCookiesMap); diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/Negotiator.java b/jdk/src/share/classes/sun/net/www/protocol/http/Negotiator.java index 522d6fbf72e..32446f63f70 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/Negotiator.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/Negotiator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,8 +45,8 @@ public abstract class Negotiator { // Makes NegotiatorImpl, and the security classes it references, a // runtime dependency rather than a static one. - Class clazz; - Constructor c; + Class clazz; + Constructor c; try { clazz = Class.forName("sun.net.www.protocol.http.spnego.NegotiatorImpl", true, null); c = clazz.getConstructor(HttpCallerInfo.class); diff --git a/jdk/src/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java index ecc75efb5b3..88c62594008 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,11 +221,11 @@ public abstract class AbstractDelegateHttpsURLConnection extends */ public java.security.cert.Certificate[] getLocalCertificates() { if (cachedResponse != null) { - List l = ((SecureCacheResponse)cachedResponse).getLocalCertificateChain(); + List l = ((SecureCacheResponse)cachedResponse).getLocalCertificateChain(); if (l == null) { return null; } else { - return (java.security.cert.Certificate[])l.toArray(); + return l.toArray(new java.security.cert.Certificate[0]); } } if (http == null) { @@ -243,11 +243,11 @@ public abstract class AbstractDelegateHttpsURLConnection extends public java.security.cert.Certificate[] getServerCertificates() throws SSLPeerUnverifiedException { if (cachedResponse != null) { - List l = ((SecureCacheResponse)cachedResponse).getServerCertificateChain(); + List l = ((SecureCacheResponse)cachedResponse).getServerCertificateChain(); if (l == null) { return null; } else { - return (java.security.cert.Certificate[])l.toArray(); + return l.toArray(new java.security.cert.Certificate[0]); } } diff --git a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java index cffc12c7260..c83860b14c6 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -529,7 +529,7 @@ final class HttpsClient extends HttpClient new BufferedOutputStream(serverSocket.getOutputStream()), false, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding+" encoding not found", e); + throw new InternalError(encoding+" encoding not found"); } // check URL spoofing if it has not been checked under handshaking @@ -623,7 +623,7 @@ final class HttpsClient extends HttpClient */ @Override public void closeIdleConnection() { - HttpClient http = (HttpClient) kac.get(url, sslSocketFactory); + HttpClient http = kac.get(url, sslSocketFactory); if (http != null) { http.closeServer(); } @@ -681,8 +681,7 @@ final class HttpsClient extends HttpClient // return the X500Principal of the end-entity cert. java.security.cert.Certificate[] certs = session.getPeerCertificates(); - principal = (X500Principal) - ((X509Certificate)certs[0]).getSubjectX500Principal(); + principal = ((X509Certificate)certs[0]).getSubjectX500Principal(); } return principal; } @@ -703,8 +702,7 @@ final class HttpsClient extends HttpClient java.security.cert.Certificate[] certs = session.getLocalCertificates(); if (certs != null) { - principal = (X500Principal) - ((X509Certificate)certs[0]).getSubjectX500Principal(); + principal = ((X509Certificate)certs[0]).getSubjectX500Principal(); } } return principal; diff --git a/jdk/src/share/classes/sun/net/www/protocol/mailto/Handler.java b/jdk/src/share/classes/sun/net/www/protocol/mailto/Handler.java index 10fe6849f79..13076fc4eca 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/mailto/Handler.java +++ b/jdk/src/share/classes/sun/net/www/protocol/mailto/Handler.java @@ -139,6 +139,20 @@ public class Handler extends URLStreamHandler { } if (nogood) throw new RuntimeException("No email address"); - setURL(u, protocol, host, port, file, null); + setURLHandler(u, protocol, host, port, file, null); + } + + /** + * This method is used to suppress the deprecated warning + * + * @param u the URL to receive the result of parsing the spec + * @param spec the URL string to parse + * @param start the character position to start parsing at. This is + * just past the ':'. + * @param limit the character position to stop parsing at. + */ + @SuppressWarnings("deprecation") + private void setURLHandler(URL u, String protocol, String host, int port, String file, String ref) { + setURL(u,protocol,host,port,file,null); } } diff --git a/jdk/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java b/jdk/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java index 6c6bdbf85d5..ad62c582691 100644 --- a/jdk/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007,2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ import java.security.AccessController; */ class DefaultDatagramSocketImplFactory { - static Class prefixImplClass = null; + static Class prefixImplClass = null; static { String prefix = null; diff --git a/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java b/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java index cd00b0bd887..20bc6fbc394 100644 --- a/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java +++ b/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007,2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,8 +54,10 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl protected native int getTimeToLive() throws IOException; + @Deprecated protected native void setTTL(byte ttl) throws IOException; + @Deprecated protected native byte getTTL() throws IOException; protected native void join(InetAddress inetaddr, NetworkInterface netIf) diff --git a/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java b/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java index 3695b5d368b..66430d40495 100644 --- a/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java +++ b/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,7 +149,7 @@ public class ResolverConfigurationImpl sl = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction>() { public LinkedList run() { - LinkedList ll; + LinkedList ll; // first try search keyword (max 6 domains) ll = resolvconf("search", 6, 1); @@ -173,7 +173,7 @@ public class ResolverConfigurationImpl String localDomain = localDomain0(); if (localDomain != null && localDomain.length() > 0) { - sl = new LinkedList(); + sl = new LinkedList(); sl.add(localDomain); return sl; } @@ -198,7 +198,7 @@ public class ResolverConfigurationImpl } // no local domain so try fallback (RPC) domain or - // hostname + // hostName sl = new LinkedList<>(); String domain = fallbackDomain0(); @@ -216,22 +216,26 @@ public class ResolverConfigurationImpl opts = new OptionsImpl(); } + @SuppressWarnings("unchecked") public List searchlist() { synchronized (lock) { loadConfig(); // List is mutable so return a shallow copy - return (List)searchlist.clone(); + return (List)searchlist.clone(); } } + @SuppressWarnings("unchecked") public List nameservers() { synchronized (lock) { loadConfig(); // List is mutable so return a shallow copy - return (List)nameservers.clone(); - } + + return (List)nameservers.clone(); + + } } public Options options() { diff --git a/jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java b/jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java index c8605c8c337..43ce6f27744 100644 --- a/jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ import java.security.PrivilegedAction; class DefaultDatagramSocketImplFactory { - static Class prefixImplClass = null; + static Class prefixImplClass = null; /* the windows version. */ private static float version; diff --git a/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 7533dea13fa..57a12a8885a 100644 --- a/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007,2011 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.net; import java.io.IOException; -import java.io.FileDescriptor; import sun.misc.SharedSecrets; import sun.misc.JavaIOFileDescriptorAccess; @@ -215,11 +214,12 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl throw new IOException("Method not implemented!"); } - + @Deprecated protected void setTTL(byte ttl) throws IOException { throw new IOException("Method not implemented!"); } + @Deprecated protected byte getTTL() throws IOException { throw new IOException("Method not implemented!"); } diff --git a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java index d8e4ec54c20..0729d76ada4 100644 --- a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -133,8 +133,10 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl protected native int getTimeToLive() throws IOException; + @Deprecated protected native void setTTL(byte ttl) throws IOException; + @Deprecated protected native byte getTTL() throws IOException; protected native void join(InetAddress inetaddr, NetworkInterface netIf) diff --git a/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java b/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java index 79708856036..eb7405de9d3 100644 --- a/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java +++ b/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java @@ -57,8 +57,8 @@ public class ResolverConfigurationImpl private static String os_nameservers; // Cached lists - private static LinkedList searchlist; - private static LinkedList nameservers; + private static LinkedList searchlist; + private static LinkedList nameservers; // Parse string that consists of token delimited by space or commas // and return LinkedHashMap @@ -111,21 +111,23 @@ public class ResolverConfigurationImpl opts = new OptionsImpl(); } + @SuppressWarnings("unchecked") // clone() public List searchlist() { synchronized (lock) { loadConfig(); // List is mutable so return a shallow copy - return (List)searchlist.clone(); + return (List)searchlist.clone(); } } + @SuppressWarnings("unchecked") // clone() public List nameservers() { synchronized (lock) { loadConfig(); // List is mutable so return a shallow copy - return (List)nameservers.clone(); + return (List)nameservers.clone(); } } diff --git a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java index c04bef8fcad..80bd9d1a66a 100644 --- a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,7 +148,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { private Permission getPermission(JarFile jarFile) { try { - URLConnection uc = (URLConnection)getConnection(jarFile); + URLConnection uc = getConnection(jarFile); if (uc != null) return uc.getPermission(); } catch (IOException ioe) { From 51763c43f7ffef9f5e27355437ed0e8630da7290 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 16 Sep 2011 16:18:46 -0700 Subject: [PATCH 094/214] 7091528: javadoc attempts to parse .class files Reviewed-by: darcy --- .../com/sun/tools/javadoc/JavadocTool.java | 29 +++----- .../javadoc/parser/7091528/T7091528.java | 71 +++++++++++++++++++ .../tools/javadoc/parser/7091528/p/C1.java | 28 ++++++++ .../tools/javadoc/parser/7091528/p/q/C2.java | 28 ++++++++ 4 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 langtools/test/tools/javadoc/parser/7091528/T7091528.java create mode 100644 langtools/test/tools/javadoc/parser/7091528/p/C1.java create mode 100644 langtools/test/tools/javadoc/parser/7091528/p/q/C2.java diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java index cac7f991354..12096869f4f 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,24 +257,15 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { for (String p: excludedPackages) includedPackages.put(p, false); - if (docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { - searchSubPackages(subPackages, - includedPackages, - packages, packageFiles, - StandardLocation.SOURCE_PATH, - EnumSet.of(JavaFileObject.Kind.SOURCE)); - searchSubPackages(subPackages, - includedPackages, - packages, packageFiles, - StandardLocation.CLASS_PATH, - EnumSet.of(JavaFileObject.Kind.CLASS)); - } else { - searchSubPackages(subPackages, - includedPackages, - packages, packageFiles, - StandardLocation.CLASS_PATH, - EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS)); - } + StandardLocation path = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) + ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; + + searchSubPackages(subPackages, + includedPackages, + packages, packageFiles, + path, + EnumSet.of(JavaFileObject.Kind.SOURCE)); + return packageFiles; } diff --git a/langtools/test/tools/javadoc/parser/7091528/T7091528.java b/langtools/test/tools/javadoc/parser/7091528/T7091528.java new file mode 100644 index 00000000000..4e06a3beb74 --- /dev/null +++ b/langtools/test/tools/javadoc/parser/7091528/T7091528.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 7091528 + * @summary javadoc attempts to parse .class files + * @compile p/C1.java p/q/C2.java + * @run main T7091528 + */ + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; + +public class T7091528 { + public static void main(String... args) { + new T7091528().run(); + } + + void run() { + File testSrc = new File(System.getProperty("test.src")); + File testClasses = new File(System.getProperty("test.classes")); + String[] args = { + "-d", ".", + "-sourcepath", testClasses + File.pathSeparator + testSrc, + "-subpackages", + "p" + }; + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + String doclet = com.sun.tools.doclets.standard.Standard.class.getName(); + int rc = com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw, doclet, args); + pw.close(); + + String out = sw.toString(); + if (!out.isEmpty()) { + System.err.println(out); + } + + if (rc != 0) + System.err.println("javadoc failed: exit code = " + rc); + + if (out.matches("(?s).*p/[^ ]+\\.class.*")) + throw new Error("reading .class files"); + + if (!new File("index.html").exists()) + throw new Error("index.html not found"); + } +} diff --git a/langtools/test/tools/javadoc/parser/7091528/p/C1.java b/langtools/test/tools/javadoc/parser/7091528/p/C1.java new file mode 100644 index 00000000000..7d8ad26643f --- /dev/null +++ b/langtools/test/tools/javadoc/parser/7091528/p/C1.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +/** This is class C1. */ +public class C1 { } + diff --git a/langtools/test/tools/javadoc/parser/7091528/p/q/C2.java b/langtools/test/tools/javadoc/parser/7091528/p/q/C2.java new file mode 100644 index 00000000000..91b8d96c2c7 --- /dev/null +++ b/langtools/test/tools/javadoc/parser/7091528/p/q/C2.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p.q; + +/** This is class p.q.C2. */ +public class C2 { } + From d381d4b0b47f447ce5e9be6738d9dcf4b7ef1c46 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 16 Sep 2011 16:21:20 -0700 Subject: [PATCH 095/214] 7071904: 4/4 HotSpot: Full Debug Symbols Add support for .debuginfo files for HSX libraries. Reviewed-by: poonam, dholmes, never --- hotspot/make/Makefile | 14 +++ hotspot/make/linux/Makefile | 1 + hotspot/make/linux/makefiles/build_vm_def.sh | 10 +- hotspot/make/linux/makefiles/buildtree.make | 4 + hotspot/make/linux/makefiles/defs.make | 77 ++++++++++++++- hotspot/make/linux/makefiles/gcc.make | 26 +++++ hotspot/make/linux/makefiles/jsig.make | 23 ++++- hotspot/make/linux/makefiles/product.make | 11 +-- hotspot/make/linux/makefiles/saproc.make | 23 ++++- hotspot/make/linux/makefiles/vm.make | 34 ++++++- hotspot/make/solaris/Makefile | 3 +- .../make/solaris/makefiles/build_vm_def.sh | 10 ++ hotspot/make/solaris/makefiles/buildtree.make | 4 + hotspot/make/solaris/makefiles/defs.make | 97 ++++++++++++++++++- hotspot/make/solaris/makefiles/dtrace.make | 65 ++++++++++++- hotspot/make/solaris/makefiles/jsig.make | 23 ++++- hotspot/make/solaris/makefiles/mapfile-vers | 5 +- hotspot/make/solaris/makefiles/product.make | 5 +- hotspot/make/solaris/makefiles/saproc.make | 21 +++- .../make/solaris/makefiles/sparcWorks.make | 18 +++- hotspot/make/solaris/makefiles/vm.make | 49 ++++++++-- 21 files changed, 488 insertions(+), 35 deletions(-) create mode 100644 hotspot/make/solaris/makefiles/build_vm_def.sh diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 64f9f0b60c3..dd20eeee3bf 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -346,6 +346,20 @@ $(EXPORT_SERVER_DIR)/%.so: $(C2_DIR)/%.so $(install-file) $(EXPORT_SERVER_DIR)/64/%.so: $(C2_DIR)/%.so $(install-file) + +# Debug info for shared library +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo + $(install-file) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo + $(install-file) +$(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo + $(install-file) +$(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_DIR)/%.debuginfo + $(install-file) +$(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo + $(install-file) +$(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_DIR)/%.debuginfo + $(install-file) endif endif diff --git a/hotspot/make/linux/Makefile b/hotspot/make/linux/Makefile index d79d4fbfd02..22dcd5369d2 100644 --- a/hotspot/make/linux/Makefile +++ b/hotspot/make/linux/Makefile @@ -210,6 +210,7 @@ TARGETS_SHARK = $(addsuffix shark,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) +BUILDTREE_VARS += OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS) diff --git a/hotspot/make/linux/makefiles/build_vm_def.sh b/hotspot/make/linux/makefiles/build_vm_def.sh index fb9a0d57a78..ea81ff6c22f 100644 --- a/hotspot/make/linux/makefiles/build_vm_def.sh +++ b/hotspot/make/linux/makefiles/build_vm_def.sh @@ -7,6 +7,10 @@ else NM=nm fi -$NM --defined-only $* | awk ' - { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" } - ' +$NM --defined-only $* \ + | awk '{ + if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" + if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" + if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";" + }' \ + | sort -u diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make index becd97477c9..f8a1e885c5f 100644 --- a/hotspot/make/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -233,6 +233,10 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ + [ -n "$(OBJCOPY)" ] && \ + echo && echo "OBJCOPY = $(OBJCOPY)"; \ + [ -n "$(STRIP_POLICY)" ] && \ + echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \ [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ echo && \ echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ diff --git a/hotspot/make/linux/makefiles/defs.make b/hotspot/make/linux/makefiles/defs.make index 5257dd2a70d..c3279748cc8 100644 --- a/hotspot/make/linux/makefiles/defs.make +++ b/hotspot/make/linux/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,67 @@ ifeq ($(ARCH), ppc) HS_ARCH = ppc endif +# determine if HotSpot is being built in JDK6 or earlier version +JDK6_OR_EARLIER=0 +ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1" + # if the longer variable names (newer build style) are set, then check those + ifeq "$(shell expr \( $(JDK_MAJOR_VERSION) = 1 \& $(JDK_MINOR_VERSION) \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +else + # the longer variables aren't set so check the shorter variable names + ifeq "$(shell expr \( '$(JDK_MAJOR_VER)' = 1 \& '$(JDK_MINOR_VER)' \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +endif + +ifeq ($(JDK6_OR_EARLIER),0) + # Full Debug Symbols is supported on JDK7 or newer + + # Default OBJCOPY comes from GNU Binutils on Linux: + DEF_OBJCOPY=/usr/bin/objcopy + ifdef CROSS_COMPILE_ARCH + # don't try to generate .debuginfo files when cross compiling + _JUNK_ := $(shell \ + echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \ + "skipping .debuginfo generation.") + OBJCOPY= + else + OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY)) + ifneq ($(ALT_OBJCOPY),) + _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)") + # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path + OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY)) + endif + endif + + ifeq ($(OBJCOPY),) + _JUNK_ := $(shell \ + echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.") + else + _JUNK_ := $(shell \ + echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.") + + # Library stripping policies for .debuginfo configs: + # all_strip - strips everything from the library + # min_strip - strips most stuff from the library; leaves minimum symbols + # no_strip - does not strip the library at all + # + # Oracle security policy requires "all_strip". A waiver was granted on + # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE. + # + DEF_STRIP_POLICY="min_strip" + ifeq ($(ALT_STRIP_POLICY),) + STRIP_POLICY=$(DEF_STRIP_POLICY) + else + STRIP_POLICY=$(ALT_STRIP_POLICY) + endif + + _JUNK_ := $(shell \ + echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)") + endif +endif + JDK_INCLUDE_SUBDIR=linux # FIXUP: The subdirectory for a debug build is NOT the same on all platforms @@ -123,18 +184,28 @@ EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.so EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.so +ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo +endif + EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client ifndef BUILD_CLIENT_ONLY EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.so + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo + endif endif ifneq ($(ZERO_BUILD), true) ifeq ($(ARCH_DATA_MODEL), 32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.so + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo + endif endif endif @@ -144,6 +215,10 @@ ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so \ $(EXPORT_LIB_DIR)/sa-jdi.jar ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so \ $(EXPORT_LIB_DIR)/sa-jdi.jar +ifneq ($(OBJCOPY),) + ADD_SA_BINARIES/x86 += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo + ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo +endif ADD_SA_BINARIES/ppc = ADD_SA_BINARIES/ia64 = ADD_SA_BINARIES/arm = diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index fa9e29cb36b..e36cec66f76 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -225,6 +225,26 @@ ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) DEBUG_CFLAGS += -gstabs endif +ifneq ($(OBJCOPY),) + FASTDEBUG_CFLAGS/ia64 = -g + FASTDEBUG_CFLAGS/amd64 = -g + FASTDEBUG_CFLAGS/arm = -g + FASTDEBUG_CFLAGS/ppc = -g + FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) + ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),) + FASTDEBUG_CFLAGS += -gstabs + endif + + OPT_CFLAGS/ia64 = -g + OPT_CFLAGS/amd64 = -g + OPT_CFLAGS/arm = -g + OPT_CFLAGS/ppc = -g + OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH)) + ifeq ($(OPT_CFLAGS/$(BUILDARCH)),) + OPT_CFLAGS += -gstabs + endif +endif + # DEBUG_BINARIES overrides everything, use full -g debug information ifeq ($(DEBUG_BINARIES), true) DEBUG_CFLAGS = -g @@ -242,3 +262,9 @@ endif ifdef MINIMIZE_RAM_USAGE CFLAGS += -DMINIMIZE_RAM_USAGE endif + +ifdef CROSS_COMPILE_ARCH + STRIP = $(ALT_COMPILER_PATH)/strip +else + STRIP = strip +endif diff --git a/hotspot/make/linux/makefiles/jsig.make b/hotspot/make/linux/makefiles/jsig.make index 18f65d9f0f0..9408e4961d4 100644 --- a/hotspot/make/linux/makefiles/jsig.make +++ b/hotspot/make/linux/makefiles/jsig.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,9 +31,13 @@ LIBJSIG = lib$(JSIG).so JSIG_G = $(JSIG)$(G_SUFFIX) LIBJSIG_G = lib$(JSIG_G).so +LIBJSIG_DEBUGINFO = lib$(JSIG).debuginfo +LIBJSIG_G_DEBUGINFO = lib$(JSIG_G).debuginfo + JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm -DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO) LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig @@ -54,9 +58,24 @@ $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE) $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl $(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJSIG_G_DEBUGINFO) ] || { ln -s $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO); } +endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" + $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" .PHONY: install_jsig diff --git a/hotspot/make/linux/makefiles/product.make b/hotspot/make/linux/makefiles/product.make index 379685f5f51..981a9be0ccc 100644 --- a/hotspot/make/linux/makefiles/product.make +++ b/hotspot/make/linux/makefiles/product.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -46,13 +46,10 @@ VERSION = optimized # use -g to strip library as -x will discard its symbol table; -x is fine for # executables. -ifdef CROSS_COMPILE_ARCH - STRIP = $(ALT_COMPILER_PATH)/strip -else - STRIP = strip -endif +# Note: these macros are not used in .debuginfo configs STRIP_LIBJVM = $(STRIP) -g $@ || exit 1; STRIP_AOUT = $(STRIP) -x $@ || exit 1; -# Don't strip in VM build; JDK build will strip libraries later +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. # LINK_LIB.CC/POST_HOOK += $(STRIP_$(LINK_INTO)) diff --git a/hotspot/make/linux/makefiles/saproc.make b/hotspot/make/linux/makefiles/saproc.make index 68ec2378ad4..4bca4538f9b 100644 --- a/hotspot/make/linux/makefiles/saproc.make +++ b/hotspot/make/linux/makefiles/saproc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,9 @@ LIBSAPROC = lib$(SAPROC).so SAPROC_G = $(SAPROC)$(G_SUFFIX) LIBSAPROC_G = lib$(SAPROC_G).so +LIBSAPROC_DEBUGINFO = lib$(SAPROC).debuginfo +LIBSAPROC_G_DEBUGINFO = lib$(SAPROC_G).debuginfo + AGENT_DIR = $(GAMMADIR)/agent SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family) @@ -45,7 +48,8 @@ SASRCFILES = $(SASRCDIR)/salibelf.c \ SAMAPFILE = $(SASRCDIR)/mapfile -DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO) # DEBUG_BINARIES overrides everything, use full -g debug information ifeq ($(DEBUG_BINARIES), true) @@ -82,10 +86,25 @@ $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) -o $@ \ -lthread_db $(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBSAPROC_G_DEBUGINFO) ] || { ln -s $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO); } +endif install_saproc: $(BUILDLIBSAPROC) $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test -f $(LIBSAPROC_DEBUGINFO) && \ + cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ fi diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index 83c51b1ccff..d40678202e2 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -60,10 +60,16 @@ Src_Dirs_I += $(GENERATED) # The order is important for the precompiled headers to work. INCLUDES += $(PRECOMPILED_HEADER_DIR:%=-I%) $(Src_Dirs_I:%=-I%) -ifeq (${VERSION}, debug) +# SYMFLAG is used by {jsig,saproc}.make +ifneq ($(OBJCOPY),) + # always build with debug info when we can create .debuginfo files SYMFLAG = -g else - SYMFLAG = + ifeq (${VERSION}, debug) + SYMFLAG = -g + else + SYMFLAG = + endif endif # HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined @@ -124,6 +130,9 @@ JVM = jvm LIBJVM = lib$(JVM).so LIBJVM_G = lib$(JVM)$(G_SUFFIX).so +LIBJVM_DEBUGINFO = lib$(JVM).debuginfo +LIBJVM_G_DEBUGINFO = lib$(JVM)$(G_SUFFIX).debuginfo + SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt SOURCE_PATHS=\ @@ -307,11 +316,30 @@ $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT) fi \ fi \ } +ifeq ($(CROSS_COMPILE_ARCH),) + ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + $(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO) + endif +endif -DEST_JVM = $(JDK_LIBDIR)/$(VM_SUBDIR)/$(LIBJVM) +DEST_SUBDIR = $(JDK_LIBDIR)/$(VM_SUBDIR) +DEST_JVM = $(DEST_SUBDIR)/$(LIBJVM) +DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" + $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" #---------------------------------------------------------------------- diff --git a/hotspot/make/solaris/Makefile b/hotspot/make/solaris/Makefile index b3af8513a73..e1f32c4cf35 100644 --- a/hotspot/make/solaris/Makefile +++ b/hotspot/make/solaris/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -168,6 +168,7 @@ TARGETS_KERNEL = $(addsuffix kernel,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) +BUILDTREE_VARS += OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS) diff --git a/hotspot/make/solaris/makefiles/build_vm_def.sh b/hotspot/make/solaris/makefiles/build_vm_def.sh new file mode 100644 index 00000000000..7f86953ddf3 --- /dev/null +++ b/hotspot/make/solaris/makefiles/build_vm_def.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +/usr/ccs/bin/nm -p $* \ + | awk '{ + if ($2 == "U") next + if ($3 ~ /^__1c.*__vtbl_$/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" + if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" + if ($3 ~ /^__1cJArgumentsRSharedArchivePath_$/) print "\t" $3 ";" + }' \ + | sort -u diff --git a/hotspot/make/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make index 591ae3c5855..30e03bedb8b 100644 --- a/hotspot/make/solaris/makefiles/buildtree.make +++ b/hotspot/make/solaris/makefiles/buildtree.make @@ -226,6 +226,10 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ + [ -n "$(OBJCOPY)" ] && \ + echo && echo "OBJCOPY = $(OBJCOPY)"; \ + [ -n "$(STRIP_POLICY)" ] && \ + echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \ [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ echo && \ echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ diff --git a/hotspot/make/solaris/makefiles/defs.make b/hotspot/make/solaris/makefiles/defs.make index e7cd905ac5d..64e96bea82a 100644 --- a/hotspot/make/solaris/makefiles/defs.make +++ b/hotspot/make/solaris/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,79 @@ else endif endif +# determine if HotSpot is being built in JDK6 or earlier version +JDK6_OR_EARLIER=0 +ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1" + # if the longer variable names (newer build style) are set, then check those + ifeq "$(shell expr \( $(JDK_MAJOR_VERSION) = 1 \& $(JDK_MINOR_VERSION) \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +else + # the longer variables aren't set so check the shorter variable names + ifeq "$(shell expr \( '$(JDK_MAJOR_VER)' = 1 \& '$(JDK_MINOR_VER)' \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +endif + +ifeq ($(JDK6_OR_EARLIER),0) + # Full Debug Symbols is supported on JDK7 or newer + +ifdef ENABLE_FULL_DEBUG_SYMBOLS + # Only check for Full Debug Symbols support on Solaris if it is + # specifically enabled. Hopefully, it can be enabled by default + # once the .debuginfo size issues are worked out. + + # Default OBJCOPY comes from the SUNWbinutils package: + DEF_OBJCOPY=/usr/sfw/bin/gobjcopy + ifeq ($(VM_PLATFORM),solaris_amd64) + # On Solaris AMD64/X64, gobjcopy is not happy and fails: + # + # usr/sfw/bin/gobjcopy --add-gnu-debuglink=.debuginfo .so + # BFD: stKPaiop: Not enough room for program headers, try linking with -N + # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value + # BFD: stKPaiop: Not enough room for program headers, try linking with -N + # /usr/sfw/bin/gobjcopy: libsaproc.debuginfo: Bad value + # BFD: stKPaiop: Not enough room for program headers, try linking with -N + # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value + _JUNK_ := $(shell \ + echo >&2 "INFO: $(DEF_OBJCOPY) is not working on Solaris AMD64/X64") + OBJCOPY= + else + OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY)) + ifneq ($(ALT_OBJCOPY),) + _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)") + # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path + OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY)) + endif + endif +endif + + ifeq ($(OBJCOPY),) + _JUNK_ := $(shell \ + echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.") + else + _JUNK_ := $(shell \ + echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.") + + # Library stripping policies for .debuginfo configs: + # all_strip - strips everything from the library + # min_strip - strips most stuff from the library; leaves minimum symbols + # no_strip - does not strip the library at all + # + # Oracle security policy requires "all_strip". A waiver was granted on + # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE. + # + DEF_STRIP_POLICY="min_strip" + ifeq ($(ALT_STRIP_POLICY),) + STRIP_POLICY=$(DEF_STRIP_POLICY) + else + STRIP_POLICY=$(ALT_STRIP_POLICY) + endif + _JUNK_ := $(shell \ + echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)") + endif +endif + JDK_INCLUDE_SUBDIR=solaris # FIXUP: The subdirectory for a debug build is NOT the same on all platforms @@ -68,6 +141,9 @@ EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.so EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.so +ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo +endif EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client @@ -77,6 +153,11 @@ EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.so EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.so EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.so + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.debuginfo + endif endif ifeq ($(ARCH_DATA_MODEL), 32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt @@ -85,11 +166,25 @@ ifeq ($(ARCH_DATA_MODEL), 32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.so EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.so EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.so + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo + endif ifneq ($(BUILD_CLIENT_ONLY), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.so EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.so + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.debuginfo + endif endif endif EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so +ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo +endif EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 8b750858cd3..c7cc1592969 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -41,10 +41,16 @@ JVM_DB = libjvm_db LIBJVM_DB = libjvm_db.so LIBJVM_DB_G = libjvm$(G_SUFFIX)_db.so +LIBJVM_DB_DEBUGINFO = libjvm_db.debuginfo +LIBJVM_DB_G_DEBUGINFO = libjvm$(G_SUFFIX)_db.debuginfo + JVM_DTRACE = jvm_dtrace LIBJVM_DTRACE = libjvm_dtrace.so LIBJVM_DTRACE_G = libjvm$(G_SUFFIX)_dtrace.so +LIBJVM_DTRACE_DEBUGINFO = libjvm_dtrace.debuginfo +LIBJVM_DTRACE_G_DEBUGINFO = libjvm$(G_SUFFIX)_dtrace.debuginfo + JVMOFFS = JvmOffsets JVMOFFS.o = $(JVMOFFS).o GENOFFS = generate$(JVMOFFS) @@ -89,12 +95,30 @@ XLIBJVM_DB_G = 64/$(LIBJVM_DB_G) XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE) XLIBJVM_DTRACE_G = 64/$(LIBJVM_DTRACE_G) +XLIBJVM_DB_DEBUGINFO = 64/$(LIBJVM_DB_DEBUGINFO) +XLIBJVM_DB_G_DEBUGINFO = 64/$(LIBJVM_DB_G_DEBUGINFO) +XLIBJVM_DTRACE_DEBUGINFO = 64/$(LIBJVM_DTRACE_DEBUGINFO) +XLIBJVM_DTRACE_G_DEBUGINFO = 64/$(LIBJVM_DTRACE_G_DEBUGINFO) + $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE) @echo Making $@ $(QUIETLY) mkdir -p 64/ ; \ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. -I$(GENERATED) \ $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc [ -f $(XLIBJVM_DB_G) ] || { ln -s $(LIBJVM_DB) $(XLIBJVM_DB_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(XLIBJVM_DB_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(XLIBJVM_DB_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(XLIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DB_DEBUGINFO) $(XLIBJVM_DB_G_DEBUGINFO); } +endif $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) @echo Making $@ @@ -102,6 +126,19 @@ $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRAC $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. \ $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor [ -f $(XLIBJVM_DTRACE_G) ] || { ln -s $(LIBJVM_DTRACE) $(XLIBJVM_DTRACE_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(XLIBJVM_DTRACE_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(XLIBJVM_DTRACE_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(XLIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DTRACE_DEBUGINFO) $(XLIBJVM_DTRACE_G_DEBUGINFO); } +endif endif # ifneq ("${ISA}","${BUILDARCH}") @@ -148,12 +185,38 @@ $(LIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS.o) $(XLIBJVM_DB) $(LIBJVM_D $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. -I$(GENERATED) \ $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc [ -f $(LIBJVM_DB_G) ] || { ln -s $@ $(LIBJVM_DB_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DB_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DB_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DB_DEBUGINFO) $(LIBJVM_DB_G_DEBUGINFO); } +endif $(LIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(XLIBJVM_DTRACE) $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) @echo Making $@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. \ $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor [ -f $(LIBJVM_DTRACE_G) ] || { ln -s $@ $(LIBJVM_DTRACE_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DTRACE_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DTRACE_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DTRACE_DEBUGINFO) $(LIBJVM_DTRACE_G_DEBUGINFO); } +endif $(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \ $(DTRACE_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d diff --git a/hotspot/make/solaris/makefiles/jsig.make b/hotspot/make/solaris/makefiles/jsig.make index 0fadae776f8..9002077f440 100644 --- a/hotspot/make/solaris/makefiles/jsig.make +++ b/hotspot/make/solaris/makefiles/jsig.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,9 +31,13 @@ LIBJSIG = lib$(JSIG).so JSIG_G = $(JSIG)$(G_SUFFIX) LIBJSIG_G = lib$(JSIG_G).so +LIBJSIG_DEBUGINFO = lib$(JSIG).debuginfo +LIBJSIG_G_DEBUGINFO = lib$(JSIG_G).debuginfo + JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm -DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO) LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig @@ -50,9 +54,24 @@ $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE) $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_JSIG) -o $@ $< -ldl [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJSIG_G_DEBUGINFO) ] || { ln -s $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO); } +endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" + $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" .PHONY: install_jsig diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index 69bee55597a..8417fd87f8f 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -3,7 +3,7 @@ # # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -256,6 +256,9 @@ SUNWprivate_1.1 { # This is for Forte Analyzer profiling support. AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + local: *; }; diff --git a/hotspot/make/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make index 122c8f37b58..300b70d1c1f 100644 --- a/hotspot/make/solaris/makefiles/product.make +++ b/hotspot/make/solaris/makefiles/product.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,8 @@ MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) REORDERFILE = $(GAMMADIR)/make/solaris/makefiles/reorder_$(TYPE)_$(BUILDARCH) endif -# Don't strip in VM build; JDK build will strip libraries later +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. # LINK_LIB.CC/POST_HOOK += $(STRIP_LIB.CC/POST_HOOK) G_SUFFIX = diff --git a/hotspot/make/solaris/makefiles/saproc.make b/hotspot/make/solaris/makefiles/saproc.make index 421f556a87a..389ed9d3295 100644 --- a/hotspot/make/solaris/makefiles/saproc.make +++ b/hotspot/make/solaris/makefiles/saproc.make @@ -32,6 +32,9 @@ LIBSAPROC = lib$(SAPROC).so SAPROC_G = $(SAPROC)$(G_SUFFIX) LIBSAPROC_G = lib$(SAPROC_G).so +LIBSAPROC_DEBUGINFO = lib$(SAPROC).debuginfo +LIBSAPROC_G_DEBUGINFO = lib$(SAPROC_G).debuginfo + AGENT_DIR = $(GAMMADIR)/agent SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)/proc @@ -40,7 +43,8 @@ SASRCFILES = $(SASRCDIR)/saproc.cpp SAMAPFILE = $(SASRCDIR)/mapfile -DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO) # if $(AGENT_DIR) does not exist, we don't build SA @@ -101,10 +105,25 @@ $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) -o $@ \ -ldl -ldemangle -lthread -lc [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBSAPROC_G_DEBUGINFO) ] || { ln -s $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO); } +endif install_saproc: $(BULDLIBSAPROC) $(QUIETLY) if [ -f $(LIBSAPROC) ] ; then \ echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test -f $(LIBSAPROC_DEBUGINFO) && \ + cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ fi diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make index 8ee34787955..67a22a20b82 100644 --- a/hotspot/make/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -481,9 +481,18 @@ CFLAGS += -DCC_INTERP endif # Flags for Debugging +# The -g0 setting allows the C++ frontend to inline, which is a big win. +# The -xs setting disables 'lazy debug info' which puts everything in +# the .so instead of requiring the '.o' files. +ifneq ($(OBJCOPY),) + OPT_CFLAGS += -g0 -xs +endif DEBUG_CFLAGS = -g FASTDEBUG_CFLAGS = -g0 -# The -g0 setting allows the C++ frontend to inline, which is a big win. +ifneq ($(OBJCOPY),) + DEBUG_CFLAGS += -xs + FASTDEBUG_CFLAGS += -xs +endif # Special global options for SS12 ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) @@ -502,6 +511,9 @@ endif # data using a unique globalization prefix. Instead force the use of # a static globalization prefix based on the source filepath so the # objects from two identical compilations are the same. +# EXTRA_CFLAGS only covers vm_version.cpp for some reason +#EXTRA_CFLAGS += -Qoption ccfe -xglobalstatic +#OPT_CFLAGS += -Qoption ccfe -xglobalstatic #DEBUG_CFLAGS += -Qoption ccfe -xglobalstatic #FASTDEBUG_CFLAGS += -Qoption ccfe -xglobalstatic @@ -562,6 +574,8 @@ LINK_LIB.CC/POST_HOOK += $(MCS) -c $@ || exit 1; # since the hook must terminate itself as a valid command.) # Also, strip debug and line number information (worth about 1.7Mb). +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. STRIP_LIB.CC/POST_HOOK = $(STRIP) -x $@ || exit 1; # STRIP_LIB.CC/POST_HOOK is incorporated into LINK_LIB.CC/POST_HOOK # in certain configurations, such as product.make. Other configurations, diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make index 5db3daeda64..7b950af7f24 100644 --- a/hotspot/make/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -55,10 +55,17 @@ VPATH += $(Src_Dirs_V:%=%:) Src_Dirs_I += $(GENERATED) INCLUDES += $(Src_Dirs_I:%=-I%) -ifeq (${VERSION}, debug) - SYMFLAG = -g +# SYMFLAG is used by {dtrace,jsig,saproc}.make. +ifneq ($(OBJCOPY),) + # always build with debug info when we can create .debuginfo files + # and disable 'lazy debug info' so the .so has everything. + SYMFLAG = -g -xs else - SYMFLAG = + ifeq (${VERSION}, debug) + SYMFLAG = -g + else + SYMFLAG = + endif endif # The following variables are defined in the generated flags.make file. @@ -140,6 +147,9 @@ JVM = jvm LIBJVM = lib$(JVM).so LIBJVM_G = lib$(JVM)$(G_SUFFIX).so +LIBJVM_DEBUGINFO = lib$(JVM).debuginfo +LIBJVM_G_DEBUGINFO = lib$(JVM)$(G_SUFFIX).debuginfo + SPECIAL_PATHS:=adlc c1 dist gc_implementation opto shark libadt SOURCE_PATHS=\ @@ -212,14 +222,24 @@ JVM_OBJ_FILES = $(Obj_Files) $(DTRACE_OBJS) vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES)) -mapfile : $(MAPFILE) $(MAPFILE_DTRACE_OPT) +mapfile : $(MAPFILE) $(MAPFILE_DTRACE_OPT) vm.def rm -f $@ - cat $^ > $@ + cat $(MAPFILE) $(MAPFILE_DTRACE_OPT) \ + | $(NAWK) '{ \ + if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") { \ + system ("cat vm.def"); \ + } else { \ + print $$0; \ + } \ + }' > $@ mapfile_reorder : mapfile $(MAPFILE_DTRACE_OPT) $(REORDERFILE) rm -f $@ cat $^ > $@ +vm.def: $(Obj_Files) + sh $(GAMMADIR)/make/solaris/makefiles/build_vm_def.sh *.o > $@ + ifeq ($(LINK_INTO),AOUT) LIBJVM.o = LIBJVM_MAPFILE = @@ -255,13 +275,30 @@ ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),) $(QUIETLY) rm -f $@.1 && ln -s $@ $@.1 $(QUIETLY) [ -f $(LIBJVM_G) ] || ln -s $@ $(LIBJVM_G) $(QUIETLY) [ -f $(LIBJVM_G).1 ] || ln -s $@.1 $(LIBJVM_G).1 +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + $(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO) +endif endif # filter -sbfast -xsbfast -DEST_JVM = $(JDK_LIBDIR)/$(VM_SUBDIR)/$(LIBJVM) +DEST_SUBDIR = $(JDK_LIBDIR)/$(VM_SUBDIR) +DEST_JVM = $(DEST_SUBDIR)/$(LIBJVM) +DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" + $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" #---------------------------------------------------------------------- From e3faa527bd1d89760a1723f6e6c3b71b916ec16f Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 16 Sep 2011 21:35:06 -0700 Subject: [PATCH 096/214] 7091545: hs23 - set hotspot version & build number Reviewed-by: tonyp, never, phh, jmasa --- hotspot/make/hotspot_version | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 39b88ce51a0..f5de8cdee87 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -33,9 +33,9 @@ # Don't put quotes (fail windows build). HOTSPOT_VM_COPYRIGHT=Copyright 2011 -HS_MAJOR_VER=22 +HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=06 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 19f1338ae9604fc849ab309e6c182c2fe5aaef7c Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sun, 18 Sep 2011 12:33:56 +0100 Subject: [PATCH 097/214] 7091935: (fs) Polling based WatchService not used on Linux Reviewed-by: forax --- jdk/make/java/nio/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/make/java/nio/Makefile b/jdk/make/java/nio/Makefile index 7a802d03531..b72cfc1eb1a 100644 --- a/jdk/make/java/nio/Makefile +++ b/jdk/make/java/nio/Makefile @@ -206,7 +206,6 @@ FILES_java += \ sun/nio/fs/LinuxUserDefinedFileAttributeView.java \ sun/nio/fs/LinuxNativeDispatcher.java \ sun/nio/fs/LinuxWatchService.java \ - sun/nio/fs/PollingWatchService.java \ sun/nio/fs/UnixChannelFactory.java \ sun/nio/fs/UnixCopyFile.java \ sun/nio/fs/UnixDirectoryStream.java \ From 5b7643e258c772b0e152446c06cd3c429f6fcd3f Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sun, 18 Sep 2011 18:14:07 -0700 Subject: [PATCH 098/214] 7091682: Move sun.misc.FpUtils code into java.lang.Math Reviewed-by: alanb --- jdk/src/share/classes/java/lang/Double.java | 4 +- jdk/src/share/classes/java/lang/Float.java | 9 +- jdk/src/share/classes/java/lang/Math.java | 338 +++++++++++++++- .../share/classes/java/lang/StrictMath.java | 32 +- .../share/classes/java/util/Formatter.java | 6 +- .../classes/sun/misc/FloatingDecimal.java | 7 +- .../sun/misc/FormattedFloatingDecimal.java | 1 - jdk/src/share/classes/sun/misc/FpUtils.java | 382 +++--------------- jdk/test/java/lang/Double/ToHexString.java | 1 - jdk/test/java/lang/Math/CubeRootTests.java | 40 +- jdk/test/java/lang/Math/Expm1Tests.java | 10 +- jdk/test/java/lang/Math/HyperbolicTests.java | 12 +- jdk/test/java/lang/Math/HypotTests.java | 10 +- .../java/lang/Math/IeeeRecommendedTests.java | 28 +- jdk/test/java/lang/Math/Log10Tests.java | 4 +- jdk/test/java/lang/Math/Log1pTests.java | 10 +- jdk/test/java/lang/Math/Rint.java | 14 +- 17 files changed, 468 insertions(+), 440 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index 6f8cdaf1eb2..fd6278a88f8 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -283,7 +283,7 @@ public final class Double extends Number implements Comparable { // Initialized to maximum size of output. StringBuffer answer = new StringBuffer(24); - if (FpUtils.rawCopySign(1.0, d) == -1.0) // value is negative, + if (Math.copySign(1.0, d) == -1.0) // value is negative, answer.append("-"); // so append sign info answer.append("0x"); @@ -322,7 +322,7 @@ public final class Double extends Number implements Comparable { // E_min -1). answer.append("p" + (subnormal ? DoubleConsts.MIN_EXPONENT: - FpUtils.getExponent(d) )); + Math.getExponent(d) )); } return answer.toString(); } diff --git a/jdk/src/share/classes/java/lang/Float.java b/jdk/src/share/classes/java/lang/Float.java index fa4bfb73857..7fac24c79f9 100644 --- a/jdk/src/share/classes/java/lang/Float.java +++ b/jdk/src/share/classes/java/lang/Float.java @@ -26,7 +26,6 @@ package java.lang; import sun.misc.FloatingDecimal; -import sun.misc.FpUtils; import sun.misc.FloatConsts; import sun.misc.DoubleConsts; @@ -279,10 +278,10 @@ public final class Float extends Number implements Comparable { // Adjust exponent to create subnormal double, then // replace subnormal double exponent with subnormal float // exponent - String s = Double.toHexString(FpUtils.scalb((double)f, - /* -1022+126 */ - DoubleConsts.MIN_EXPONENT- - FloatConsts.MIN_EXPONENT)); + String s = Double.toHexString(Math.scalb((double)f, + /* -1022+126 */ + DoubleConsts.MIN_EXPONENT- + FloatConsts.MIN_EXPONENT)); return s.replaceFirst("p-1022$", "p-126"); } else // double string will be the same as float string diff --git a/jdk/src/share/classes/java/lang/Math.java b/jdk/src/share/classes/java/lang/Math.java index 177d710aa9e..ff9ffe2f09d 100644 --- a/jdk/src/share/classes/java/lang/Math.java +++ b/jdk/src/share/classes/java/lang/Math.java @@ -26,6 +26,8 @@ package java.lang; import java.util.Random; +import sun.misc.FloatConsts; +import sun.misc.DoubleConsts; /** * The class {@code Math} contains methods for performing basic @@ -963,7 +965,31 @@ public final class Math { * @since 1.5 */ public static double ulp(double d) { - return sun.misc.FpUtils.ulp(d); + int exp = getExponent(d); + + switch(exp) { + case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity + return Math.abs(d); + + case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal + return Double.MIN_VALUE; + + default: + assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT; + + // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) + exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1); + if (exp >= DoubleConsts.MIN_EXPONENT) { + return powerOfTwoD(exp); + } + else { + // return a subnormal result; left shift integer + // representation of Double.MIN_VALUE appropriate + // number of positions + return Double.longBitsToDouble(1L << + (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) )); + } + } } /** @@ -990,7 +1016,31 @@ public final class Math { * @since 1.5 */ public static float ulp(float f) { - return sun.misc.FpUtils.ulp(f); + int exp = getExponent(f); + + switch(exp) { + case FloatConsts.MAX_EXPONENT+1: // NaN or infinity + return Math.abs(f); + + case FloatConsts.MIN_EXPONENT-1: // zero or subnormal + return FloatConsts.MIN_VALUE; + + default: + assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT; + + // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) + exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1); + if (exp >= FloatConsts.MIN_EXPONENT) { + return powerOfTwoF(exp); + } + else { + // return a subnormal result; left shift integer + // representation of FloatConsts.MIN_VALUE appropriate + // number of positions + return Float.intBitsToFloat(1 << + (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) )); + } + } } /** @@ -1011,7 +1061,7 @@ public final class Math { * @since 1.5 */ public static double signum(double d) { - return sun.misc.FpUtils.signum(d); + return (d == 0.0 || Double.isNaN(d))?d:copySign(1.0, d); } /** @@ -1032,7 +1082,7 @@ public final class Math { * @since 1.5 */ public static float signum(float f) { - return sun.misc.FpUtils.signum(f); + return (f == 0.0f || Float.isNaN(f))?f:copySign(1.0f, f); } /** @@ -1252,7 +1302,11 @@ public final class Math { * @since 1.6 */ public static double copySign(double magnitude, double sign) { - return sun.misc.FpUtils.rawCopySign(magnitude, sign); + return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) & + (DoubleConsts.SIGN_BIT_MASK)) | + (Double.doubleToRawLongBits(magnitude) & + (DoubleConsts.EXP_BIT_MASK | + DoubleConsts.SIGNIF_BIT_MASK))); } /** @@ -1271,7 +1325,11 @@ public final class Math { * @since 1.6 */ public static float copySign(float magnitude, float sign) { - return sun.misc.FpUtils.rawCopySign(magnitude, sign); + return Float.intBitsToFloat((Float.floatToRawIntBits(sign) & + (FloatConsts.SIGN_BIT_MASK)) | + (Float.floatToRawIntBits(magnitude) & + (FloatConsts.EXP_BIT_MASK | + FloatConsts.SIGNIF_BIT_MASK))); } /** @@ -1289,7 +1347,13 @@ public final class Math { * @since 1.6 */ public static int getExponent(float f) { - return sun.misc.FpUtils.getExponent(f); + /* + * Bitwise convert f to integer, mask out exponent bits, shift + * to the right and then subtract out float's bias adjust to + * get true exponent value + */ + return ((Float.floatToRawIntBits(f) & FloatConsts.EXP_BIT_MASK) >> + (FloatConsts.SIGNIFICAND_WIDTH - 1)) - FloatConsts.EXP_BIAS; } /** @@ -1307,7 +1371,13 @@ public final class Math { * @since 1.6 */ public static int getExponent(double d) { - return sun.misc.FpUtils.getExponent(d); + /* + * Bitwise convert d to long, mask out exponent bits, shift + * to the right and then subtract out double's bias adjust to + * get true exponent value. + */ + return (int)(((Double.doubleToRawLongBits(d) & DoubleConsts.EXP_BIT_MASK) >> + (DoubleConsts.SIGNIFICAND_WIDTH - 1)) - DoubleConsts.EXP_BIAS); } /** @@ -1351,7 +1421,63 @@ public final class Math { * @since 1.6 */ public static double nextAfter(double start, double direction) { - return sun.misc.FpUtils.nextAfter(start, direction); + /* + * The cases: + * + * nextAfter(+infinity, 0) == MAX_VALUE + * nextAfter(+infinity, +infinity) == +infinity + * nextAfter(-infinity, 0) == -MAX_VALUE + * nextAfter(-infinity, -infinity) == -infinity + * + * are naturally handled without any additional testing + */ + + // First check for NaN values + if (Double.isNaN(start) || Double.isNaN(direction)) { + // return a NaN derived from the input NaN(s) + return start + direction; + } else if (start == direction) { + return direction; + } else { // start > direction or start < direction + // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0) + // then bitwise convert start to integer. + long transducer = Double.doubleToRawLongBits(start + 0.0d); + + /* + * IEEE 754 floating-point numbers are lexicographically + * ordered if treated as signed- magnitude integers . + * Since Java's integers are two's complement, + * incrementing" the two's complement representation of a + * logically negative floating-point value *decrements* + * the signed-magnitude representation. Therefore, when + * the integer representation of a floating-point values + * is less than zero, the adjustment to the representation + * is in the opposite direction than would be expected at + * first . + */ + if (direction > start) { // Calculate next greater value + transducer = transducer + (transducer >= 0L ? 1L:-1L); + } else { // Calculate next lesser value + assert direction < start; + if (transducer > 0L) + --transducer; + else + if (transducer < 0L ) + ++transducer; + /* + * transducer==0, the result is -MIN_VALUE + * + * The transition from zero (implicitly + * positive) to the smallest negative + * signed magnitude value must be done + * explicitly. + */ + else + transducer = DoubleConsts.SIGN_BIT_MASK | 1L; + } + + return Double.longBitsToDouble(transducer); + } } /** @@ -1394,7 +1520,63 @@ public final class Math { * @since 1.6 */ public static float nextAfter(float start, double direction) { - return sun.misc.FpUtils.nextAfter(start, direction); + /* + * The cases: + * + * nextAfter(+infinity, 0) == MAX_VALUE + * nextAfter(+infinity, +infinity) == +infinity + * nextAfter(-infinity, 0) == -MAX_VALUE + * nextAfter(-infinity, -infinity) == -infinity + * + * are naturally handled without any additional testing + */ + + // First check for NaN values + if (Float.isNaN(start) || Double.isNaN(direction)) { + // return a NaN derived from the input NaN(s) + return start + (float)direction; + } else if (start == direction) { + return (float)direction; + } else { // start > direction or start < direction + // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0) + // then bitwise convert start to integer. + int transducer = Float.floatToRawIntBits(start + 0.0f); + + /* + * IEEE 754 floating-point numbers are lexicographically + * ordered if treated as signed- magnitude integers . + * Since Java's integers are two's complement, + * incrementing" the two's complement representation of a + * logically negative floating-point value *decrements* + * the signed-magnitude representation. Therefore, when + * the integer representation of a floating-point values + * is less than zero, the adjustment to the representation + * is in the opposite direction than would be expected at + * first. + */ + if (direction > start) {// Calculate next greater value + transducer = transducer + (transducer >= 0 ? 1:-1); + } else { // Calculate next lesser value + assert direction < start; + if (transducer > 0) + --transducer; + else + if (transducer < 0 ) + ++transducer; + /* + * transducer==0, the result is -MIN_VALUE + * + * The transition from zero (implicitly + * positive) to the smallest negative + * signed magnitude value must be done + * explicitly. + */ + else + transducer = FloatConsts.SIGN_BIT_MASK | 1; + } + + return Float.intBitsToFloat(transducer); + } } /** @@ -1423,7 +1605,13 @@ public final class Math { * @since 1.6 */ public static double nextUp(double d) { - return sun.misc.FpUtils.nextUp(d); + if( Double.isNaN(d) || d == Double.POSITIVE_INFINITY) + return d; + else { + d += 0.0d; + return Double.longBitsToDouble(Double.doubleToRawLongBits(d) + + ((d >= 0.0d)?+1L:-1L)); + } } /** @@ -1452,7 +1640,13 @@ public final class Math { * @since 1.6 */ public static float nextUp(float f) { - return sun.misc.FpUtils.nextUp(f); + if( Float.isNaN(f) || f == FloatConsts.POSITIVE_INFINITY) + return f; + else { + f += 0.0f; + return Float.intBitsToFloat(Float.floatToRawIntBits(f) + + ((f >= 0.0f)?+1:-1)); + } } @@ -1487,7 +1681,80 @@ public final class Math { * @since 1.6 */ public static double scalb(double d, int scaleFactor) { - return sun.misc.FpUtils.scalb(d, scaleFactor); + /* + * This method does not need to be declared strictfp to + * compute the same correct result on all platforms. When + * scaling up, it does not matter what order the + * multiply-store operations are done; the result will be + * finite or overflow regardless of the operation ordering. + * However, to get the correct result when scaling down, a + * particular ordering must be used. + * + * When scaling down, the multiply-store operations are + * sequenced so that it is not possible for two consecutive + * multiply-stores to return subnormal results. If one + * multiply-store result is subnormal, the next multiply will + * round it away to zero. This is done by first multiplying + * by 2 ^ (scaleFactor % n) and then multiplying several + * times by by 2^n as needed where n is the exponent of number + * that is a covenient power of two. In this way, at most one + * real rounding error occurs. If the double value set is + * being used exclusively, the rounding will occur on a + * multiply. If the double-extended-exponent value set is + * being used, the products will (perhaps) be exact but the + * stores to d are guaranteed to round to the double value + * set. + * + * It is _not_ a valid implementation to first multiply d by + * 2^MIN_EXPONENT and then by 2 ^ (scaleFactor % + * MIN_EXPONENT) since even in a strictfp program double + * rounding on underflow could occur; e.g. if the scaleFactor + * argument was (MIN_EXPONENT - n) and the exponent of d was a + * little less than -(MIN_EXPONENT - n), meaning the final + * result would be subnormal. + * + * Since exact reproducibility of this method can be achieved + * without any undue performance burden, there is no + * compelling reason to allow double rounding on underflow in + * scalb. + */ + + // magnitude of a power of two so large that scaling a finite + // nonzero value by it would be guaranteed to over or + // underflow; due to rounding, scaling down takes takes an + // additional power of two which is reflected here + final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT + + DoubleConsts.SIGNIFICAND_WIDTH + 1; + int exp_adjust = 0; + int scale_increment = 0; + double exp_delta = Double.NaN; + + // Make sure scaling factor is in a reasonable range + + if(scaleFactor < 0) { + scaleFactor = Math.max(scaleFactor, -MAX_SCALE); + scale_increment = -512; + exp_delta = twoToTheDoubleScaleDown; + } + else { + scaleFactor = Math.min(scaleFactor, MAX_SCALE); + scale_increment = 512; + exp_delta = twoToTheDoubleScaleUp; + } + + // Calculate (scaleFactor % +/-512), 512 = 2^9, using + // technique from "Hacker's Delight" section 10-2. + int t = (scaleFactor >> 9-1) >>> 32 - 9; + exp_adjust = ((scaleFactor + t) & (512 -1)) - t; + + d *= powerOfTwoD(exp_adjust); + scaleFactor -= exp_adjust; + + while(scaleFactor != 0) { + d *= exp_delta; + scaleFactor -= scale_increment; + } + return d; } /** @@ -1521,6 +1788,49 @@ public final class Math { * @since 1.6 */ public static float scalb(float f, int scaleFactor) { - return sun.misc.FpUtils.scalb(f, scaleFactor); + // magnitude of a power of two so large that scaling a finite + // nonzero value by it would be guaranteed to over or + // underflow; due to rounding, scaling down takes takes an + // additional power of two which is reflected here + final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT + + FloatConsts.SIGNIFICAND_WIDTH + 1; + + // Make sure scaling factor is in a reasonable range + scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE); + + /* + * Since + MAX_SCALE for float fits well within the double + * exponent range and + float -> double conversion is exact + * the multiplication below will be exact. Therefore, the + * rounding that occurs when the double product is cast to + * float will be the correctly rounded float result. Since + * all operations other than the final multiply will be exact, + * it is not necessary to declare this method strictfp. + */ + return (float)((double)f*powerOfTwoD(scaleFactor)); + } + + // Constants used in scalb + static double twoToTheDoubleScaleUp = powerOfTwoD(512); + static double twoToTheDoubleScaleDown = powerOfTwoD(-512); + + /** + * Returns a floating-point power of two in the normal range. + */ + static double powerOfTwoD(int n) { + assert(n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT); + return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) << + (DoubleConsts.SIGNIFICAND_WIDTH-1)) + & DoubleConsts.EXP_BIT_MASK); + } + + /** + * Returns a floating-point power of two in the normal range. + */ + public static float powerOfTwoF(int n) { + assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT); + return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) << + (FloatConsts.SIGNIFICAND_WIDTH-1)) + & FloatConsts.EXP_BIT_MASK); } } diff --git a/jdk/src/share/classes/java/lang/StrictMath.java b/jdk/src/share/classes/java/lang/StrictMath.java index 42c701fa5cb..bb4cf219346 100644 --- a/jdk/src/share/classes/java/lang/StrictMath.java +++ b/jdk/src/share/classes/java/lang/StrictMath.java @@ -25,7 +25,6 @@ package java.lang; import java.util.Random; -import sun.misc.FpUtils; import sun.misc.DoubleConsts; /** @@ -428,7 +427,7 @@ public final class StrictMath { * 1.0, which is exact too. */ double twoToThe52 = (double)(1L << 52); // 2^52 - double sign = FpUtils.rawCopySign(1.0, a); // preserve sign info + double sign = Math.copySign(1.0, a); // preserve sign info a = Math.abs(a); if (a < twoToThe52) { // E_min <= ilogb(a) <= 51 @@ -955,7 +954,7 @@ public final class StrictMath { * @since 1.5 */ public static double ulp(double d) { - return sun.misc.FpUtils.ulp(d); + return Math.ulp(d); } /** @@ -982,7 +981,7 @@ public final class StrictMath { * @since 1.5 */ public static float ulp(float f) { - return sun.misc.FpUtils.ulp(f); + return Math.ulp(f); } /** @@ -1003,7 +1002,7 @@ public final class StrictMath { * @since 1.5 */ public static double signum(double d) { - return sun.misc.FpUtils.signum(d); + return Math.signum(d); } /** @@ -1024,7 +1023,7 @@ public final class StrictMath { * @since 1.5 */ public static float signum(float f) { - return sun.misc.FpUtils.signum(f); + return Math.signum(f); } /** @@ -1202,7 +1201,7 @@ public final class StrictMath { * @since 1.6 */ public static double copySign(double magnitude, double sign) { - return sun.misc.FpUtils.copySign(magnitude, sign); + return Math.copySign(magnitude, (Double.isNaN(sign)?1.0d:sign)); } /** @@ -1218,7 +1217,7 @@ public final class StrictMath { * @since 1.6 */ public static float copySign(float magnitude, float sign) { - return sun.misc.FpUtils.copySign(magnitude, sign); + return Math.copySign(magnitude, (Float.isNaN(sign)?1.0f:sign)); } /** * Returns the unbiased exponent used in the representation of a @@ -1234,7 +1233,7 @@ public final class StrictMath { * @since 1.6 */ public static int getExponent(float f) { - return sun.misc.FpUtils.getExponent(f); + return Math.getExponent(f); } /** @@ -1251,7 +1250,7 @@ public final class StrictMath { * @since 1.6 */ public static int getExponent(double d) { - return sun.misc.FpUtils.getExponent(d); + return Math.getExponent(d); } /** @@ -1294,7 +1293,7 @@ public final class StrictMath { * @since 1.6 */ public static double nextAfter(double start, double direction) { - return sun.misc.FpUtils.nextAfter(start, direction); + return Math.nextAfter(start, direction); } /** @@ -1336,7 +1335,7 @@ public final class StrictMath { * @since 1.6 */ public static float nextAfter(float start, double direction) { - return sun.misc.FpUtils.nextAfter(start, direction); + return Math.nextAfter(start, direction); } /** @@ -1365,7 +1364,7 @@ public final class StrictMath { * @since 1.6 */ public static double nextUp(double d) { - return sun.misc.FpUtils.nextUp(d); + return Math.nextUp(d); } /** @@ -1394,10 +1393,9 @@ public final class StrictMath { * @since 1.6 */ public static float nextUp(float f) { - return sun.misc.FpUtils.nextUp(f); + return Math.nextUp(f); } - /** * Return {@code d} × * 2{@code scaleFactor} rounded as if performed @@ -1429,7 +1427,7 @@ public final class StrictMath { * @since 1.6 */ public static double scalb(double d, int scaleFactor) { - return sun.misc.FpUtils.scalb(d, scaleFactor); + return Math.scalb(d, scaleFactor); } /** @@ -1463,6 +1461,6 @@ public final class StrictMath { * @since 1.6 */ public static float scalb(float f, int scaleFactor) { - return sun.misc.FpUtils.scalb(f, scaleFactor); + return Math.scalb(f, scaleFactor); } } diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index bcd36ea6120..05ca8cc6ef3 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -3423,18 +3423,18 @@ public final class Formatter implements Closeable, Flushable { else { assert(prec >= 1 && prec <= 12); - int exponent = FpUtils.getExponent(d); + int exponent = Math.getExponent(d); boolean subnormal = (exponent == DoubleConsts.MIN_EXPONENT - 1); // If this is subnormal input so normalize (could be faster to // do as integer operation). if (subnormal) { - scaleUp = FpUtils.scalb(1.0, 54); + scaleUp = Math.scalb(1.0, 54); d *= scaleUp; // Calculate the exponent. This is not just exponent + 54 // since the former is not the normalized exponent. - exponent = FpUtils.getExponent(d); + exponent = Math.getExponent(d); assert exponent >= DoubleConsts.MIN_EXPONENT && exponent <= DoubleConsts.MAX_EXPONENT: exponent; } diff --git a/jdk/src/share/classes/sun/misc/FloatingDecimal.java b/jdk/src/share/classes/sun/misc/FloatingDecimal.java index 1e3a25e84af..4df0487c88e 100644 --- a/jdk/src/share/classes/sun/misc/FloatingDecimal.java +++ b/jdk/src/share/classes/sun/misc/FloatingDecimal.java @@ -25,7 +25,6 @@ package sun.misc; -import sun.misc.FpUtils; import sun.misc.DoubleConsts; import sun.misc.FloatConsts; import java.util.regex.*; @@ -2297,9 +2296,9 @@ public class FloatingDecimal{ significand++; } - FloatingDecimal fd = new FloatingDecimal(FpUtils.rawCopySign( - Double.longBitsToDouble(significand), - sign)); + FloatingDecimal fd = new FloatingDecimal(Math.copySign( + Double.longBitsToDouble(significand), + sign)); /* * Set roundingDir variable field of fd properly so diff --git a/jdk/src/share/classes/sun/misc/FormattedFloatingDecimal.java b/jdk/src/share/classes/sun/misc/FormattedFloatingDecimal.java index 0b6dd85051f..261dbc07e2f 100644 --- a/jdk/src/share/classes/sun/misc/FormattedFloatingDecimal.java +++ b/jdk/src/share/classes/sun/misc/FormattedFloatingDecimal.java @@ -25,7 +25,6 @@ package sun.misc; -import sun.misc.FpUtils; import sun.misc.DoubleConsts; import sun.misc.FloatConsts; import java.util.regex.*; diff --git a/jdk/src/share/classes/sun/misc/FpUtils.java b/jdk/src/share/classes/sun/misc/FpUtils.java index 1050d322a11..9e03067cbef 100644 --- a/jdk/src/share/classes/sun/misc/FpUtils.java +++ b/jdk/src/share/classes/sun/misc/FpUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,10 +125,6 @@ public class FpUtils { */ private FpUtils() {} - // Constants used in scalb - static double twoToTheDoubleScaleUp = powerOfTwoD(512); - static double twoToTheDoubleScaleDown = powerOfTwoD(-512); - // Helper Methods // The following helper methods are used in the implementation of @@ -137,49 +133,22 @@ public class FpUtils { /** * Returns unbiased exponent of a {@code double}. + * @deprecated Use Math.getExponent. */ + @Deprecated public static int getExponent(double d){ - /* - * Bitwise convert d to long, mask out exponent bits, shift - * to the right and then subtract out double's bias adjust to - * get true exponent value. - */ - return (int)(((Double.doubleToRawLongBits(d) & DoubleConsts.EXP_BIT_MASK) >> - (DoubleConsts.SIGNIFICAND_WIDTH - 1)) - DoubleConsts.EXP_BIAS); + return Math.getExponent(d); } /** * Returns unbiased exponent of a {@code float}. + * @deprecated Use Math.getExponent. */ + @Deprecated public static int getExponent(float f){ - /* - * Bitwise convert f to integer, mask out exponent bits, shift - * to the right and then subtract out float's bias adjust to - * get true exponent value - */ - return ((Float.floatToRawIntBits(f) & FloatConsts.EXP_BIT_MASK) >> - (FloatConsts.SIGNIFICAND_WIDTH - 1)) - FloatConsts.EXP_BIAS; + return Math.getExponent(f); } - /** - * Returns a floating-point power of two in the normal range. - */ - static double powerOfTwoD(int n) { - assert(n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT); - return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) << - (DoubleConsts.SIGNIFICAND_WIDTH-1)) - & DoubleConsts.EXP_BIT_MASK); - } - - /** - * Returns a floating-point power of two in the normal range. - */ - static float powerOfTwoF(int n) { - assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT); - return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) << - (FloatConsts.SIGNIFICAND_WIDTH-1)) - & FloatConsts.EXP_BIT_MASK); - } /** * Returns the first floating-point argument with the sign of the @@ -195,13 +164,11 @@ public class FpUtils { * @return a value with the magnitude of {@code magnitude} * and the sign of {@code sign}. * @author Joseph D. Darcy + * @deprecated Use Math.copySign. */ + @Deprecated public static double rawCopySign(double magnitude, double sign) { - return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) & - (DoubleConsts.SIGN_BIT_MASK)) | - (Double.doubleToRawLongBits(magnitude) & - (DoubleConsts.EXP_BIT_MASK | - DoubleConsts.SIGNIF_BIT_MASK))); + return Math.copySign(magnitude, sign); } /** @@ -218,13 +185,11 @@ public class FpUtils { * @return a value with the magnitude of {@code magnitude} * and the sign of {@code sign}. * @author Joseph D. Darcy + * @deprecated Use Math.copySign. */ + @Deprecated public static float rawCopySign(float magnitude, float sign) { - return Float.intBitsToFloat((Float.floatToRawIntBits(sign) & - (FloatConsts.SIGN_BIT_MASK)) | - (Float.floatToRawIntBits(magnitude) & - (FloatConsts.EXP_BIT_MASK | - FloatConsts.SIGNIF_BIT_MASK))); + return Math.copySign(magnitude, sign); } /* ***************************************************************** */ @@ -558,82 +523,11 @@ public class FpUtils { * @param scale_factor power of 2 used to scale {@code d} * @return {@code d * }2{@code scale_factor} * @author Joseph D. Darcy + * @deprecated Use Math.scalb. */ + @Deprecated public static double scalb(double d, int scale_factor) { - /* - * This method does not need to be declared strictfp to - * compute the same correct result on all platforms. When - * scaling up, it does not matter what order the - * multiply-store operations are done; the result will be - * finite or overflow regardless of the operation ordering. - * However, to get the correct result when scaling down, a - * particular ordering must be used. - * - * When scaling down, the multiply-store operations are - * sequenced so that it is not possible for two consecutive - * multiply-stores to return subnormal results. If one - * multiply-store result is subnormal, the next multiply will - * round it away to zero. This is done by first multiplying - * by 2 ^ (scale_factor % n) and then multiplying several - * times by by 2^n as needed where n is the exponent of number - * that is a covenient power of two. In this way, at most one - * real rounding error occurs. If the double value set is - * being used exclusively, the rounding will occur on a - * multiply. If the double-extended-exponent value set is - * being used, the products will (perhaps) be exact but the - * stores to d are guaranteed to round to the double value - * set. - * - * It is _not_ a valid implementation to first multiply d by - * 2^MIN_EXPONENT and then by 2 ^ (scale_factor % - * MIN_EXPONENT) since even in a strictfp program double - * rounding on underflow could occur; e.g. if the scale_factor - * argument was (MIN_EXPONENT - n) and the exponent of d was a - * little less than -(MIN_EXPONENT - n), meaning the final - * result would be subnormal. - * - * Since exact reproducibility of this method can be achieved - * without any undue performance burden, there is no - * compelling reason to allow double rounding on underflow in - * scalb. - */ - - // magnitude of a power of two so large that scaling a finite - // nonzero value by it would be guaranteed to over or - // underflow; due to rounding, scaling down takes takes an - // additional power of two which is reflected here - final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT + - DoubleConsts.SIGNIFICAND_WIDTH + 1; - int exp_adjust = 0; - int scale_increment = 0; - double exp_delta = Double.NaN; - - // Make sure scaling factor is in a reasonable range - - if(scale_factor < 0) { - scale_factor = Math.max(scale_factor, -MAX_SCALE); - scale_increment = -512; - exp_delta = twoToTheDoubleScaleDown; - } - else { - scale_factor = Math.min(scale_factor, MAX_SCALE); - scale_increment = 512; - exp_delta = twoToTheDoubleScaleUp; - } - - // Calculate (scale_factor % +/-512), 512 = 2^9, using - // technique from "Hacker's Delight" section 10-2. - int t = (scale_factor >> 9-1) >>> 32 - 9; - exp_adjust = ((scale_factor + t) & (512 -1)) - t; - - d *= powerOfTwoD(exp_adjust); - scale_factor -= exp_adjust; - - while(scale_factor != 0) { - d *= exp_delta; - scale_factor -= scale_increment; - } - return d; + return Math.scalb(d, scale_factor); } /** @@ -667,28 +561,11 @@ public class FpUtils { * @param scale_factor power of 2 used to scale {@code f} * @return {@code f * }2{@code scale_factor} * @author Joseph D. Darcy + * @deprecated Use Math.scalb. */ - public static float scalb(float f, int scale_factor) { - // magnitude of a power of two so large that scaling a finite - // nonzero value by it would be guaranteed to over or - // underflow; due to rounding, scaling down takes takes an - // additional power of two which is reflected here - final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT + - FloatConsts.SIGNIFICAND_WIDTH + 1; - - // Make sure scaling factor is in a reasonable range - scale_factor = Math.max(Math.min(scale_factor, MAX_SCALE), -MAX_SCALE); - - /* - * Since + MAX_SCALE for float fits well within the double - * exponent range and + float -> double conversion is exact - * the multiplication below will be exact. Therefore, the - * rounding that occurs when the double product is cast to - * float will be the correctly rounded float result. Since - * all operations other than the final multiply will be exact, - * it is not necessary to declare this method strictfp. - */ - return (float)((double)f*powerOfTwoD(scale_factor)); + @Deprecated + public static float scalb(float f, int scale_factor) { + return Math.scalb(f, scale_factor); } /** @@ -730,65 +607,11 @@ public class FpUtils { * @return The floating-point number adjacent to {@code start} in the * direction of {@code direction}. * @author Joseph D. Darcy + * @deprecated Use Math.nextAfter */ + @Deprecated public static double nextAfter(double start, double direction) { - /* - * The cases: - * - * nextAfter(+infinity, 0) == MAX_VALUE - * nextAfter(+infinity, +infinity) == +infinity - * nextAfter(-infinity, 0) == -MAX_VALUE - * nextAfter(-infinity, -infinity) == -infinity - * - * are naturally handled without any additional testing - */ - - // First check for NaN values - if (isNaN(start) || isNaN(direction)) { - // return a NaN derived from the input NaN(s) - return start + direction; - } else if (start == direction) { - return direction; - } else { // start > direction or start < direction - // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0) - // then bitwise convert start to integer. - long transducer = Double.doubleToRawLongBits(start + 0.0d); - - /* - * IEEE 754 floating-point numbers are lexicographically - * ordered if treated as signed- magnitude integers . - * Since Java's integers are two's complement, - * incrementing" the two's complement representation of a - * logically negative floating-point value *decrements* - * the signed-magnitude representation. Therefore, when - * the integer representation of a floating-point values - * is less than zero, the adjustment to the representation - * is in the opposite direction than would be expected at - * first . - */ - if (direction > start) { // Calculate next greater value - transducer = transducer + (transducer >= 0L ? 1L:-1L); - } else { // Calculate next lesser value - assert direction < start; - if (transducer > 0L) - --transducer; - else - if (transducer < 0L ) - ++transducer; - /* - * transducer==0, the result is -MIN_VALUE - * - * The transition from zero (implicitly - * positive) to the smallest negative - * signed magnitude value must be done - * explicitly. - */ - else - transducer = DoubleConsts.SIGN_BIT_MASK | 1L; - } - - return Double.longBitsToDouble(transducer); - } + return Math.nextAfter(start, direction); } /** @@ -830,65 +653,11 @@ public class FpUtils { * @return The floating-point number adjacent to {@code start} in the * direction of {@code direction}. * @author Joseph D. Darcy + * @deprecated Use Math.nextAfter. */ - public static float nextAfter(float start, double direction) { - /* - * The cases: - * - * nextAfter(+infinity, 0) == MAX_VALUE - * nextAfter(+infinity, +infinity) == +infinity - * nextAfter(-infinity, 0) == -MAX_VALUE - * nextAfter(-infinity, -infinity) == -infinity - * - * are naturally handled without any additional testing - */ - - // First check for NaN values - if (isNaN(start) || isNaN(direction)) { - // return a NaN derived from the input NaN(s) - return start + (float)direction; - } else if (start == direction) { - return (float)direction; - } else { // start > direction or start < direction - // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0) - // then bitwise convert start to integer. - int transducer = Float.floatToRawIntBits(start + 0.0f); - - /* - * IEEE 754 floating-point numbers are lexicographically - * ordered if treated as signed- magnitude integers . - * Since Java's integers are two's complement, - * incrementing" the two's complement representation of a - * logically negative floating-point value *decrements* - * the signed-magnitude representation. Therefore, when - * the integer representation of a floating-point values - * is less than zero, the adjustment to the representation - * is in the opposite direction than would be expected at - * first. - */ - if (direction > start) {// Calculate next greater value - transducer = transducer + (transducer >= 0 ? 1:-1); - } else { // Calculate next lesser value - assert direction < start; - if (transducer > 0) - --transducer; - else - if (transducer < 0 ) - ++transducer; - /* - * transducer==0, the result is -MIN_VALUE - * - * The transition from zero (implicitly - * positive) to the smallest negative - * signed magnitude value must be done - * explicitly. - */ - else - transducer = FloatConsts.SIGN_BIT_MASK | 1; - } - - return Float.intBitsToFloat(transducer); - } + @Deprecated + public static float nextAfter(float start, double direction) { + return Math.nextAfter(start, direction); } /** @@ -915,15 +684,11 @@ public class FpUtils { * @return The adjacent floating-point value closer to positive * infinity. * @author Joseph D. Darcy + * @deprecated use Math.nextUp. */ + @Deprecated public static double nextUp(double d) { - if( isNaN(d) || d == Double.POSITIVE_INFINITY) - return d; - else { - d += 0.0d; - return Double.longBitsToDouble(Double.doubleToRawLongBits(d) + - ((d >= 0.0d)?+1L:-1L)); - } + return Math.nextUp(d); } /** @@ -950,15 +715,11 @@ public class FpUtils { * @return The adjacent floating-point value closer to positive * infinity. * @author Joseph D. Darcy + * @deprecated Use Math.nextUp. */ - public static float nextUp(float f) { - if( isNaN(f) || f == FloatConsts.POSITIVE_INFINITY) - return f; - else { - f += 0.0f; - return Float.intBitsToFloat(Float.floatToRawIntBits(f) + - ((f >= 0.0f)?+1:-1)); - } + @Deprecated + public static float nextUp(float f) { + return Math.nextUp(f); } /** @@ -1047,9 +808,11 @@ public class FpUtils { * and the sign of {@code sign}. * @author Joseph D. Darcy * @since 1.5 + * @deprecated Use StrictMath.copySign. */ + @Deprecated public static double copySign(double magnitude, double sign) { - return rawCopySign(magnitude, (isNaN(sign)?1.0d:sign)); + return StrictMath.copySign(magnitude, sign); } /** @@ -1063,9 +826,11 @@ public class FpUtils { * @return a value with the magnitude of {@code magnitude} * and the sign of {@code sign}. * @author Joseph D. Darcy + * @deprecated Use StrictMath.copySign. */ - public static float copySign(float magnitude, float sign) { - return rawCopySign(magnitude, (isNaN(sign)?1.0f:sign)); + @Deprecated + public static float copySign(float magnitude, float sign) { + return StrictMath.copySign(magnitude, sign); } /** @@ -1090,33 +855,11 @@ public class FpUtils { * @return the size of an ulp of the argument * @author Joseph D. Darcy * @since 1.5 + * @deprecated Use Math.ulp. */ + @Deprecated public static double ulp(double d) { - int exp = getExponent(d); - - switch(exp) { - case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity - return Math.abs(d); - - case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal - return Double.MIN_VALUE; - - default: - assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT; - - // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) - exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1); - if (exp >= DoubleConsts.MIN_EXPONENT) { - return powerOfTwoD(exp); - } - else { - // return a subnormal result; left shift integer - // representation of Double.MIN_VALUE appropriate - // number of positions - return Double.longBitsToDouble(1L << - (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) )); - } - } + return Math.ulp(d); } /** @@ -1141,33 +884,11 @@ public class FpUtils { * @return the size of an ulp of the argument * @author Joseph D. Darcy * @since 1.5 + * @deprecated Use Math.ulp. */ + @Deprecated public static float ulp(float f) { - int exp = getExponent(f); - - switch(exp) { - case FloatConsts.MAX_EXPONENT+1: // NaN or infinity - return Math.abs(f); - - case FloatConsts.MIN_EXPONENT-1: // zero or subnormal - return FloatConsts.MIN_VALUE; - - default: - assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT; - - // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) - exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1); - if (exp >= FloatConsts.MIN_EXPONENT) { - return powerOfTwoF(exp); - } - else { - // return a subnormal result; left shift integer - // representation of FloatConsts.MIN_VALUE appropriate - // number of positions - return Float.intBitsToFloat(1 << - (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) )); - } - } + return Math.ulp(f); } /** @@ -1186,9 +907,11 @@ public class FpUtils { * @return the signum function of the argument * @author Joseph D. Darcy * @since 1.5 + * @deprecated Use Math.signum. */ + @Deprecated public static double signum(double d) { - return (d == 0.0 || isNaN(d))?d:copySign(1.0, d); + return Math.signum(d); } /** @@ -1207,9 +930,10 @@ public class FpUtils { * @return the signum function of the argument * @author Joseph D. Darcy * @since 1.5 + * @deprecated Use Math.signum. */ + @Deprecated public static float signum(float f) { - return (f == 0.0f || isNaN(f))?f:copySign(1.0f, f); + return Math.signum(f); } - } diff --git a/jdk/test/java/lang/Double/ToHexString.java b/jdk/test/java/lang/Double/ToHexString.java index fcea456714a..c9fb07e9587 100644 --- a/jdk/test/java/lang/Double/ToHexString.java +++ b/jdk/test/java/lang/Double/ToHexString.java @@ -29,7 +29,6 @@ */ import java.util.regex.*; -import sun.misc.FpUtils; import sun.misc.DoubleConsts; public class ToHexString { diff --git a/jdk/test/java/lang/Math/CubeRootTests.java b/jdk/test/java/lang/Math/CubeRootTests.java index 6b70da3e43f..8b82183377c 100644 --- a/jdk/test/java/lang/Math/CubeRootTests.java +++ b/jdk/test/java/lang/Math/CubeRootTests.java @@ -95,14 +95,14 @@ public class CubeRootTests { // Test cbrt(2^(3n)) = 2^n. for(int i = 18; i <= DoubleConsts.MAX_EXPONENT/3; i++) { - failures += testCubeRootCase(FpUtils.scalb(1.0, 3*i), - FpUtils.scalb(1.0, i) ); + failures += testCubeRootCase(Math.scalb(1.0, 3*i), + Math.scalb(1.0, i) ); } // Test cbrt(2^(-3n)) = 2^-n. - for(int i = -1; i >= FpUtils.ilogb(Double.MIN_VALUE)/3; i--) { - failures += testCubeRootCase(FpUtils.scalb(1.0, 3*i), - FpUtils.scalb(1.0, i) ); + for(int i = -1; i >= DoubleConsts.MIN_SUB_EXPONENT/3; i--) { + failures += testCubeRootCase(Math.scalb(1.0, 3*i), + Math.scalb(1.0, i) ); } // Test random perfect cubes. Create double values with @@ -110,10 +110,10 @@ public class CubeRootTests { // significant bits in the significand set; 17*3 = 51, which // is less than the number of bits in a double's significand. long exponentBits1 = - Double.doubleToLongBits(FpUtils.scalb(1.0, 55)) & + Double.doubleToLongBits(Math.scalb(1.0, 55)) & DoubleConsts.EXP_BIT_MASK; long exponentBits2= - Double.doubleToLongBits(FpUtils.scalb(1.0, -55)) & + Double.doubleToLongBits(Math.scalb(1.0, -55)) & DoubleConsts.EXP_BIT_MASK; for(int i = 0; i < 100; i++) { // Take 16 bits since the 17th bit is implicit in the @@ -177,16 +177,16 @@ public class CubeRootTests { err = d - StrictMath.pow(y1, 3); if (err != 0.0) { - if(FpUtils.isNaN(err)) { + if(Double.isNaN(err)) { failures++; System.err.println("Encountered unexpected NaN value: d = " + d + "\tcbrt(d) = " + y1); } else { if (err < 0.0) { - err_adjacent = StrictMath.pow(FpUtils.nextUp(y1), 3) - d; + err_adjacent = StrictMath.pow(Math.nextUp(y1), 3) - d; } else { // (err > 0.0) - err_adjacent = StrictMath.pow(FpUtils.nextAfter(y1,0.0), 3) - d; + err_adjacent = StrictMath.pow(Math.nextAfter(y1,0.0), 3) - d; } if (Math.abs(err) > Math.abs(err_adjacent)) { @@ -200,16 +200,16 @@ public class CubeRootTests { err = d - StrictMath.pow(y2, 3); if (err != 0.0) { - if(FpUtils.isNaN(err)) { + if(Double.isNaN(err)) { failures++; System.err.println("Encountered unexpected NaN value: d = " + d + "\tcbrt(d) = " + y2); } else { if (err < 0.0) { - err_adjacent = StrictMath.pow(FpUtils.nextUp(y2), 3) - d; + err_adjacent = StrictMath.pow(Math.nextUp(y2), 3) - d; } else { // (err > 0.0) - err_adjacent = StrictMath.pow(FpUtils.nextAfter(y2,0.0), 3) - d; + err_adjacent = StrictMath.pow(Math.nextAfter(y2,0.0), 3) - d; } if (Math.abs(err) > Math.abs(err_adjacent)) { @@ -242,13 +242,13 @@ public class CubeRootTests { // Test near cbrt(2^(3n)) = 2^n. for(int i = 18; i <= DoubleConsts.MAX_EXPONENT/3; i++) { - double pc = FpUtils.scalb(1.0, 3*i); + double pc = Math.scalb(1.0, 3*i); pcNeighbors[2] = pc; pcNeighbors[1] = FpUtils.nextDown(pc); pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); - pcNeighbors[3] = FpUtils.nextUp(pc); - pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + pcNeighbors[3] = Math.nextUp(pc); + pcNeighbors[4] = Math.nextUp(pcNeighbors[3]); for(int j = 0; j < pcNeighbors.length; j++) { pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]); @@ -280,14 +280,14 @@ public class CubeRootTests { } // Test near cbrt(2^(-3n)) = 2^-n. - for(int i = -1; i >= FpUtils.ilogb(Double.MIN_VALUE)/3; i--) { - double pc = FpUtils.scalb(1.0, 3*i); + for(int i = -1; i >= DoubleConsts.MIN_SUB_EXPONENT/3; i--) { + double pc = Math.scalb(1.0, 3*i); pcNeighbors[2] = pc; pcNeighbors[1] = FpUtils.nextDown(pc); pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); - pcNeighbors[3] = FpUtils.nextUp(pc); - pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + pcNeighbors[3] = Math.nextUp(pc); + pcNeighbors[4] = Math.nextUp(pcNeighbors[3]); for(int j = 0; j < pcNeighbors.length; j++) { pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]); diff --git a/jdk/test/java/lang/Math/Expm1Tests.java b/jdk/test/java/lang/Math/Expm1Tests.java index 49fb968e3dc..f0f55d43d9e 100644 --- a/jdk/test/java/lang/Math/Expm1Tests.java +++ b/jdk/test/java/lang/Math/Expm1Tests.java @@ -82,7 +82,7 @@ public class Expm1Tests { // For |x| < 2^-54 expm1(x) ~= x for(int i = DoubleConsts.MIN_SUB_EXPONENT; i <= -54; i++) { - double d = FpUtils.scalb(2, i); + double d = Math.scalb(2, i); failures += testExpm1Case(d, d); failures += testExpm1Case(-d, -d); } @@ -101,7 +101,7 @@ public class Expm1Tests { // For x > 710, expm1(x) should be infinity for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { - double d = FpUtils.scalb(2, i); + double d = Math.scalb(2, i); failures += testExpm1Case(d, infinityD); } @@ -118,7 +118,7 @@ public class Expm1Tests { } for(int i = 7; i <= DoubleConsts.MAX_EXPONENT; i++) { - double d = -FpUtils.scalb(2, i); + double d = -Math.scalb(2, i); failures += testExpm1CaseWithUlpDiff(d, -1.0, 1, reachedLimit); } @@ -145,8 +145,8 @@ public class Expm1Tests { pcNeighbors[2] = pc; pcNeighbors[1] = FpUtils.nextDown(pc); pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); - pcNeighbors[3] = FpUtils.nextUp(pc); - pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + pcNeighbors[3] = Math.nextUp(pc); + pcNeighbors[4] = Math.nextUp(pcNeighbors[3]); for(int j = 0; j < pcNeighbors.length; j++) { pcNeighborsExpm1[j] = Math.expm1(pcNeighbors[j]); diff --git a/jdk/test/java/lang/Math/HyperbolicTests.java b/jdk/test/java/lang/Math/HyperbolicTests.java index db121575136..d82da690ea0 100644 --- a/jdk/test/java/lang/Math/HyperbolicTests.java +++ b/jdk/test/java/lang/Math/HyperbolicTests.java @@ -266,7 +266,7 @@ public class HyperbolicTests { // double significand. for(int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) { - double d = FpUtils.scalb(2.0, i); + double d = Math.scalb(2.0, i); // Result and expected are the same. failures += testSinhCaseWithUlpDiff(d, d, 2.5); @@ -344,7 +344,7 @@ public class HyperbolicTests { // sinh(x) overflows for values greater than 710; in // particular, it overflows for all 2^i, i > 10. for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { - double d = FpUtils.scalb(2.0, i); + double d = Math.scalb(2.0, i); // Result and expected are the same. failures += testSinhCaseWithUlpDiff(d, @@ -625,7 +625,7 @@ public class HyperbolicTests { // rounded. for(int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) { - double d = FpUtils.scalb(2.0, i); + double d = Math.scalb(2.0, i); // Result and expected are the same. failures += testCoshCaseWithUlpDiff(d, 1.0, 2.5); @@ -703,7 +703,7 @@ public class HyperbolicTests { // cosh(x) overflows for values greater than 710; in // particular, it overflows for all 2^i, i > 10. for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { - double d = FpUtils.scalb(2.0, i); + double d = Math.scalb(2.0, i); // Result and expected are the same. failures += testCoshCaseWithUlpDiff(d, @@ -984,7 +984,7 @@ public class HyperbolicTests { // double significand. for(int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) { - double d = FpUtils.scalb(2.0, i); + double d = Math.scalb(2.0, i); // Result and expected are the same. failures += testTanhCaseWithUlpDiff(d, d, 2.5); @@ -998,7 +998,7 @@ public class HyperbolicTests { } for(int i = 5; i <= DoubleConsts.MAX_EXPONENT; i++) { - double d = FpUtils.scalb(2.0, i); + double d = Math.scalb(2.0, i); failures += testTanhCaseWithUlpDiff(d, 1.0, 2.5); } diff --git a/jdk/test/java/lang/Math/HypotTests.java b/jdk/test/java/lang/Math/HypotTests.java index e124220c046..465497e0a4b 100644 --- a/jdk/test/java/lang/Math/HypotTests.java +++ b/jdk/test/java/lang/Math/HypotTests.java @@ -90,7 +90,7 @@ public class HypotTests { for(int i = DoubleConsts.MIN_SUB_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) { - double input = FpUtils.scalb(2, i); + double input = Math.scalb(2, i); failures += testHypotCase(input, 0.0, input); } @@ -126,7 +126,7 @@ public class HypotTests { for(int i = 0; i < 1000; i++) { double d = rand.nextDouble(); // Scale d to have an exponent equal to MAX_EXPONENT -15 - d = FpUtils.scalb(d, DoubleConsts.MAX_EXPONENT + d = Math.scalb(d, DoubleConsts.MAX_EXPONENT -15 - FpUtils.ilogb(d)); for(int j = 0; j <= 13; j += 1) { failures += testHypotCase(3*d, 4*d, 5*d, 2.5); @@ -153,13 +153,13 @@ public class HypotTests { for(int i = -18; i <= 18; i++) { - double pc = FpUtils.scalb(1.0, i); + double pc = Math.scalb(1.0, i); pcNeighbors[2] = pc; pcNeighbors[1] = FpUtils.nextDown(pc); pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); - pcNeighbors[3] = FpUtils.nextUp(pc); - pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + pcNeighbors[3] = Math.nextUp(pc); + pcNeighbors[4] = Math.nextUp(pcNeighbors[3]); for(int j = 0; j < pcNeighbors.length; j++) { pcNeighborsHypot[j] = Math.hypot(2.0, pcNeighbors[j]); diff --git a/jdk/test/java/lang/Math/IeeeRecommendedTests.java b/jdk/test/java/lang/Math/IeeeRecommendedTests.java index 6b4199e84b6..68e8a5ce6c4 100644 --- a/jdk/test/java/lang/Math/IeeeRecommendedTests.java +++ b/jdk/test/java/lang/Math/IeeeRecommendedTests.java @@ -177,7 +177,7 @@ public class IeeeRecommendedTests { } if (i > FloatConsts.MIN_EXPONENT) { - float po2minus = FpUtils.nextAfter(po2, + float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY); failures += testGetExponentCase(po2minus, i-1); } @@ -205,7 +205,7 @@ public class IeeeRecommendedTests { // Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE - testGetExponentCase(FpUtils.nextAfter(top, 0.0f), + testGetExponentCase(Math.nextAfter(top, 0.0f), FloatConsts.MIN_EXPONENT - 1); if( i >= 10) { @@ -284,7 +284,7 @@ public class IeeeRecommendedTests { } if (i > DoubleConsts.MIN_EXPONENT) { - double po2minus = FpUtils.nextAfter(po2, + double po2minus = Math.nextAfter(po2, Double.NEGATIVE_INFINITY); failures += testGetExponentCase(po2minus, i-1); } @@ -312,7 +312,7 @@ public class IeeeRecommendedTests { // Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE - testGetExponentCase(FpUtils.nextAfter(top, 0.0), + testGetExponentCase(Math.nextAfter(top, 0.0), DoubleConsts.MIN_EXPONENT - 1); if( i >= 10) { @@ -1061,7 +1061,7 @@ public class IeeeRecommendedTests { float value = someTestCases[i]; failures+=testScalbCase(value, scaleFactor, - FpUtils.copySign( (scaleFactor>0?infinityF:0.0f), value) ); + Math.copySign( (scaleFactor>0?infinityF:0.0f), value) ); } } } @@ -1095,7 +1095,7 @@ public class IeeeRecommendedTests { failures+=testScalbCase(value, scaleFactor, (FpUtils.ilogb(value) +j > FloatConsts.MAX_EXPONENT ) ? - FpUtils.copySign(infinityF, value) : // overflow + Math.copySign(infinityF, value) : // overflow // calculate right answer twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) ); scale*=2.0f; @@ -1268,7 +1268,7 @@ public class IeeeRecommendedTests { double value = someTestCases[i]; failures+=testScalbCase(value, scaleFactor, - FpUtils.copySign( (scaleFactor>0?infinityD:0.0), value) ); + Math.copySign( (scaleFactor>0?infinityD:0.0), value) ); } } } @@ -1302,7 +1302,7 @@ public class IeeeRecommendedTests { failures+=testScalbCase(value, scaleFactor, (FpUtils.ilogb(value) +j > DoubleConsts.MAX_EXPONENT ) ? - FpUtils.copySign(infinityD, value) : // overflow + Math.copySign(infinityD, value) : // overflow // calculate right answer twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) ); scale*=2.0; @@ -1423,7 +1423,7 @@ public class IeeeRecommendedTests { // Create power of two float po2 = powerOfTwoF(i); - expected = FpUtils.scalb(1.0f, i - (FloatConsts.SIGNIFICAND_WIDTH-1)); + expected = Math.scalb(1.0f, i - (FloatConsts.SIGNIFICAND_WIDTH-1)); failures += testUlpCase(po2, expected); @@ -1443,7 +1443,7 @@ public class IeeeRecommendedTests { } if (i > FloatConsts.MIN_EXPONENT) { - float po2minus = FpUtils.nextAfter(po2, + float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY); failures += testUlpCase(po2minus, expected/2.0f); } @@ -1470,7 +1470,7 @@ public class IeeeRecommendedTests { // Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE - testUlpCase(FpUtils.nextAfter(top, 0.0f), + testUlpCase(Math.nextAfter(top, 0.0f), Float.MIN_VALUE); if( i >= 10) { @@ -1528,7 +1528,7 @@ public class IeeeRecommendedTests { // Create power of two double po2 = powerOfTwoD(i); - expected = FpUtils.scalb(1.0, i - (DoubleConsts.SIGNIFICAND_WIDTH-1)); + expected = Math.scalb(1.0, i - (DoubleConsts.SIGNIFICAND_WIDTH-1)); failures += testUlpCase(po2, expected); @@ -1548,7 +1548,7 @@ public class IeeeRecommendedTests { } if (i > DoubleConsts.MIN_EXPONENT) { - double po2minus = FpUtils.nextAfter(po2, + double po2minus = Math.nextAfter(po2, Double.NEGATIVE_INFINITY); failures += testUlpCase(po2minus, expected/2.0f); } @@ -1575,7 +1575,7 @@ public class IeeeRecommendedTests { // Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE - testUlpCase(FpUtils.nextAfter(top, 0.0f), + testUlpCase(Math.nextAfter(top, 0.0f), Double.MIN_VALUE); if( i >= 10) { diff --git a/jdk/test/java/lang/Math/Log10Tests.java b/jdk/test/java/lang/Math/Log10Tests.java index 60d9ec6f3f5..c245a7477ff 100644 --- a/jdk/test/java/lang/Math/Log10Tests.java +++ b/jdk/test/java/lang/Math/Log10Tests.java @@ -153,12 +153,12 @@ public class Log10Tests { for(int i = 0; i < half; i++) { if (i == 0) { input[half] = 1.0; - up = FpUtils.nextUp(1.0); + up = Math.nextUp(1.0); down = FpUtils.nextDown(1.0); } else { input[half + i] = up; input[half - i] = down; - up = FpUtils.nextUp(up); + up = Math.nextUp(up); down = FpUtils.nextDown(down); } } diff --git a/jdk/test/java/lang/Math/Log1pTests.java b/jdk/test/java/lang/Math/Log1pTests.java index 1666d7b6c62..bd5f0e0aeab 100644 --- a/jdk/test/java/lang/Math/Log1pTests.java +++ b/jdk/test/java/lang/Math/Log1pTests.java @@ -88,14 +88,14 @@ public class Log1pTests { // For |x| < 2^-54 log1p(x) ~= x for(int i = DoubleConsts.MIN_SUB_EXPONENT; i <= -54; i++) { - double d = FpUtils.scalb(2, i); + double d = Math.scalb(2, i); failures += testLog1pCase(d, d); failures += testLog1pCase(-d, -d); } // For x > 2^53 log1p(x) ~= log(x) for(int i = 53; i <= DoubleConsts.MAX_EXPONENT; i++) { - double d = FpUtils.scalb(2, i); + double d = Math.scalb(2, i); failures += testLog1pCaseWithUlpDiff(d, StrictMath.log(d), 2.001); } @@ -105,7 +105,7 @@ public class Log1pTests { for(int i = 0; i < 1000; i++) { double d = rand.nextDouble(); - d = FpUtils.scalb(d, -53 - FpUtils.ilogb(d)); + d = Math.scalb(d, -53 - FpUtils.ilogb(d)); for(int j = -53; j <= 52; j++) { failures += testLog1pCaseWithUlpDiff(d, hp15cLogp(d), 5); @@ -137,8 +137,8 @@ public class Log1pTests { pcNeighbors[2] = pc; pcNeighbors[1] = FpUtils.nextDown(pc); pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); - pcNeighbors[3] = FpUtils.nextUp(pc); - pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + pcNeighbors[3] = Math.nextUp(pc); + pcNeighbors[4] = Math.nextUp(pcNeighbors[3]); for(int j = 0; j < pcNeighbors.length; j++) { pcNeighborsLog1p[j] = Math.log1p(pcNeighbors[j]); diff --git a/jdk/test/java/lang/Math/Rint.java b/jdk/test/java/lang/Math/Rint.java index 49a8edd4352..09821c82b0b 100644 --- a/jdk/test/java/lang/Math/Rint.java +++ b/jdk/test/java/lang/Math/Rint.java @@ -48,7 +48,7 @@ public class Rint { public static void main(String args[]) { int failures = 0; - double twoToThe52 = FpUtils.scalb(1.0, 52); // 2^52 + double twoToThe52 = Math.scalb(1.0, 52); // 2^52 double [][] testCases = { {0.0, 0.0}, @@ -60,16 +60,16 @@ public class Rint { {FpUtils.nextDown(0.5), 0.0}, { 0.5, 0.0}, - { FpUtils.nextUp(0.5), 1.0}, + { Math.nextUp(0.5), 1.0}, {0.7, 1.0}, {FpUtils.nextDown(1.0), 1.0}, { 1.0, 1.0}, - { FpUtils.nextUp(1.0), 1.0}, + { Math.nextUp(1.0), 1.0}, {FpUtils.nextDown(1.5), 1.0}, { 1.5, 2.0}, - { FpUtils.nextUp(1.5), 2.0}, + { Math.nextUp(1.5), 2.0}, {4.2, 4.0}, {4.5, 4.0}, @@ -81,10 +81,10 @@ public class Rint { {150000.75, 150001.0}, {300000.5, 300000.0}, - {FpUtils.nextUp(300000.5), 300001.0}, + {Math.nextUp(300000.5), 300001.0}, {FpUtils.nextDown(300000.75), 300001.0}, {300000.75, 300001.0}, - {FpUtils.nextUp(300000.75), 300001.0}, + {Math.nextUp(300000.75), 300001.0}, {300000.99, 300001.0}, {262144.75, 262145.0}, //(2^18 ) + 0.75 {499998.75, 499999.0}, @@ -93,7 +93,7 @@ public class Rint { {FpUtils.nextDown(twoToThe52), twoToThe52}, {twoToThe52, twoToThe52}, - {FpUtils.nextUp(twoToThe52), FpUtils.nextUp(twoToThe52)}, + {Math.nextUp(twoToThe52), Math.nextUp(twoToThe52)}, {Double.MAX_VALUE, Double.MAX_VALUE}, {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, From b88865d91f1859b3d30617bc65de0beca11c8bf3 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Mon, 19 Sep 2011 15:14:17 +0100 Subject: [PATCH 099/214] 7091369: DatagramSocket/Limit.java failing on 8 and 7u2 Reviewed-by: chegar, alanb --- .../classes/java/net/TwoStacksPlainDatagramSocketImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java index 0729d76ada4..ebd5e527ca2 100644 --- a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -68,7 +68,12 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl protected synchronized void create() throws SocketException { fd1 = new FileDescriptor(); - super.create(); + try { + super.create(); + } catch (IOException e) { + fd1 = null; + throw e; + } } protected synchronized void bind(int lport, InetAddress laddr) From 9661feecbc94a4ac110ed555098da20746d11c0d Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 19 Sep 2011 15:21:03 -0700 Subject: [PATCH 100/214] 7091764: Tiered: enable aastore profiling Turn on aastore profiling Reviewed-by: jrose, twisti --- hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp | 5 +++-- hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp | 5 +++-- hotspot/src/share/vm/c1/c1_LIR.cpp | 11 +++++++++-- hotspot/src/share/vm/c1/c1_LIR.hpp | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 7b60789d221..abf3ab9d513 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -328,7 +328,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { bool use_length = x->length() != NULL; bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT; bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL || - !get_jobject_constant(x->value())->is_null_object()); + !get_jobject_constant(x->value())->is_null_object() || + x->should_profile()); LIRItem array(x->array(), this); LIRItem index(x->index(), this); @@ -382,7 +383,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { LIR_Opr tmp3 = FrameMap::G5_opr; CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info); - __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info); + __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci()); } if (obj_store) { diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index c71590a2614..1ff91cafb90 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -267,7 +267,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { bool use_length = x->length() != NULL; bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT; bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL || - !get_jobject_constant(x->value())->is_null_object()); + !get_jobject_constant(x->value())->is_null_object() || + x->should_profile()); LIRItem array(x->array(), this); LIRItem index(x->index(), this); @@ -321,7 +322,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { LIR_Opr tmp3 = new_register(objectType); CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info); - __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info); + __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci()); } if (obj_store) { diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index 44f2b62a7bd..267b966641c 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1394,8 +1394,15 @@ void LIR_List::instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Op } -void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception) { - append(new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception)); +void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, + CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci) { + LIR_OpTypeCheck* c = new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception); + if (profiled_method != NULL) { + c->set_profiled_method(profiled_method); + c->set_profiled_bci(profiled_bci); + c->set_should_profile(true); + } + append(c); } diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index a2770e402df..c440b71374f 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -2100,7 +2100,7 @@ class LIR_List: public CompilationResourceObj { void fpop_raw() { append(new LIR_Op0(lir_fpop_raw)); } void instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch, ciMethod* profiled_method, int profiled_bci); - void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception); + void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci); void checkcast (LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, From 4d4a89de9b13d1184674cd5e51c96f031e73702a Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 20 Sep 2011 12:40:23 +0800 Subject: [PATCH 101/214] 7091290: fails to build jdk8 b05 Embedded build Reviewed-by: xuelei, dholmes --- jdk/src/share/classes/org/ietf/jgss/Oid.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/org/ietf/jgss/Oid.java b/jdk/src/share/classes/org/ietf/jgss/Oid.java index 294ec1fce72..eb55ff95197 100644 --- a/jdk/src/share/classes/org/ietf/jgss/Oid.java +++ b/jdk/src/share/classes/org/ietf/jgss/Oid.java @@ -157,7 +157,7 @@ public class Oid { return (true); if (other instanceof Oid) - return this.oid.equals(((Oid) other).oid); + return this.oid.equals((Object)((Oid) other).oid); else if (other instanceof ObjectIdentifier) return this.oid.equals(other); else From a46128d0ddf85158a80510059a8a932d84d6cc0c Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 20 Sep 2011 08:39:40 -0700 Subject: [PATCH 102/214] 7081842: assert(Compile::current()->unique() < (uint)MaxNodeLimit) failed: Node limit exceeded Add missing node limit check in IGVN optimizer Reviewed-by: iveresov, never --- hotspot/make/linux/build.sh | 5 ++- .../sun/hotspot/tools/compiler/CallSite.java | 33 ++++++++++++++++--- .../tools/compiler/LogCompilation.java | 4 +-- .../sun/hotspot/tools/compiler/LogParser.java | 9 +++-- .../com/sun/hotspot/tools/compiler/Phase.java | 4 +-- hotspot/src/share/vm/opto/phaseX.cpp | 6 +++- 6 files changed, 48 insertions(+), 13 deletions(-) diff --git a/hotspot/make/linux/build.sh b/hotspot/make/linux/build.sh index f46b8dfcfa0..79844c51e1e 100644 --- a/hotspot/make/linux/build.sh +++ b/hotspot/make/linux/build.sh @@ -1,6 +1,6 @@ #! /bin/sh # -# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,9 @@ case `uname -m` in i386|i486|i586|i686) mach=i386 ;; + x86_64) + mach=amd64 + ;; *) echo "Unsupported machine: " `uname -m` exit 1 diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java index c72d77714d9..354b32a99d7 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ public class CallSite { private int receiver_count; private String reason; private List calls; + private int endNodes; + private double timeStamp; CallSite() { } @@ -93,18 +95,22 @@ public class CallSite { emit(stream, indent); String m = getMethod().getHolder().replace('/', '.') + "::" + getMethod().getName(); if (getReason() == null) { - stream.println(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); + stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); } else { if (isCompat()) { - stream.println(" @ " + getBci() + " " + m + " " + getReason()); + stream.print(" @ " + getBci() + " " + m + " " + getReason()); } else { - stream.println("- @ " + getBci() + " " + m + + stream.print("- @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes) " + getReason()); } } + if (getEndNodes() > 0) { + stream.printf(" (end time: %6.4f nodes: %d)", getTimeStamp(), getEndNodes()); + } + stream.println(""); if (getReceiver() != null) { - emit(stream, indent + 3); + emit(stream, indent + 4); // stream.println("type profile " + method.holder + " -> " + receiver + " (" + // receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)"); stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" + @@ -180,4 +186,21 @@ public class CallSite { public static void setCompat(boolean aCompat) { compat = aCompat; } + + void setEndNodes(int n) { + endNodes = n; + } + + public int getEndNodes() { + return endNodes; + } + + void setTimeStamp(double time) { + timeStamp = time; + } + + public double getTimeStamp() { + return timeStamp; + } + } diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java index 57058882f91..12689b0d3cc 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,6 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons maxattempts = Math.max(maxattempts,c.getAttempts()); elapsed += c.getElapsedTime(); for (Phase phase : c.getPhases()) { - out.printf("\t%s %6.4f\n", phase.getName(), phase.getElapsedTime()); Double v = phaseTime.get(phase.getName()); if (v == null) { v = Double.valueOf(0.0); @@ -138,6 +137,7 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons v2 = Integer.valueOf(0); } phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes())); + out.printf("\t%s %6.4f %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes()); } } else if (e instanceof MakeNotEntrantEvent) { MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e; diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java index 265e92e0dfd..d864db0ff71 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -365,7 +365,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants if (currentTrap != null) { currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); } else { - System.err.println("Missing uncommon_trap for jvms"); + // Ignore and } } else if (qname.equals("nmethod")) { String id = makeId(atts); @@ -391,6 +391,11 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants throw new InternalError("call site and parse don't match"); } } + } else if (qname.equals("parse_done")) { + CallSite call = scopes.pop(); + call.setEndNodes(Integer.parseInt(search(atts, "nodes"))); + call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); + scopes.push(call); } } diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java index 4dc50ca4e5a..b448f457bee 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ public class Phase extends BasicLogEvent { } int getNodes() { - return getStartNodes(); + return getEndNodes() - getStartNodes(); } void setEndNodes(int n) { diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index 7b5d6cddc23..541744ac8a5 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -864,6 +864,10 @@ void PhaseIterGVN::optimize() { // Pull from worklist; transform node; // If node has changed: update edge info and put uses on worklist. while( _worklist.size() ) { + if (C->check_node_count(NodeLimitFudgeFactor * 2, + "out of nodes optimizing method")) { + return; + } Node *n = _worklist.pop(); if (++loop_count >= K * C->unique()) { debug_only(n->dump(4);) From 1577e0f0733210fff49b789fc8e589d8d6082911 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 20 Sep 2011 12:08:48 -0700 Subject: [PATCH 103/214] 7030473: Remove dead field JCCompilationUnit.flags Reviewed-by: dlsmith --- langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java | 1 - 1 file changed, 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 87f147f23cf..564e63cd30e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -436,7 +436,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public PackageSymbol packge; public ImportScope namedImportScope; public StarImportScope starImportScope; - public long flags; public Position.LineMap lineMap = null; public Map docComments = null; public Map endPositions = null; From b9c11d661eaf0606e040da69fed405b6cebd1794 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 20 Sep 2011 12:27:45 -0700 Subject: [PATCH 104/214] 7074264: Switches to packages tree view and adds unit tests to sources Reviewed-by: igor --- jdk/make/netbeans/README | 45 ++++++++----------- .../netbeans/common/closed-share-view.ent | 4 +- jdk/make/netbeans/common/java-data-native.ent | 7 ++- .../netbeans/common/java-data-no-native.ent | 7 ++- jdk/make/netbeans/common/jtreg-view.ent | 2 +- jdk/make/netbeans/common/sample-view.ent | 2 +- jdk/make/netbeans/common/share-view.ent | 2 +- jdk/make/netbeans/common/unix-view.ent | 2 +- jdk/make/netbeans/common/windows-view.ent | 2 +- jdk/make/netbeans/j2se/nbproject/project.xml | 6 ++- 10 files changed, 42 insertions(+), 37 deletions(-) diff --git a/jdk/make/netbeans/README b/jdk/make/netbeans/README index a375b8b55e3..ffae80f95ce 100644 --- a/jdk/make/netbeans/README +++ b/jdk/make/netbeans/README @@ -5,7 +5,7 @@ Working on OpenJDK using NetBeans Getting Started In addition to the source bundle for Open JDK, you'll need to download - and install copies of the JDK and of NetBeans 6. And if you want to run + and install copies of the JDK and of NetBeans. And if you want to run tests on the JDK (you do want to run tests, right?), you'll need to install the jtreg test harness. @@ -20,30 +20,28 @@ Getting Started Downloading the JDK You've probably done this a million times. Download and install it - from http://java.sun.com/javase + from http://www.oracle.com/technetwork/java/javase/overview/index.html Downloading the OpenJDK sources Since you're reading this, d you've already downloaded the OpenJDK source bundle. Later in this document we'll refer to the location where you installed the Open JDK sources as *install-dir*. - Downloading a pre-built, JDK 7 + Downloading a pre-built, JDK 8 This will be necessary to do builds of some of the projects. In general, you want to download and install a pre-built JDK that corresponds to the OpenJDK sources you download. Building the entire OpenJDK depends on a few parts of the pre-built JDK. Get this from - http://download.java.net/jdk7/binaries + http://download.java.net/jdk8/binaries - Note: For working on certain projects, like JMX and JConsole, you - may find convenient to use a pre-built version of JDK 7 (or + Note: For working on certain projects, like JMX and JConsole, you + may find convenient to use a pre-built version of JDK 8 (or OpenJDK) rather than building your own. This will allow you to build only that part of the OpenJDK sources which correspond - to that project. + to that project. - NetBeans 6 - Yep, NetBeans *6*. Nope, not FCS'd yet. We're on the edge here, - enjoy it! Get the latest working development build of NetBeans 6 - from http://netbeans.org + NetBeans 7.0 or later + Older versions may also work but are unsupported. jtreg "jtreg" is the test harness for running OpenJDK's regression tests. @@ -51,7 +49,7 @@ Getting Started Ant NetBeans comes with ant, but if you use a separately-installed copy - please make sure that it is at least version 1.7.0. + please make sure that it is at least version 1.8.1. Configuring Building OpenJDK is hard and complex. No, strike that. While it's not @@ -92,8 +90,8 @@ Configuring situation: make.options=\ - ALT_BOOTDIR=/home/me/bin/jdk1.6.0 \ - ALT_JDK_IMPORT_PATH=/home/me/bin/jdk1.7.0 \ + ALT_BOOTDIR=/home/me/bin/jdk1.7.0 \ + ALT_JDK_IMPORT_PATH=/home/me/bin/jdk1.8.0 \ OPENJDK=true The trailing '\' are important, so that make gets the above as a @@ -107,7 +105,7 @@ Configuring Windows-specific configuration First, please note that the entire JDK cannot currently be built on Windows platforms. This will likely limit your ability to build - make-based projects. See + make-based projects. See *install-dir*/jdk/make/README-builds.html for full information on issues with building on the Windows platform. @@ -141,7 +139,7 @@ Configuring editor. Locale Requirements - To build the Open JDK sources, be certain that you are using the "C" + To build the OpenJDK sources, be certain that you are using the "C" locale on Unix (R) platforms, or "English (United States)" locale on Windows. @@ -220,13 +218,13 @@ Provided NetBeans projects running and debugging JConsole. This ant-based project does *not* require that you build the jdk - project first, provided that you use a pre-built version of JDK 7. + project first, provided that you use a pre-built version of JDK 7. Java (TM) Management Extensions (JMX(TM)) API (directory "jmx") For working on JMX source code. Creates ../dist/lib/jmx.jar. This ant-based project does *not* require that you build the jdk - project first, provided that you use a pre-built version of JDK 7. + project first, provided that you use a pre-built version of JDK 7. Jar & Zip (directory "jarzip") For working on jar & zip. It builds the zip library (including @@ -242,12 +240,12 @@ Provided NetBeans projects running and debugging the SampleTree demo. This ant-based project does *not* require that you build the jdk - project first, provided that you use a pre-built version of JDK 7. + project first, provided that you use a pre-built version of JDK 7. In addition, there are projects for building the compiler, javadoc, and related tools, in the OpenJDK langtools component. These projects are separate from those described here, and have their - own set of guidelines and conventions. For more details, see the + own set of guidelines and conventions. For more details, see the README files in make/netbeans in the OpenJDK langtools component. Running Tests @@ -603,13 +601,6 @@ Appendix 1: Customizations * -clean-make Known Issues - Tests won't run: waiting for lock - Occasionally when running tests, there will be a delay, followed by a - message like this: - Waiting to lock test result cache for - /tmp/jdk/build/linux-i586/jtreg/jconsole/JTwork for 20 seconds - The workaround is to stop the tests, rm -rf the offending jtreg/ - directory by hand, and re-run the tests. Can't run nor debug a single test in the JConsole test In most projects, you can run a single test by opening it in the editor, diff --git a/jdk/make/netbeans/common/closed-share-view.ent b/jdk/make/netbeans/common/closed-share-view.ent index 6ef29331f9d..82fe0cab525 100644 --- a/jdk/make/netbeans/common/closed-share-view.ent +++ b/jdk/make/netbeans/common/closed-share-view.ent @@ -31,8 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - - + + ${root}/src/closed/share/classes ${includes} ${excludes} diff --git a/jdk/make/netbeans/common/java-data-native.ent b/jdk/make/netbeans/common/java-data-native.ent index fb531ed8921..a801e821db6 100644 --- a/jdk/make/netbeans/common/java-data-native.ent +++ b/jdk/make/netbeans/common/java-data-native.ent @@ -38,7 +38,12 @@ ${root}/src/solaris/classes ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes - ${root}/build/javadoc/${name} + ${root}/build/${platform}-${arch}/docs/api + 1.7 + + + ${root}/test + 1.7 diff --git a/jdk/make/netbeans/common/java-data-no-native.ent b/jdk/make/netbeans/common/java-data-no-native.ent index 2e1b791bd50..a204f3a6f17 100644 --- a/jdk/make/netbeans/common/java-data-no-native.ent +++ b/jdk/make/netbeans/common/java-data-no-native.ent @@ -36,7 +36,12 @@ ${root}/src/share/classes ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes - ${root}/build/javadoc/${name} + ${root}/build/${platform}-${arch}/docs/api + 1.7 + + + ${root}/test + 1.7 diff --git a/jdk/make/netbeans/common/jtreg-view.ent b/jdk/make/netbeans/common/jtreg-view.ent index 899df888e23..ce0d2dad3ed 100644 --- a/jdk/make/netbeans/common/jtreg-view.ent +++ b/jdk/make/netbeans/common/jtreg-view.ent @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + ${root}/test ${jtreg.tests} diff --git a/jdk/make/netbeans/common/sample-view.ent b/jdk/make/netbeans/common/sample-view.ent index 70cdd2397ca..9b470ef9d54 100644 --- a/jdk/make/netbeans/common/sample-view.ent +++ b/jdk/make/netbeans/common/sample-view.ent @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + ${root}/src/share/sample ${samples} diff --git a/jdk/make/netbeans/common/share-view.ent b/jdk/make/netbeans/common/share-view.ent index 0b0dde08a2b..2d607889ce6 100644 --- a/jdk/make/netbeans/common/share-view.ent +++ b/jdk/make/netbeans/common/share-view.ent @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + ${root}/src/share/classes ${includes} diff --git a/jdk/make/netbeans/common/unix-view.ent b/jdk/make/netbeans/common/unix-view.ent index c1176f66d74..84f168b2927 100644 --- a/jdk/make/netbeans/common/unix-view.ent +++ b/jdk/make/netbeans/common/unix-view.ent @@ -35,7 +35,7 @@ UNIX is a registered trademark in the United States and other countries, exclusively licensed through X/Open Company, Ltd. --> - + ${root}/src/solaris/classes ${includes} diff --git a/jdk/make/netbeans/common/windows-view.ent b/jdk/make/netbeans/common/windows-view.ent index 38419c2cf5a..8e80c6cfce3 100644 --- a/jdk/make/netbeans/common/windows-view.ent +++ b/jdk/make/netbeans/common/windows-view.ent @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + ${root}/src/windows/classes ${includes} diff --git a/jdk/make/netbeans/j2se/nbproject/project.xml b/jdk/make/netbeans/j2se/nbproject/project.xml index 7cc5b516721..784ab7232b8 100644 --- a/jdk/make/netbeans/j2se/nbproject/project.xml +++ b/jdk/make/netbeans/j2se/nbproject/project.xml @@ -1,7 +1,7 @@