This commit is contained in:
Erik Trimble 2008-12-05 15:32:59 -08:00
commit 349adae76a
54 changed files with 795 additions and 428 deletions

View File

@ -200,29 +200,6 @@ BUILD_WIN_SA = 0
checkSA::
@echo Not building SA: ARCH = ia64
!elseif exist("$(MSVCDIR)\PlatformSDK\Include\dbgeng.h")
# These don't have to be set because the default
# setting of INCLUDE and LIB already contain the needed dirs.
SA_INCLUDE =
SA_LIB =
!elseif exist("$(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h")
# These don't have to be set because the default
# setting of INCLUDE and LIB already contain the needed dirs.
SA_INCLUDE =
SA_LIB =
!else
checkSA::
@echo .
@echo ERROR: Can't build SA because dbgeng.h does not exist here:
@echo $(MSVCDIR)\PlatformSDK\Include\dbgeng.h
@echo nor here:
@echo $(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h
@echo You must use Vis. Studio .Net 2003 on Win 32, and you must
@echo have the Microsoft SDK installed on Win amd64.
@echo You can disable building of SA by specifying BUILD_WIN_SA = 0
@echo . && false
!endif # ! "$(BUILD_WIN_SA)" != "1"
#########################################################################

View File

@ -119,7 +119,7 @@ endif
# we want to release it. If we build it here,
# the SDK makefiles will copy it over and put it into
# the created image.
BUILD_WIN_SA = 0
BUILD_WIN_SA = 1
ifneq ($(ALT_BUILD_WIN_SA),)
BUILD_WIN_SA = $(ALT_BUILD_WIN_SA)
endif

View File

@ -49,6 +49,9 @@ SA_PROPERTIES = $(SA_CLASSDIR)\sa.properties
default:: $(GENERATED)\sa-jdi.jar
# Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space
# at the end of SA version string and causes a version mismatch with the target VM version.
$(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
@if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR)
@echo ...Building sa-jdi.jar
@ -56,15 +59,15 @@ $(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
$(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP) > $(SA_PROPERTIES)
$(RUN_JAR) cf $@ -C saclasses .
$(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES)
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql
$(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/*
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/
$(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/
$(QUIETLY) rm -rf $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
$(QUIETLY) mkdir $(SA_CLASSDIR)\sun\jvm\hotspot\ui\resources
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
$(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)
$(RUN_JAR) cf $@ -C saclasses .
$(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext
@ -93,7 +96,7 @@ SA_LINK_FLAGS = bufferoverflowU.lib
SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /ZI /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
!endif
!if "$(MT)" != ""
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
!endif
SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
SA_LFLAGS = $(SA_LINK_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE)

View File

@ -2085,7 +2085,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache,
} else {
if (has_tos) {
// save object pointer before call_VM() clobbers it
__ mov(Otos_i, Lscratch);
__ push_ptr(Otos_i); // put object on tos where GC wants it.
} else {
// Load top of stack (do not pop the value off the stack);
__ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), Otos_i);
@ -2097,7 +2097,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache,
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access),
Otos_i, Rcache);
if (!is_static && has_tos) {
__ mov(Lscratch, Otos_i); // restore object pointer
__ pop_ptr(Otos_i); // restore object pointer
__ verify_oop(Otos_i);
}
__ get_cache_and_index_at_bcp(Rcache, index, 1);

View File

@ -2272,7 +2272,9 @@ void os::free_memory(char *addr, size_t bytes) {
uncommit_memory(addr, bytes);
}
void os::numa_make_global(char *addr, size_t bytes) { }
void os::numa_make_global(char *addr, size_t bytes) {
Linux::numa_interleave_memory(addr, bytes);
}
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
Linux::numa_tonode_memory(addr, bytes, lgrp_hint);
@ -2314,7 +2316,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
extern "C" void numa_warn(int number, char *where, ...) { }
extern "C" void numa_error(char *where) { }
void os::Linux::libnuma_init() {
bool os::Linux::libnuma_init() {
// sched_getcpu() should be in libc.
set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
dlsym(RTLD_DEFAULT, "sched_getcpu")));
@ -2330,31 +2332,51 @@ void os::Linux::libnuma_init() {
dlsym(handle, "numa_available")));
set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
dlsym(handle, "numa_tonode_memory")));
set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
dlsym(handle, "numa_interleave_memory")));
if (numa_available() != -1) {
set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes"));
// Create a cpu -> node mapping
_cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true);
rebuild_cpu_to_node_map();
return true;
}
}
}
return false;
}
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void os::Linux::rebuild_cpu_to_node_map() {
int cpu_num = os::active_processor_count();
const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
// in libnuma (possible values are starting from 16,
// and continuing up with every other power of 2, but less
// than the maximum number of CPUs supported by kernel), and
// is a subject to change (in libnuma version 2 the requirements
// are more reasonable) we'll just hardcode the number they use
// in the library.
const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
size_t cpu_num = os::active_processor_count();
size_t cpu_map_size = NCPUS / BitsPerCLong;
size_t cpu_map_valid_size =
MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
cpu_to_node()->clear();
cpu_to_node()->at_grow(cpu_num - 1);
int node_num = numa_get_groups_num();
int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong;
size_t node_num = numa_get_groups_num();
unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
for (int i = 0; i < node_num; i++) {
for (size_t i = 0; i < node_num; i++) {
if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
for (int j = 0; j < cpu_map_size; j++) {
for (size_t j = 0; j < cpu_map_valid_size; j++) {
if (cpu_map[j] != 0) {
for (int k = 0; k < BitsPerLong; k++) {
for (size_t k = 0; k < BitsPerCLong; k++) {
if (cpu_map[j] & (1UL << k)) {
cpu_to_node()->at_put(j * BitsPerLong + k, i);
cpu_to_node()->at_put(j * BitsPerCLong + k, i);
}
}
}
@ -2377,7 +2399,8 @@ os::Linux::numa_node_to_cpus_func_t os::Linux::_numa_node_to_cpus;
os::Linux::numa_max_node_func_t os::Linux::_numa_max_node;
os::Linux::numa_available_func_t os::Linux::_numa_available;
os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory;
os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
unsigned long* os::Linux::_numa_all_nodes;
bool os::uncommit_memory(char* addr, size_t size) {
return ::mmap(addr, size,
@ -3695,7 +3718,17 @@ jint os::init_2(void)
}
if (UseNUMA) {
Linux::libnuma_init();
if (!Linux::libnuma_init()) {
UseNUMA = false;
} else {
if ((Linux::numa_max_node() < 1)) {
// There's only one node(they start from 0), disable NUMA.
UseNUMA = false;
}
}
if (!UseNUMA && ForceNUMA) {
UseNUMA = true;
}
}
if (MaxFDLimit) {

View File

@ -146,7 +146,7 @@ class Linux {
static bool is_floating_stack() { return _is_floating_stack; }
static void libpthread_init();
static void libnuma_init();
static bool libnuma_init();
// Minimum stack size a thread can be created with (allowing
// the VM to completely create the thread and enter user code)
@ -240,20 +240,23 @@ private:
typedef int (*numa_max_node_func_t)(void);
typedef int (*numa_available_func_t)(void);
typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);
typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);
static sched_getcpu_func_t _sched_getcpu;
static numa_node_to_cpus_func_t _numa_node_to_cpus;
static numa_max_node_func_t _numa_max_node;
static numa_available_func_t _numa_available;
static numa_tonode_memory_func_t _numa_tonode_memory;
static numa_interleave_memory_func_t _numa_interleave_memory;
static unsigned long* _numa_all_nodes;
static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }
static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }
static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }
static void set_numa_available(numa_available_func_t func) { _numa_available = func; }
static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
public:
static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
@ -264,6 +267,11 @@ public:
static int numa_tonode_memory(void *start, size_t size, int node) {
return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;
}
static void numa_interleave_memory(void *start, size_t size) {
if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) {
_numa_interleave_memory(start, size, _numa_all_nodes);
}
}
static int get_node_by_cpu(int cpu_id);
};

View File

@ -4638,7 +4638,7 @@ void os::Solaris::synchronization_init() {
}
}
void os::Solaris::liblgrp_init() {
bool os::Solaris::liblgrp_init() {
void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
if (handle != NULL) {
os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
@ -4653,9 +4653,9 @@ void os::Solaris::liblgrp_init() {
lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
set_lgrp_cookie(c);
} else {
warning("your OS does not support NUMA");
return true;
}
return false;
}
void os::Solaris::misc_sym_init() {
@ -4824,9 +4824,25 @@ jint os::init_2(void) {
vm_page_size()));
Solaris::libthread_init();
if (UseNUMA) {
Solaris::liblgrp_init();
if (!Solaris::liblgrp_init()) {
UseNUMA = false;
} else {
size_t lgrp_limit = os::numa_get_groups_num();
int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
FREE_C_HEAP_ARRAY(int, lgrp_ids);
if (lgrp_num < 2) {
// There's only one locality group, disable NUMA.
UseNUMA = false;
}
}
if (!UseNUMA && ForceNUMA) {
UseNUMA = true;
}
}
Solaris::misc_sym_init();
Solaris::signal_sets_init();
Solaris::init_signal_mem();

View File

@ -176,7 +176,7 @@ class Solaris {
public:
static void libthread_init();
static void synchronization_init();
static void liblgrp_init();
static bool liblgrp_init();
// Load miscellaneous symbols.
static void misc_sym_init();
// This boolean allows users to forward their own non-matching signals

View File

@ -2217,15 +2217,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
// We only expect null pointers in the stubs (vtable)
// the rest are checked explicitly now.
//
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb != NULL) {
if (VtableStubs::stub_containing(pc) != NULL) {
if (((uintptr_t)addr) < os::vm_page_size() ) {
// an access to the first page of VM--assume it is a null pointer
return Handle_Exception(exceptionInfo,
SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL));
}
}
if (((uintptr_t)addr) < os::vm_page_size() ) {
// an access to the first page of VM--assume it is a null pointer
address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
if (stub != NULL) return Handle_Exception(exceptionInfo, stub);
}
}
} // in_java
@ -2241,9 +2236,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
// Windows 98 reports faulting addresses incorrectly
if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) ||
!os::win32::is_nt()) {
return Handle_Exception(exceptionInfo,
SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL));
address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
if (stub != NULL) return Handle_Exception(exceptionInfo, stub);
}
report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
exceptionInfo->ContextRecord);
@ -3353,6 +3347,10 @@ jint os::init_2(void) {
// initialize thread priority policy
prio_init();
if (UseNUMA && !ForceNUMA) {
UseNUMA = false; // Currently unsupported.
}
return JNI_OK;
}

View File

@ -676,21 +676,6 @@ GraphBuilder::ScopeData::ScopeData(ScopeData* parent)
}
void GraphBuilder::kill_field(ciField* field) {
if (UseLocalValueNumbering) {
vmap()->kill_field(field);
}
}
void GraphBuilder::kill_array(Value value) {
if (UseLocalValueNumbering) {
vmap()->kill_array(value->type());
}
_memory->store_value(value);
}
void GraphBuilder::kill_all() {
if (UseLocalValueNumbering) {
vmap()->kill_all();
@ -987,8 +972,8 @@ void GraphBuilder::store_indexed(BasicType type) {
length = append(new ArrayLength(array, lock_stack()));
}
StoreIndexed* result = new StoreIndexed(array, index, length, type, value, lock_stack());
kill_array(value); // invalidate all CSEs that are memory accesses of the same type
append(result);
_memory->store_value(value);
}
@ -1478,9 +1463,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
case Bytecodes::_putstatic:
{ Value val = pop(type);
append(new StoreField(append(obj), offset, field, val, true, lock_stack(), state_copy, is_loaded, is_initialized));
if (UseLocalValueNumbering) {
vmap()->kill_field(field); // invalidate all CSEs that are memory accesses
}
}
break;
case Bytecodes::_getfield :
@ -1503,7 +1485,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
if (is_loaded) store = _memory->store(store);
if (store != NULL) {
append(store);
kill_field(field); // invalidate all CSEs that are accesses of this field
}
}
break;
@ -1900,6 +1881,8 @@ Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
assert(i2->bci() != -1, "should already be linked");
return i2;
}
ValueNumberingEffects vne(vmap());
i1->visit(&vne);
}
if (i1->as_Phi() == NULL && i1->as_Local() == NULL) {
@ -1926,14 +1909,8 @@ Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
assert(_last == i1, "adjust code below");
StateSplit* s = i1->as_StateSplit();
if (s != NULL && i1->as_BlockEnd() == NULL) {
// Continue CSE across certain intrinsics
Intrinsic* intrinsic = s->as_Intrinsic();
if (UseLocalValueNumbering) {
if (intrinsic == NULL || !intrinsic->preserves_state()) {
vmap()->kill_all(); // for now, hopefully we need this only for calls eventually
}
}
if (EliminateFieldAccess) {
Intrinsic* intrinsic = s->as_Intrinsic();
if (s->as_Invoke() != NULL || (intrinsic && !intrinsic->preserves_state())) {
_memory->kill();
}

View File

@ -283,8 +283,6 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
Dependencies* dependency_recorder() const; // = compilation()->dependencies()
bool direct_compare(ciKlass* k);
void kill_field(ciField* field);
void kill_array(Value value);
void kill_all();
ValueStack* lock_stack();

View File

@ -133,53 +133,77 @@ class ValueNumberingVisitor: public InstructionVisitor {
virtual void kill_array(ValueType* type) = 0;
// visitor functions
void do_StoreField (StoreField* x) { kill_field(x->field()); };
void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); };
void do_MonitorEnter (MonitorEnter* x) { kill_memory(); };
void do_MonitorExit (MonitorExit* x) { kill_memory(); };
void do_Invoke (Invoke* x) { kill_memory(); };
void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); };
void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); };
void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); };
void do_StoreField (StoreField* x) {
if (!x->is_initialized()) {
kill_memory();
} else {
kill_field(x->field());
}
}
void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); }
void do_MonitorEnter (MonitorEnter* x) { kill_memory(); }
void do_MonitorExit (MonitorExit* x) { kill_memory(); }
void do_Invoke (Invoke* x) { kill_memory(); }
void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); }
void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); }
void do_Phi (Phi* x) { /* nothing to do */ };
void do_Local (Local* x) { /* nothing to do */ };
void do_Constant (Constant* x) { /* nothing to do */ };
void do_LoadField (LoadField* x) { /* nothing to do */ };
void do_ArrayLength (ArrayLength* x) { /* nothing to do */ };
void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ };
void do_NegateOp (NegateOp* x) { /* nothing to do */ };
void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ };
void do_ShiftOp (ShiftOp* x) { /* nothing to do */ };
void do_LogicOp (LogicOp* x) { /* nothing to do */ };
void do_CompareOp (CompareOp* x) { /* nothing to do */ };
void do_IfOp (IfOp* x) { /* nothing to do */ };
void do_Convert (Convert* x) { /* nothing to do */ };
void do_NullCheck (NullCheck* x) { /* nothing to do */ };
void do_NewInstance (NewInstance* x) { /* nothing to do */ };
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ };
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ };
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ };
void do_CheckCast (CheckCast* x) { /* nothing to do */ };
void do_InstanceOf (InstanceOf* x) { /* nothing to do */ };
void do_BlockBegin (BlockBegin* x) { /* nothing to do */ };
void do_Goto (Goto* x) { /* nothing to do */ };
void do_If (If* x) { /* nothing to do */ };
void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ };
void do_TableSwitch (TableSwitch* x) { /* nothing to do */ };
void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ };
void do_Return (Return* x) { /* nothing to do */ };
void do_Throw (Throw* x) { /* nothing to do */ };
void do_Base (Base* x) { /* nothing to do */ };
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ };
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
void do_RoundFP (RoundFP* x) { /* nothing to do */ };
void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ };
void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ };
void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ };
void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ };
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ };
void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ };
void do_Phi (Phi* x) { /* nothing to do */ }
void do_Local (Local* x) { /* nothing to do */ }
void do_Constant (Constant* x) { /* nothing to do */ }
void do_LoadField (LoadField* x) {
if (!x->is_initialized()) {
kill_memory();
}
}
void do_ArrayLength (ArrayLength* x) { /* nothing to do */ }
void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ }
void do_NegateOp (NegateOp* x) { /* nothing to do */ }
void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ }
void do_ShiftOp (ShiftOp* x) { /* nothing to do */ }
void do_LogicOp (LogicOp* x) { /* nothing to do */ }
void do_CompareOp (CompareOp* x) { /* nothing to do */ }
void do_IfOp (IfOp* x) { /* nothing to do */ }
void do_Convert (Convert* x) { /* nothing to do */ }
void do_NullCheck (NullCheck* x) { /* nothing to do */ }
void do_NewInstance (NewInstance* x) { /* nothing to do */ }
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }
void do_CheckCast (CheckCast* x) { /* nothing to do */ }
void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }
void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }
void do_Goto (Goto* x) { /* nothing to do */ }
void do_If (If* x) { /* nothing to do */ }
void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ }
void do_TableSwitch (TableSwitch* x) { /* nothing to do */ }
void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ }
void do_Return (Return* x) { /* nothing to do */ }
void do_Throw (Throw* x) { /* nothing to do */ }
void do_Base (Base* x) { /* nothing to do */ }
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
void do_RoundFP (RoundFP* x) { /* nothing to do */ }
void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ }
void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ }
void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }
void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ }
};
class ValueNumberingEffects: public ValueNumberingVisitor {
private:
ValueMap* _map;
public:
// implementation for abstract methods of ValueNumberingVisitor
void kill_memory() { _map->kill_memory(); }
void kill_field(ciField* field) { _map->kill_field(field); }
void kill_array(ValueType* type) { _map->kill_array(type); }
ValueNumberingEffects(ValueMap* map): _map(map) {}
};

