--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu Jul 15 19:52:58 2010 -0700
@@ -35,7 +35,6 @@
public class NMethod extends CodeBlob {
private static long pcDescSize;
- private static CIntegerField zombieInstructionSizeField;
private static sun.jvm.hotspot.types.OopField methodField;
/** != InvocationEntryBci if this nmethod is an on-stack replacement method */
private static CIntegerField entryBCIField;
@@ -88,7 +87,6 @@
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("nmethod");
- zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
methodField = type.getOopField("_method");
entryBCIField = type.getCIntegerField("_entry_bci");
osrLinkField = type.getAddressField("_osr_link");
--- a/hotspot/make/linux/makefiles/sa.make Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/make/linux/makefiles/sa.make Thu Jul 15 19:52:58 2010 -0700
@@ -40,6 +40,9 @@
# tools.jar is needed by the JDI - SA binding
SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
# gnumake 3.78.1 does not accept the *s that
# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
@@ -65,7 +68,7 @@
echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
exit 1; \
fi
- $(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \
+ $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
echo ""; \
exit 1; \
--- a/hotspot/make/solaris/makefiles/sa.make Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/make/solaris/makefiles/sa.make Thu Jul 15 19:52:58 2010 -0700
@@ -36,6 +36,9 @@
# tools.jar is needed by the JDI - SA binding
SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
# gnumake 3.78.1 does not accept the *s that
# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
@@ -59,7 +62,7 @@
echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
exit 1; \
fi
- $(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \
+ $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
echo ""; \
exit 1; \
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -376,10 +376,17 @@
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
+ static bool supports_processor_topology() {
+ return (_cpuid_info.std_max_function >= 0xB) &&
+ // eax[4:0] | ebx[0:15] == 0 indicates invalid topology level.
+ // Some cpus have max cpuid >= 0xB but do not support processor topology.
+ ((_cpuid_info.tpl_cpuidB0_eax & 0x1f | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0);
+ }
+
static uint cores_per_cpu() {
uint result = 1;
if (is_intel()) {
- if (_cpuid_info.std_max_function >= 0xB) {
+ if (supports_processor_topology()) {
result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
_cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
} else {
@@ -393,7 +400,7 @@
static uint threads_per_core() {
uint result = 1;
- if (is_intel() && _cpuid_info.std_max_function >= 0xB) {
+ if (is_intel() && supports_processor_topology()) {
result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
} else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -2079,9 +2079,9 @@
static char saved_jvm_path[MAXPATHLEN] = {0};
// Find the full path to the current module, libjvm.so or libjvm_g.so
-void os::jvm_path(char *buf, jint len) {
+void os::jvm_path(char *buf, jint buflen) {
// Error checking.
- if (len < MAXPATHLEN) {
+ if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0';
return;
@@ -2117,6 +2117,9 @@
// Look for JAVA_HOME in the environment.
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != NULL && java_home_var[0] != 0) {
+ char* jrelib_p;
+ int len;
+
// Check the current module name "libjvm.so" or "libjvm_g.so".
p = strrchr(buf, '/');
assert(strstr(p, "/libjvm") == p, "invalid library name");
@@ -2124,14 +2127,24 @@
if (realpath(java_home_var, buf) == NULL)
return;
- sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch);
+
+ // determine if this is a legacy image or modules image
+ // modules image doesn't have "jre" subdirectory
+ len = strlen(buf);
+ jrelib_p = buf + len;
+ snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+ if (0 != access(buf, F_OK)) {
+ snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+ }
+
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm[_g].so" instead of
// "libjvm"debug_only("_g")".so" since for fastdebug version
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
// It is used when we are choosing the HPI library's name
// "libhpi[_g].so" in hpi::initialize_get_interface().
- sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p);
+ len = strlen(buf);
+ snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
} else {
// Go back to path of .so
if (realpath(dli_fname, buf) == NULL)
--- a/hotspot/src/os/linux/vm/vtune_linux.cpp Thu Jul 15 19:51:34 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_linux.cpp.incl"
-
-// empty implementation
-
-void VTune::start_GC() {}
-void VTune::end_GC() {}
-void VTune::start_class_load() {}
-void VTune::end_class_load() {}
-void VTune::exit() {}
-void VTune::register_stub(const char* name, address start, address end) {}
-
-void VTune::create_nmethod(nmethod* nm) {}
-void VTune::delete_nmethod(nmethod* nm) {}
-
-void vtune_init() {}
-
-
-// Reconciliation History
-// vtune_solaris.cpp 1.8 99/07/12 23:54:21
-// End
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -2435,6 +2435,8 @@
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != NULL && java_home_var[0] != 0) {
char cpu_arch[12];
+ char* jrelib_p;
+ int len;
sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof(cpu_arch));
#ifdef _LP64
// If we are on sparc running a 64-bit vm, look in jre/lib/sparcv9.
@@ -2450,14 +2452,23 @@
p = strstr(p, "_g") ? "_g" : "";
realpath(java_home_var, buf);
- sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch);
+ // determine if this is a legacy image or modules image
+ // modules image doesn't have "jre" subdirectory
+ len = strlen(buf);
+ jrelib_p = buf + len;
+ snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+ if (0 != access(buf, F_OK)) {
+ snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+ }
+
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm[_g].so" instead of
// "libjvm"debug_only("_g")".so" since for fastdebug version
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
// It is used when we are choosing the HPI library's name
// "libhpi[_g].so" in hpi::initialize_get_interface().
- sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p);
+ len = strlen(buf);
+ snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
} else {
// Go back to path of .so
realpath((char *)dlinfo.dli_fname, buf);
--- a/hotspot/src/os/solaris/vm/vtune_solaris.cpp Thu Jul 15 19:51:34 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_solaris.cpp.incl"
-
-// empty implementation
-
-void VTune::start_GC() {}
-void VTune::end_GC() {}
-void VTune::start_class_load() {}
-void VTune::end_class_load() {}
-void VTune::exit() {}
-void VTune::register_stub(const char* name, address start, address end) {}
-
-void VTune::create_nmethod(nmethod* nm) {}
-void VTune::delete_nmethod(nmethod* nm) {}
-
-void vtune_init() {}
--- a/hotspot/src/os/windows/vm/vtune_windows.cpp Thu Jul 15 19:51:34 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_windows.cpp.incl"
-
-static int current_method_ID = 0;
-
-// ------------- iJITProf.h -------------------
-// defined by Intel -- do not change
-
-#include "windows.h"
-
-extern "C" {
- enum iJITP_Event {
- ExceptionOccurred_S, // Java exception
- ExceptionOccurred_IDS,
-
- Shutdown, // VM exit
-
- ThreadCreate, // threads
- ThreadDestroy,
- ThreadSwitch,
-
- ClassLoadStart, // class loading
- ClassLoadEnd,
-
- GCStart, // GC
- GCEnd,
-
- NMethodCreate = 13, // nmethod creation
- NMethodDelete
-
- // rest of event types omitted (call profiling not supported yet)
- };
-
- // version number -- 0 if VTune not installed
- int WINAPI iJitP_VersionNumber();
-
- enum iJITP_ModeFlags {
- NoNotification = 0x0, // don't call vtune
- NotifyNMethodCreate = 0x1, // notify NMethod_Create
- NotifyNMethodDelete = 0x2, // notify NMethod_Create
- NotifyMethodEnter = 0x4, // method entry
- NotifyMethodExit = 0x8, // method exit
- NotifyShutdown = 0x10, // VM exit
- NotifyGC = 0x20, // GC
- };
-
- // call back function type
- typedef void (WINAPI *ModeChangedFn)(iJITP_ModeFlags flags);
-
- // ------------- VTune method interfaces ----------------------
- typedef void (WINAPI *RegisterCallbackFn)(ModeChangedFn fn); // register callback
- typedef int (WINAPI *NotifyEventFn)(iJITP_Event, void* event_data);
-
- // specific event data structures
-
- // data for NMethodCreate
-
- struct VTuneObj { // base class for allocation
- // (can't use CHeapObj -- has vtable ptr)
- void* operator new(size_t size) { return os::malloc(size); }
- void operator delete(void* p) { fatal("never delete VTune data"); }
- };
-
- struct LineNumberInfo : VTuneObj { // PC-to-line number mapping
- unsigned long offset; // byte offset from start of method
- unsigned long line_num; // corresponding line number
- };
-
- struct MethodLoadInfo : VTuneObj {
- unsigned long methodID; // unique method ID
- const char* name; // method name
- unsigned long instr_start; // start address
- unsigned long instr_size; // length in bytes
- unsigned long line_number_size; // size of line number table
- LineNumberInfo* line_number_table; // line number mapping
- unsigned long classID; // unique class ID
- char* class_file_name; // fully qualified class file name
- char* source_file_name; // fully qualified source file name
-
- MethodLoadInfo(nmethod* nm); // for real nmethods
- MethodLoadInfo(const char* vm_name, address start, address end);
- // for "nmethods" like stubs, interpreter, etc
-
- };
-
- // data for NMethodDelete
- struct MethodInfo : VTuneObj {
- unsigned long methodID; // unique method ID
- unsigned long classID; // (added for convenience -- not part of Intel interface)
-
- MethodInfo(methodOop m);
- };
-};
-
-MethodInfo::MethodInfo(methodOop m) {
- // just give it a new ID -- we're not compiling methods twice (usually)
- // (and even if we did, one might want to see the two versions separately)
- methodID = ++current_method_ID;
-}
-
-MethodLoadInfo::MethodLoadInfo(const char* vm_name, address start, address end) {
- classID = 0;
- methodID = ++current_method_ID;
- name = vm_name;
- instr_start = (unsigned long)start;
- instr_size = end - start;
- line_number_size = 0;
- line_number_table = NULL;
- class_file_name = source_file_name = "HotSpot JVM";
-}
-
-MethodLoadInfo::MethodLoadInfo(nmethod* nm) {
- methodOop m = nm->method();
- MethodInfo info(m);
- classID = info.classID;
- methodID = info.methodID;
- name = strdup(m->name()->as_C_string());
- instr_start = (unsigned long)nm->instructions_begin();
- instr_size = nm->code_size();
- line_number_size = 0;
- line_number_table = NULL;
- klassOop kl = m->method_holder();
- char* class_name = Klass::cast(kl)->name()->as_C_string();
- char* file_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + 1);
- strcpy(file_name, class_name);
- class_file_name = file_name;
- char* src_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + strlen(".java") + 1);
- strcpy(src_name, class_name);
- strcat(src_name, ".java");
- source_file_name = src_name;
-}
-
-// --------------------- DLL loading functions ------------------------
-
-#define DLLNAME "iJitProf.dll"
-
-static HINSTANCE load_lib(char* name) {
- HINSTANCE lib = NULL;
- HKEY hk;
-
- // try to get VTune directory from the registry
- if (RegOpenKey(HKEY_CURRENT_USER, "Software\\VB and VBA Program Settings\\VTune\\StartUp", &hk) == ERROR_SUCCESS) {
- for (int i = 0; true; i++) {
- char szName[MAX_PATH + 1];
- char szVal [MAX_PATH + 1];
- DWORD cbName, cbVal;
-
- cbName = cbVal = MAX_PATH + 1;
- if (RegEnumValue(hk, i, szName, &cbName, NULL, NULL, (LPBYTE)szVal, &cbVal) == ERROR_SUCCESS) {
- // get VTune directory
- if (!strcmp(szName, name)) {
- char*p = szVal;
- while (*p == ' ') p++; // trim
- char* q = p + strlen(p) - 1;
- while (*q == ' ') *(q--) = '\0';
-
- // chdir to the VTune dir
- GetCurrentDirectory(MAX_PATH + 1, szName);
- SetCurrentDirectory(p);
- // load lib
- lib = LoadLibrary(strcat(strcat(p, "\\"), DLLNAME));
- if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s", p);
- // restore current dir
- SetCurrentDirectory(szName);
- break;
- }
- } else {
- break;
- }
- }
- }
- return lib;
-}
-
-static RegisterCallbackFn iJIT_RegisterCallback = NULL;
-static NotifyEventFn iJIT_NotifyEvent = NULL;
-
-static bool load_iJIT_funcs() {
- // first try to load from PATH
- HINSTANCE lib = LoadLibrary(DLLNAME);
- if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s via PATH", DLLNAME);
-
- // if not successful, try to look in the VTUNE directory
- if (lib == NULL) lib = load_lib("VTUNEDIR30");
- if (lib == NULL) lib = load_lib("VTUNEDIR25");
- if (lib == NULL) lib = load_lib("VTUNEDIR");
-
- if (lib == NULL) return false; // unsuccessful
-
- // try to load the functions
- iJIT_RegisterCallback = (RegisterCallbackFn)GetProcAddress(lib, "iJIT_RegisterCallback");
- iJIT_NotifyEvent = (NotifyEventFn) GetProcAddress(lib, "iJIT_NotifyEvent");
-
- if (!iJIT_RegisterCallback) tty->print_cr("*couldn't find VTune entry point iJIT_RegisterCallback");
- if (!iJIT_NotifyEvent) tty->print_cr("*couldn't find VTune entry point iJIT_NotifyEvent");
- return iJIT_RegisterCallback != NULL && iJIT_NotifyEvent != NULL;
-}
-
-// --------------------- VTune class ------------------------
-
-static bool active = false;
-static int flags = 0;
-
-void VTune::start_GC() {
- if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCStart, NULL);
-}
-
-void VTune::end_GC() {
- if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCEnd, NULL);
-}
-
-void VTune::start_class_load() {
- // not yet implemented in VTune
-}
-
-void VTune::end_class_load() {
- // not yet implemented in VTune
-}
-
-void VTune::exit() {
- if (active && (flags & NotifyShutdown)) iJIT_NotifyEvent(Shutdown, NULL);
-}
-
-void VTune::register_stub(const char* name, address start, address end) {
- if (flags & NotifyNMethodCreate) {
- MethodLoadInfo* info = new MethodLoadInfo(name, start, end);
- if (PrintMiscellaneous && WizardMode && Verbose) {
- tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
- info->instr_start, info->instr_start + info->instr_size);
- }
- iJIT_NotifyEvent(NMethodCreate, info);
- }
-}
-
-void VTune::create_nmethod(nmethod* nm) {
- if (flags & NotifyNMethodCreate) {
- MethodLoadInfo* info = new MethodLoadInfo(nm);
- if (PrintMiscellaneous && WizardMode && Verbose) {
- tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
- info->instr_start, info->instr_start + info->instr_size);
- }
- iJIT_NotifyEvent(NMethodCreate, info);
- }
-}
-
-void VTune::delete_nmethod(nmethod* nm) {
- if (flags & NotifyNMethodDelete) {
- MethodInfo* info = new MethodInfo(nm->method());
- iJIT_NotifyEvent(NMethodDelete, info);
- }
-}
-
-static void set_flags(int new_flags) {
- flags = new_flags;
- // if (WizardMode) tty->print_cr("*new VTune flags: %#x", flags);
-}
-
-void vtune_init() {
- if (!UseVTune) return;
- active = load_iJIT_funcs();
- if (active) {
- iJIT_RegisterCallback((ModeChangedFn)set_flags);
- } else {
- assert(flags == 0, "flags shouldn't be set");
- }
-}
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -106,7 +106,7 @@
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i))
- _arg_returned.set_bit(i);
+ _arg_returned.set(i);
}
_return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
@@ -126,16 +126,16 @@
if (_conservative)
return true;
for (int i = 0; i < _arg_size; i++) {
- if (vars.contains(i) && _arg_stack.at(i))
+ if (vars.contains(i) && _arg_stack.test(i))
return true;
}
return false;
}
-void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) {
+void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) {
- bm.clear_bit(i);
+ bm >>= i;
}
}
}
@@ -1157,15 +1157,15 @@
ciSignature* sig = method()->signature();
int j = 0;
if (!method()->is_static()) {
- _arg_local.set_bit(0);
- _arg_stack.set_bit(0);
+ _arg_local.set(0);
+ _arg_stack.set(0);
j++;
}
for (i = 0; i < sig->count(); i++) {
ciType* t = sig->type_at(i);
if (!t->is_primitive_type()) {
- _arg_local.set_bit(j);
- _arg_stack.set_bit(j);
+ _arg_local.set(j);
+ _arg_stack.set(j);
}
j += t->size();
}
@@ -1198,9 +1198,9 @@
set_modified(var, OFFSET_ANY, 4);
set_global_escape(var);
}
- _arg_local.clear();
- _arg_stack.clear();
- _arg_returned.clear();
+ _arg_local.Clear();
+ _arg_stack.Clear();
+ _arg_returned.Clear();
_return_local = false;
_return_allocated = false;
_allocated_escapes = true;
@@ -1254,7 +1254,7 @@
// Do not scan method if it has no object parameters and
// does not returns an object (_return_allocated is set in initialize()).
- if (_arg_local.is_empty() && !_return_allocated) {
+ if (_arg_local.Size() == 0 && !_return_allocated) {
// Clear all info since method's bytecode was not analysed and
// set pessimistic escape information.
clear_escape_info();
@@ -1275,14 +1275,14 @@
//
if (!has_dependencies() && !methodData()->is_empty()) {
for (i = 0; i < _arg_size; i++) {
- if (_arg_local.at(i)) {
- assert(_arg_stack.at(i), "inconsistent escape info");
+ if (_arg_local.test(i)) {
+ assert(_arg_stack.test(i), "inconsistent escape info");
methodData()->set_arg_local(i);
methodData()->set_arg_stack(i);
- } else if (_arg_stack.at(i)) {
+ } else if (_arg_stack.test(i)) {
methodData()->set_arg_stack(i);
}
- if (_arg_returned.at(i)) {
+ if (_arg_returned.test(i)) {
methodData()->set_arg_returned(i);
}
methodData()->set_arg_modified(i, _arg_modified[i]);
@@ -1308,9 +1308,12 @@
// read escape information from method descriptor
for (int i = 0; i < _arg_size; i++) {
- _arg_local.at_put(i, methodData()->is_arg_local(i));
- _arg_stack.at_put(i, methodData()->is_arg_stack(i));
- _arg_returned.at_put(i, methodData()->is_arg_returned(i));
+ if (methodData()->is_arg_local(i))
+ _arg_local.set(i);
+ if (methodData()->is_arg_stack(i))
+ _arg_stack.set(i);
+ if (methodData()->is_arg_returned(i))
+ _arg_returned.set(i);
_arg_modified[i] = methodData()->arg_modified(i);
}
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
@@ -1358,26 +1361,26 @@
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
: _conservative(method == NULL || !EstimateArgEscape)
+ , _arena(CURRENT_ENV->arena())
, _method(method)
, _methodData(method ? method->method_data() : NULL)
, _arg_size(method ? method->arg_size() : 0)
- , _stack()
- , _arg_local(_arg_size)
- , _arg_stack(_arg_size)
- , _arg_returned(_arg_size)
- , _dirty(_arg_size)
+ , _arg_local(_arena)
+ , _arg_stack(_arena)
+ , _arg_returned(_arena)
+ , _dirty(_arena)
, _return_local(false)
, _return_allocated(false)
, _allocated_escapes(false)
, _unknown_modified(false)
- , _dependencies()
+ , _dependencies(_arena, 4, 0, NULL)
, _parent(parent)
, _level(parent == NULL ? 0 : parent->level() + 1) {
if (!_conservative) {
- _arg_local.clear();
- _arg_stack.clear();
- _arg_returned.clear();
- _dirty.clear();
+ _arg_local.Clear();
+ _arg_stack.Clear();
+ _arg_returned.Clear();
+ _dirty.Clear();
Arena* arena = CURRENT_ENV->arena();
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
@@ -1414,8 +1417,8 @@
deps->assert_evol_method(method());
}
for (int i = 0; i < _dependencies.length(); i+=2) {
- ciKlass *k = _dependencies[i]->as_klass();
- ciMethod *m = _dependencies[i+1]->as_method();
+ ciKlass *k = _dependencies.at(i)->as_klass();
+ ciMethod *m = _dependencies.at(i+1)->as_method();
deps->assert_unique_concrete_method(k, m);
}
}
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -22,9 +22,6 @@
*
*/
-define_array(ciObjectArray, ciObject*);
-define_stack(ciObjectList, ciObjectArray);
-
// This class implements a fast, conservative analysis of effect of methods
// on the escape state of their arguments. The analysis is at the bytecode
// level.
@@ -34,18 +31,17 @@
class BCEscapeAnalyzer : public ResourceObj {
private:
+ Arena* _arena; // ciEnv arena
+
bool _conservative; // If true, return maximally
// conservative results.
ciMethod* _method;
ciMethodData* _methodData;
int _arg_size;
-
- intStack _stack;
-
- BitMap _arg_local;
- BitMap _arg_stack;
- BitMap _arg_returned;
- BitMap _dirty;
+ VectorSet _arg_local;
+ VectorSet _arg_stack;
+ VectorSet _arg_returned;
+ VectorSet _dirty;
enum{ ARG_OFFSET_MAX = 31};
uint *_arg_modified;
@@ -54,7 +50,7 @@
bool _allocated_escapes;
bool _unknown_modified;
- ciObjectList _dependencies;
+ GrowableArray<ciObject *> _dependencies;
ciMethodBlocks *_methodBlocks;
@@ -68,20 +64,10 @@
private:
// helper functions
bool is_argument(int i) { return i >= 0 && i < _arg_size; }
-
- void raw_push(int i) { _stack.push(i); }
- int raw_pop() { return _stack.is_empty() ? -1 : _stack.pop(); }
- void apush(int i) { raw_push(i); }
- void spush() { raw_push(-1); }
- void lpush() { spush(); spush(); }
- int apop() { return raw_pop(); }
- void spop() { assert(_stack.is_empty() || _stack.top() == -1, ""); raw_pop(); }
- void lpop() { spop(); spop(); }
-
void set_returned(ArgumentMap vars);
bool is_argument(ArgumentMap vars);
bool is_arg_stack(ArgumentMap vars);
- void clear_bits(ArgumentMap vars, BitMap &bs);
+ void clear_bits(ArgumentMap vars, VectorSet &bs);
void set_method_escape(ArgumentMap vars);
void set_global_escape(ArgumentMap vars);
void set_dirty(ArgumentMap vars);
@@ -116,25 +102,25 @@
ciMethodData* methodData() const { return _methodData; }
BCEscapeAnalyzer* parent() const { return _parent; }
int level() const { return _level; }
- ciObjectList* dependencies() { return &_dependencies; }
+ GrowableArray<ciObject *>* dependencies() { return &_dependencies; }
bool has_dependencies() const { return !_dependencies.is_empty(); }
// retrieval of interprocedural escape information
// The given argument does not escape the callee.
bool is_arg_local(int i) const {
- return !_conservative && _arg_local.at(i);
+ return !_conservative && _arg_local.test(i);
}
// The given argument escapes the callee, but does not become globally
// reachable.
bool is_arg_stack(int i) const {
- return !_conservative && _arg_stack.at(i);
+ return !_conservative && _arg_stack.test(i);
}
// The given argument does not escape globally, and may be returned.
bool is_arg_returned(int i) const {
- return !_conservative && _arg_returned.at(i); }
+ return !_conservative && _arg_returned.test(i); }
// True iff only input arguments are returned.
bool is_return_local() const {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,9 +44,7 @@
_flags = ciFlags(access_flags);
_has_finalizer = access_flags.has_finalizer();
_has_subklass = ik->subklass() != NULL;
- _is_initialized = ik->is_initialized();
- // Next line must follow and use the result of the previous line:
- _is_linked = _is_initialized || ik->is_linked();
+ _init_state = (instanceKlass::ClassState)ik->get_init_state();
_nonstatic_field_size = ik->nonstatic_field_size();
_has_nonstatic_fields = ik->has_nonstatic_fields();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
@@ -91,8 +89,7 @@
: ciKlass(name, ciInstanceKlassKlass::make())
{
assert(name->byte_at(0) != '[', "not an instance klass");
- _is_initialized = false;
- _is_linked = false;
+ _init_state = (instanceKlass::ClassState)0;
_nonstatic_field_size = -1;
_has_nonstatic_fields = false;
_nonstatic_fields = NULL;
@@ -109,21 +106,10 @@
// ------------------------------------------------------------------
// ciInstanceKlass::compute_shared_is_initialized
-bool ciInstanceKlass::compute_shared_is_initialized() {
+void ciInstanceKlass::compute_shared_init_state() {
GUARDED_VM_ENTRY(
instanceKlass* ik = get_instanceKlass();
- _is_initialized = ik->is_initialized();
- return _is_initialized;
- )
-}
-
-// ------------------------------------------------------------------
-// ciInstanceKlass::compute_shared_is_linked
-bool ciInstanceKlass::compute_shared_is_linked() {
- GUARDED_VM_ENTRY(
- instanceKlass* ik = get_instanceKlass();
- _is_linked = ik->is_linked();
- return _is_linked;
+ _init_state = (instanceKlass::ClassState)ik->get_init_state();
)
}
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,9 +39,8 @@
jobject _loader;
jobject _protection_domain;
+ instanceKlass::ClassState _init_state; // state of class
bool _is_shared;
- bool _is_initialized;
- bool _is_linked;
bool _has_finalizer;
bool _has_subklass;
bool _has_nonstatic_fields;
@@ -87,27 +86,34 @@
bool is_shared() { return _is_shared; }
- bool compute_shared_is_initialized();
- bool compute_shared_is_linked();
+ void compute_shared_init_state();
bool compute_shared_has_subklass();
int compute_shared_nof_implementors();
int compute_nonstatic_fields();
GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
+ // Update the init_state for shared klasses
+ void update_if_shared(instanceKlass::ClassState expected) {
+ if (_is_shared && _init_state != expected) {
+ if (is_loaded()) compute_shared_init_state();
+ }
+ }
+
public:
// Has this klass been initialized?
bool is_initialized() {
- if (_is_shared && !_is_initialized) {
- return is_loaded() && compute_shared_is_initialized();
- }
- return _is_initialized;
+ update_if_shared(instanceKlass::fully_initialized);
+ return _init_state == instanceKlass::fully_initialized;
+ }
+ // Is this klass being initialized?
+ bool is_being_initialized() {
+ update_if_shared(instanceKlass::being_initialized);
+ return _init_state == instanceKlass::being_initialized;
}
// Has this klass been linked?
bool is_linked() {
- if (_is_shared && !_is_linked) {
- return is_loaded() && compute_shared_is_linked();
- }
- return _is_linked;
+ update_if_shared(instanceKlass::linked);
+ return _init_state >= instanceKlass::linked;
}
// General klass information.
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -54,10 +54,10 @@
_code = NULL;
_exception_handlers = NULL;
_liveness = NULL;
- _bcea = NULL;
_method_blocks = NULL;
#ifdef COMPILER2
_flow = NULL;
+ _bcea = NULL;
#endif // COMPILER2
ciEnv *env = CURRENT_ENV;
@@ -121,11 +121,11 @@
_intrinsic_id = vmIntrinsics::_none;
_liveness = NULL;
_can_be_statically_bound = false;
- _bcea = NULL;
_method_blocks = NULL;
_method_data = NULL;
#ifdef COMPILER2
_flow = NULL;
+ _bcea = NULL;
#endif // COMPILER2
}
@@ -1033,10 +1033,15 @@
bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); }
BCEscapeAnalyzer *ciMethod::get_bcea() {
+#ifdef COMPILER2
if (_bcea == NULL) {
_bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
}
return _bcea;
+#else // COMPILER2
+ ShouldNotReachHere();
+ return NULL;
+#endif // COMPILER2
}
ciMethodBlocks *ciMethod::get_method_blocks() {
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -48,7 +48,6 @@
ciInstanceKlass* _holder;
ciSignature* _signature;
ciMethodData* _method_data;
- BCEscapeAnalyzer* _bcea;
ciMethodBlocks* _method_blocks;
// Code attributes.
@@ -72,7 +71,8 @@
// Optional liveness analyzer.
MethodLiveness* _liveness;
#ifdef COMPILER2
- ciTypeFlow* _flow;
+ ciTypeFlow* _flow;
+ BCEscapeAnalyzer* _bcea;
#endif
ciMethod(methodHandle h_m);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -832,7 +832,6 @@
instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
- VTuneClassLoadMarker clm;
ResourceMark rm(THREAD);
EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
--- a/hotspot/src/share/vm/code/codeBlob.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -210,6 +210,7 @@
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) AdapterBlob(size, cb);
+ CodeCache::commit(blob);
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
@@ -281,7 +282,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub);
Disassembler::decode(stub->instructions_begin(), stub->instructions_end());
}
- VTune::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
Forte::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -356,7 +356,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -414,7 +413,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -474,7 +472,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -533,7 +530,6 @@
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/code/codeCache.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -93,6 +93,8 @@
CodeHeap * CodeCache::_heap = new CodeHeap();
int CodeCache::_number_of_blobs = 0;
+int CodeCache::_number_of_adapters = 0;
+int CodeCache::_number_of_nmethods = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
@@ -176,8 +178,14 @@
verify_if_often();
print_trace("free", cb);
- if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
- _number_of_nmethods_with_dependencies--;
+ if (cb->is_nmethod()) {
+ _number_of_nmethods--;
+ if (((nmethod *)cb)->has_dependencies()) {
+ _number_of_nmethods_with_dependencies--;
+ }
+ }
+ if (cb->is_adapter_blob()) {
+ _number_of_adapters--;
}
_number_of_blobs--;
@@ -191,9 +199,16 @@
void CodeCache::commit(CodeBlob* cb) {
// this is called by nmethod::nmethod, which must already own CodeCache_lock
assert_locked_or_safepoint(CodeCache_lock);
- if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
- _number_of_nmethods_with_dependencies++;
+ if (cb->is_nmethod()) {
+ _number_of_nmethods++;
+ if (((nmethod *)cb)->has_dependencies()) {
+ _number_of_nmethods_with_dependencies++;
+ }
}
+ if (cb->is_adapter_blob()) {
+ _number_of_adapters++;
+ }
+
// flush the hardware I-cache
ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size());
}
--- a/hotspot/src/share/vm/code/codeCache.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,8 @@
// 4422213 or 4436291 for details.
static CodeHeap * _heap;
static int _number_of_blobs;
+ static int _number_of_adapters;
+ static int _number_of_nmethods;
static int _number_of_nmethods_with_dependencies;
static bool _needs_cache_clean;
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
@@ -105,6 +107,8 @@
static nmethod* first_nmethod();
static nmethod* next_nmethod (CodeBlob* cb);
static int nof_blobs() { return _number_of_blobs; }
+ static int nof_adapters() { return _number_of_adapters; }
+ static int nof_nmethods() { return _number_of_nmethods; }
// GC support
static void gc_epilogue();
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -397,11 +397,6 @@
//-------------end of code for ExceptionCache--------------
-void nmFlags::clear() {
- assert(sizeof(nmFlags) == sizeof(int), "using more than one word for nmFlags");
- *(jint*)this = 0;
-}
-
int nmethod::total_size() const {
return
code_size() +
@@ -419,8 +414,32 @@
return NULL;
}
-// %%% This variable is no longer used?
-int nmethod::_zombie_instruction_size = NativeJump::instruction_size;
+// Fill in default values for various flag fields
+void nmethod::init_defaults() {
+ _state = alive;
+ _marked_for_reclamation = 0;
+ _has_flushed_dependencies = 0;
+ _speculatively_disconnected = 0;
+ _has_unsafe_access = 0;
+ _has_method_handle_invokes = 0;
+ _marked_for_deoptimization = 0;
+ _lock_count = 0;
+ _stack_traversal_mark = 0;
+ _unload_reported = false; // jvmti state
+
+ NOT_PRODUCT(_has_debug_info = false);
+ _oops_do_mark_link = NULL;
+ _jmethod_id = NULL;
+ _osr_link = NULL;
+ _scavenge_root_link = NULL;
+ _scavenge_root_state = 0;
+ _saved_nmethod_link = NULL;
+ _compiler = NULL;
+
+#ifdef HAVE_DTRACE_H
+ _trap_offset = 0;
+#endif // def HAVE_DTRACE_H
+}
nmethod* nmethod::new_native_nmethod(methodHandle method,
@@ -580,25 +599,16 @@
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
_entry_bci = InvocationEntryBci;
- _jmethod_id = NULL;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
- _saved_nmethod_link = NULL;
- _compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
_deoptimize_offset = 0;
_deoptimize_mh_offset = 0;
_orig_pc_offset = 0;
-#ifdef HAVE_DTRACE_H
- _trap_offset = 0;
-#endif // def HAVE_DTRACE_H
+
_stub_offset = data_offset();
_consts_offset = data_offset();
_oops_offset = data_offset();
@@ -616,17 +626,9 @@
_exception_cache = NULL;
_pc_desc_cache.reset_to(NULL);
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
code_buffer->copy_oops_to(this);
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
- VTune::create_nmethod(this);
}
if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -674,15 +676,9 @@
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
_entry_bci = InvocationEntryBci;
- _jmethod_id = NULL;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
- _compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
@@ -708,17 +704,9 @@
_exception_cache = NULL;
_pc_desc_cache.reset_to(NULL);
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
code_buffer->copy_oops_to(this);
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
- VTune::create_nmethod(this);
}
if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -783,21 +771,13 @@
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
- _jmethod_id = NULL;
+ _entry_bci = entry_bci;
_compile_id = compile_id;
_comp_level = comp_level;
- _entry_bci = entry_bci;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
_compiler = compiler;
_orig_pc_offset = orig_pc_offset;
-#ifdef HAVE_DTRACE_H
- _trap_offset = 0;
-#endif // def HAVE_DTRACE_H
_stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
// Exception handler and deopt handler are in the stub section
@@ -824,15 +804,6 @@
_exception_cache = NULL;
_pc_desc_cache.reset_to(scopes_pcs_begin());
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _unload_reported = false; // jvmti state
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
// Copy contents of ScopeDescRecorder to nmethod
code_buffer->copy_oops_to(this);
debug_info->copy_to(this);
@@ -844,8 +815,6 @@
CodeCache::commit(this);
- VTune::create_nmethod(this);
-
// Copy contents of ExceptionHandlerTable to nmethod
handler_table->copy_to(this);
nul_chk_table->copy_to(this);
@@ -991,11 +960,6 @@
}
-void nmethod::set_version(int v) {
- flags.version = v;
-}
-
-
// Promote one word from an assembly-time handle to a live embedded oop.
inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
if (handle == NULL ||
@@ -1142,6 +1106,8 @@
// This is a private interface with the sweeper.
void nmethod::mark_as_seen_on_stack() {
assert(is_not_entrant(), "must be a non-entrant method");
+ // Set the traversal mark to ensure that the sweeper does 2
+ // cleaning passes before moving to zombie.
set_stack_traversal_mark(NMethodSweeper::traversal_count());
}
@@ -1210,7 +1176,7 @@
// for later on.
CodeCache::set_needs_cache_clean(true);
}
- flags.state = unloaded;
+ _state = unloaded;
// Log the unloading.
log_state_change();
@@ -1236,21 +1202,21 @@
if (LogCompilation) {
if (xtty != NULL) {
ttyLocker ttyl; // keep the following output all in one block
- if (flags.state == unloaded) {
+ if (_state == unloaded) {
xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
os::current_thread_id());
} else {
xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
os::current_thread_id(),
- (flags.state == zombie ? " zombie='1'" : ""));
+ (_state == zombie ? " zombie='1'" : ""));
}
log_identity(xtty);
xtty->stamp();
xtty->end_elem();
}
}
- if (PrintCompilation && flags.state != unloaded) {
- print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
+ if (PrintCompilation && _state != unloaded) {
+ print_on(tty, _state == zombie ? "made zombie " : "made not entrant ");
tty->cr();
}
}
@@ -1261,8 +1227,9 @@
bool was_alive = false;
- // Make sure the nmethod is not flushed in case of a safepoint in code below.
+ // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
nmethodLocker nml(this);
+ methodHandle the_method(method());
{
// If the method is already zombie there is nothing to do
@@ -1282,7 +1249,7 @@
// Enter critical section. Does not block for safepoint.
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
- if (flags.state == state) {
+ if (_state == state) {
// another thread already performed this transition so nothing
// to do, but return false to indicate this.
return false;
@@ -1293,17 +1260,37 @@
if (!is_osr_method() && !is_not_entrant()) {
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
SharedRuntime::get_handle_wrong_method_stub());
- assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
}
- was_alive = is_in_use(); // Read state under lock
+ if (is_in_use()) {
+ // It's a true state change, so mark the method as decompiled.
+ // Do it only for transition from alive.
+ inc_decompile_count();
+ }
// Change state
- flags.state = state;
+ _state = state;
// Log the transition once
log_state_change();
+ // Remove nmethod from method.
+ // We need to check if both the _code and _from_compiled_code_entry_point
+ // refer to this nmethod because there is a race in setting these two fields
+ // in methodOop as seen in bugid 4947125.
+ // If the vep() points to the zombie nmethod, the memory for the nmethod
+ // could be flushed and the compiler and vtable stubs could still call
+ // through it.
+ if (method() != NULL && (method()->code() == this ||
+ method()->from_compiled_entry() == verified_entry_point())) {
+ HandleMark hm;
+ method()->clear_code();
+ }
+
+ if (state == not_entrant) {
+ mark_as_seen_on_stack();
+ }
+
} // leave critical region under Patching_lock
// When the nmethod becomes zombie it is no longer alive so the
@@ -1311,18 +1298,17 @@
// state will be flushed later when the transition to zombie
// happens or they get unloaded.
if (state == zombie) {
+ // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
+ // and it hasn't already been reported for this nmethod then report it now.
+ // (the event may have been reported earilier if the GC marked it for unloading).
+ post_compiled_method_unload();
+
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
flush_dependencies(NULL);
} else {
assert(state == not_entrant, "other cases may need to be handled differently");
}
- if (state == not_entrant) {
- Events::log("Make nmethod not entrant " INTPTR_FORMAT, this);
- } else {
- Events::log("Make nmethod zombie " INTPTR_FORMAT, this);
- }
-
if (TraceCreateZombies) {
tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
}
@@ -1330,47 +1316,6 @@
// Make sweeper aware that there is a zombie method that needs to be removed
NMethodSweeper::notify(this);
- // not_entrant only stuff
- if (state == not_entrant) {
- mark_as_seen_on_stack();
- }
-
- if (was_alive) {
- // It's a true state change, so mark the method as decompiled.
- // Do it only for transition from alive.
- inc_decompile_count();
- }
-
- // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
- // and it hasn't already been reported for this nmethod then report it now.
- // (the event may have been reported earilier if the GC marked it for unloading).
- if (state == zombie) {
- post_compiled_method_unload();
- }
-
-
- // Zombie only stuff
- if (state == zombie) {
- VTune::delete_nmethod(this);
- }
-
- // Check whether method got unloaded at a safepoint before this,
- // if so we can skip the flushing steps below
- if (method() == NULL) return true;
-
- // Remove nmethod from method.
- // We need to check if both the _code and _from_compiled_code_entry_point
- // refer to this nmethod because there is a race in setting these two fields
- // in methodOop as seen in bugid 4947125.
- // If the vep() points to the zombie nmethod, the memory for the nmethod
- // could be flushed and the compiler and vtable stubs could still call
- // through it.
- if (method()->code() == this ||
- method()->from_compiled_entry() == verified_entry_point()) {
- HandleMark hm;
- method()->clear_code();
- }
-
return true;
}
@@ -2109,7 +2054,6 @@
void nmethod_init() {
// make sure you didn't forget to adjust the filler fields
- assert(sizeof(nmFlags) <= 4, "nmFlags occupies more than a word");
assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
}
@@ -2345,7 +2289,6 @@
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
tty->print(" for method " INTPTR_FORMAT , (address)method());
tty->print(" { ");
- if (version()) tty->print("v%d ", version());
if (is_in_use()) tty->print("in_use ");
if (is_not_entrant()) tty->print("not_entrant ");
if (is_zombie()) tty->print("zombie ");
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -78,29 +78,8 @@
// nmethods (native methods) are the compiled code versions of Java methods.
-
-struct nmFlags {
- friend class VMStructs;
- unsigned int version:8; // version number (0 = first version)
- unsigned int age:4; // age (in # of sweep steps)
-
- unsigned int state:2; // {alive, zombie, unloaded)
-
- unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
- unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
- unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
- unsigned int markedForReclamation:1; // Used by NMethodSweeper
-
- unsigned int has_unsafe_access:1; // May fault due to unsafe access.
- unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
-
- unsigned int speculatively_disconnected:1; // Marked for potential unload
-
- void clear();
-};
-
-
-// A nmethod contains:
+//
+// An nmethod contains:
// - header (the nmethod structure)
// [Relocation]
// - relocation information
@@ -131,8 +110,6 @@
friend class CodeCache; // non-perm oops
private:
// Shared fields for all nmethod's
- static int _zombie_instruction_size;
-
methodOop _method;
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
@@ -147,6 +124,11 @@
AbstractCompiler* _compiler; // The compiler which compiled this nmethod
+ // offsets for entry points
+ address _entry_point; // entry point with class check
+ address _verified_entry_point; // entry point without class check
+ address _osr_entry_point; // entry point for on stack replacement
+
// Offsets for different nmethod parts
int _exception_offset;
// All deoptee's will resume execution at this location described by
@@ -175,23 +157,31 @@
// pc during a deopt.
int _orig_pc_offset;
- int _compile_id; // which compilation made this nmethod
- int _comp_level; // compilation level
+ int _compile_id; // which compilation made this nmethod
+ int _comp_level; // compilation level
+
+ // protected by CodeCache_lock
+ bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
+ bool _speculatively_disconnected; // Marked for potential unload
+
+ bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
+ bool _marked_for_deoptimization; // Used for stack deoptimization
- // offsets for entry points
- address _entry_point; // entry point with class check
- address _verified_entry_point; // entry point without class check
- address _osr_entry_point; // entry point for on stack replacement
+ // used by jvmti to track if an unload event has been posted for this nmethod.
+ bool _unload_reported;
- nmFlags flags; // various flags to keep track of nmethod state
- bool _markedForDeoptimization; // Used for stack deoptimization
+ // set during construction
+ unsigned int _has_unsafe_access:1; // May fault due to unsafe access.
+ unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
+
+ // Protected by Patching_lock
+ unsigned char _state; // {alive, not_entrant, zombie, unloaded)
+
enum { alive = 0,
not_entrant = 1, // uncommon trap has happened but activations may still exist
zombie = 2,
unloaded = 3 };
- // used by jvmti to track if an unload event has been posted for this nmethod.
- bool _unload_reported;
jbyte _scavenge_root_state;
@@ -270,15 +260,15 @@
bool make_not_entrant_or_zombie(unsigned int state);
void inc_decompile_count();
- // used to check that writes to nmFlags are done consistently.
- static void check_safepoint() PRODUCT_RETURN;
-
// Used to manipulate the exception cache
void add_exception_cache_entry(ExceptionCache* new_entry);
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
// Inform external interfaces that a compiled method has been unloaded
- inline void post_compiled_method_unload();
+ void post_compiled_method_unload();
+
+ // Initailize fields to their default values
+ void init_defaults();
public:
// create nmethod with entry_bci
@@ -393,11 +383,11 @@
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
// flag accessing and manipulation
- bool is_in_use() const { return flags.state == alive; }
- bool is_alive() const { return flags.state == alive || flags.state == not_entrant; }
- bool is_not_entrant() const { return flags.state == not_entrant; }
- bool is_zombie() const { return flags.state == zombie; }
- bool is_unloaded() const { return flags.state == unloaded; }
+ bool is_in_use() const { return _state == alive; }
+ bool is_alive() const { return _state == alive || _state == not_entrant; }
+ bool is_not_entrant() const { return _state == not_entrant; }
+ bool is_zombie() const { return _state == zombie; }
+ bool is_unloaded() const { return _state == unloaded; }
// Make the nmethod non entrant. The nmethod will continue to be
// alive. It is used when an uncommon trap happens. Returns true
@@ -410,37 +400,33 @@
bool unload_reported() { return _unload_reported; }
void set_unload_reported() { _unload_reported = true; }
- bool is_marked_for_deoptimization() const { return _markedForDeoptimization; }
- void mark_for_deoptimization() { _markedForDeoptimization = true; }
+ bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
+ void mark_for_deoptimization() { _marked_for_deoptimization = true; }
void make_unloaded(BoolObjectClosure* is_alive, oop cause);
bool has_dependencies() { return dependencies_size() != 0; }
void flush_dependencies(BoolObjectClosure* is_alive);
- bool has_flushed_dependencies() { return flags.hasFlushedDependencies; }
- void set_has_flushed_dependencies() {
+ bool has_flushed_dependencies() { return _has_flushed_dependencies; }
+ void set_has_flushed_dependencies() {
assert(!has_flushed_dependencies(), "should only happen once");
- flags.hasFlushedDependencies = 1;
+ _has_flushed_dependencies = 1;
}
- bool is_marked_for_reclamation() const { return flags.markedForReclamation; }
- void mark_for_reclamation() { flags.markedForReclamation = 1; }
- void unmark_for_reclamation() { flags.markedForReclamation = 0; }
+ bool is_marked_for_reclamation() const { return _marked_for_reclamation; }
+ void mark_for_reclamation() { _marked_for_reclamation = 1; }
+
+ bool has_unsafe_access() const { return _has_unsafe_access; }
+ void set_has_unsafe_access(bool z) { _has_unsafe_access = z; }
- bool has_unsafe_access() const { return flags.has_unsafe_access; }
- void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
+ bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
+ void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
- bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
- void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
-
- bool is_speculatively_disconnected() const { return flags.speculatively_disconnected; }
- void set_speculatively_disconnected(bool z) { flags.speculatively_disconnected = z; }
+ bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
+ void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
int comp_level() const { return _comp_level; }
- int version() const { return flags.version; }
- void set_version(int v);
-
// Support for oops in scopes and relocs:
// Note: index 0 is reserved for null.
oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
--- a/hotspot/src/share/vm/code/vtableStubs.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/code/vtableStubs.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,6 @@
}
_chunk = blob->instructions_begin();
_chunk_end = _chunk + bytes;
- VTune::register_stub("vtable stub", _chunk, _chunk_end);
Forte::register_stub("vtable stub", _chunk, _chunk_end);
// Notify JVMTI about this stub. The event will be recorded by the enclosing
// JvmtiDynamicCodeEventCollector and posted when this thread has released
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Thu Jul 15 19:52:58 2010 -0700
@@ -270,7 +270,7 @@
psParallelCompact.cpp pcTasks.hpp
psParallelCompact.cpp psMarkSweep.hpp
psParallelCompact.cpp psMarkSweepDecorator.hpp
-psParallelCompact.cpp psCompactionManager.hpp
+psParallelCompact.cpp psCompactionManager.inline.hpp
psParallelCompact.cpp psPromotionManager.inline.hpp
psParallelCompact.cpp psOldGen.hpp
psParallelCompact.cpp psParallelCompact.hpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
ParCompactionManager::_objarray_queues = NULL;
ObjectStartArray* ParCompactionManager::_start_array = NULL;
ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL;
-RegionTaskQueueSet* ParCompactionManager::_region_array = NULL;
+RegionTaskQueueSet* ParCompactionManager::_region_array = NULL;
ParCompactionManager::ParCompactionManager() :
_action(CopyAndUpdate) {
@@ -43,25 +43,9 @@
_old_gen = heap->old_gen();
_start_array = old_gen()->start_array();
-
marking_stack()->initialize();
-
- // We want the overflow stack to be permanent
- _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
-
- _objarray_queue.initialize();
- _objarray_overflow_stack =
- new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true);
-
-#ifdef USE_RegionTaskQueueWithOverflow
+ _objarray_stack.initialize();
region_stack()->initialize();
-#else
- region_stack()->initialize();
-
- // We want the overflow stack to be permanent
- _region_overflow_stack =
- new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true);
-#endif
// Note that _revisit_klass_stack is allocated out of the
// C heap (as opposed to out of ResourceArena).
@@ -71,12 +55,9 @@
// From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will
// have to do for now until we are able to investigate a more optimal setting.
_revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
-
}
ParCompactionManager::~ParCompactionManager() {
- delete _overflow_stack;
- delete _objarray_overflow_stack;
delete _revisit_klass_stack;
delete _revisit_mdo_stack;
// _manager_array and _stack_array are statics
@@ -108,12 +89,8 @@
_manager_array[i] = new ParCompactionManager();
guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
stack_array()->register_queue(i, _manager_array[i]->marking_stack());
- _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue);
-#ifdef USE_RegionTaskQueueWithOverflow
- region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue());
-#else
+ _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack);
region_array()->register_queue(i, _manager_array[i]->region_stack());
-#endif
}
// The VMThread gets its own ParCompactionManager, which is not available
@@ -149,57 +126,6 @@
return action() == ParCompactionManager::ResetObjects;
}
-// For now save on a stack
-void ParCompactionManager::save_for_scanning(oop m) {
- stack_push(m);
-}
-
-void ParCompactionManager::stack_push(oop obj) {
-
- if(!marking_stack()->push(obj)) {
- overflow_stack()->push(obj);
- }
-}
-
-oop ParCompactionManager::retrieve_for_scanning() {
-
- // Should not be used in the parallel case
- ShouldNotReachHere();
- return NULL;
-}
-
-// Save region on a stack
-void ParCompactionManager::save_for_processing(size_t region_index) {
-#ifdef ASSERT
- const ParallelCompactData& sd = PSParallelCompact::summary_data();
- ParallelCompactData::RegionData* const region_ptr = sd.region(region_index);
- assert(region_ptr->claimed(), "must be claimed");
- assert(region_ptr->_pushed++ == 0, "should only be pushed once");
-#endif
- region_stack_push(region_index);
-}
-
-void ParCompactionManager::region_stack_push(size_t region_index) {
-
-#ifdef USE_RegionTaskQueueWithOverflow
- region_stack()->save(region_index);
-#else
- if(!region_stack()->push(region_index)) {
- region_overflow_stack()->push(region_index);
- }
-#endif
-}
-
-bool ParCompactionManager::retrieve_for_processing(size_t& region_index) {
-#ifdef USE_RegionTaskQueueWithOverflow
- return region_stack()->retrieve(region_index);
-#else
- // Should not be used in the parallel case
- ShouldNotReachHere();
- return false;
-#endif
-}
-
ParCompactionManager*
ParCompactionManager::gc_thread_compaction_manager(int index) {
assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
@@ -218,8 +144,8 @@
do {
// Drain the overflow stack first, to allow stealing from the marking stack.
oop obj;
- while (!overflow_stack()->is_empty()) {
- overflow_stack()->pop()->follow_contents(this);
+ while (marking_stack()->pop_overflow(obj)) {
+ obj->follow_contents(this);
}
while (marking_stack()->pop_local(obj)) {
obj->follow_contents(this);
@@ -227,11 +153,10 @@
// Process ObjArrays one at a time to avoid marking stack bloat.
ObjArrayTask task;
- if (!_objarray_overflow_stack->is_empty()) {
- task = _objarray_overflow_stack->pop();
+ if (_objarray_stack.pop_overflow(task)) {
objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
k->oop_follow_contents(this, task.obj(), task.index());
- } else if (_objarray_queue.pop_local(task)) {
+ } else if (_objarray_stack.pop_local(task)) {
objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
k->oop_follow_contents(this, task.obj(), task.index());
}
@@ -240,68 +165,18 @@
assert(marking_stacks_empty(), "Sanity");
}
-void ParCompactionManager::drain_region_overflow_stack() {
- size_t region_index = (size_t) -1;
- while(region_stack()->retrieve_from_overflow(region_index)) {
- PSParallelCompact::fill_and_update_region(this, region_index);
- }
-}
-
void ParCompactionManager::drain_region_stacks() {
-#ifdef ASSERT
- ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
- MutableSpace* to_space = heap->young_gen()->to_space();
- MutableSpace* old_space = heap->old_gen()->object_space();
- MutableSpace* perm_space = heap->perm_gen()->object_space();
-#endif /* ASSERT */
-
-#if 1 // def DO_PARALLEL - the serial code hasn't been updated
do {
-
-#ifdef USE_RegionTaskQueueWithOverflow
- // Drain overflow stack first, so other threads can steal from
- // claimed stack while we work.
- size_t region_index = (size_t) -1;
- while(region_stack()->retrieve_from_overflow(region_index)) {
+ // Drain overflow stack first so other threads can steal.
+ size_t region_index;
+ while (region_stack()->pop_overflow(region_index)) {
PSParallelCompact::fill_and_update_region(this, region_index);
}
- while (region_stack()->retrieve_from_stealable_queue(region_index)) {
+ while (region_stack()->pop_local(region_index)) {
PSParallelCompact::fill_and_update_region(this, region_index);
}
} while (!region_stack()->is_empty());
-#else
- // Drain overflow stack first, so other threads can steal from
- // claimed stack while we work.
- while(!region_overflow_stack()->is_empty()) {
- size_t region_index = region_overflow_stack()->pop();
- PSParallelCompact::fill_and_update_region(this, region_index);
- }
-
- size_t region_index = -1;
- // obj is a reference!!!
- while (region_stack()->pop_local(region_index)) {
- // It would be nice to assert about the type of objects we might
- // pop, but they can come from anywhere, unfortunately.
- PSParallelCompact::fill_and_update_region(this, region_index);
- }
- } while((region_stack()->size() != 0) ||
- (region_overflow_stack()->length() != 0));
-#endif
-
-#ifdef USE_RegionTaskQueueWithOverflow
- assert(region_stack()->is_empty(), "Sanity");
-#else
- assert(region_stack()->size() == 0, "Sanity");
- assert(region_overflow_stack()->length() == 0, "Sanity");
-#endif
-#else
- oop obj;
- while (obj = retrieve_for_scanning()) {
- obj->follow_contents(this);
- }
-#endif
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,10 +59,10 @@
private:
// 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB
- #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
- typedef GenericTaskQueue<ObjArrayTask, OBJARRAY_QUEUE_SIZE> ObjArrayTaskQueue;
- typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
- #undef OBJARRAY_QUEUE_SIZE
+ #define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
+ typedef OverflowTaskQueue<ObjArrayTask, QUEUE_SIZE> ObjArrayTaskQueue;
+ typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
+ #undef QUEUE_SIZE
static ParCompactionManager** _manager_array;
static OopTaskQueueSet* _stack_array;
@@ -72,23 +72,13 @@
static PSOldGen* _old_gen;
private:
- OopTaskQueue _marking_stack;
- GrowableArray<oop>* _overflow_stack;
-
- typedef GrowableArray<ObjArrayTask> ObjArrayOverflowStack;
- ObjArrayTaskQueue _objarray_queue;
- ObjArrayOverflowStack* _objarray_overflow_stack;
+ OverflowTaskQueue<oop> _marking_stack;
+ ObjArrayTaskQueue _objarray_stack;
// Is there a way to reuse the _marking_stack for the
// saving empty regions? For now just create a different
// type of TaskQueue.
-
-#ifdef USE_RegionTaskQueueWithOverflow
- RegionTaskQueueWithOverflow _region_stack;
-#else
RegionTaskQueue _region_stack;
- GrowableArray<size_t>* _region_overflow_stack;
-#endif
#if 1 // does this happen enough to need a per thread stack?
GrowableArray<Klass*>* _revisit_klass_stack;
@@ -107,16 +97,8 @@
protected:
// Array of tasks. Needed by the ParallelTaskTerminator.
static RegionTaskQueueSet* region_array() { return _region_array; }
- OopTaskQueue* marking_stack() { return &_marking_stack; }
- GrowableArray<oop>* overflow_stack() { return _overflow_stack; }
-#ifdef USE_RegionTaskQueueWithOverflow
- RegionTaskQueueWithOverflow* region_stack() { return &_region_stack; }
-#else
- RegionTaskQueue* region_stack() { return &_region_stack; }
- GrowableArray<size_t>* region_overflow_stack() {
- return _region_overflow_stack;
- }
-#endif
+ OverflowTaskQueue<oop>* marking_stack() { return &_marking_stack; }
+ RegionTaskQueue* region_stack() { return &_region_stack; }
// Pushes onto the marking stack. If the marking stack is full,
// pushes onto the overflow stack.
@@ -124,11 +106,7 @@
// Do not implement an equivalent stack_pop. Deal with the
// marking stack and overflow stack directly.
- // Pushes onto the region stack. If the region stack is full,
- // pushes onto the region overflow stack.
- void region_stack_push(size_t region_index);
-
-public:
+ public:
Action action() { return _action; }
void set_action(Action v) { _action = v; }
@@ -157,22 +135,15 @@
GrowableArray<DataLayout*>* revisit_mdo_stack() { return _revisit_mdo_stack; }
#endif
- // Save oop for later processing. Must not fail.
- void save_for_scanning(oop m);
- // Get a oop for scanning. If returns null, no oop were found.
- oop retrieve_for_scanning();
-
- inline void push_objarray(oop obj, size_t index);
-
- // Save region for later processing. Must not fail.
- void save_for_processing(size_t region_index);
- // Get a region for processing. If returns null, no region were found.
- bool retrieve_for_processing(size_t& region_index);
+ // Save for later processing. Must not fail.
+ inline void push(oop obj) { _marking_stack.push(obj); }
+ inline void push_objarray(oop objarray, size_t index);
+ inline void push_region(size_t index);
// Access function for compaction managers
static ParCompactionManager* gc_thread_compaction_manager(int index);
- static bool steal(int queue_num, int* seed, Task& t) {
+ static bool steal(int queue_num, int* seed, oop& t) {
return stack_array()->steal(queue_num, seed, t);
}
@@ -180,8 +151,8 @@
return _objarray_queues->steal(queue_num, seed, t);
}
- static bool steal(int queue_num, int* seed, RegionTask& t) {
- return region_array()->steal(queue_num, seed, t);
+ static bool steal(int queue_num, int* seed, size_t& region) {
+ return region_array()->steal(queue_num, seed, region);
}
// Process tasks remaining on any marking stack
@@ -191,9 +162,6 @@
// Process tasks remaining on any stack
void drain_region_stacks();
- // Process tasks remaining on any stack
- void drain_region_overflow_stack();
-
// Debugging support
#ifdef ASSERT
bool stacks_have_been_allocated();
@@ -208,6 +176,5 @@
}
bool ParCompactionManager::marking_stacks_empty() const {
- return _marking_stack.size() == 0 && _overflow_stack->is_empty() &&
- _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty();
+ return _marking_stack.is_empty() && _objarray_stack.is_empty();
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -26,7 +26,16 @@
{
ObjArrayTask task(obj, index);
assert(task.is_valid(), "bad ObjArrayTask");
- if (!_objarray_queue.push(task)) {
- _objarray_overflow_stack->push(task);
- }
+ _objarray_stack.push(task);
}
+
+void ParCompactionManager::push_region(size_t index)
+{
+#ifdef ASSERT
+ const ParallelCompactData& sd = PSParallelCompact::summary_data();
+ ParallelCompactData::RegionData* const region_ptr = sd.region(index);
+ assert(region_ptr->claimed(), "must be claimed");
+ assert(region_ptr->_pushed++ == 0, "should only be pushed once");
+#endif
+ region_stack()->push(index);
+}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -2474,7 +2474,7 @@
for (size_t cur = end_region - 1; cur >= beg_region; --cur) {
if (sd.region(cur)->claim_unsafe()) {
ParCompactionManager* cm = ParCompactionManager::manager_array(which);
- cm->save_for_processing(cur);
+ cm->push_region(cur);
if (TraceParallelOldGCCompactionPhase && Verbose) {
const size_t count_mod_8 = fillable_regions & 7;
@@ -3138,7 +3138,7 @@
assert(cur->data_size() > 0, "region must have live data");
cur->decrement_destination_count();
if (cur < enqueue_end && cur->available() && cur->claim()) {
- cm->save_for_processing(sd.region(cur));
+ cm->push_region(sd.region(cur));
}
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1297,11 +1297,8 @@
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (mark_bitmap()->is_unmarked(obj)) {
- if (mark_obj(obj)) {
- // This thread marked the object and owns the subsequent processing of it.
- cm->save_for_scanning(obj);
- }
+ if (mark_bitmap()->is_unmarked(obj) && mark_obj(obj)) {
+ cm->push(obj);
}
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,45 +94,13 @@
print_stats();
#endif // PS_PM_STATS
- for(uint i=0; i<ParallelGCThreads+1; i++) {
+ for (uint i = 0; i < ParallelGCThreads + 1; i++) {
PSPromotionManager* manager = manager_array(i);
-
- // the guarantees are a bit gratuitous but, if one fires, we'll
- // have a better idea of what went wrong
- if (i < ParallelGCThreads) {
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->overflow_stack_depth()->length() <= 0),
- "promotion manager overflow stack must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->overflow_stack_breadth()->length() <= 0),
- "promotion manager overflow stack must be empty");
-
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->claimed_stack_depth()->size() <= 0),
- "promotion manager claimed stack must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->claimed_stack_breadth()->size() <= 0),
- "promotion manager claimed stack must be empty");
+ if (UseDepthFirstScavengeOrder) {
+ assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
} else {
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->overflow_stack_depth()->length() <= 0),
- "VM Thread promotion manager overflow stack "
- "must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->overflow_stack_breadth()->length() <= 0),
- "VM Thread promotion manager overflow stack "
- "must be empty");
-
- guarantee((!UseDepthFirstScavengeOrder ||
- manager->claimed_stack_depth()->size() <= 0),
- "VM Thread promotion manager claimed stack "
- "must be empty");
- guarantee((UseDepthFirstScavengeOrder ||
- manager->claimed_stack_breadth()->size() <= 0),
- "VM Thread promotion manager claimed stack "
- "must be empty");
+ assert(manager->claimed_stack_breadth()->is_empty(), "should be empty");
}
-
manager->flush_labs();
}
}
@@ -181,15 +149,9 @@
if (depth_first()) {
claimed_stack_depth()->initialize();
queue_size = claimed_stack_depth()->max_elems();
- // We want the overflow stack to be permanent
- _overflow_stack_depth = new (ResourceObj::C_HEAP) GrowableArray<StarTask>(10, true);
- _overflow_stack_breadth = NULL;
} else {
claimed_stack_breadth()->initialize();
queue_size = claimed_stack_breadth()->max_elems();
- // We want the overflow stack to be permanent
- _overflow_stack_breadth = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
- _overflow_stack_depth = NULL;
}
_totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0);
@@ -209,8 +171,7 @@
}
void PSPromotionManager::reset() {
- assert(claimed_stack_empty(), "reset of non-empty claimed stack");
- assert(overflow_stack_empty(), "reset of non-empty overflow stack");
+ assert(stacks_empty(), "reset of non-empty stack");
// We need to get an assert in here to make sure the labs are always flushed.
@@ -243,7 +204,7 @@
void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
assert(depth_first(), "invariant");
- assert(overflow_stack_depth() != NULL, "invariant");
+ assert(claimed_stack_depth()->overflow_stack() != NULL, "invariant");
totally_drain = totally_drain || _totally_drain;
#ifdef ASSERT
@@ -254,41 +215,35 @@
MutableSpace* perm_space = heap->perm_gen()->object_space();
#endif /* ASSERT */
+ OopStarTaskQueue* const tq = claimed_stack_depth();
do {
StarTask p;
// Drain overflow stack first, so other threads can steal from
// claimed stack while we work.
- while(!overflow_stack_depth()->is_empty()) {
- // linux compiler wants different overloaded operator= in taskqueue to
- // assign to p that the other compilers don't like.
- StarTask ptr = overflow_stack_depth()->pop();
- process_popped_location_depth(ptr);
+ while (tq->pop_overflow(p)) {
+ process_popped_location_depth(p);
}
if (totally_drain) {
- while (claimed_stack_depth()->pop_local(p)) {
+ while (tq->pop_local(p)) {
process_popped_location_depth(p);
}
} else {
- while (claimed_stack_depth()->size() > _target_stack_size &&
- claimed_stack_depth()->pop_local(p)) {
+ while (tq->size() > _target_stack_size && tq->pop_local(p)) {
process_popped_location_depth(p);
}
}
- } while( (totally_drain && claimed_stack_depth()->size() > 0) ||
- (overflow_stack_depth()->length() > 0) );
+ } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
- assert(!totally_drain || claimed_stack_empty(), "Sanity");
- assert(totally_drain ||
- claimed_stack_depth()->size() <= _target_stack_size,
- "Sanity");
- assert(overflow_stack_empty(), "Sanity");
+ assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
+ assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
+ assert(tq->overflow_empty(), "Sanity");
}
void PSPromotionManager::drain_stacks_breadth(bool totally_drain) {
assert(!depth_first(), "invariant");
- assert(overflow_stack_breadth() != NULL, "invariant");
+ assert(claimed_stack_breadth()->overflow_stack() != NULL, "invariant");
totally_drain = totally_drain || _totally_drain;
#ifdef ASSERT
@@ -299,51 +254,39 @@
MutableSpace* perm_space = heap->perm_gen()->object_space();
#endif /* ASSERT */
+ OverflowTaskQueue<oop>* const tq = claimed_stack_breadth();
do {
oop obj;
// Drain overflow stack first, so other threads can steal from
// claimed stack while we work.
- while(!overflow_stack_breadth()->is_empty()) {
- obj = overflow_stack_breadth()->pop();
+ while (tq->pop_overflow(obj)) {
obj->copy_contents(this);
}
if (totally_drain) {
- // obj is a reference!!!
- while (claimed_stack_breadth()->pop_local(obj)) {
- // It would be nice to assert about the type of objects we might
- // pop, but they can come from anywhere, unfortunately.
+ while (tq->pop_local(obj)) {
obj->copy_contents(this);
}
} else {
- // obj is a reference!!!
- while (claimed_stack_breadth()->size() > _target_stack_size &&
- claimed_stack_breadth()->pop_local(obj)) {
- // It would be nice to assert about the type of objects we might
- // pop, but they can come from anywhere, unfortunately.
+ while (tq->size() > _target_stack_size && tq->pop_local(obj)) {
obj->copy_contents(this);
}
}
// If we could not find any other work, flush the prefetch queue
- if (claimed_stack_breadth()->size() == 0 &&
- (overflow_stack_breadth()->length() == 0)) {
+ if (tq->is_empty()) {
flush_prefetch_queue();
}
- } while((totally_drain && claimed_stack_breadth()->size() > 0) ||
- (overflow_stack_breadth()->length() > 0));
+ } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
- assert(!totally_drain || claimed_stack_empty(), "Sanity");
- assert(totally_drain ||
- claimed_stack_breadth()->size() <= _target_stack_size,
- "Sanity");
- assert(overflow_stack_empty(), "Sanity");
+ assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
+ assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
+ assert(tq->overflow_empty(), "Sanity");
}
void PSPromotionManager::flush_labs() {
- assert(claimed_stack_empty(), "Attempt to flush lab with live stack");
- assert(overflow_stack_empty(), "Attempt to flush lab with live overflow stack");
+ assert(stacks_empty(), "Attempt to flush lab with live stack");
// If either promotion lab fills up, we can flush the
// lab but not refill it, so check first.
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -78,9 +78,7 @@
PrefetchQueue _prefetch_queue;
OopStarTaskQueue _claimed_stack_depth;
- GrowableArray<StarTask>* _overflow_stack_depth;
- OopTaskQueue _claimed_stack_breadth;
- GrowableArray<oop>* _overflow_stack_breadth;
+ OverflowTaskQueue<oop> _claimed_stack_breadth;
bool _depth_first;
bool _totally_drain;
@@ -97,9 +95,6 @@
template <class T> inline void claim_or_forward_internal_depth(T* p);
template <class T> inline void claim_or_forward_internal_breadth(T* p);
- GrowableArray<StarTask>* overflow_stack_depth() { return _overflow_stack_depth; }
- GrowableArray<oop>* overflow_stack_breadth() { return _overflow_stack_breadth; }
-
// On the task queues we push reference locations as well as
// partially-scanned arrays (in the latter case, we push an oop to
// the from-space image of the array and the length on the
@@ -151,18 +146,19 @@
#if PS_PM_STATS
++_total_pushes;
+ int stack_length = claimed_stack_depth()->overflow_stack()->length();
#endif // PS_PM_STATS
- if (!claimed_stack_depth()->push(p)) {
- overflow_stack_depth()->push(p);
+ claimed_stack_depth()->push(p);
+
#if PS_PM_STATS
+ if (claimed_stack_depth()->overflow_stack()->length() != stack_length) {
++_overflow_pushes;
- uint stack_length = (uint) overflow_stack_depth()->length();
- if (stack_length > _max_overflow_length) {
- _max_overflow_length = stack_length;
+ if ((uint)stack_length + 1 > _max_overflow_length) {
+ _max_overflow_length = (uint)stack_length + 1;
}
+ }
#endif // PS_PM_STATS
- }
}
void push_breadth(oop o) {
@@ -170,18 +166,19 @@
#if PS_PM_STATS
++_total_pushes;
+ int stack_length = claimed_stack_breadth()->overflow_stack()->length();
#endif // PS_PM_STATS
- if(!claimed_stack_breadth()->push(o)) {
- overflow_stack_breadth()->push(o);
+ claimed_stack_breadth()->push(o);
+
#if PS_PM_STATS
+ if (claimed_stack_breadth()->overflow_stack()->length() != stack_length) {
++_overflow_pushes;
- uint stack_length = (uint) overflow_stack_breadth()->length();
- if (stack_length > _max_overflow_length) {
- _max_overflow_length = stack_length;
+ if ((uint)stack_length + 1 > _max_overflow_length) {
+ _max_overflow_length = (uint)stack_length + 1;
}
+ }
#endif // PS_PM_STATS
- }
}
protected:
@@ -199,12 +196,10 @@
static PSPromotionManager* vm_thread_promotion_manager();
static bool steal_depth(int queue_num, int* seed, StarTask& t) {
- assert(stack_array_depth() != NULL, "invariant");
return stack_array_depth()->steal(queue_num, seed, t);
}
- static bool steal_breadth(int queue_num, int* seed, Task& t) {
- assert(stack_array_breadth() != NULL, "invariant");
+ static bool steal_breadth(int queue_num, int* seed, oop& t) {
return stack_array_breadth()->steal(queue_num, seed, t);
}
@@ -214,7 +209,7 @@
OopStarTaskQueue* claimed_stack_depth() {
return &_claimed_stack_depth;
}
- OopTaskQueue* claimed_stack_breadth() {
+ OverflowTaskQueue<oop>* claimed_stack_breadth() {
return &_claimed_stack_breadth;
}
@@ -246,25 +241,13 @@
void drain_stacks_depth(bool totally_drain);
void drain_stacks_breadth(bool totally_drain);
- bool claimed_stack_empty() {
- if (depth_first()) {
- return claimed_stack_depth()->size() <= 0;
- } else {
- return claimed_stack_breadth()->size() <= 0;
- }
- }
- bool overflow_stack_empty() {
- if (depth_first()) {
- return overflow_stack_depth()->length() <= 0;
- } else {
- return overflow_stack_breadth()->length() <= 0;
- }
+ bool depth_first() const {
+ return _depth_first;
}
bool stacks_empty() {
- return claimed_stack_empty() && overflow_stack_empty();
- }
- bool depth_first() {
- return _depth_first;
+ return depth_first() ?
+ claimed_stack_depth()->is_empty() :
+ claimed_stack_breadth()->is_empty();
}
inline void process_popped_location_depth(StarTask p);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -414,7 +414,6 @@
}
// Finally, flush the promotion_manager's labs, and deallocate its stacks.
- assert(promotion_manager->claimed_stack_empty(), "Sanity");
PSPromotionManager::post_scavenge();
promotion_failure_occurred = promotion_failed();
--- a/hotspot/src/share/vm/includeDB_compiler2 Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler2 Thu Jul 15 19:52:58 2010 -0700
@@ -89,6 +89,21 @@
allocation.hpp c2_globals.hpp
+bcEscapeAnalyzer.cpp bcEscapeAnalyzer.hpp
+bcEscapeAnalyzer.cpp bitMap.inline.hpp
+bcEscapeAnalyzer.cpp bytecode.hpp
+bcEscapeAnalyzer.cpp ciConstant.hpp
+bcEscapeAnalyzer.cpp ciField.hpp
+bcEscapeAnalyzer.cpp ciMethodBlocks.hpp
+bcEscapeAnalyzer.cpp ciStreams.hpp
+
+bcEscapeAnalyzer.hpp allocation.hpp
+bcEscapeAnalyzer.hpp ciMethod.hpp
+bcEscapeAnalyzer.hpp ciMethodData.hpp
+bcEscapeAnalyzer.hpp dependencies.hpp
+bcEscapeAnalyzer.hpp growableArray.hpp
+bcEscapeAnalyzer.hpp vectset.hpp
+
block.cpp allocation.inline.hpp
block.cpp block.hpp
block.cpp cfgnode.hpp
@@ -239,6 +254,7 @@
ciEnv.cpp compileLog.hpp
ciEnv.cpp runtime.hpp
+ciMethod.cpp bcEscapeAnalyzer.hpp
ciMethod.cpp ciTypeFlow.hpp
ciMethod.cpp methodOop.hpp
--- a/hotspot/src/share/vm/includeDB_core Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_core Thu Jul 15 19:52:58 2010 -0700
@@ -301,20 +301,6 @@
barrierSet.inline.hpp barrierSet.hpp
barrierSet.inline.hpp cardTableModRefBS.hpp
-bcEscapeAnalyzer.cpp bcEscapeAnalyzer.hpp
-bcEscapeAnalyzer.cpp bitMap.inline.hpp
-bcEscapeAnalyzer.cpp bytecode.hpp
-bcEscapeAnalyzer.cpp ciConstant.hpp
-bcEscapeAnalyzer.cpp ciField.hpp
-bcEscapeAnalyzer.cpp ciMethodBlocks.hpp
-bcEscapeAnalyzer.cpp ciStreams.hpp
-
-bcEscapeAnalyzer.hpp allocation.hpp
-bcEscapeAnalyzer.hpp ciMethod.hpp
-bcEscapeAnalyzer.hpp ciMethodData.hpp
-bcEscapeAnalyzer.hpp dependencies.hpp
-bcEscapeAnalyzer.hpp growableArray.hpp
-
biasedLocking.cpp biasedLocking.hpp
biasedLocking.cpp klass.inline.hpp
biasedLocking.cpp markOop.hpp
@@ -665,7 +651,6 @@
ciMethod.cpp abstractCompiler.hpp
ciMethod.cpp allocation.inline.hpp
-ciMethod.cpp bcEscapeAnalyzer.hpp
ciMethod.cpp bitMap.inline.hpp
ciMethod.cpp ciCallProfile.hpp
ciMethod.cpp ciExceptionHandler.hpp
@@ -964,7 +949,6 @@
classLoader.cpp timer.hpp
classLoader.cpp universe.inline.hpp
classLoader.cpp vmSymbols.hpp
-classLoader.cpp vtune.hpp
classLoader.hpp classFileParser.hpp
classLoader.hpp perfData.hpp
@@ -1004,7 +988,6 @@
codeBlob.cpp safepoint.hpp
codeBlob.cpp sharedRuntime.hpp
codeBlob.cpp vframe.hpp
-codeBlob.cpp vtune.hpp
codeBlob.hpp codeBuffer.hpp
codeBlob.hpp frame.hpp
@@ -2167,7 +2150,6 @@
interpreter.cpp stubRoutines.hpp
interpreter.cpp templateTable.hpp
interpreter.cpp timer.hpp
-interpreter.cpp vtune.hpp
interpreter.hpp cppInterpreter.hpp
interpreter.hpp stubs.hpp
@@ -2323,7 +2305,6 @@
java.cpp vmError.hpp
java.cpp vm_operations.hpp
java.cpp vm_version_<arch>.hpp
-java.cpp vtune.hpp
java.hpp os.hpp
@@ -3050,7 +3031,6 @@
nmethod.cpp scopeDesc.hpp
nmethod.cpp sharedRuntime.hpp
nmethod.cpp sweeper.hpp
-nmethod.cpp vtune.hpp
nmethod.cpp xmlstream.hpp
nmethod.hpp codeBlob.hpp
@@ -3773,7 +3753,6 @@
sharedRuntime.cpp vmSymbols.hpp
sharedRuntime.cpp vmreg_<arch>.inline.hpp
sharedRuntime.cpp vtableStubs.hpp
-sharedRuntime.cpp vtune.hpp
sharedRuntime.cpp xmlstream.hpp
sharedRuntime.hpp allocation.hpp
@@ -3937,7 +3916,6 @@
stubCodeGenerator.cpp forte.hpp
stubCodeGenerator.cpp oop.inline.hpp
stubCodeGenerator.cpp stubCodeGenerator.hpp
-stubCodeGenerator.cpp vtune.hpp
stubCodeGenerator.hpp allocation.hpp
stubCodeGenerator.hpp assembler.hpp
@@ -4458,7 +4436,6 @@
universe.cpp universe.inline.hpp
universe.cpp vmSymbols.hpp
universe.cpp vm_operations.hpp
-universe.cpp vtune.hpp
universe.hpp growableArray.hpp
universe.hpp handles.hpp
@@ -4721,7 +4698,6 @@
vtableStubs.cpp resourceArea.hpp
vtableStubs.cpp sharedRuntime.hpp
vtableStubs.cpp vtableStubs.hpp
-vtableStubs.cpp vtune.hpp
vtableStubs.hpp allocation.hpp
@@ -4735,11 +4711,6 @@
vtableStubs_<arch_model>.cpp vmreg_<arch>.inline.hpp
vtableStubs_<arch_model>.cpp vtableStubs.hpp
-vtune.hpp allocation.hpp
-
-vtune_<os_family>.cpp interpreter.hpp
-vtune_<os_family>.cpp vtune.hpp
-
watermark.hpp allocation.hpp
watermark.hpp globalDefinitions.hpp
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -99,11 +99,6 @@
#endif // PRODUCT
// need to hit every safepoint in order to call zapping routine
// register the interpreter
- VTune::register_stub(
- "Interpreter",
- AbstractInterpreter::code()->code_start(),
- AbstractInterpreter::code()->code_end()
- );
Forte::register_stub(
"Interpreter",
AbstractInterpreter::code()->code_start(),
--- a/hotspot/src/share/vm/opto/doCall.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -343,7 +343,8 @@
// being initialized. Uncommon-trap for not-initialized static or
// v-calls. Let interface calls happen.
ciInstanceKlass* holder_klass = dest_method->holder();
- if (!holder_klass->is_initialized() &&
+ if (!holder_klass->is_being_initialized() &&
+ !holder_klass->is_initialized() &&
!holder_klass->is_interface()) {
uncommon_trap(Deoptimization::Reason_uninitialized,
Deoptimization::Action_reinterpret,
--- a/hotspot/src/share/vm/opto/parse.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -480,6 +480,7 @@
bool push_constant(ciConstant con, bool require_constant = false);
// implementation of object creation bytecodes
+ void emit_guard_for_new(ciInstanceKlass* klass);
void do_new();
void do_newarray(BasicType elemtype);
void do_anewarray();
--- a/hotspot/src/share/vm/opto/parseHelper.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -197,6 +197,43 @@
}
+void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
+ // Emit guarded new
+ // if (klass->_init_thread != current_thread ||
+ // klass->_init_state != being_initialized)
+ // uncommon_trap
+ Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() );
+ Node* merge = new (C, 3) RegionNode(3);
+ _gvn.set_type(merge, Type::CONTROL);
+ Node* kls = makecon(TypeKlassPtr::make(klass));
+
+ Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+ Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset);
+ Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS);
+ Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq);
+ IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
+ set_control(IfTrue(iff));
+ merge->set_req(1, IfFalse(iff));
+
+ Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+ adr_node = basic_plus_adr(kls, kls, init_state_offset);
+ Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT);
+ Node* being_init = _gvn.intcon(instanceKlass::being_initialized);
+ tst = Bool( CmpI( init_state, being_init), BoolTest::eq);
+ iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
+ set_control(IfTrue(iff));
+ merge->set_req(2, IfFalse(iff));
+
+ PreserveJVMState pjvms(this);
+ record_for_igvn(merge);
+ set_control(merge);
+
+ uncommon_trap(Deoptimization::Reason_uninitialized,
+ Deoptimization::Action_reinterpret,
+ klass);
+}
+
+
//------------------------------do_new-----------------------------------------
void Parse::do_new() {
kill_dead_locals();
@@ -206,7 +243,7 @@
assert(will_link, "_new: typeflow responsibility");
// Should initialize, or throw an InstantiationError?
- if (!klass->is_initialized() ||
+ if (!klass->is_initialized() && !klass->is_being_initialized() ||
klass->is_abstract() || klass->is_interface() ||
klass->name() == ciSymbol::java_lang_Class() ||
iter().is_unresolved_klass()) {
@@ -215,6 +252,9 @@
klass);
return;
}
+ if (klass->is_being_initialized()) {
+ emit_guard_for_new(klass);
+ }
Node* kls = makecon(TypeKlassPtr::make(klass));
Node* obj = new_instance(kls);
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -118,7 +118,6 @@
for (int i=0; i<_global_code_blobs->length(); i++) {
JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i);
if (addr == scb->code_begin()) {
- ShouldNotReachHere();
return;
}
}
@@ -206,11 +205,11 @@
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
nmethod* current = CodeCache::first_nmethod();
while (current != NULL) {
- // Lock the nmethod so it can't be freed
- nmethodLocker nml(current);
-
// Only notify for live nmethods
if (current->is_alive()) {
+ // Lock the nmethod so it can't be freed
+ nmethodLocker nml(current);
+
// Don't hold the lock over the notify or jmethodID creation
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
current->get_and_cache_jmethod_id();
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -2541,9 +2541,6 @@
"Enable String cache capabilities on String.java") \
\
/* statistics */ \
- develop(bool, UseVTune, false, \
- "enable support for Intel's VTune profiler") \
- \
develop(bool, CountCompiledCalls, false, \
"counts method invocations") \
\
--- a/hotspot/src/share/vm/runtime/init.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/init.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -34,7 +34,6 @@
// Initialization done by Java thread in init_globals()
void management_init();
-void vtune_init();
void bytecodes_init();
void classLoader_init();
void codeCache_init();
@@ -82,7 +81,6 @@
jint init_globals() {
HandleMark hm;
management_init();
- vtune_init();
bytecodes_init();
classLoader_init();
codeCache_init();
--- a/hotspot/src/share/vm/runtime/java.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -432,8 +432,6 @@
print_statistics();
Universe::heap()->print_tracing_info();
- VTune::exit();
-
{ MutexLocker ml(BeforeExit_lock);
_before_exit_status = BEFORE_EXIT_DONE;
BeforeExit_lock->notify_all();
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -886,6 +886,11 @@
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
+
+ // ## TEMPORARY hack to keep the legacy launcher working when
+ // ## only the boot module is installed (cf. j.l.ClassLoader)
+ "%/lib/modules/jdk.boot.jar:"
+
"%/classes";
char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
if (sysclasspath == NULL) return false;
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -2251,7 +2251,6 @@
B->name(),
fingerprint->as_string(),
B->instructions_begin());
- VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -132,7 +132,6 @@
_cdesc->set_end(_cgen->assembler()->pc());
assert(StubCodeDesc::_list == _cdesc, "expected order on list");
_cgen->stub_epilog(_cdesc);
- VTune::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,14 +27,15 @@
long NMethodSweeper::_traversals = 0; // No. of stack traversals performed
nmethod* NMethodSweeper::_current = NULL; // Current nmethod
-int NMethodSweeper::_seen = 0 ; // No. of blobs we have currently processed in current pass of CodeCache
-int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
+int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache
+
+volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
+volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
jint NMethodSweeper::_locked_seen = 0;
jint NMethodSweeper::_not_entrant_seen_on_stack = 0;
bool NMethodSweeper::_rescan = false;
bool NMethodSweeper::_do_sweep = false;
-jint NMethodSweeper::_sweep_started = 0;
bool NMethodSweeper::_was_full = false;
jint NMethodSweeper::_advise_to_sweep = 0;
jlong NMethodSweeper::_last_was_full = 0;
@@ -108,23 +109,14 @@
// code cache is filling up
_last_was_full = os::javaTimeMillis();
- if (PrintMethodFlushing) {
- tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("restart_compiler");
}
}
}
}
void NMethodSweeper::possibly_sweep() {
+ assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
if ((!MethodFlushing) || (!_do_sweep)) return;
if (_invocations > 0) {
@@ -133,32 +125,31 @@
if (old != 0) {
return;
}
- sweep_code_cache();
+ if (_invocations > 0) {
+ sweep_code_cache();
+ _invocations--;
+ }
+ _sweep_started = 0;
}
- _sweep_started = 0;
}
void NMethodSweeper::sweep_code_cache() {
#ifdef ASSERT
jlong sweep_start;
- if(PrintMethodFlushing) {
+ if (PrintMethodFlushing) {
sweep_start = os::javaTimeMillis();
}
#endif
if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_blobs(), _invocations);
+ tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
}
- // We want to visit all nmethods after NmethodSweepFraction invocations.
- // If invocation is 1 we do the rest
- int todo = CodeCache::nof_blobs();
- if (_invocations > 1) {
- todo = (CodeCache::nof_blobs() - _seen) / _invocations;
- }
-
- // Compilers may check to sweep more often than stack scans happen,
- // don't keep trying once it is all scanned
- _invocations--;
+ // We want to visit all nmethods after NmethodSweepFraction
+ // invocations so divide the remaining number of nmethods by the
+ // remaining number of invocations. This is only an estimate since
+ // the number of nmethods changes during the sweep so the final
+ // stage must iterate until it there are no more nmethods.
+ int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
assert(!CodeCache_lock->owned_by_self(), "just checking");
@@ -166,11 +157,12 @@
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- for(int i = 0; i < todo && _current != NULL; i++) {
+ // The last invocation iterates until there are no more nmethods
+ for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) {
- // Since we will give up the CodeCache_lock, always skip ahead to an nmethod.
- // Other blobs can be deleted by other threads
- // Read next before we potentially delete current
+ // Since we will give up the CodeCache_lock, always skip ahead
+ // to the next nmethod. Other blobs can be deleted by other
+ // threads but nmethods are only reclaimed by the sweeper.
nmethod* next = CodeCache::next_nmethod(_current);
// Now ready to process nmethod and give up CodeCache_lock
@@ -183,6 +175,8 @@
}
}
+ assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
+
if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
// we've completed a scan without making progress but there were
// nmethods we were unable to process either because they were
@@ -201,6 +195,10 @@
tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
}
#endif
+
+ if (_invocations == 1) {
+ log_sweep("finished");
+ }
}
@@ -223,7 +221,7 @@
if (nm->is_zombie()) {
// If it is first time, we see nmethod then we mark it. Otherwise,
// we reclame it. When we have seen a zombie method twice, we know that
- // there are no inline caches that referes to it.
+ // there are no inline caches that refer to it.
if (nm->is_marked_for_reclamation()) {
assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
if (PrintMethodFlushing && Verbose) {
@@ -320,16 +318,8 @@
jlong curr_interval = now - _last_was_full;
if (curr_interval < max_interval) {
_rescan = true;
- if (PrintMethodFlushing) {
- tty->print_cr("### handle full too often, turning off compiler");
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("disable_compiler flushing_interval='" UINT64_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- curr_interval/1000, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("disable_compiler", "flushing_interval='" UINT64_FORMAT "'",
+ curr_interval/1000);
return;
}
}
@@ -349,17 +339,7 @@
if ((!was_full()) && (is_full)) {
if (!CodeCache::needs_flushing()) {
- if (PrintMethodFlushing) {
- tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("restart_compiler");
CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
return;
}
@@ -368,17 +348,7 @@
// Traverse the code cache trying to dump the oldest nmethods
uint curr_max_comp_id = CompileBroker::get_compilation_id();
uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
- if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Cleaning code cache: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("start_cleaning_code_cache live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("start_cleaning");
nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
jint disconnected = 0;
@@ -411,13 +381,9 @@
nm = CodeCache::alive_nmethod(CodeCache::next(nm));
}
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("stop_cleaning_code_cache disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- disconnected, made_not_entrant, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("stop_cleaning",
+ "disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "'",
+ disconnected, made_not_entrant);
// Shut off compiler. Sweeper will start over with a new stack scan and
// traversal cycle and turn it back on if it clears enough space.
@@ -435,3 +401,38 @@
}
#endif
}
+
+
+// Print out some state information about the current sweep and the
+// state of the code cache if it's requested.
+void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
+ if (PrintMethodFlushing) {
+ ttyLocker ttyl;
+ tty->print("### sweeper: %s ", msg);
+ if (format != NULL) {
+ va_list ap;
+ va_start(ap, format);
+ tty->vprint(format, ap);
+ va_end(ap);
+ }
+ tty->print_cr(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+ }
+
+ if (LogCompilation && (xtty != NULL)) {
+ ttyLocker ttyl;
+ xtty->begin_elem("sweeper state='%s' traversals='" INTX_FORMAT "' ", msg, (intx)traversal_count());
+ if (format != NULL) {
+ va_list ap;
+ va_start(ap, format);
+ xtty->vprint(format, ap);
+ va_end(ap);
+ }
+ xtty->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+ xtty->stamp();
+ xtty->end_elem();
+ }
+}
--- a/hotspot/src/share/vm/runtime/sweeper.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,13 @@
static long _traversals; // Stack traversal count
static nmethod* _current; // Current nmethod
static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache
- static int _invocations; // No. of invocations left until we are completed with this pass
+
+ static volatile int _invocations; // No. of invocations left until we are completed with this pass
+ static volatile int _sweep_started; // Flag to control conc sweeper
static bool _rescan; // Indicates that we should do a full rescan of the
// of the code cache looking for work to do.
static bool _do_sweep; // Flag to skip the conc sweep if no stack scan happened
- static jint _sweep_started; // Flag to control conc sweeper
static int _locked_seen; // Number of locked nmethods encountered during the scan
static int _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack
@@ -47,6 +48,9 @@
static long _was_full_traversal; // trav number at last emergency unloading
static void process_nmethod(nmethod *nm);
+
+ static void log_sweep(const char* msg, const char* format = NULL, ...);
+
public:
static long traversal_count() { return _traversals; }
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -747,6 +747,8 @@
ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL ;
+ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL ;
+int ObjectSynchronizer::gOmInUseCount = 0;
static volatile intptr_t ListLock = 0 ; // protects global monitor free-list cache
static volatile int MonitorFreeCount = 0 ; // # on gFreeList
static volatile int MonitorPopulation = 0 ; // # Extant -- in circulation
@@ -826,6 +828,22 @@
}
}
}
+/* Too slow for general assert or debug
+void ObjectSynchronizer::verifyInUse (Thread *Self) {
+ ObjectMonitor* mid;
+ int inusetally = 0;
+ for (mid = Self->omInUseList; mid != NULL; mid = mid->FreeNext) {
+ inusetally ++;
+ }
+ assert(inusetally == Self->omInUseCount, "inuse count off");
+
+ int freetally = 0;
+ for (mid = Self->omFreeList; mid != NULL; mid = mid->FreeNext) {
+ freetally ++;
+ }
+ assert(freetally == Self->omFreeCount, "free count off");
+}
+*/
ObjectMonitor * ATTR ObjectSynchronizer::omAlloc (Thread * Self) {
// A large MAXPRIVATE value reduces both list lock contention
@@ -853,6 +871,9 @@
m->FreeNext = Self->omInUseList;
Self->omInUseList = m;
Self->omInUseCount ++;
+ // verifyInUse(Self);
+ } else {
+ m->FreeNext = NULL;
}
return m ;
}
@@ -874,13 +895,12 @@
guarantee (take->object() == NULL, "invariant") ;
guarantee (!take->is_busy(), "invariant") ;
take->Recycle() ;
- omRelease (Self, take) ;
+ omRelease (Self, take, false) ;
}
Thread::muxRelease (&ListLock) ;
Self->omFreeProvision += 1 + (Self->omFreeProvision/2) ;
if (Self->omFreeProvision > MAXPRIVATE ) Self->omFreeProvision = MAXPRIVATE ;
TEVENT (omFirst - reprovision) ;
- continue ;
const int mx = MonitorBound ;
if (mx > 0 && (MonitorPopulation-MonitorFreeCount) > mx) {
@@ -961,11 +981,34 @@
// That is, *not* one-at-a-time.
-void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m) {
+void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m, bool fromPerThreadAlloc) {
guarantee (m->object() == NULL, "invariant") ;
- m->FreeNext = Self->omFreeList ;
- Self->omFreeList = m ;
- Self->omFreeCount ++ ;
+
+ // Remove from omInUseList
+ if (MonitorInUseLists && fromPerThreadAlloc) {
+ ObjectMonitor* curmidinuse = NULL;
+ for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; ) {
+ if (m == mid) {
+ // extract from per-thread in-use-list
+ if (mid == Self->omInUseList) {
+ Self->omInUseList = mid->FreeNext;
+ } else if (curmidinuse != NULL) {
+ curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+ }
+ Self->omInUseCount --;
+ // verifyInUse(Self);
+ break;
+ } else {
+ curmidinuse = mid;
+ mid = mid->FreeNext;
+ }
+ }
+ }
+
+ // FreeNext is used for both onInUseList and omFreeList, so clear old before setting new
+ m->FreeNext = Self->omFreeList ;
+ Self->omFreeList = m ;
+ Self->omFreeCount ++ ;
}
// Return the monitors of a moribund thread's local free list to
@@ -975,6 +1018,10 @@
// consecutive STW safepoints. Relatedly, we might decay
// omFreeProvision at STW safepoints.
//
+// Also return the monitors of a moribund thread"s omInUseList to
+// a global gOmInUseList under the global list lock so these
+// will continue to be scanned.
+//
// We currently call omFlush() from the Thread:: dtor _after the thread
// has been excised from the thread list and is no longer a mutator.
// That means that omFlush() can run concurrently with a safepoint and
@@ -987,24 +1034,50 @@
void ObjectSynchronizer::omFlush (Thread * Self) {
ObjectMonitor * List = Self->omFreeList ; // Null-terminated SLL
Self->omFreeList = NULL ;
- if (List == NULL) return ;
ObjectMonitor * Tail = NULL ;
- ObjectMonitor * s ;
int Tally = 0;
- for (s = List ; s != NULL ; s = s->FreeNext) {
- Tally ++ ;
- Tail = s ;
- guarantee (s->object() == NULL, "invariant") ;
- guarantee (!s->is_busy(), "invariant") ;
- s->set_owner (NULL) ; // redundant but good hygiene
- TEVENT (omFlush - Move one) ;
+ if (List != NULL) {
+ ObjectMonitor * s ;
+ for (s = List ; s != NULL ; s = s->FreeNext) {
+ Tally ++ ;
+ Tail = s ;
+ guarantee (s->object() == NULL, "invariant") ;
+ guarantee (!s->is_busy(), "invariant") ;
+ s->set_owner (NULL) ; // redundant but good hygiene
+ TEVENT (omFlush - Move one) ;
+ }
+ guarantee (Tail != NULL && List != NULL, "invariant") ;
}
- guarantee (Tail != NULL && List != NULL, "invariant") ;
+ ObjectMonitor * InUseList = Self->omInUseList;
+ ObjectMonitor * InUseTail = NULL ;
+ int InUseTally = 0;
+ if (InUseList != NULL) {
+ Self->omInUseList = NULL;
+ ObjectMonitor *curom;
+ for (curom = InUseList; curom != NULL; curom = curom->FreeNext) {
+ InUseTail = curom;
+ InUseTally++;
+ }
+// TODO debug
+ assert(Self->omInUseCount == InUseTally, "inuse count off");
+ Self->omInUseCount = 0;
+ guarantee (InUseTail != NULL && InUseList != NULL, "invariant");
+ }
+
Thread::muxAcquire (&ListLock, "omFlush") ;
- Tail->FreeNext = gFreeList ;
- gFreeList = List ;
- MonitorFreeCount += Tally;
+ if (Tail != NULL) {
+ Tail->FreeNext = gFreeList ;
+ gFreeList = List ;
+ MonitorFreeCount += Tally;
+ }
+
+ if (InUseTail != NULL) {
+ InUseTail->FreeNext = gOmInUseList;
+ gOmInUseList = InUseList;
+ gOmInUseCount += InUseTally;
+ }
+
Thread::muxRelease (&ListLock) ;
TEVENT (omFlush) ;
}
@@ -1166,7 +1239,6 @@
// We do this before the CAS in order to minimize the length of time
// in which INFLATING appears in the mark.
m->Recycle();
- m->FreeNext = NULL ;
m->_Responsible = NULL ;
m->OwnerIsThread = 0 ;
m->_recursions = 0 ;
@@ -1174,7 +1246,7 @@
markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
if (cmp != mark) {
- omRelease (Self, m) ;
+ omRelease (Self, m, true) ;
continue ; // Interference -- just retry
}
@@ -1262,7 +1334,6 @@
m->set_object(object);
m->OwnerIsThread = 1 ;
m->_recursions = 0 ;
- m->FreeNext = NULL ;
m->_Responsible = NULL ;
m->_SpinDuration = Knob_SpinLimit ; // consider: keep metastats by type/class
@@ -1271,7 +1342,7 @@
m->set_owner (NULL) ;
m->OwnerIsThread = 0 ;
m->Recycle() ;
- omRelease (Self, m) ;
+ omRelease (Self, m, true) ;
m = NULL ;
continue ;
// interference - the markword changed - just retry.
@@ -1852,6 +1923,10 @@
// only scans the per-thread inuse lists. omAlloc() puts all
// assigned monitors on the per-thread list. deflate_idle_monitors()
// returns the non-busy monitors to the global free list.
+// When a thread dies, omFlush() adds the list of active monitors for
+// that thread to a global gOmInUseList acquiring the
+// global list lock. deflate_idle_monitors() acquires the global
+// list lock to scan for non-busy monitors to the global free list.
// An alternative could have used a single global inuse list. The
// downside would have been the additional cost of acquiring the global list lock
// for every omAlloc().
@@ -1904,6 +1979,7 @@
if (*FreeHeadp == NULL) *FreeHeadp = mid;
if (*FreeTailp != NULL) {
ObjectMonitor * prevtail = *FreeTailp;
+ assert(prevtail->FreeNext == NULL, "cleaned up deflated?"); // TODO KK
prevtail->FreeNext = mid;
}
*FreeTailp = mid;
@@ -1912,6 +1988,39 @@
return deflated;
}
+// Caller acquires ListLock
+int ObjectSynchronizer::walk_monitor_list(ObjectMonitor** listheadp,
+ ObjectMonitor** FreeHeadp, ObjectMonitor** FreeTailp) {
+ ObjectMonitor* mid;
+ ObjectMonitor* next;
+ ObjectMonitor* curmidinuse = NULL;
+ int deflatedcount = 0;
+
+ for (mid = *listheadp; mid != NULL; ) {
+ oop obj = (oop) mid->object();
+ bool deflated = false;
+ if (obj != NULL) {
+ deflated = deflate_monitor(mid, obj, FreeHeadp, FreeTailp);
+ }
+ if (deflated) {
+ // extract from per-thread in-use-list
+ if (mid == *listheadp) {
+ *listheadp = mid->FreeNext;
+ } else if (curmidinuse != NULL) {
+ curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+ }
+ next = mid->FreeNext;
+ mid->FreeNext = NULL; // This mid is current tail in the FreeHead list
+ mid = next;
+ deflatedcount++;
+ } else {
+ curmidinuse = mid;
+ mid = mid->FreeNext;
+ }
+ }
+ return deflatedcount;
+}
+
void ObjectSynchronizer::deflate_idle_monitors() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
int nInuse = 0 ; // currently associated with objects
@@ -1929,36 +2038,25 @@
Thread::muxAcquire (&ListLock, "scavenge - return") ;
if (MonitorInUseLists) {
- ObjectMonitor* mid;
- ObjectMonitor* next;
- ObjectMonitor* curmidinuse;
+ int inUse = 0;
for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
- curmidinuse = NULL;
- for (mid = cur->omInUseList; mid != NULL; ) {
- oop obj = (oop) mid->object();
- deflated = false;
- if (obj != NULL) {
- deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);
- }
- if (deflated) {
- // extract from per-thread in-use-list
- if (mid == cur->omInUseList) {
- cur->omInUseList = mid->FreeNext;
- } else if (curmidinuse != NULL) {
- curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
- }
- next = mid->FreeNext;
- mid->FreeNext = NULL; // This mid is current tail in the FreeHead list
- mid = next;
- cur->omInUseCount--;
- nScavenged ++ ;
- } else {
- curmidinuse = mid;
- mid = mid->FreeNext;
- nInuse ++;
- }
+ nInCirculation+= cur->omInUseCount;
+ int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);
+ cur->omInUseCount-= deflatedcount;
+ // verifyInUse(cur);
+ nScavenged += deflatedcount;
+ nInuse += cur->omInUseCount;
}
- }
+
+ // For moribund threads, scan gOmInUseList
+ if (gOmInUseList) {
+ nInCirculation += gOmInUseCount;
+ int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);
+ gOmInUseCount-= deflatedcount;
+ nScavenged += deflatedcount;
+ nInuse += gOmInUseCount;
+ }
+
} else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
// Iterate over all extant monitors - Scavenge all idle monitors.
assert(block->object() == CHAINMARKER, "must be a block header");
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -122,8 +122,9 @@
static void reenter (Handle obj, intptr_t recursion, TRAPS);
// thread-specific and global objectMonitor free list accessors
+// static void verifyInUse (Thread * Self) ; too slow for general assert/debug
static ObjectMonitor * omAlloc (Thread * Self) ;
- static void omRelease (Thread * Self, ObjectMonitor * m) ;
+ static void omRelease (Thread * Self, ObjectMonitor * m, bool FromPerThreadAlloc) ;
static void omFlush (Thread * Self) ;
// Inflate light weight monitor to heavy weight monitor
@@ -150,6 +151,9 @@
// Basically we deflate all monitors that are not busy.
// An adaptive profile-based deflation policy could be used if needed
static void deflate_idle_monitors();
+ static int walk_monitor_list(ObjectMonitor** listheadp,
+ ObjectMonitor** FreeHeadp,
+ ObjectMonitor** FreeTailp);
static bool deflate_monitor(ObjectMonitor* mid, oop obj, ObjectMonitor** FreeHeadp,
ObjectMonitor** FreeTailp);
static void oops_do(OopClosure* f);
@@ -163,6 +167,8 @@
enum { _BLOCKSIZE = 128 };
static ObjectMonitor* gBlockList;
static ObjectMonitor * volatile gFreeList;
+ static ObjectMonitor * volatile gOmInUseList; // for moribund thread, so monitors they inflated still get scanned
+ static int gOmInUseCount;
public:
static void Initialize () ;
--- a/hotspot/src/share/vm/runtime/thread.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -270,6 +270,7 @@
static void interrupt(Thread* thr);
static bool is_interrupted(Thread* thr, bool clear_interrupted);
+ ObjectMonitor** omInUseList_addr() { return (ObjectMonitor **)&omInUseList; }
Monitor* SR_lock() const { return _SR_lock; }
bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -614,7 +614,6 @@
/* NMethods (NOTE: incomplete, but only a little) */ \
/**************************************************/ \
\
- static_field(nmethod, _zombie_instruction_size, int) \
nonstatic_field(nmethod, _method, methodOop) \
nonstatic_field(nmethod, _entry_bci, int) \
nonstatic_field(nmethod, _osr_link, nmethod*) \
--- a/hotspot/src/share/vm/runtime/vtune.hpp Thu Jul 15 19:51:34 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-// Interface to Intel's VTune profiler.
-
-class VTune : AllStatic {
- public:
- static void create_nmethod(nmethod* nm); // register newly created nmethod
- static void delete_nmethod(nmethod* nm); // unregister nmethod before discarding it
-
- static void register_stub(const char* name, address start, address end);
- // register internal VM stub
- static void start_GC(); // start/end of GC or scavenge
- static void end_GC();
-
- static void start_class_load(); // start/end of class loading
- static void end_class_load();
-
- static void exit(); // VM exit
-};
-
-
-// helper objects
-class VTuneGCMarker : StackObj {
- public:
- VTuneGCMarker() { VTune::start_GC(); }
- ~VTuneGCMarker() { VTune::end_GC(); }
-};
-
-class VTuneClassLoadMarker : StackObj {
- public:
- VTuneClassLoadMarker() { VTune::start_class_load(); }
- ~VTuneClassLoadMarker() { VTune::end_class_load(); }
-};
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -182,73 +182,3 @@
_index < objArrayOop(_obj)->length();
}
#endif // ASSERT
-
-bool RegionTaskQueueWithOverflow::is_empty() {
- return (_region_queue.size() == 0) &&
- (_overflow_stack->length() == 0);
-}
-
-bool RegionTaskQueueWithOverflow::stealable_is_empty() {
- return _region_queue.size() == 0;
-}
-
-bool RegionTaskQueueWithOverflow::overflow_is_empty() {
- return _overflow_stack->length() == 0;
-}
-
-void RegionTaskQueueWithOverflow::initialize() {
- _region_queue.initialize();
- assert(_overflow_stack == 0, "Creating memory leak");
- _overflow_stack =
- new (ResourceObj::C_HEAP) GrowableArray<RegionTask>(10, true);
-}
-
-void RegionTaskQueueWithOverflow::save(RegionTask t) {
- if (TraceRegionTasksQueuing && Verbose) {
- gclog_or_tty->print_cr("CTQ: save " PTR_FORMAT, t);
- }
- if(!_region_queue.push(t)) {
- _overflow_stack->push(t);
- }
-}
-
-// Note that using this method will retrieve all regions
-// that have been saved but that it will always check
-// the overflow stack. It may be more efficient to
-// check the stealable queue and the overflow stack
-// separately.
-bool RegionTaskQueueWithOverflow::retrieve(RegionTask& region_task) {
- bool result = retrieve_from_overflow(region_task);
- if (!result) {
- result = retrieve_from_stealable_queue(region_task);
- }
- if (TraceRegionTasksQueuing && Verbose && result) {
- gclog_or_tty->print_cr(" CTQ: retrieve " PTR_FORMAT, result);
- }
- return result;
-}
-
-bool RegionTaskQueueWithOverflow::retrieve_from_stealable_queue(
- RegionTask& region_task) {
- bool result = _region_queue.pop_local(region_task);
- if (TraceRegionTasksQueuing && Verbose) {
- gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
- }
- return result;
-}
-
-bool
-RegionTaskQueueWithOverflow::retrieve_from_overflow(RegionTask& region_task) {
- bool result;
- if (!_overflow_stack->is_empty()) {
- region_task = _overflow_stack->pop();
- result = true;
- } else {
- region_task = (RegionTask) NULL;
- result = false;
- }
- if (TraceRegionTasksQueuing && Verbose) {
- gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
- }
- return result;
-}
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp Thu Jul 15 19:51:34 2010 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp Thu Jul 15 19:52:58 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -109,8 +109,9 @@
public:
TaskQueueSuper() : _bottom(0), _age() {}
- // Return true if the TaskQueue contains any tasks.
- bool peek() { return _bottom != _age.top(); }
+ // Return true if the TaskQueue contains/does not contain any tasks.
+ bool peek() const { return _bottom != _age.top(); }
+ bool is_empty() const { return size() == 0; }
// Return an estimate of the number of elements in the queue.
// The "careful" version admits the possibility of pop_local/pop_global
@@ -165,18 +166,16 @@
void initialize();
- // Push the task "t" on the queue. Returns "false" iff the queue is
- // full.
+ // Push the task "t" on the queue. Returns "false" iff the queue is full.
inline bool push(E t);
- // If succeeds in claiming a task (from the 'local' end, that is, the
- // most recently pushed task), returns "true" and sets "t" to that task.
- // Otherwise, the queue is empty and returns false.
+ // Attempts to claim a task from the "local" end of the queue (the most
+ // recently pushed). If successful, returns true and sets t to the task;
+ // otherwise, returns false (the queue is empty).
inline bool pop_local(E& t);
- // If succeeds in claiming a task (from the 'global' end, that is, the
- // least recently pushed task), returns "true" and sets "t" to that task.
- // Otherwise, the queue is empty and returns false.
+ // Like pop_local(), but uses the "global" end of the queue (the least
+ // recently pushed).
bool pop_global(E& t);
// Delete any resource associated with the queue.
@@ -198,7 +197,6 @@
template<class E, unsigned int N>
void GenericTaskQueue<E, N>::initialize() {
_elems = NEW_C_HEAP_ARRAY(E, N);
- guarantee(_elems != NULL, "Allocation failed.");
}
template<class E, unsigned int N>
@@ -289,7 +287,87 @@
FREE_C_HEAP_ARRAY(E, _elems);
}
-// Inherits the typedef of "Task" from above.
+// OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
+// elements that do not fit in the TaskQueue.
+//
+// Three methods from super classes are overridden:
+//
+// initialize() - initialize the super classes and create the overflow stack
+// push() - push onto the task queue or, if that fails, onto the overflow stack
+// is_empty() - return true if both the TaskQueue and overflow stack are empty
+//
+// Note that size() is not overridden--it returns the number of elements in the
+// TaskQueue, and does not include the size of the overflow stack. This
+// simplifies replacement of GenericTaskQueues with OverflowTaskQueues.
+template<class E, unsigned int N = TASKQUEUE_SIZE>
+class OverflowTaskQueue: public GenericTaskQueue<E, N>
+{
+public:
+ typedef GrowableArray<E> overflow_t;
+ typedef GenericTaskQueue<E, N> taskqueue_t;
+
+ OverflowTaskQueue();
+ ~OverflowTaskQueue();
+ void initialize();
+
+ inline overflow_t* overflow_stack() const { return _overflow_stack; }
+
+ // Push task t onto the queue or onto the overflow stack. Return true.
+ inline bool push(E t);
+
+ // Attempt to pop from the overflow stack; return true if anything was popped.
+ inline bool pop_overflow(E& t);
+
+ inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
+ inline bool overflow_empty() const { return overflow_stack()->is_empty(); }
+ inline bool is_empty() const {
+ return taskqueue_empty() && overflow_empty();
+ }
+
+private:
+ overflow_t* _overflow_stack;
+};
+
+template <class E, unsigned int N>
+OverflowTaskQueue<E, N>::OverflowTaskQueue()
+{
+ _overflow_stack = NULL;
+}
+
+template <class E, unsigned int N>
+OverflowTaskQueue<E, N>::~OverflowTaskQueue()
+{
+ if (_overflow_stack != NULL) {
+ delete _overflow_stack;
+ _overflow_stack = NULL;
+ }
+}
+
+template <class E, unsigned int N>
+void OverflowTaskQueue<E, N>::initialize()
+{
+ taskqueue_t::initialize();
+ assert(_overflow_stack == NULL, "memory leak");
+ _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<E>(10, true);
+}
+
+template <class E, unsigned int N>
+bool OverflowTaskQueue<E, N>::push(E t)
+{
+ if (!taskqueue_t::push(t)) {
+ overflow_stack()->push(t);
+ }
+ return true;
+}
+
+template <class E, unsigned int N>
+bool OverflowTaskQueue<E, N>::pop_overflow(E& t)
+{
+ if (overflow_empty()) return false;
+ t = overflow_stack()->pop();
+ return true;
+}
+
class TaskQueueSetSuper: public CHeapObj {
protected:
static int randomParkAndMiller(int* seed0);
@@ -323,11 +401,11 @@
T* queue(uint n);
- // The thread with queue number "queue_num" (and whose random number seed
- // is at "seed") is trying to steal a task from some other queue. (It
- // may try several queues, according to some configuration parameter.)
- // If some steal succeeds, returns "true" and sets "t" the stolen task,
- // otherwise returns false.
+ // The thread with queue number "queue_num" (and whose random number seed is
+ // at "seed") is trying to steal a task from some other queue. (It may try
+ // several queues, according to some configuration parameter.) If some steal
+ // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
+ // false.
bool steal(uint queue_num, int* seed, E& t);
bool peek();
@@ -507,7 +585,7 @@
uint localBot = _bottom;
// This value cannot be N-1. That can only occur as a result of
// the assignment to bottom in this method. If it does, this method
- // resets the size( to 0 before the next call (which is sequential,
+ // resets the size to 0 before the next call (which is sequential,
// since this is pop_local.)
uint dirty_n_elems = dirty_size(localBot, _age.top());
assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
@@ -533,8 +611,7 @@
}
}
-typedef oop Task;
-typedef GenericTaskQueue<Task> OopTaskQueue;
+typedef GenericTaskQueue<oop> OopTaskQueue;
typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet;
#ifdef _MSC_VER
@@ -615,35 +692,8 @@
#pragma warning(pop)
#endif
-typedef GenericTaskQueue<StarTask> OopStarTaskQueue;
+typedef OverflowTaskQueue<StarTask> OopStarTaskQueue;
typedef GenericTaskQueueSet<OopStarTaskQueue> OopStarTaskQueueSet;
-typedef size_t RegionTask; // index for region
-typedef GenericTaskQueue<RegionTask> RegionTaskQueue;
-typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet;
-
-class RegionTaskQueueWithOverflow: public CHeapObj {
- protected:
- RegionTaskQueue _region_queue;
- GrowableArray<RegionTask>* _overflow_stack;
-
- public:
- RegionTaskQueueWithOverflow() : _overflow_stack(NULL) {}
- // Initialize both stealable queue and overflow
- void initialize();
- // Save first to stealable queue and then to overflow
- void save(RegionTask t);
- // Retrieve first from overflow and then from stealable queue
- bool retrieve(RegionTask& region_index);
- // Retrieve from stealable queue
- bool retrieve_from_stealable_queue(RegionTask& region_index);
- // Retrieve from overflow
- bool retrieve_from_overflow(RegionTask& region_index);
- bool is_empty();
- bool stealable_is_empty();
- bool overflow_is_empty();
- uint stealable_size() { return _region_queue.size(); }
- RegionTaskQueue* task_queue() { return &_region_queue; }
-};
-
-#define USE_RegionTaskQueueWithOverflow
+typedef OverflowTaskQueue<size_t> RegionTaskQueue;
+typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet;