Merge
This commit is contained in:
commit
0745d10694
@ -518,10 +518,10 @@ static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id,
|
||||
}
|
||||
|
||||
static ps_prochandle_ops core_ops = {
|
||||
release: core_release,
|
||||
p_pread: core_read_data,
|
||||
p_pwrite: core_write_data,
|
||||
get_lwp_regs: core_get_lwp_regs
|
||||
.release= core_release,
|
||||
.p_pread= core_read_data,
|
||||
.p_pwrite= core_write_data,
|
||||
.get_lwp_regs= core_get_lwp_regs
|
||||
};
|
||||
|
||||
// read regs and create thread from NT_PRSTATUS entries from core file
|
||||
|
@ -291,10 +291,10 @@ static void process_cleanup(struct ps_prochandle* ph) {
|
||||
}
|
||||
|
||||
static ps_prochandle_ops process_ops = {
|
||||
release: process_cleanup,
|
||||
p_pread: process_read_data,
|
||||
p_pwrite: process_write_data,
|
||||
get_lwp_regs: process_get_lwp_regs
|
||||
.release= process_cleanup,
|
||||
.p_pread= process_read_data,
|
||||
.p_pwrite= process_write_data,
|
||||
.get_lwp_regs= process_get_lwp_regs
|
||||
};
|
||||
|
||||
// attach to the process. One and only one exposed stuff
|
||||
|
@ -80,6 +80,11 @@ ifneq ("$(filter $(LP64_ARCH),$(BUILDARCH))","")
|
||||
MFLAGS += " LP64=1 "
|
||||
endif
|
||||
|
||||
# pass USE_SUNCC further, through MFLAGS
|
||||
ifdef USE_SUNCC
|
||||
MFLAGS += " USE_SUNCC=1 "
|
||||
endif
|
||||
|
||||
# The following renders pathnames in generated Makefiles valid on
|
||||
# machines other than the machine containing the build tree.
|
||||
#
|
||||
|
@ -35,6 +35,8 @@ CFLAGS += -DVM_LITTLE_ENDIAN
|
||||
CFLAGS += -D_LP64=1
|
||||
|
||||
# The serviceability agent relies on frame pointer (%rbp) to walk thread stack
|
||||
CFLAGS += -fno-omit-frame-pointer
|
||||
ifndef USE_SUNCC
|
||||
CFLAGS += -fno-omit-frame-pointer
|
||||
endif
|
||||
|
||||
OPT_CFLAGS/compactingPermGenGen.o = -O1
|
||||
|
@ -63,7 +63,11 @@ QUIETLY$(MAKE_VERBOSE) = @
|
||||
# For now, until the compiler is less wobbly:
|
||||
TESTFLAGS = -Xbatch -showversion
|
||||
|
||||
PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH)
|
||||
ifdef USE_SUNCC
|
||||
PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH).suncc
|
||||
else
|
||||
PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH)
|
||||
endif
|
||||
|
||||
ifdef FORCE_TIERED
|
||||
ifeq ($(VARIANT),tiered)
|
||||
|
93
hotspot/build/linux/makefiles/sparcWorks.make
Normal file
93
hotspot/build/linux/makefiles/sparcWorks.make
Normal file
@ -0,0 +1,93 @@
|
||||
#
|
||||
# Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact 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.
|
||||
#
|
||||
#
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# CC, CPP & AS
|
||||
|
||||
CPP = CC
|
||||
CC = cc
|
||||
AS = $(CC) -c
|
||||
|
||||
ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
|
||||
ARCHFLAG/i486 = -m32
|
||||
ARCHFLAG/amd64 = -m64
|
||||
|
||||
CFLAGS += $(ARCHFLAG)
|
||||
AOUT_FLAGS += $(ARCHFLAG)
|
||||
LFLAGS += $(ARCHFLAG)
|
||||
ASFLAGS += $(ARCHFLAG)
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Compiler flags
|
||||
|
||||
# position-independent code
|
||||
PICFLAG = -KPIC
|
||||
|
||||
CFLAGS += $(PICFLAG)
|
||||
# no more exceptions
|
||||
CFLAGS += -features=no%except
|
||||
# Reduce code bloat by reverting back to 5.0 behavior for static initializers
|
||||
CFLAGS += -features=no%split_init
|
||||
# allow zero sized arrays
|
||||
CFLAGS += -features=zla
|
||||
|
||||
# Use C++ Interpreter
|
||||
ifdef CC_INTERP
|
||||
CFLAGS += -DCC_INTERP
|
||||
endif
|
||||
|
||||
# We don't need libCstd.so and librwtools7.so, only libCrun.so
|
||||
CFLAGS += -library=Crun
|
||||
LIBS += -lCrun
|
||||
|
||||
CFLAGS += -mt
|
||||
LFLAGS += -mt
|
||||
|
||||
# Compiler warnings are treated as errors
|
||||
#WARNINGS_ARE_ERRORS = -errwarn=%all
|
||||
CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS)
|
||||
# Special cases
|
||||
CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
|
||||
|
||||
# The flags to use for an Optimized build
|
||||
OPT_CFLAGS+=-xO4
|
||||
OPT_CFLAGS/NOOPT=-xO0
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Linker flags
|
||||
|
||||
# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
|
||||
MAPFLAG = -Wl,--version-script=FILENAME
|
||||
|
||||
# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
|
||||
SONAMEFLAG = -h SONAME
|
||||
|
||||
# Build shared library
|
||||
SHARED_FLAG = -G
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Debug flags
|
||||
DEBUG_CFLAGS += -g
|
||||
FASTDEBUG_CFLAGS = -g0
|
||||
|
17
hotspot/build/linux/platform_amd64.suncc
Normal file
17
hotspot/build/linux/platform_amd64.suncc
Normal file
@ -0,0 +1,17 @@
|
||||
os_family = linux
|
||||
|
||||
arch = x86
|
||||
|
||||
arch_model = x86_64
|
||||
|
||||
os_arch = linux_x86
|
||||
|
||||
os_arch_model = linux_x86_64
|
||||
|
||||
lib_arch = amd64
|
||||
|
||||
compiler = sparcWorks
|
||||
|
||||
gnu_dis_arch = amd64
|
||||
|
||||
sysdefs = -DLINUX -DSPARC_WORKS -D_GNU_SOURCE -DAMD64
|
17
hotspot/build/linux/platform_i486.suncc
Normal file
17
hotspot/build/linux/platform_i486.suncc
Normal file
@ -0,0 +1,17 @@
|
||||
os_family = linux
|
||||
|
||||
arch = x86
|
||||
|
||||
arch_model = x86_32
|
||||
|
||||
os_arch = linux_x86
|
||||
|
||||
os_arch_model = linux_x86_32
|
||||
|
||||
lib_arch = i386
|
||||
|
||||
compiler = sparcWorks
|
||||
|
||||
gnu_dis_arch = i386
|
||||
|
||||
sysdefs = -DLINUX -DSPARC_WORKS -D_GNU_SOURCE -DIA32
|
@ -1304,7 +1304,7 @@ void Assembler::movl(Address dst, Register src) {
|
||||
emit_operand(src, dst);
|
||||
}
|
||||
|
||||
void Assembler::mov64(Register dst, int64_t imm64) {
|
||||
void Assembler::mov64(Register dst, intptr_t imm64) {
|
||||
InstructionMark im(this);
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
emit_byte(0xB8 | encode);
|
||||
@ -1331,7 +1331,7 @@ void Assembler::movq(Register dst, Address src) {
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::mov64(Address dst, int64_t imm32) {
|
||||
void Assembler::mov64(Address dst, intptr_t imm32) {
|
||||
assert(is_simm32(imm32), "lost bits");
|
||||
InstructionMark im(this);
|
||||
prefixq(dst);
|
||||
|
@ -232,7 +232,7 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
|
||||
// where <ver> is the protocol version (1), <cmd> is the command
|
||||
// name ("load", "datadump", ...), and <arg> is an argument
|
||||
int expected_str_count = 2 + AttachOperation::arg_count_max;
|
||||
int max_len = (strlen(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
|
||||
const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
|
||||
AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
|
||||
|
||||
char buf[max_len];
|
||||
|
@ -60,7 +60,18 @@ inline u4 Bytes::swap_u4(u4 x) {
|
||||
|
||||
#ifdef AMD64
|
||||
inline u8 Bytes::swap_u8(u8 x) {
|
||||
#ifdef SPARC_WORKS
|
||||
// workaround for SunStudio12 CR6615391
|
||||
__asm__ __volatile__ (
|
||||
"bswapq %0"
|
||||
:"=r" (x) // output : register 0 => x
|
||||
:"0" (x) // input : x => register 0
|
||||
:"0" // clobbered register
|
||||
);
|
||||
return x;
|
||||
#else
|
||||
return bswap_64(x);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
// Helper function for swap_u8
|
||||
|
@ -62,8 +62,14 @@
|
||||
#endif // AMD64
|
||||
|
||||
address os::current_stack_pointer() {
|
||||
#ifdef SPARC_WORKS
|
||||
register void *esp;
|
||||
__asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp));
|
||||
return (address) ((char*)esp + sizeof(long)*2);
|
||||
#else
|
||||
register void *esp __asm__ (SPELL_REG_SP);
|
||||
return (address) esp;
|
||||
#endif
|
||||
}
|
||||
|
||||
char* os::non_memory_address_word() {
|
||||
@ -139,7 +145,12 @@ frame os::get_sender_for_C_frame(frame* fr) {
|
||||
}
|
||||
|
||||
intptr_t* _get_previous_fp() {
|
||||
#ifdef SPARC_WORKS
|
||||
register intptr_t **ebp;
|
||||
__asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp));
|
||||
#else
|
||||
register intptr_t **ebp __asm__ (SPELL_REG_FP);
|
||||
#endif
|
||||
return (intptr_t*) *ebp; // we want what it points to.
|
||||
}
|
||||
|
||||
@ -560,7 +571,9 @@ bool os::Linux::supports_variable_stack_size() { return true; }
|
||||
#else
|
||||
size_t os::Linux::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
|
||||
#endif
|
||||
|
||||
// Test if pthread library can support variable thread stack size. LinuxThreads
|
||||
// in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
|
||||
@ -591,7 +604,11 @@ bool os::Linux::supports_variable_stack_size() {
|
||||
// return true and skip _thread_safety_check(), so we may not be able to
|
||||
// detect stack-heap collisions. But otherwise it's harmless.
|
||||
//
|
||||
#ifdef __GNUC__
|
||||
return (GET_GS() != 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // AMD64
|
||||
|
@ -155,8 +155,8 @@ bool Dictionary::do_unloading(BoolObjectClosure* is_alive) {
|
||||
for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
|
||||
// check the previous versions array for GC'ed weak refs
|
||||
PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
|
||||
jweak cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
|
||||
jobject cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
|
||||
if (cp_ref == NULL) {
|
||||
delete pv_node;
|
||||
ik->previous_versions()->remove_at(i);
|
||||
|
@ -3067,6 +3067,7 @@ oopMap.hpp vmreg.hpp
|
||||
|
||||
oopMapCache.cpp allocation.inline.hpp
|
||||
oopMapCache.cpp handles.inline.hpp
|
||||
oopMapCache.cpp jvmtiRedefineClassesTrace.hpp
|
||||
oopMapCache.cpp oop.inline.hpp
|
||||
oopMapCache.cpp oopMapCache.hpp
|
||||
oopMapCache.cpp resourceArea.hpp
|
||||
|
@ -532,6 +532,10 @@ void OopMapCache::flush_obsolete_entries() {
|
||||
if (!_array[i].is_empty() && _array[i].method()->is_old()) {
|
||||
// Cache entry is occupied by an old redefined method and we don't want
|
||||
// to pin it down so flush the entry.
|
||||
RC_TRACE(0x08000000, ("flush: %s(%s): cached entry @%d",
|
||||
_array[i].method()->name()->as_C_string(),
|
||||
_array[i].method()->signature()->as_C_string(), i));
|
||||
|
||||
_array[i].flush();
|
||||
}
|
||||
}
|
||||
@ -577,6 +581,15 @@ void OopMapCache::lookup(methodHandle method,
|
||||
// Entry is not in hashtable.
|
||||
// Compute entry and return it
|
||||
|
||||
if (method->should_not_be_cached()) {
|
||||
// It is either not safe or not a good idea to cache this methodOop
|
||||
// at this time. We give the caller of lookup() a copy of the
|
||||
// interesting info via parameter entry_for, but we don't add it to
|
||||
// the cache. See the gory details in methodOop.cpp.
|
||||
compute_one_oop_map(method, bci, entry_for);
|
||||
return;
|
||||
}
|
||||
|
||||
// First search for an empty slot
|
||||
for(i = 0; i < _probe_depth; i++) {
|
||||
entry = entry_at(probe + i);
|
||||
@ -584,12 +597,6 @@ void OopMapCache::lookup(methodHandle method,
|
||||
entry->fill(method, bci);
|
||||
entry_for->resource_copy(entry);
|
||||
assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
|
||||
if (method->is_old()) {
|
||||
// The caller of lookup() will receive a copy of the interesting
|
||||
// info via entry_for, but we don't keep an old redefined method in
|
||||
// the cache to avoid pinning down the method.
|
||||
entry->flush();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -623,13 +630,6 @@ void OopMapCache::lookup(methodHandle method,
|
||||
}
|
||||
assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
|
||||
|
||||
if (method->is_old()) {
|
||||
// The caller of lookup() will receive a copy of the interesting
|
||||
// info via entry_for, but we don't keep an old redefined method in
|
||||
// the cache to avoid pinning down the method.
|
||||
entry->flush();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,27 @@
|
||||
#include "incls/_compactingPermGenGen.cpp.incl"
|
||||
|
||||
|
||||
// Recursively adjust all pointers in an object and all objects by
|
||||
// referenced it. Clear marks on objects in order to prevent visiting
|
||||
// any object twice.
|
||||
// An ObjectClosure helper: Recursively adjust all pointers in an object
|
||||
// and all objects by referenced it. Clear marks on objects in order to
|
||||
// prevent visiting any object twice. This helper is used when the
|
||||
// RedefineClasses() API has been called.
|
||||
|
||||
class AdjustSharedObjectClosure : public ObjectClosure {
|
||||
public:
|
||||
void do_object(oop obj) {
|
||||
if (obj->is_shared_readwrite()) {
|
||||
if (obj->mark()->is_marked()) {
|
||||
obj->init_mark(); // Don't revisit this object.
|
||||
obj->adjust_pointers(); // Adjust this object's references.
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// An OopClosure helper: Recursively adjust all pointers in an object
|
||||
// and all objects by referenced it. Clear marks on objects in order
|
||||
// to prevent visiting any object twice.
|
||||
|
||||
class RecursiveAdjustSharedObjectClosure : public OopClosure {
|
||||
public:
|
||||
@ -274,15 +292,34 @@ CompactingPermGenGen::CompactingPermGenGen(ReservedSpace rs,
|
||||
// objects in the space will page in more objects than we need.
|
||||
// Instead, use the system dictionary as strong roots into the read
|
||||
// write space.
|
||||
//
|
||||
// If a RedefineClasses() call has been made, then we have to iterate
|
||||
// over the entire shared read-write space in order to find all the
|
||||
// objects that need to be forwarded. For example, it is possible for
|
||||
// an nmethod to be found and marked in GC phase-1 only for the nmethod
|
||||
// to be freed by the time we reach GC phase-3. The underlying method
|
||||
// is still marked, but we can't (easily) find it in GC phase-3 so we
|
||||
// blow up in GC phase-4. With RedefineClasses() we want replaced code
|
||||
// (EMCP or obsolete) to go away (i.e., be collectible) once it is no
|
||||
// longer being executed by any thread so we keep minimal attachments
|
||||
// to the replaced code. However, we can't guarantee when those EMCP
|
||||
// or obsolete methods will be collected so they may still be out there
|
||||
// even after we've severed our minimal attachments.
|
||||
|
||||
void CompactingPermGenGen::pre_adjust_pointers() {
|
||||
if (spec()->enable_shared_spaces()) {
|
||||
RecursiveAdjustSharedObjectClosure blk;
|
||||
Universe::oops_do(&blk);
|
||||
StringTable::oops_do(&blk);
|
||||
SystemDictionary::always_strong_classes_do(&blk);
|
||||
TraversePlaceholdersClosure tpc;
|
||||
SystemDictionary::placeholders_do(&tpc);
|
||||
if (JvmtiExport::has_redefined_a_class()) {
|
||||
// RedefineClasses() requires a brute force approach
|
||||
AdjustSharedObjectClosure blk;
|
||||
rw_space()->object_iterate(&blk);
|
||||
} else {
|
||||
RecursiveAdjustSharedObjectClosure blk;
|
||||
Universe::oops_do(&blk);
|
||||
StringTable::oops_do(&blk);
|
||||
SystemDictionary::always_strong_classes_do(&blk);
|
||||
TraversePlaceholdersClosure tpc;
|
||||
SystemDictionary::placeholders_do(&tpc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -972,7 +972,6 @@ jmethodID instanceKlass::jmethod_id_for_impl(instanceKlassHandle ik_h, methodHan
|
||||
// These allocations will have to be freed if they are unused.
|
||||
|
||||
// Allocate a new array of methods.
|
||||
jmethodID* to_dealloc_jmeths = NULL;
|
||||
jmethodID* new_jmeths = NULL;
|
||||
if (length <= idnum) {
|
||||
// A new array will be needed (unless some other thread beats us to it)
|
||||
@ -983,7 +982,6 @@ jmethodID instanceKlass::jmethod_id_for_impl(instanceKlassHandle ik_h, methodHan
|
||||
}
|
||||
|
||||
// Allocate a new method ID.
|
||||
jmethodID to_dealloc_id = NULL;
|
||||
jmethodID new_id = NULL;
|
||||
if (method_h->is_old() && !method_h->is_obsolete()) {
|
||||
// The method passed in is old (but not obsolete), we need to use the current version
|
||||
@ -997,40 +995,51 @@ jmethodID instanceKlass::jmethod_id_for_impl(instanceKlassHandle ik_h, methodHan
|
||||
new_id = JNIHandles::make_jmethod_id(method_h);
|
||||
}
|
||||
|
||||
{
|
||||
if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {
|
||||
// No need and unsafe to lock the JmethodIdCreation_lock at safepoint.
|
||||
id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
|
||||
} else {
|
||||
MutexLocker ml(JmethodIdCreation_lock);
|
||||
|
||||
// We must not go to a safepoint while holding this lock.
|
||||
debug_only(No_Safepoint_Verifier nosafepoints;)
|
||||
|
||||
// Retry lookup after we got the lock
|
||||
jmeths = ik_h->methods_jmethod_ids_acquire();
|
||||
if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
|
||||
if (jmeths != NULL) {
|
||||
// We have grown the array: copy the existing entries, and delete the old array
|
||||
for (size_t index = 0; index < length; index++) {
|
||||
new_jmeths[index+1] = jmeths[index+1];
|
||||
}
|
||||
to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
|
||||
}
|
||||
ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
|
||||
} else {
|
||||
id = jmeths[idnum+1];
|
||||
to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
|
||||
}
|
||||
if (id == NULL) {
|
||||
id = new_id;
|
||||
jmeths[idnum+1] = id; // install the new method ID
|
||||
} else {
|
||||
to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
|
||||
}
|
||||
id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
// Free up unneeded or no longer needed resources
|
||||
FreeHeap(to_dealloc_jmeths);
|
||||
if (to_dealloc_id != NULL) {
|
||||
JNIHandles::destroy_jmethod_id(to_dealloc_id);
|
||||
|
||||
jmethodID instanceKlass::get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
|
||||
jmethodID new_id, jmethodID* new_jmeths) {
|
||||
// Retry lookup after we got the lock or ensured we are at safepoint
|
||||
jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
|
||||
jmethodID id = NULL;
|
||||
jmethodID to_dealloc_id = NULL;
|
||||
jmethodID* to_dealloc_jmeths = NULL;
|
||||
size_t length;
|
||||
|
||||
if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
|
||||
if (jmeths != NULL) {
|
||||
// We have grown the array: copy the existing entries, and delete the old array
|
||||
for (size_t index = 0; index < length; index++) {
|
||||
new_jmeths[index+1] = jmeths[index+1];
|
||||
}
|
||||
to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
|
||||
}
|
||||
ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
|
||||
} else {
|
||||
id = jmeths[idnum+1];
|
||||
to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
|
||||
}
|
||||
if (id == NULL) {
|
||||
id = new_id;
|
||||
jmeths[idnum+1] = id; // install the new method ID
|
||||
} else {
|
||||
to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
|
||||
}
|
||||
|
||||
// Free up unneeded or no longer needed resources
|
||||
FreeHeap(to_dealloc_jmeths);
|
||||
if (to_dealloc_id != NULL) {
|
||||
JNIHandles::destroy_jmethod_id(to_dealloc_id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@ -2187,12 +2196,20 @@ void instanceKlass::add_previous_version(instanceKlassHandle ikh,
|
||||
RC_TRACE(0x00000100, ("adding previous version ref for %s @%d, EMCP_cnt=%d",
|
||||
ikh->external_name(), _previous_versions->length(), emcp_method_count));
|
||||
constantPoolHandle cp_h(ikh->constants());
|
||||
jweak cp_ref = JNIHandles::make_weak_global(cp_h);
|
||||
jobject cp_ref;
|
||||
if (cp_h->is_shared()) {
|
||||
// a shared ConstantPool requires a regular reference; a weak
|
||||
// reference would be collectible
|
||||
cp_ref = JNIHandles::make_global(cp_h);
|
||||
} else {
|
||||
cp_ref = JNIHandles::make_weak_global(cp_h);
|
||||
}
|
||||
PreviousVersionNode * pv_node = NULL;
|
||||
objArrayOop old_methods = ikh->methods();
|
||||
|
||||
if (emcp_method_count == 0) {
|
||||
pv_node = new PreviousVersionNode(cp_ref, NULL);
|
||||
// non-shared ConstantPool gets a weak reference
|
||||
pv_node = new PreviousVersionNode(cp_ref, !cp_h->is_shared(), NULL);
|
||||
RC_TRACE(0x00000400,
|
||||
("add: all methods are obsolete; flushing any EMCP weak refs"));
|
||||
} else {
|
||||
@ -2212,7 +2229,8 @@ void instanceKlass::add_previous_version(instanceKlassHandle ikh,
|
||||
}
|
||||
}
|
||||
}
|
||||
pv_node = new PreviousVersionNode(cp_ref, method_refs);
|
||||
// non-shared ConstantPool gets a weak reference
|
||||
pv_node = new PreviousVersionNode(cp_ref, !cp_h->is_shared(), method_refs);
|
||||
}
|
||||
|
||||
_previous_versions->append(pv_node);
|
||||
@ -2230,7 +2248,7 @@ void instanceKlass::add_previous_version(instanceKlassHandle ikh,
|
||||
// check the previous versions array for a GC'ed weak refs
|
||||
pv_node = _previous_versions->at(i);
|
||||
cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
|
||||
assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
|
||||
if (cp_ref == NULL) {
|
||||
delete pv_node;
|
||||
_previous_versions->remove_at(i);
|
||||
@ -2303,7 +2321,7 @@ void instanceKlass::add_previous_version(instanceKlassHandle ikh,
|
||||
// check the previous versions array for a GC'ed weak refs
|
||||
pv_node = _previous_versions->at(j);
|
||||
cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
|
||||
assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
|
||||
if (cp_ref == NULL) {
|
||||
delete pv_node;
|
||||
_previous_versions->remove_at(j);
|
||||
@ -2401,8 +2419,8 @@ bool instanceKlass::has_previous_version() const {
|
||||
// been GC'ed
|
||||
PreviousVersionNode * pv_node = _previous_versions->at(i);
|
||||
|
||||
jweak cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "weak reference was unexpectedly cleared");
|
||||
jobject cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "cp reference was unexpectedly cleared");
|
||||
if (cp_ref == NULL) {
|
||||
continue; // robustness
|
||||
}
|
||||
@ -2462,10 +2480,11 @@ void instanceKlass::set_methods_annotations_of(int idnum, typeArrayOop anno, obj
|
||||
|
||||
// Construct a PreviousVersionNode entry for the array hung off
|
||||
// the instanceKlass.
|
||||
PreviousVersionNode::PreviousVersionNode(jweak prev_constant_pool,
|
||||
GrowableArray<jweak>* prev_EMCP_methods) {
|
||||
PreviousVersionNode::PreviousVersionNode(jobject prev_constant_pool,
|
||||
bool prev_cp_is_weak, GrowableArray<jweak>* prev_EMCP_methods) {
|
||||
|
||||
_prev_constant_pool = prev_constant_pool;
|
||||
_prev_cp_is_weak = prev_cp_is_weak;
|
||||
_prev_EMCP_methods = prev_EMCP_methods;
|
||||
}
|
||||
|
||||
@ -2473,7 +2492,11 @@ PreviousVersionNode::PreviousVersionNode(jweak prev_constant_pool,
|
||||
// Destroy a PreviousVersionNode
|
||||
PreviousVersionNode::~PreviousVersionNode() {
|
||||
if (_prev_constant_pool != NULL) {
|
||||
JNIHandles::destroy_weak_global(_prev_constant_pool);
|
||||
if (_prev_cp_is_weak) {
|
||||
JNIHandles::destroy_weak_global(_prev_constant_pool);
|
||||
} else {
|
||||
JNIHandles::destroy_global(_prev_constant_pool);
|
||||
}
|
||||
}
|
||||
|
||||
if (_prev_EMCP_methods != NULL) {
|
||||
@ -2493,8 +2516,8 @@ PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) {
|
||||
_prev_constant_pool_handle = constantPoolHandle(); // NULL handle
|
||||
_prev_EMCP_method_handles = NULL;
|
||||
|
||||
jweak cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "weak constant pool ref was unexpectedly cleared");
|
||||
jobject cp_ref = pv_node->prev_constant_pool();
|
||||
assert(cp_ref != NULL, "constant pool ref was unexpectedly cleared");
|
||||
if (cp_ref == NULL) {
|
||||
return; // robustness
|
||||
}
|
||||
|
@ -432,6 +432,8 @@ class instanceKlass: public Klass {
|
||||
_enclosing_method_method_index = method_index; }
|
||||
|
||||
// jmethodID support
|
||||
static jmethodID get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
|
||||
jmethodID new_id, jmethodID* new_jmeths);
|
||||
static jmethodID jmethod_id_for_impl(instanceKlassHandle ik_h, methodHandle method_h);
|
||||
jmethodID jmethod_id_or_null(methodOop method);
|
||||
|
||||
@ -838,11 +840,20 @@ class BreakpointInfo;
|
||||
// A collection point for interesting information about the previous
|
||||
// version(s) of an instanceKlass. This class uses weak references to
|
||||
// the information so that the information may be collected as needed
|
||||
// by the system. A GrowableArray of PreviousVersionNodes is attached
|
||||
// by the system. If the information is shared, then a regular
|
||||
// reference must be used because a weak reference would be seen as
|
||||
// collectible. A GrowableArray of PreviousVersionNodes is attached
|
||||
// to the instanceKlass as needed. See PreviousVersionWalker below.
|
||||
class PreviousVersionNode : public CHeapObj {
|
||||
private:
|
||||
jweak _prev_constant_pool;
|
||||
// A shared ConstantPool is never collected so we'll always have
|
||||
// a reference to it so we can update items in the cache. We'll
|
||||
// have a weak reference to a non-shared ConstantPool until all
|
||||
// of the methods (EMCP or obsolete) have been collected; the
|
||||
// non-shared ConstantPool becomes collectible at that point.
|
||||
jobject _prev_constant_pool; // regular or weak reference
|
||||
bool _prev_cp_is_weak; // true if not a shared ConstantPool
|
||||
|
||||
// If the previous version of the instanceKlass doesn't have any
|
||||
// EMCP methods, then _prev_EMCP_methods will be NULL. If all the
|
||||
// EMCP methods have been collected, then _prev_EMCP_methods can
|
||||
@ -850,10 +861,10 @@ class PreviousVersionNode : public CHeapObj {
|
||||
GrowableArray<jweak>* _prev_EMCP_methods;
|
||||
|
||||
public:
|
||||
PreviousVersionNode(jweak prev_constant_pool,
|
||||
PreviousVersionNode(jobject prev_constant_pool, bool prev_cp_is_weak,
|
||||
GrowableArray<jweak>* prev_EMCP_methods);
|
||||
~PreviousVersionNode();
|
||||
jweak prev_constant_pool() const {
|
||||
jobject prev_constant_pool() const {
|
||||
return _prev_constant_pool;
|
||||
}
|
||||
GrowableArray<jweak>* prev_EMCP_methods() const {
|
||||
|
@ -37,3 +37,32 @@ void markOopDesc::print_on(outputStream* st) const {
|
||||
st->print("age %d)", age());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Give advice about whether the oop that contains this markOop
|
||||
// should be cached or not.
|
||||
bool markOopDesc::should_not_be_cached() const {
|
||||
// the cast is because decode_pointer() isn't marked const
|
||||
if (is_marked() && ((markOopDesc *)this)->decode_pointer() != NULL) {
|
||||
// If the oop containing this markOop is being forwarded, then
|
||||
// we are in the middle of GC and we do not want the containing
|
||||
// oop to be added to a cache. We have no way of knowing whether
|
||||
// the cache has already been visited by the current GC phase so
|
||||
// we don't know whether the forwarded oop will be properly
|
||||
// processed in this phase. If the forwarded oop is not properly
|
||||
// processed, then we'll see strange crashes or asserts during
|
||||
// the next GC run because the markOop will contain an unexpected
|
||||
// value.
|
||||
//
|
||||
// This situation has been seen when we are GC'ing a methodOop
|
||||
// because we use the methodOop while we're GC'ing it. Scary
|
||||
// stuff. Some of the uses the methodOop cause the methodOop to
|
||||
// be added to the OopMapCache in the instanceKlass as a side
|
||||
// effect. This check lets the cache maintainer know when a
|
||||
// cache addition would not be safe.
|
||||
return true;
|
||||
}
|
||||
|
||||
// caching the containing oop should be just fine
|
||||
return false;
|
||||
}
|
||||
|
@ -357,4 +357,7 @@ class markOopDesc: public oopDesc {
|
||||
|
||||
// Recover address of oop from encoded form used in mark
|
||||
inline void* decode_pointer() { if (UseBiasedLocking && has_bias_pattern()) return NULL; return clear_lock_bits(); }
|
||||
|
||||
// see the definition in markOop.cpp for the gory details
|
||||
bool should_not_be_cached() const;
|
||||
};
|
||||
|
@ -765,6 +765,28 @@ bool methodOopDesc::is_overridden_in(klassOop k) const {
|
||||
}
|
||||
|
||||
|
||||
// give advice about whether this methodOop should be cached or not
|
||||
bool methodOopDesc::should_not_be_cached() const {
|
||||
if (is_old()) {
|
||||
// This method has been redefined. It is either EMCP or obsolete
|
||||
// and we don't want to cache it because that would pin the method
|
||||
// down and prevent it from being collectible if and when it
|
||||
// finishes executing.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mark()->should_not_be_cached()) {
|
||||
// It is either not safe or not a good idea to cache this
|
||||
// method at this time because of the state of the embedded
|
||||
// markOop. See markOop.cpp for the gory details.
|
||||
return true;
|
||||
}
|
||||
|
||||
// caching this method should be just fine
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
|
||||
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
|
||||
// Code below does not work for native methods - they should never get rewritten anyway
|
||||
|
@ -524,6 +524,8 @@ class methodOopDesc : public oopDesc {
|
||||
void set_is_old() { _access_flags.set_is_old(); }
|
||||
bool is_obsolete() const { return access_flags().is_obsolete(); }
|
||||
void set_is_obsolete() { _access_flags.set_is_obsolete(); }
|
||||
// see the definition in methodOop.cpp for the gory details
|
||||
bool should_not_be_cached() const;
|
||||
|
||||
// JVMTI Native method prefixing support:
|
||||
bool is_prefixed_native() const { return access_flags().is_prefixed_native(); }
|
||||
|
@ -64,7 +64,7 @@
|
||||
// 0x01000000 | 16777216 - impl details: nmethod evolution info
|
||||
// 0x02000000 | 33554432 - impl details: annotation updates
|
||||
// 0x04000000 | 67108864 - impl details: StackMapTable updates
|
||||
// 0x08000000 | 134217728 - unused
|
||||
// 0x08000000 | 134217728 - impl details: OopMapCache updates
|
||||
// 0x10000000 | 268435456 - unused
|
||||
// 0x20000000 | 536870912 - unused
|
||||
// 0x40000000 | 1073741824 - unused
|
||||
|
@ -1548,10 +1548,11 @@ oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle
|
||||
}
|
||||
|
||||
instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(mirror));
|
||||
if (!klass->methods()->is_within_bounds(slot)) {
|
||||
methodOop m = klass->method_with_idnum(slot);
|
||||
if (m == NULL) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke");
|
||||
}
|
||||
methodHandle method(THREAD, methodOop(klass->methods()->obj_at(slot)));
|
||||
methodHandle method(THREAD, m);
|
||||
|
||||
return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD);
|
||||
}
|
||||
@ -1564,10 +1565,11 @@ oop Reflection::invoke_constructor(oop constructor_mirror, objArrayHandle args,
|
||||
objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror)));
|
||||
|
||||
instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(mirror));
|
||||
if (!klass->methods()->is_within_bounds(slot)) {
|
||||
methodOop m = klass->method_with_idnum(slot);
|
||||
if (m == NULL) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke");
|
||||
}
|
||||
methodHandle method(THREAD, methodOop(klass->methods()->obj_at(slot)));
|
||||
methodHandle method(THREAD, m);
|
||||
assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor");
|
||||
|
||||
// Make sure klass gets initialize
|
||||
|
@ -1317,10 +1317,6 @@ JavaThread::~JavaThread() {
|
||||
ThreadSafepointState::destroy(this);
|
||||
if (_thread_profiler != NULL) delete _thread_profiler;
|
||||
if (_thread_stat != NULL) delete _thread_stat;
|
||||
|
||||
if (jvmti_thread_state() != NULL) {
|
||||
JvmtiExport::cleanup_thread(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1571,6 +1567,10 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
|
||||
tlab().make_parsable(true); // retire TLAB
|
||||
}
|
||||
|
||||
if (jvmti_thread_state() != NULL) {
|
||||
JvmtiExport::cleanup_thread(this);
|
||||
}
|
||||
|
||||
// Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
|
||||
Threads::remove(this);
|
||||
}
|
||||
|
@ -37,23 +37,45 @@
|
||||
# include <stdlib.h>
|
||||
# include <wchar.h>
|
||||
# include <stdarg.h>
|
||||
#ifdef SOLARIS
|
||||
# include <ieeefp.h>
|
||||
#endif
|
||||
# include <math.h>
|
||||
#ifdef LINUX
|
||||
#ifndef FP_PZERO
|
||||
// Linux doesn't have positive/negative zero
|
||||
#define FP_PZERO FP_ZERO
|
||||
#endif
|
||||
#ifndef fpclass
|
||||
#define fpclass fpclassify
|
||||
#endif
|
||||
#endif
|
||||
# include <time.h>
|
||||
# include <fcntl.h>
|
||||
# include <dlfcn.h>
|
||||
# include <pthread.h>
|
||||
#ifdef SOLARIS
|
||||
# include <thread.h>
|
||||
#endif
|
||||
# include <limits.h>
|
||||
# include <errno.h>
|
||||
#ifdef SOLARIS
|
||||
# include <sys/trap.h>
|
||||
# include <sys/regset.h>
|
||||
# include <sys/procset.h>
|
||||
# include <ucontext.h>
|
||||
# include <setjmp.h>
|
||||
#endif
|
||||
# ifdef SOLARIS_MUTATOR_LIBTHREAD
|
||||
# include <sys/procfs.h>
|
||||
# endif
|
||||
#ifdef LINUX
|
||||
# include <inttypes.h>
|
||||
# include <signal.h>
|
||||
# include <ucontext.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
// 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures
|
||||
// When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in
|
||||
@ -68,6 +90,11 @@
|
||||
// pointer when it extracts the argument, then we have a problem.
|
||||
//
|
||||
// Solution: For 64-bit architectures, redefine NULL as 64-bit constant 0.
|
||||
//
|
||||
// Note: this fix doesn't work well on Linux because NULL will be overwritten
|
||||
// whenever a system header file is included. Linux handles NULL correctly
|
||||
// through a special type '__null'.
|
||||
#ifdef SOLARIS
|
||||
#ifdef _LP64
|
||||
#undef NULL
|
||||
#define NULL 0L
|
||||
@ -76,13 +103,25 @@
|
||||
#define NULL 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// NULL vs NULL_WORD:
|
||||
// On Linux NULL is defined as a special type '__null'. Assigning __null to
|
||||
// integer variable will cause gcc warning. Use NULL_WORD in places where a
|
||||
// pointer is stored as integer value.
|
||||
#define NULL_WORD NULL
|
||||
// pointer is stored as integer value. On some platforms, sizeof(intptr_t) >
|
||||
// sizeof(void*), so here we want something which is integer type, but has the
|
||||
// same size as a pointer.
|
||||
#ifdef LINUX
|
||||
#ifdef _LP64
|
||||
#define NULL_WORD 0L
|
||||
#else
|
||||
#define NULL_WORD 0
|
||||
#endif
|
||||
#else
|
||||
#define NULL_WORD NULL
|
||||
#endif
|
||||
|
||||
#ifndef LINUX
|
||||
// Compiler-specific primitive types
|
||||
typedef unsigned short uint16_t;
|
||||
#ifndef _UINT32_T
|
||||
@ -100,6 +139,7 @@ typedef unsigned int uintptr_t;
|
||||
// If this gets an error, figure out a symbol XXX that implies the
|
||||
// prior definition of intptr_t, and add "&& !defined(XXX)" above.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Additional Java basic types
|
||||
|
||||
@ -128,7 +168,7 @@ inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; }
|
||||
const jlong min_jlong = CONST64(0x8000000000000000);
|
||||
const jlong max_jlong = CONST64(0x7fffffffffffffff);
|
||||
|
||||
|
||||
#ifdef SOLARIS
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// ANSI C++ fixes
|
||||
// NOTE:In the ANSI committee's continuing attempt to make each version
|
||||
@ -162,7 +202,7 @@ extern "C" {
|
||||
typedef int (*int_fnP_cond_tP_i_vP)(cond_t *cv, int scope, void *arg);
|
||||
typedef int (*int_fnP_cond_tP)(cond_t *cv);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Debugging
|
||||
@ -173,7 +213,7 @@ extern "C" void breakpoint();
|
||||
#define BREAKPOINT ::breakpoint()
|
||||
|
||||
// checking for nanness
|
||||
|
||||
#ifdef SOLARIS
|
||||
#ifdef SPARC
|
||||
inline int g_isnan(float f) { return isnanf(f); }
|
||||
#else
|
||||
@ -182,6 +222,12 @@ inline int g_isnan(float f) { return isnand(f); }
|
||||
#endif
|
||||
|
||||
inline int g_isnan(double f) { return isnand(f); }
|
||||
#elif LINUX
|
||||
inline int g_isnan(float f) { return isnanf(f); }
|
||||
inline int g_isnan(double f) { return isnan(f); }
|
||||
#else
|
||||
#error "missing platform-specific definition here"
|
||||
#endif
|
||||
|
||||
// Checking for finiteness
|
||||
|
||||
@ -195,9 +241,11 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
|
||||
|
||||
|
||||
// Misc
|
||||
// NOTE: This one leads to an infinite recursion on Linux
|
||||
#ifndef LINUX
|
||||
int local_vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr);
|
||||
#define vsnprintf local_vsnprintf
|
||||
|
||||
#endif
|
||||
|
||||
// Portability macros
|
||||
#define PRAGMA_INTERFACE
|
||||
|
Loading…
Reference in New Issue
Block a user