View File

@ -325,24 +325,30 @@ class Par_PushOrMarkClosure: public OopClosure {
// For objects in CMS generation, this closure marks
// given objects (transitively) as being reachable/live.
// This is currently used during the (weak) reference object
// processing phase of the CMS final checkpoint step.
// processing phase of the CMS final checkpoint step, as
// well as during the concurrent precleaning of the discovered
// reference lists.
class CMSKeepAliveClosure: public OopClosure {
private:
CMSCollector* _collector;
const MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
bool _concurrent_precleaning;
protected:
DO_OOP_WORK_DEFN
public:
CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack):
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack) {
_mark_stack(mark_stack),
_concurrent_precleaning(cpc) {
assert(!_span.is_empty(), "Empty span could spell trouble");
}
bool concurrent_precleaning() const { return _concurrent_precleaning; }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); }

View File

@ -538,6 +538,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
_survivor_chunk_capacity(0), // -- ditto --
_survivor_chunk_index(0), // -- ditto --
_ser_pmc_preclean_ovflw(0),
_ser_kac_preclean_ovflw(0),
_ser_pmc_remark_ovflw(0),
_par_pmc_remark_ovflw(0),
_ser_kac_ovflw(0),
@ -1960,6 +1961,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
ref_processor()->set_enqueuing_is_done(false);
ref_processor()->enable_discovery();
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
// collection, clear the _modUnionTable.
@ -2383,6 +2385,9 @@ void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) {
Universe::verify(true);
}
// Snapshot the soft reference policy to be used in this collection cycle.
ref_processor()->setup_policy(clear_all_soft_refs);
bool init_mark_was_synchronous = false; // until proven otherwise
while (_collectorState != Idling) {
if (TraceCMSState) {
@ -4388,10 +4393,10 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
CMSPrecleanRefsYieldClosure yield_cl(this);
assert(rp->span().equals(_span), "Spans should be equal");
CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap,
&_markStack);
&_markStack, true /* preclean */);
CMSDrainMarkingStackClosure complete_trace(this,
_span, &_markBitMap, &_markStack,
&keep_alive);
_span, &_markBitMap, &_markStack,
&keep_alive, true /* preclean */);
// We don't want this step to interfere with a young
// collection because we don't want to take CPU
@ -4590,11 +4595,11 @@ size_t CMSCollector::preclean_mod_union_table(
if (!dirtyRegion.is_empty()) {
assert(numDirtyCards > 0, "consistency check");
HeapWord* stop_point = NULL;
stopTimer();
CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
bitMapLock());
startTimer();
{
stopTimer();
CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
bitMapLock());
startTimer();
verify_work_stacks_empty();
verify_overflow_empty();
sample_eden();
@ -4611,10 +4616,6 @@ size_t CMSCollector::preclean_mod_union_table(
assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) ||
(_collectorState == AbortablePreclean && should_abort_preclean()),
"Unparsable objects should only be in perm gen.");
stopTimer();
CMSTokenSyncWithLocks ts(true, bitMapLock());
startTimer();
_modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end()));
if (should_abort_preclean()) {
break; // out of preclean loop
@ -4852,17 +4853,19 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch,
// recurrence of that condition.
assert(_markStack.isEmpty(), "No grey objects");
size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
_ser_kac_ovflw;
_ser_kac_ovflw + _ser_kac_preclean_ovflw;
if (ser_ovflw > 0) {
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Marking stack overflow (benign) "
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")",
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT
", kac_preclean="SIZE_FORMAT")",
_ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
_ser_kac_ovflw);
_ser_kac_ovflw, _ser_kac_preclean_ovflw);
}
_markStack.expand();
_ser_pmc_remark_ovflw = 0;
_ser_pmc_preclean_ovflw = 0;
_ser_kac_preclean_ovflw = 0;
_ser_kac_ovflw = 0;
}
if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
@ -5675,40 +5678,29 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
ReferencePolicy* soft_ref_policy;
assert(!ref_processor()->enqueuing_is_done(), "Enqueuing should not be complete");
// Process weak references.
if (clear_all_soft_refs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
verify_work_stacks_empty();
ReferenceProcessor* rp = ref_processor();
assert(rp->span().equals(_span), "Spans should be equal");
assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
// Process weak references.
rp->setup_policy(clear_all_soft_refs);
verify_work_stacks_empty();
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
&_markStack);
&_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack,
&cmsKeepAliveClosure);
&cmsKeepAliveClosure, false /* !preclean */);
{
TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
if (rp->processing_is_mt()) {
CMSRefProcTaskExecutor task_executor(*this);
rp->process_discovered_references(soft_ref_policy,
&_is_alive_closure,
rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor);
} else {
rp->process_discovered_references(soft_ref_policy,
&_is_alive_closure,
rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL);
@ -6163,8 +6155,8 @@ void CMSCollector::verify_ok_to_terminate() const {
#endif
size_t CMSCollector::block_size_using_printezis_bits(HeapWord* addr) const {
assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
"missing Printezis mark?");
assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
"missing Printezis mark?");
HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
size_t size = pointer_delta(nextOneAddr + 1, addr);
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
@ -8302,8 +8294,29 @@ void CMSKeepAliveClosure::do_oop(oop obj) {
}
)
if (simulate_overflow || !_mark_stack->push(obj)) {
_collector->push_on_overflow_list(obj);
_collector->_ser_kac_ovflw++;
if (_concurrent_precleaning) {
// We dirty the overflown object and let the remark
// phase deal with it.
assert(_collector->overflow_list_is_empty(), "Error");
// In the case of object arrays, we need to dirty all of
// the cards that the object spans. No locking or atomics
// are needed since no one else can be mutating the mod union
// table.
if (obj->is_objArray()) {
size_t sz = obj->size();
HeapWord* end_card_addr =
(HeapWord*)round_to((intptr_t)(addr+sz), CardTableModRefBS::card_size);
MemRegion redirty_range = MemRegion(addr, end_card_addr);
assert(!redirty_range.is_empty(), "Arithmetical tautology");
_collector->_modUnionTable.mark_range(redirty_range);
} else {
_collector->_modUnionTable.mark(addr);
}
_collector->_ser_kac_preclean_ovflw++;
} else {
_collector->push_on_overflow_list(obj);
_collector->_ser_kac_ovflw++;
}
}
}
}
@ -8400,6 +8413,8 @@ const char* CMSExpansionCause::to_string(CMSExpansionCause::Cause cause) {
void CMSDrainMarkingStackClosure::do_void() {
// the max number to take from overflow list at a time
const size_t num = _mark_stack->capacity()/4;
assert(!_concurrent_precleaning || _collector->overflow_list_is_empty(),
"Overflow list should be NULL during concurrent phases");
while (!_mark_stack->isEmpty() ||
// if stack is empty, check the overflow list
_collector->take_from_overflow_list(num, _mark_stack)) {

View File

@ -592,6 +592,7 @@ class CMSCollector: public CHeapObj {
size_t _ser_pmc_preclean_ovflw;
size_t _ser_pmc_remark_ovflw;
size_t _par_pmc_remark_ovflw;
size_t _ser_kac_preclean_ovflw;
size_t _ser_kac_ovflw;
size_t _par_kac_ovflw;
NOT_PRODUCT(size_t _num_par_pushes;)
@ -1749,21 +1750,30 @@ class SweepClosure: public BlkClosureCareful {
// work-routine/closure used to complete transitive
// marking of objects as live after a certain point
// in which an initial set has been completely accumulated.
// This closure is currently used both during the final
// remark stop-world phase, as well as during the concurrent
// precleaning of the discovered reference lists.
class CMSDrainMarkingStackClosure: public VoidClosure {
CMSCollector* _collector;
MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
CMSKeepAliveClosure* _keep_alive;
bool _concurrent_precleaning;
public:
CMSDrainMarkingStackClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
CMSKeepAliveClosure* keep_alive):
CMSKeepAliveClosure* keep_alive,
bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
_keep_alive(keep_alive) { }
_keep_alive(keep_alive),
_concurrent_precleaning(cpc) {
assert(_concurrent_precleaning == _keep_alive->concurrent_precleaning(),
"Mismatch");
}
void do_void();
};

View File

@ -811,6 +811,7 @@ void ConcurrentMark::checkpointRootsInitialPost() {
ReferenceProcessor* rp = g1h->ref_processor();
rp->verify_no_references_recorded();
rp->enable_discovery(); // enable ("weak") refs discovery
rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold);
@ -1829,32 +1830,21 @@ class G1CMDrainMarkingStackClosure: public VoidClosure {
void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
ReferencePolicy* soft_ref_policy;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
ReferenceProcessor* rp = g1h->ref_processor();
// Process weak references.
if (clear_all_soft_refs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif
}
rp->setup_policy(clear_all_soft_refs);
assert(_markStack.isEmpty(), "mark stack should be empty");
G1CollectedHeap* g1 = G1CollectedHeap::heap();
G1CMIsAliveClosure g1IsAliveClosure(g1);
G1CMKeepAliveClosure g1KeepAliveClosure(g1, this, nextMarkBitMap());
G1CMIsAliveClosure g1IsAliveClosure (g1h);
G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap());
G1CMDrainMarkingStackClosure
g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack,
&g1KeepAliveClosure);
// XXXYYY Also: copy the parallel ref processing code from CMS.
ReferenceProcessor* rp = g1->ref_processor();
rp->process_discovered_references(soft_ref_policy,
&g1IsAliveClosure,
rp->process_discovered_references(&g1IsAliveClosure,
&g1KeepAliveClosure,
&g1DrainMarkingStackClosure,
NULL);

View File

@ -891,6 +891,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_soft_refs);
// Do collection work
{
@ -2463,7 +2464,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
// We want to turn off ref discovere, if necessary, and turn it back on
// We want to turn off ref discovery, if necessary, and turn it back on
// on again later if we do.
bool was_enabled = ref_processor()->discovery_enabled();
if (was_enabled) ref_processor()->disable_discovery();

View File

@ -33,8 +33,9 @@ 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");
GenMarkSweep::_ref_processor = rp;
assert(rp != NULL, "should be non-NULL");
GenMarkSweep::_ref_processor = rp;
rp->setup_policy(clear_all_softrefs);
// When collecting the permanent generation methodOops may be moving,
// so we either have to flush all bcp data or convert it into bci.
@ -121,23 +122,12 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
&GenMarkSweep::follow_root_closure);
// Process reference objects found during marking
ReferencePolicy *soft_ref_policy;
if (clear_all_softrefs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif
}
assert(soft_ref_policy != NULL,"No soft reference policy");
GenMarkSweep::ref_processor()->process_discovered_references(
soft_ref_policy,
&GenMarkSweep::is_alive,
&GenMarkSweep::keep_alive,
&GenMarkSweep::follow_stack_closure,
NULL);
ReferenceProcessor* rp = GenMarkSweep::ref_processor();
rp->setup_policy(clear_all_softrefs);
rp->process_discovered_references(&GenMarkSweep::is_alive,
&GenMarkSweep::keep_alive,
&GenMarkSweep::follow_stack_closure,
NULL);
// Follow system dictionary roots and unload classes
bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);

View File

@ -759,17 +759,12 @@ void ParNewGeneration::collect(bool full,
thread_state_set.steals(),
thread_state_set.pops()+thread_state_set.steals());
}
assert(thread_state_set.pushes() == thread_state_set.pops() + thread_state_set.steals(),
assert(thread_state_set.pushes() == thread_state_set.pops()
+ thread_state_set.steals(),
"Or else the queues are leaky.");
// For now, process discovered weak refs sequentially.
#ifdef COMPILER2
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
#else
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
// Process (weak) reference objects found during scavenge.
ReferenceProcessor* rp = ref_processor();
IsAliveClosure is_alive(this);
ScanWeakRefClosure scan_weak_ref(this);
KeepAliveClosure keep_alive(&scan_weak_ref);
@ -778,18 +773,17 @@ void ParNewGeneration::collect(bool full,
set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
&scan_without_gc_barrier, &scan_with_gc_barrier);
if (ref_processor()->processing_is_mt()) {
rp->setup_policy(clear_all_soft_refs);
if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
&task_executor);
rp->process_discovered_references(&is_alive, &keep_alive,
&evacuate_followers, &task_executor);
} else {
thread_state_set.flush();
gch->set_par_threads(0); // 0 ==> non-parallel.
gch->save_marks();
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
NULL);
rp->process_discovered_references(&is_alive, &keep_alive,
&evacuate_followers, NULL);
}
if (!promotion_failed()) {
// Swap the survivor spaces.
@ -851,14 +845,14 @@ void ParNewGeneration::collect(bool full,
SpecializationStats::print();
ref_processor()->set_enqueuing_is_done(true);
if (ref_processor()->processing_is_mt()) {
rp->set_enqueuing_is_done(true);
if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
ref_processor()->enqueue_discovered_references(&task_executor);
rp->enqueue_discovered_references(&task_executor);
} else {
ref_processor()->enqueue_discovered_references(NULL);
rp->enqueue_discovered_references(NULL);
}
ref_processor()->verify_no_references_recorded();
rp->verify_no_references_recorded();
}
static int sum;
@ -1211,7 +1205,7 @@ ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
int n = 0;
while (cur != NULL) {
oop obj_to_push = cur->forwardee();
oop next = oop(cur->klass());
oop next = oop(cur->klass_or_null());
cur->set_klass(obj_to_push->klass());
if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
obj_to_push = cur;

View File

@ -172,6 +172,7 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_softrefs);
mark_sweep_phase1(clear_all_softrefs);
@ -517,20 +518,9 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
// Process reference objects found during marking
{
ReferencePolicy *soft_ref_policy;
if (clear_all_softrefs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
assert(soft_ref_policy != NULL,"No soft reference policy");
ref_processor()->setup_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
soft_ref_policy, is_alive_closure(), mark_and_push_closure(),
follow_stack_closure(), NULL);
is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL);
}
// Follow system dictionary roots and unload classes

View File

@ -1578,6 +1578,7 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
ref_processor()->setup_policy(maximum_heap_compaction);
bool marked_for_unloading = false;
@ -1894,26 +1895,14 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
// Process reference objects found during marking
{
TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty);
ReferencePolicy *soft_ref_policy;
if (maximum_heap_compaction) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
assert(soft_ref_policy != NULL, "No soft reference policy");
if (ref_processor()->processing_is_mt()) {
RefProcTaskExecutor task_executor;
ref_processor()->process_discovered_references(
soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
&follow_stack_closure, &task_executor);
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
&task_executor);
} else {
ref_processor()->process_discovered_references(
soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
&follow_stack_closure, NULL);
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL);
}
}

View File

@ -330,6 +330,7 @@ bool PSScavenge::invoke_no_policy() {
COMPILER2_PRESENT(DerivedPointerTable::clear());
reference_processor()->enable_discovery();
reference_processor()->setup_policy(false);
// We track how much was promoted to the next generation for
// the AdaptiveSizePolicy.
@ -394,24 +395,16 @@ bool PSScavenge::invoke_no_policy() {
// Process reference objects discovered during scavenge
{
#ifdef COMPILER2
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
#else
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
reference_processor()->setup_policy(false); // not always_clear
PSKeepAliveClosure keep_alive(promotion_manager);
PSEvacuateFollowersClosure evac_followers(promotion_manager);
assert(soft_ref_policy != NULL,"No soft reference policy");
if (reference_processor()->processing_is_mt()) {
PSRefProcTaskExecutor task_executor;
reference_processor()->process_discovered_references(
soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
&task_executor);
&_is_alive_closure, &keep_alive, &evac_followers, &task_executor);
} else {
reference_processor()->process_discovered_references(
soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
NULL);
&_is_alive_closure, &keep_alive, &evac_followers, NULL);
}
}

View File

@ -414,9 +414,20 @@ size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) {
if (limit > 0) {
limit = round_down(limit, page_size());
if (chunk_size > current_chunk_size(i)) {
chunk_size = MIN2((off_t)chunk_size, (off_t)current_chunk_size(i) + (off_t)limit);
size_t upper_bound = pages_available * page_size();
if (upper_bound > limit &&
current_chunk_size(i) < upper_bound - limit) {
// The resulting upper bound should not exceed the available
// amount of memory (pages_available * page_size()).
upper_bound = current_chunk_size(i) + limit;
}
chunk_size = MIN2(chunk_size, upper_bound);
} else {
chunk_size = MAX2((off_t)chunk_size, (off_t)current_chunk_size(i) - (off_t)limit);
size_t lower_bound = page_size();
if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow.
lower_bound = current_chunk_size(i) - limit;
}
chunk_size = MAX2(chunk_size, lower_bound);
}
}
assert(chunk_size <= pages_available * page_size(), "Chunk size out of range");

View File

@ -2303,6 +2303,7 @@ javaCalls.cpp handles.inline.hpp
javaCalls.cpp interfaceSupport.hpp
javaCalls.cpp interpreter.hpp
javaCalls.cpp javaCalls.hpp
javaCalls.cpp jniCheck.hpp
javaCalls.cpp linkResolver.hpp
javaCalls.cpp mutexLocker.hpp
javaCalls.cpp nmethod.hpp
@ -3434,6 +3435,7 @@ referenceProcessor.cpp referenceProcessor.hpp
referenceProcessor.cpp systemDictionary.hpp
referenceProcessor.hpp instanceRefKlass.hpp
referenceProcessor.hpp referencePolicy.hpp
reflection.cpp arguments.hpp
reflection.cpp handles.inline.hpp

View File

@ -115,6 +115,8 @@ heapInspection.cpp klassOop.hpp
heapInspection.cpp os.hpp
heapInspection.cpp resourceArea.hpp
javaCalls.cpp jniCheck.hpp
jniCheck.cpp fieldDescriptor.hpp
jniCheck.cpp handles.hpp
jniCheck.cpp instanceKlass.hpp

View File

@ -540,14 +540,6 @@ void DefNewGeneration::collect(bool full,
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
// Weak refs.
// FIXME: Are these storage leaks, or are they resource objects?
#ifdef COMPILER2
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
#else
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
// Not very pretty.
CollectorPolicy* cp = gch->collector_policy();
@ -574,8 +566,10 @@ void DefNewGeneration::collect(bool full,
evacuate_followers.do_void();
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers, NULL);
ReferenceProcessor* rp = ref_processor();
rp->setup_policy(clear_all_soft_refs);
rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
NULL);
if (!promotion_failed()) {
// Swap the survivor spaces.
eden()->clear(SpaceDecorator::Mangle);

View File

@ -525,8 +525,9 @@ void GenCollectedHeap::do_collection(bool full,
if (rp->discovery_is_atomic()) {
rp->verify_no_references_recorded();
rp->enable_discovery();
rp->setup_policy(clear_all_soft_refs);
} else {
// collect() will enable discovery as appropriate
// collect() below will enable discovery as appropriate
}
_gens[i]->collect(full, clear_all_soft_refs, size, is_tlab);
if (!rp->enqueuing_is_done()) {

View File

@ -31,8 +31,9 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
// hook up weak ref data so it can be used during Mark-Sweep
assert(ref_processor() == NULL, "no stomping");
_ref_processor = rp;
assert(rp != NULL, "should be non-NULL");
_ref_processor = rp;
rp->setup_policy(clear_all_softrefs);
TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
@ -245,20 +246,9 @@ void GenMarkSweep::mark_sweep_phase1(int level,
// Process reference objects found during marking
{
ReferencePolicy *soft_ref_policy;
if (clear_all_softrefs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
assert(soft_ref_policy != NULL,"No soft reference policy");
ref_processor()->setup_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive,
&follow_stack_closure, NULL);
&is_alive, &keep_alive, &follow_stack_closure, NULL);
}
// Follow system dictionary roots and unload classes

View File

@ -26,6 +26,11 @@
# include "incls/_referencePolicy.cpp.incl"
LRUCurrentHeapPolicy::LRUCurrentHeapPolicy() {
setup();
}
// Capture state (of-the-VM) information needed to evaluate the policy
void LRUCurrentHeapPolicy::setup() {
_max_interval = (Universe::get_heap_free_at_last_gc() / M) * SoftRefLRUPolicyMSPerMB;
assert(_max_interval >= 0,"Sanity check");
}
@ -47,6 +52,11 @@ bool LRUCurrentHeapPolicy::should_clear_reference(oop p) {
/////////////////////// MaxHeap //////////////////////
LRUMaxHeapPolicy::LRUMaxHeapPolicy() {
setup();
}
// Capture state (of-the-VM) information needed to evaluate the policy
void LRUMaxHeapPolicy::setup() {
size_t max_heap = MaxHeapSize;
max_heap -= Universe::get_heap_used_at_last_gc();
max_heap /= M;

View File

@ -26,9 +26,11 @@
// should be cleared.
class ReferencePolicy : public ResourceObj {
class ReferencePolicy : public CHeapObj {
public:
virtual bool should_clear_reference(oop p) { ShouldNotReachHere(); return true; }
// Capture state (of-the-VM) information needed to evaluate the policy
virtual void setup() { /* do nothing */ }
};
class NeverClearPolicy : public ReferencePolicy {
@ -48,6 +50,8 @@ class LRUCurrentHeapPolicy : public ReferencePolicy {
public:
LRUCurrentHeapPolicy();
// Capture state (of-the-VM) information needed to evaluate the policy
void setup();
bool should_clear_reference(oop p);
};
@ -58,5 +62,7 @@ class LRUMaxHeapPolicy : public ReferencePolicy {
public:
LRUMaxHeapPolicy();
// Capture state (of-the-VM) information needed to evaluate the policy
void setup();
bool should_clear_reference(oop p);
};

View File

@ -25,6 +25,11 @@
# include "incls/_precompiled.incl"
# include "incls/_referenceProcessor.cpp.incl"
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.
class DiscoveredList {
public:
@ -47,7 +52,9 @@ public:
}
bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); }
size_t length() { return _len; }
void set_length(size_t len) { _len = 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.
@ -56,10 +63,6 @@ private:
size_t _len;
};
oop ReferenceProcessor::_sentinelRef = NULL;
const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
void referenceProcessor_init() {
ReferenceProcessor::init_statics();
}
@ -80,6 +83,12 @@ void ReferenceProcessor::init_statics() {
}
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());
if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
vm_exit_during_initialization("Could not allocate reference policy object");
}
guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
RefDiscoveryPolicy == ReferentBasedDiscovery,
"Unrecongnized RefDiscoveryPolicy");
@ -106,6 +115,7 @@ ReferenceProcessor::create_ref_processor(MemRegion span,
vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
}
rp->set_is_alive_non_header(is_alive_non_header);
rp->setup_policy(false /* default soft ref policy */);
return rp;
}
@ -192,7 +202,6 @@ void ReferenceProcessor::update_soft_ref_master_clock() {
}
void ReferenceProcessor::process_discovered_references(
ReferencePolicy* policy,
BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
@ -207,7 +216,7 @@ void ReferenceProcessor::process_discovered_references(
// Soft references
{
TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);
process_discovered_reflist(_discoveredSoftRefs, policy, true,
process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
is_alive, keep_alive, complete_gc, task_executor);
}
@ -436,13 +445,13 @@ public:
// 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.
// 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 and move to the next.
// Remove the current reference from the list
inline void remove();
// Make the Reference object active again.
@ -476,7 +485,6 @@ public:
inline size_t removed() const { return _removed; }
)
private:
inline void move_to_next();
private:
@ -553,7 +561,7 @@ inline void DiscoveredListIterator::remove() {
oopDesc::store_heap_oop((oop*)_prev_next, _next);
}
NOT_PRODUCT(_removed++);
move_to_next();
_refs_list.dec_length(1);
}
inline void DiscoveredListIterator::move_to_next() {
@ -591,12 +599,13 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
iter.obj(), iter.obj()->blueprint()->internal_name());
}
// Remove Reference object from list
iter.remove();
// Make the Reference object active again
iter.make_active();
// keep the referent around
iter.make_referent_alive();
// Remove Reference object from list
iter.remove();
iter.move_to_next();
} else {
iter.next();
}
@ -629,12 +638,13 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list,
iter.obj(), iter.obj()->blueprint()->internal_name());
}
// The referent is reachable after all.
// Remove Reference object from list.
iter.remove();
// Update the referent pointer as necessary: Note that this
// should not entail any recursive marking because the
// referent must already have been traversed.
iter.make_referent_alive();
// Remove Reference object from list
iter.remove();
iter.move_to_next();
} else {
iter.next();
}
@ -670,6 +680,7 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list,
} else {
keep_alive->do_oop((oop*)next_addr);
}
iter.move_to_next();
} else {
iter.next();
}
@ -832,9 +843,9 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[])
}
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].set_length(ref_lists[to_idx].length() + refs_to_move);
ref_lists[to_idx].inc_length(refs_to_move);
ref_lists[from_idx].set_head(new_head);
ref_lists[from_idx].set_length(ref_lists[from_idx].length() - refs_to_move);
ref_lists[from_idx].dec_length(refs_to_move);
} else {
++to_idx;
}
@ -923,7 +934,6 @@ void ReferenceProcessor::clean_up_discovered_references() {
void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
assert(!discovery_is_atomic(), "Else why call this method?");
DiscoveredListIterator iter(refs_list, NULL, NULL);
size_t length = refs_list.length();
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop next = java_lang_ref_Reference::next(iter.obj());
@ -941,12 +951,11 @@ void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list)
)
// Remove Reference object from list
iter.remove();
--length;
iter.move_to_next();
} else {
iter.next();
}
}
refs_list.set_length(length);
NOT_PRODUCT(
if (PrintGCDetails && TraceReferenceGC) {
gclog_or_tty->print(
@ -1024,7 +1033,7 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list,
// We have separate lists for enqueueing so no synchronization
// is necessary.
refs_list.set_head(obj);
refs_list.set_length(refs_list.length() + 1);
refs_list.inc_length(1);
if (_discovered_list_needs_barrier) {
_bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
}
@ -1090,15 +1099,28 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
// reachable.
if (is_alive_non_header() != NULL) {
oop referent = java_lang_ref_Reference::referent(obj);
// We'd like to assert the following:
// assert(referent != NULL, "Refs with null referents already filtered");
// However, since this code may be executed concurrently with
// mutators, which can clear() the referent, it is not
// guaranteed that the referent is non-NULL.
// In the case of non-concurrent discovery, the last
// disjunct below should hold. It may not hold in the
// case of concurrent discovery because mutators may
// concurrently clear() a Reference.
assert(UseConcMarkSweepGC || UseG1GC || referent != NULL,
"Refs with null referents already filtered");
if (is_alive_non_header()->do_object_b(referent)) {
return false; // referent is reachable
}
}
if (rt == REF_SOFT) {
// For soft refs we can decide now if these are not
// current candidates for clearing, in which case we
// can mark through them now, rather than delaying that
// to the reference-processing phase. Since all current
// time-stamp policies advance the soft-ref clock only
// at a major collection cycle, this is always currently
// accurate.
if (!_current_soft_ref_policy->should_clear_reference(obj)) {
return false;
}
}
HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj);
const oop discovered = java_lang_ref_Reference::discovered(obj);
@ -1168,7 +1190,7 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
_bs->write_ref_field((oop*)discovered_addr, current_head);
}
list->set_head(obj);
list->set_length(list->length() + 1);
list->inc_length(1);
}
// In the MT discovery case, it is currently possible to see
@ -1209,45 +1231,48 @@ void ReferenceProcessor::preclean_discovered_references(
TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
if (yield->should_return()) {
return;
}
// Weak references
{
TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
if (yield->should_return()) {
return;
}
// Final references
{
TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
if (yield->should_return()) {
return;
}
// Phantom references
{
TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
@ -1256,9 +1281,12 @@ void ReferenceProcessor::preclean_discovered_references(
// Walk the given discovered ref list, and remove all reference objects
// whose referents are still alive, whose referents are NULL or which
// are not active (have a non-NULL next field). NOTE: For this to work
// correctly, refs discovery can not be happening concurrently with this
// step.
// are not active (have a non-NULL next field). NOTE: When we are
// thus precleaning the ref lists (which happens single-threaded today),
// we do not disable refs discovery to honour the correct semantics of
// java.lang.Reference. As a result, we need to be careful below
// that ref removal steps interleave safely with ref discovery steps
// (in this thread).
void
ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
BoolObjectClosure* is_alive,
@ -1266,7 +1294,6 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
VoidClosure* complete_gc,
YieldClosure* yield) {
DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
size_t length = refs_list.length();
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop obj = iter.obj();
@ -1281,7 +1308,6 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
}
// Remove Reference object from list
iter.remove();
--length;
// Keep alive its cohort.
iter.make_referent_alive();
if (UseCompressedOops) {
@ -1291,12 +1317,11 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
keep_alive->do_oop(next_addr);
}
iter.move_to_next();
} else {
iter.next();
}
}
refs_list.set_length(length);
// Close the reachable set
complete_gc->do_void();

View File

@ -23,7 +23,7 @@
*/
// ReferenceProcessor class encapsulates the per-"collector" processing
// of "weak" references for GC. The interface is useful for supporting
// of java.lang.Reference objects for GC. The interface is useful for supporting
// a generational abstraction, in particular when there are multiple
// generations that are being independently collected -- possibly
// concurrently and/or incrementally. Note, however, that the
@ -75,6 +75,14 @@ class ReferenceProcessor : public CHeapObj {
// all collectors but the CMS collector).
BoolObjectClosure* _is_alive_non_header;
// Soft ref clearing policies
// . the default policy
static ReferencePolicy* _default_soft_ref_policy;
// . the "clear all" policy
static ReferencePolicy* _always_clear_soft_ref_policy;
// . the current policy below is either one of the above
ReferencePolicy* _current_soft_ref_policy;
// The discovered ref lists themselves
// The MT'ness degree of the queues below
@ -90,6 +98,12 @@ class ReferenceProcessor : public CHeapObj {
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;
_current_soft_ref_policy->setup(); // snapshot the policy threshold
return _current_soft_ref_policy;
}
public:
// Process references with a certain reachability level.
@ -297,8 +311,7 @@ class ReferenceProcessor : public CHeapObj {
bool discover_reference(oop obj, ReferenceType rt);
// Process references found during GC (called by the garbage collector)
void process_discovered_references(ReferencePolicy* policy,
BoolObjectClosure* is_alive,
void process_discovered_references(BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
AbstractRefProcTaskExecutor* task_executor);

View File

@ -96,7 +96,7 @@ bool Universe::_bootstrapping = false;
bool Universe::_fully_initialized = false;
size_t Universe::_heap_capacity_at_last_gc;
size_t Universe::_heap_used_at_last_gc;
size_t Universe::_heap_used_at_last_gc = 0;
CollectedHeap* Universe::_collectedHeap = NULL;
address Universe::_heap_base = NULL;

View File

@ -92,7 +92,7 @@ inline void oopDesc::set_klass_to_list_ptr(oop k) {
// This is only to be used during GC, for from-space objects, so no
// barrier is needed.
if (UseCompressedOops) {
_metadata._compressed_klass = encode_heap_oop_not_null(k);
_metadata._compressed_klass = encode_heap_oop(k); // may be null (parnew overflow handling)
} else {
_metadata._klass = (klassOop)k;
}

View File

@ -395,7 +395,13 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st)
OptoReg::regname(OptoReg::c_frame_pointer),
regalloc->reg2offset(box_reg));
}
format_helper( regalloc, st, obj, "MON-OBJ[", i, &scobjs );
const char* obj_msg = "MON-OBJ[";
if (EliminateLocks) {
while( !box->is_BoxLock() ) box = box->in(1);
if (box->as_BoxLock()->is_eliminated())
obj_msg = "MON-OBJ(LOCK ELIMINATED)[";
}
format_helper( regalloc, st, obj, obj_msg, i, &scobjs );
}
for (i = 0; i < (uint)scobjs.length(); i++) {
@ -908,8 +914,9 @@ void SafePointNode::push_monitor(const FastLockNode *lock) {
add_req(lock->box_node());
add_req(lock->obj_node());
} else {
add_req(NULL);
add_req(NULL);
Node* top = Compile::current()->top();
add_req(top);
add_req(top);
}
jvms()->set_scloff(nextmon+MonitorEdges);
jvms()->set_endoff(req());
@ -1382,7 +1389,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//
// If we are locking an unescaped object, the lock/unlock is unnecessary
//
ConnectionGraph *cgr = Compile::current()->congraph();
ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase);
@ -1450,6 +1457,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Mark it eliminated to update any counters
lock->set_eliminated();
lock->set_coarsened();
}
} else if (result != NULL && ctrl->is_Region() &&
iter->_worklist.member(ctrl)) {
@ -1484,7 +1492,7 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//
// If we are unlocking an unescaped object, the lock/unlock is unnecessary.
//
ConnectionGraph *cgr = Compile::current()->congraph();
ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase);

View File

@ -780,7 +780,8 @@ public:
//------------------------------AbstractLockNode-----------------------------------
class AbstractLockNode: public CallNode {
private:
bool _eliminate; // indicates this lock can be safely eliminated
bool _eliminate; // indicates this lock can be safely eliminated
bool _coarsened; // indicates this lock was coarsened
#ifndef PRODUCT
NamedCounter* _counter;
#endif
@ -801,6 +802,7 @@ protected:
public:
AbstractLockNode(const TypeFunc *tf)
: CallNode(tf, NULL, TypeRawPtr::BOTTOM),
_coarsened(false),
_eliminate(false)
{
#ifndef PRODUCT
@ -819,6 +821,9 @@ public:
// mark node as eliminated and update the counter if there is one
void set_eliminated();
bool is_coarsened() { return _coarsened; }
void set_coarsened() { _coarsened = true; }
// locking does not modify its arguments
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}

View File

@ -1532,11 +1532,6 @@ void Compile::Optimize() {
if (failing()) return;
// get rid of the connection graph since it's information is not
// updated by optimizations
_congraph = NULL;
// Loop transforms on the ideal graph. Range Check Elimination,
// peeling, unrolling, etc.

View File

@ -199,7 +199,8 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform
es = ptnode_adr(idx)->escape_state();
// if we have already computed a value, return it
if (es != PointsToNode::UnknownEscape)
if (es != PointsToNode::UnknownEscape &&
ptnode_adr(idx)->node_type() == PointsToNode::JavaObject)
return es;
// PointsTo() calls n->uncast() which can return a new ideal node.

View File

@ -44,10 +44,15 @@ BoxLockNode::BoxLockNode( int slot ) : Node( Compile::current()->root() ),
_inmask.Insert(reg);
}
//-----------------------------hash--------------------------------------------
uint BoxLockNode::hash() const {
return Node::hash() + _slot + (_is_eliminated ? Compile::current()->fixed_slots() : 0);
}
//------------------------------cmp--------------------------------------------
uint BoxLockNode::cmp( const Node &n ) const {
const BoxLockNode &bn = (const BoxLockNode &)n;
return bn._slot == _slot;
return bn._slot == _slot && bn._is_eliminated == _is_eliminated;
}
OptoReg::Name BoxLockNode::stack_slot(Node* box_node) {

View File

@ -36,7 +36,7 @@ public:
virtual const RegMask &in_RegMask(uint) const;
virtual const RegMask &out_RegMask() const;
virtual uint size_of() const;
virtual uint hash() const { return Node::hash() + _slot; }
virtual uint hash() const;
virtual uint cmp( const Node &n ) const;
virtual const class Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
virtual uint ideal_reg() const { return Op_RegP; }

View File

@ -59,7 +59,7 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal
for (uint i = old_dbg_start; i < oldcall->req(); i++) {
Node* old_in = oldcall->in(i);
// Clone old SafePointScalarObjectNodes, adjusting their field contents.
if (old_in->is_SafePointScalarObject()) {
if (old_in != NULL && old_in->is_SafePointScalarObject()) {
SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
uint old_unique = C->unique();
Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
@ -1509,21 +1509,63 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
if (!alock->is_eliminated()) {
return false;
}
// Mark the box lock as eliminated if all correspondent locks are eliminated
// to construct correct debug info.
BoxLockNode* box = alock->box_node()->as_BoxLock();
if (!box->is_eliminated()) {
bool eliminate = true;
for (DUIterator_Fast imax, i = box->fast_outs(imax); i < imax; i++) {
Node *lck = box->fast_out(i);
if (lck->is_Lock() && !lck->as_AbstractLock()->is_eliminated()) {
eliminate = false;
break;
}
}
if (eliminate)
box->set_eliminated();
}
if (alock->is_Lock() && !alock->is_coarsened()) {
// Create new "eliminated" BoxLock node and use it
// in monitor debug info for the same object.
BoxLockNode* oldbox = alock->box_node()->as_BoxLock();
Node* obj = alock->obj_node();
if (!oldbox->is_eliminated()) {
BoxLockNode* newbox = oldbox->clone()->as_BoxLock();
newbox->set_eliminated();
transform_later(newbox);
// Replace old box node with new box for all users
// of the same object.
for (uint i = 0; i < oldbox->outcnt();) {
bool next_edge = true;
Node* u = oldbox->raw_out(i);
if (u == alock) {
i++;
continue; // It will be removed below
}
if (u->is_Lock() &&
u->as_Lock()->obj_node() == obj &&
// oldbox could be referenced in debug info also
u->as_Lock()->box_node() == oldbox) {
assert(u->as_Lock()->is_eliminated(), "sanity");
_igvn.hash_delete(u);
u->set_req(TypeFunc::Parms + 1, newbox);
next_edge = false;
#ifdef ASSERT
} else if (u->is_Unlock() && u->as_Unlock()->obj_node() == obj) {
assert(u->as_Unlock()->is_eliminated(), "sanity");
#endif
}
// Replace old box in monitor debug info.
if (u->is_SafePoint() && u->as_SafePoint()->jvms()) {
SafePointNode* sfn = u->as_SafePoint();
JVMState* youngest_jvms = sfn->jvms();
int max_depth = youngest_jvms->depth();
for (int depth = 1; depth <= max_depth; depth++) {
JVMState* jvms = youngest_jvms->of_depth(depth);
int num_mon = jvms->nof_monitors();
// Loop over monitors
for (int idx = 0; idx < num_mon; idx++) {
Node* obj_node = sfn->monitor_obj(jvms, idx);
Node* box_node = sfn->monitor_box(jvms, idx);
if (box_node == oldbox && obj_node == obj) {
int j = jvms->monitor_box_offset(idx);
_igvn.hash_delete(u);
u->set_req(j, newbox);
next_edge = false;
}
} // for (int idx = 0;
} // for (int depth = 1;
} // if (u->is_SafePoint()
if (next_edge) i++;
} // for (uint i = 0; i < oldbox->outcnt();)
} // if (!oldbox->is_eliminated())
} // if (alock->is_Lock() && !lock->is_coarsened())
#ifndef PRODUCT
if (PrintEliminateLocks) {
@ -1562,6 +1604,15 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
_igvn.subsume_node(ctrlproj, fallthroughproj);
_igvn.hash_delete(memproj);
_igvn.subsume_node(memproj, memproj_fallthrough);
// Delete FastLock node also if this Lock node is unique user
// (a loop peeling may clone a Lock node).
Node* flock = alock->as_Lock()->fastlock_node();
if (flock->outcnt() == 1) {
assert(flock->unique_out() == alock, "sanity");
_igvn.hash_delete(flock);
_igvn.subsume_node(flock, top());
}
}
// Seach for MemBarRelease node and delete it also.
@ -1887,8 +1938,28 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
bool PhaseMacroExpand::expand_macro_nodes() {
if (C->macro_count() == 0)
return false;
// attempt to eliminate allocations
// First, attempt to eliminate locks
bool progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
Node * n = C->macro_node(i-1);
bool success = false;
debug_only(int old_macro_count = C->macro_count(););
if (n->is_AbstractLock()) {
success = eliminate_locking_node(n->as_AbstractLock());
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
_igvn.add_users_to_worklist(n);
_igvn.hash_delete(n);
_igvn.subsume_node(n, n->in(1));
success = true;
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;
}
}
// Next, attempt to eliminate allocations
progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
@ -1902,17 +1973,10 @@ bool PhaseMacroExpand::expand_macro_nodes() {
break;
case Node::Class_Lock:
case Node::Class_Unlock:
success = eliminate_locking_node(n->as_AbstractLock());
assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
break;
default:
if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
_igvn.add_users_to_worklist(n);
_igvn.hash_delete(n);
_igvn.subsume_node(n, n->in(1));
success = true;
} else {
assert(false, "unknown node type in macro list");
}
assert(false, "unknown node type in macro list");
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;

View File

@ -849,10 +849,8 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
// Loop over monitors and insert into array
for(idx = 0; idx < num_mon; idx++) {
// Grab the node that defines this monitor
Node* box_node;
Node* obj_node;
box_node = sfn->monitor_box(jvms, idx);
obj_node = sfn->monitor_obj(jvms, idx);
Node* box_node = sfn->monitor_box(jvms, idx);
Node* obj_node = sfn->monitor_obj(jvms, idx);
// Create ScopeValue for object
ScopeValue *scval = NULL;
@ -890,6 +888,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
Location basic_lock = Location::new_stk_loc(Location::normal,_regalloc->reg2offset(box_reg));
while( !box_node->is_BoxLock() ) box_node = box_node->in(1);
monarray->append(new MonitorValue(scval, basic_lock, box_node->as_BoxLock()->is_eliminated()));
}

View File

@ -112,18 +112,6 @@ static const char * fatal_instance_field_mismatch = "Field type (instance) misma
static const char * fatal_non_string = "JNI string operation received a non-string";
// Report a JNI failure caught by -Xcheck:jni. Perform a core dump.
// Note: two variations -- one to be called when in VM state (e.g. when
// within IN_VM macro), one to be called when in NATIVE state.
// When in VM state:
static void ReportJNIFatalError(JavaThread* thr, const char *msg) {
tty->print_cr("FATAL ERROR in native method: %s", msg);
thr->print_stack();
os::abort(true);
}
// When in VM state:
static void ReportJNIWarning(JavaThread* thr, const char *msg) {
tty->print_cr("WARNING in native method: %s", msg);

View File

@ -22,6 +22,19 @@
*
*/
extern "C" {
// Report a JNI failure caught by -Xcheck:jni. Perform a core dump.
// Note: two variations -- one to be called when in VM state (e.g. when
// within IN_VM macro), one to be called when in NATIVE state.
// When in VM state:
static void ReportJNIFatalError(JavaThread* thr, const char *msg) {
tty->print_cr("FATAL ERROR in native method: %s", msg);
thr->print_stack();
os::abort(true);
}
}
//
// Checked JNI routines that are useful for outside of checked JNI
//

View File

@ -2322,7 +2322,12 @@ SOLARIS_ONLY(
return JNI_ERR;
}
}
// Change the default value for flags which have different default values
// when working with older JDKs.
if (JDK_Version::current().compare_major(6) <= 0 &&
FLAG_IS_DEFAULT(UseVMInterruptibleIO)) {
FLAG_SET_DEFAULT(UseVMInterruptibleIO, true);
}
return JNI_OK;
}

View File

@ -582,13 +582,19 @@ BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attem
if (heuristics == HR_NOT_BIASED) {
return NOT_BIASED;
} else if (heuristics == HR_SINGLE_REVOKE) {
if (mark->biased_locker() == THREAD) {
Klass *k = Klass::cast(obj->klass());
markOop prototype_header = k->prototype_header();
if (mark->biased_locker() == THREAD &&
prototype_header->bias_epoch() == mark->bias_epoch()) {
// A thread is trying to revoke the bias of an object biased
// toward it, again likely due to an identity hash code
// computation. We can again avoid a safepoint in this case
// since we are only going to walk our own stack. There are no
// races with revocations occurring in other threads because we
// reach no safepoints in the revocation path.
// Also check the epoch because even if threads match, another thread
// can come in with a CAS to steal the bias of an object that has a
// stale epoch.
ResourceMark rm;
if (TraceBiasedLocking) {
tty->print_cr("Revoking bias by walking my own stack:");

View File

@ -342,6 +342,9 @@ class CommandLineFlags {
product(bool, UseNUMA, false, \
"Use NUMA if available") \
\
product(bool, ForceNUMA, false, \
"Force NUMA optimizations on single-node/UMA systems") \
\
product(intx, NUMAChunkResizeWeight, 20, \
"Percentage (0-100) used to weight the current sample when " \
"computing exponentially decaying average for " \
@ -1474,7 +1477,7 @@ class CommandLineFlags {
"CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence" \
" ratio") \
\
product(bool, CMSPrecleanRefLists1, false, \
product(bool, CMSPrecleanRefLists1, true, \
"Preclean ref lists during (initial) preclean phase") \
\
product(bool, CMSPrecleanRefLists2, false, \
@ -3262,9 +3265,10 @@ class CommandLineFlags {
diagnostic(bool, PrintDTraceDOF, false, \
"Print the DTrace DOF passed to the system for JSDT probes") \
\
product(bool, UseVMInterruptibleIO, true, \
product(bool, UseVMInterruptibleIO, false, \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"EINTR for I/O operations results in OS_INTRPT")
"EINTR for I/O operations results in OS_INTRPT. The default value"\
" of this flag is true for JDK 6 and earliers")
/*

View File

@ -309,8 +309,12 @@ void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArgument
CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
// Make sure that the arguments have the right type
debug_only(args->verify(method, result->get_type(), thread));
// Verify the arguments
if (CheckJNICalls) {
args->verify(method, result->get_type(), thread);
}
else debug_only(args->verify(method, result->get_type(), thread));
// Ignore call if method is empty
if (method->is_empty_method()) {
@ -431,24 +435,26 @@ intptr_t* JavaCallArguments::parameters() {
return TaggedStackInterpreter ? _parameters : _value;
}
//--------------------------------------------------------------------------------------
// Non-Product code
#ifndef PRODUCT
class SignatureChekker : public SignatureIterator {
private:
bool *_is_oop;
int _pos;
BasicType _return_type;
intptr_t* _value;
Thread* _thread;
public:
bool _is_return;
SignatureChekker(symbolHandle signature, BasicType return_type, bool is_static, bool* is_oop) : SignatureIterator(signature) {
SignatureChekker(symbolHandle signature, BasicType return_type, bool is_static, bool* is_oop, intptr_t* value, Thread* thread) : SignatureIterator(signature) {
_is_oop = is_oop;
_is_return = false;
_return_type = return_type;
_pos = 0;
_value = value;
_thread = thread;
if (!is_static) {
check_value(true); // Receiver must be an oop
}
@ -489,6 +495,24 @@ class SignatureChekker : public SignatureIterator {
check_return_type(t);
return;
}
// verify handle and the oop pointed to by handle
int p = _pos;
bool bad = false;
// If argument is oop
if (_is_oop[p]) {
intptr_t v = _value[p];
if (v != 0 ) {
size_t t = (size_t)v;
bad = (t < (size_t)os::vm_page_size() ) || !(*(oop*)v)->is_oop_or_null(true);
if (CheckJNICalls && bad) {
ReportJNIFatalError((JavaThread*)_thread, "Bad JNI oop argument");
}
}
// for the regular debug case.
assert(!bad, "Bad JNI oop argument");
}
check_value(true);
}
@ -505,6 +529,7 @@ class SignatureChekker : public SignatureIterator {
void do_array(int begin, int end) { check_obj(T_OBJECT); }
};
void JavaCallArguments::verify(methodHandle method, BasicType return_type,
Thread *thread) {
guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed");
@ -515,10 +540,9 @@ void JavaCallArguments::verify(methodHandle method, BasicType return_type,
// Check that oop information is correct
symbolHandle signature (thread, method->signature());
SignatureChekker sc(signature, return_type, method->is_static(),_is_oop);
SignatureChekker sc(signature, return_type, method->is_static(),_is_oop, _value, thread);
sc.iterate_parameters();
sc.check_doing_return(true);
sc.iterate_returntype();
}
#endif // PRODUCT

View File

@ -150,7 +150,7 @@ class JavaCallArguments : public StackObj {
int size_of_parameters() const { return _size; }
// Verify that pushed arguments fits a given method
void verify(methodHandle method, BasicType return_type, Thread *thread) PRODUCT_RETURN;
void verify(methodHandle method, BasicType return_type, Thread *thread);
};
// All calls to Java have to go via JavaCalls. Sets up the stack frame

View File

@ -556,7 +556,10 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
// the caller was at a call site, it's safe to destroy all
// caller-saved registers, as these entry points do.
VtableStub* vt_stub = VtableStubs::stub_containing(pc);
guarantee(vt_stub != NULL, "unable to find SEGVing vtable stub");
// If vt_stub is NULL, then return NULL to signal handler to report the SEGV error.
if (vt_stub == NULL) return NULL;
if (vt_stub->is_abstract_method_error(pc)) {
assert(!vt_stub->is_vtable_stub(), "should never see AbstractMethodErrors from vtable-type VtableStubs");
return StubRoutines::throw_AbstractMethodError_entry();
@ -565,7 +568,9 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
}
} else {
CodeBlob* cb = CodeCache::find_blob(pc);
guarantee(cb != NULL, "exception happened outside interpreter, nmethods and vtable stubs (1)");
// If code blob is NULL, then return NULL to signal handler to report the SEGV error.
if (cb == NULL) return NULL;
// Exception happened in CodeCache. Must be either:
// 1. Inline-cache check in C2I handler blob,
@ -574,7 +579,7 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
if (!cb->is_nmethod()) {
guarantee(cb->is_adapter_blob(),
"exception happened outside interpreter, nmethods and vtable stubs (2)");
"exception happened outside interpreter, nmethods and vtable stubs (1)");
// There is no handler here, so we will simply unwind.
return StubRoutines::throw_NullPointerException_at_call_entry();
}

View File

@ -65,8 +65,10 @@
// COMPILER2 variant
#ifdef COMPILER2
#define COMPILER2_PRESENT(code) code
#define NOT_COMPILER2(code)
#else // COMPILER2
#define COMPILER2_PRESENT(code)
#define NOT_COMPILER2(code) code
#endif // COMPILER2

View File

@ -0,0 +1,55 @@
/*
* Copyright 2008 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.
*/
/**
* @test
* @bug 6756768
* @summary C1 generates invalid code
*
* @run main/othervm -Xcomp Test6756768
*/
class Test6756768a
{
static boolean var_1 = true;
}
final class Test6756768b
{
static boolean var_24 = false;
static int var_25 = 0;
static boolean var_temp1 = Test6756768a.var_1 = false;
}
public final class Test6756768 extends Test6756768a
{
final static int var = var_1 ^ (Test6756768b.var_24 ? var_1 : var_1) ? Test6756768b.var_25 : 1;
static public void main(String[] args) {
if (var != 0) {
throw new InternalError("var = " + var);
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2008 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.
*/
/**
* @test
* @bug 6756768
* @summary C1 generates invalid code
*
* @run main/othervm -Xcomp Test6756768_2
*/
class Test6756768_2a {
static int var = ++Test6756768_2.var;
}
public class Test6756768_2 {
static int var = 1;
static Object d2 = null;
static void test_static_field() {
int v = var;
int v2 = Test6756768_2a.var;
int v3 = var;
var = v3;
}
public static void main(String[] args) {
var = 1;
test_static_field();
if (var != 2) {
throw new InternalError();
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2008 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.
*
*/
/*
* @test
* @bug 6775880
* @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
* @compile -source 1.4 -target 1.4 Test.java
* @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test
*/
public class Test {
int cnt;
int b[];
String s;
String test() {
String res="";
for (int i=0; i < cnt; i++) {
if (i != 0) {
res = res +".";
}
res = res + b[i];
}
return res;
}
public static void main(String[] args) {
Test t = new Test();
t.cnt = 3;
t.b = new int[3];
t.b[0] = 0;
t.b[1] = 1;
t.b[2] = 2;
int j=0;
t.s = "";
for (int i=0; i<10001; i++) {
t.s = "c";
t.s = t.test();
}
System.out.println("After s=" + t.s);
}
}