Merge
This commit is contained in:
commit
ffb15fdb04
@ -35,7 +35,6 @@ import sun.jvm.hotspot.utilities.*;
|
|||||||
|
|
||||||
public class NMethod extends CodeBlob {
|
public class NMethod extends CodeBlob {
|
||||||
private static long pcDescSize;
|
private static long pcDescSize;
|
||||||
private static CIntegerField zombieInstructionSizeField;
|
|
||||||
private static sun.jvm.hotspot.types.OopField methodField;
|
private static sun.jvm.hotspot.types.OopField methodField;
|
||||||
/** != InvocationEntryBci if this nmethod is an on-stack replacement method */
|
/** != InvocationEntryBci if this nmethod is an on-stack replacement method */
|
||||||
private static CIntegerField entryBCIField;
|
private static CIntegerField entryBCIField;
|
||||||
@ -88,7 +87,6 @@ public class NMethod extends CodeBlob {
|
|||||||
private static void initialize(TypeDataBase db) {
|
private static void initialize(TypeDataBase db) {
|
||||||
Type type = db.lookupType("nmethod");
|
Type type = db.lookupType("nmethod");
|
||||||
|
|
||||||
zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
|
|
||||||
methodField = type.getOopField("_method");
|
methodField = type.getOopField("_method");
|
||||||
entryBCIField = type.getCIntegerField("_entry_bci");
|
entryBCIField = type.getCIntegerField("_entry_bci");
|
||||||
osrLinkField = type.getAddressField("_osr_link");
|
osrLinkField = type.getAddressField("_osr_link");
|
||||||
|
@ -376,10 +376,17 @@ public:
|
|||||||
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
|
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 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() {
|
static uint cores_per_cpu() {
|
||||||
uint result = 1;
|
uint result = 1;
|
||||||
if (is_intel()) {
|
if (is_intel()) {
|
||||||
if (_cpuid_info.std_max_function >= 0xB) {
|
if (supports_processor_topology()) {
|
||||||
result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
|
result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
|
||||||
_cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
|
_cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
|
||||||
} else {
|
} else {
|
||||||
@ -393,7 +400,7 @@ public:
|
|||||||
|
|
||||||
static uint threads_per_core() {
|
static uint threads_per_core() {
|
||||||
uint result = 1;
|
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;
|
result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
|
||||||
} else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
|
} else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
|
||||||
result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
|
result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
|
||||||
|
@ -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
|
|
@ -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() {}
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
@ -106,7 +106,7 @@ public:
|
|||||||
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
|
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
|
||||||
for (int i = 0; i < _arg_size; i++) {
|
for (int i = 0; i < _arg_size; i++) {
|
||||||
if (vars.contains(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_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
|
||||||
_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
|
_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
|
||||||
@ -126,16 +126,16 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
|
|||||||
if (_conservative)
|
if (_conservative)
|
||||||
return true;
|
return true;
|
||||||
for (int i = 0; i < _arg_size; i++) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
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++) {
|
for (int i = 0; i < _arg_size; i++) {
|
||||||
if (vars.contains(i)) {
|
if (vars.contains(i)) {
|
||||||
bm.clear_bit(i);
|
bm >>= i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1157,15 +1157,15 @@ void BCEscapeAnalyzer::initialize() {
|
|||||||
ciSignature* sig = method()->signature();
|
ciSignature* sig = method()->signature();
|
||||||
int j = 0;
|
int j = 0;
|
||||||
if (!method()->is_static()) {
|
if (!method()->is_static()) {
|
||||||
_arg_local.set_bit(0);
|
_arg_local.set(0);
|
||||||
_arg_stack.set_bit(0);
|
_arg_stack.set(0);
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < sig->count(); i++) {
|
for (i = 0; i < sig->count(); i++) {
|
||||||
ciType* t = sig->type_at(i);
|
ciType* t = sig->type_at(i);
|
||||||
if (!t->is_primitive_type()) {
|
if (!t->is_primitive_type()) {
|
||||||
_arg_local.set_bit(j);
|
_arg_local.set(j);
|
||||||
_arg_stack.set_bit(j);
|
_arg_stack.set(j);
|
||||||
}
|
}
|
||||||
j += t->size();
|
j += t->size();
|
||||||
}
|
}
|
||||||
@ -1198,9 +1198,9 @@ void BCEscapeAnalyzer::clear_escape_info() {
|
|||||||
set_modified(var, OFFSET_ANY, 4);
|
set_modified(var, OFFSET_ANY, 4);
|
||||||
set_global_escape(var);
|
set_global_escape(var);
|
||||||
}
|
}
|
||||||
_arg_local.clear();
|
_arg_local.Clear();
|
||||||
_arg_stack.clear();
|
_arg_stack.Clear();
|
||||||
_arg_returned.clear();
|
_arg_returned.Clear();
|
||||||
_return_local = false;
|
_return_local = false;
|
||||||
_return_allocated = false;
|
_return_allocated = false;
|
||||||
_allocated_escapes = true;
|
_allocated_escapes = true;
|
||||||
@ -1254,7 +1254,7 @@ void BCEscapeAnalyzer::compute_escape_info() {
|
|||||||
|
|
||||||
// Do not scan method if it has no object parameters and
|
// Do not scan method if it has no object parameters and
|
||||||
// does not returns an object (_return_allocated is set in initialize()).
|
// 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
|
// Clear all info since method's bytecode was not analysed and
|
||||||
// set pessimistic escape information.
|
// set pessimistic escape information.
|
||||||
clear_escape_info();
|
clear_escape_info();
|
||||||
@ -1275,14 +1275,14 @@ void BCEscapeAnalyzer::compute_escape_info() {
|
|||||||
//
|
//
|
||||||
if (!has_dependencies() && !methodData()->is_empty()) {
|
if (!has_dependencies() && !methodData()->is_empty()) {
|
||||||
for (i = 0; i < _arg_size; i++) {
|
for (i = 0; i < _arg_size; i++) {
|
||||||
if (_arg_local.at(i)) {
|
if (_arg_local.test(i)) {
|
||||||
assert(_arg_stack.at(i), "inconsistent escape info");
|
assert(_arg_stack.test(i), "inconsistent escape info");
|
||||||
methodData()->set_arg_local(i);
|
methodData()->set_arg_local(i);
|
||||||
methodData()->set_arg_stack(i);
|
methodData()->set_arg_stack(i);
|
||||||
} else if (_arg_stack.at(i)) {
|
} else if (_arg_stack.test(i)) {
|
||||||
methodData()->set_arg_stack(i);
|
methodData()->set_arg_stack(i);
|
||||||
}
|
}
|
||||||
if (_arg_returned.at(i)) {
|
if (_arg_returned.test(i)) {
|
||||||
methodData()->set_arg_returned(i);
|
methodData()->set_arg_returned(i);
|
||||||
}
|
}
|
||||||
methodData()->set_arg_modified(i, _arg_modified[i]);
|
methodData()->set_arg_modified(i, _arg_modified[i]);
|
||||||
@ -1308,9 +1308,12 @@ void BCEscapeAnalyzer::read_escape_info() {
|
|||||||
|
|
||||||
// read escape information from method descriptor
|
// read escape information from method descriptor
|
||||||
for (int i = 0; i < _arg_size; i++) {
|
for (int i = 0; i < _arg_size; i++) {
|
||||||
_arg_local.at_put(i, methodData()->is_arg_local(i));
|
if (methodData()->is_arg_local(i))
|
||||||
_arg_stack.at_put(i, methodData()->is_arg_stack(i));
|
_arg_local.set(i);
|
||||||
_arg_returned.at_put(i, methodData()->is_arg_returned(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);
|
_arg_modified[i] = methodData()->arg_modified(i);
|
||||||
}
|
}
|
||||||
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
|
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
|
||||||
@ -1358,26 +1361,26 @@ void BCEscapeAnalyzer::dump() {
|
|||||||
|
|
||||||
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
|
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
|
||||||
: _conservative(method == NULL || !EstimateArgEscape)
|
: _conservative(method == NULL || !EstimateArgEscape)
|
||||||
|
, _arena(CURRENT_ENV->arena())
|
||||||
, _method(method)
|
, _method(method)
|
||||||
, _methodData(method ? method->method_data() : NULL)
|
, _methodData(method ? method->method_data() : NULL)
|
||||||
, _arg_size(method ? method->arg_size() : 0)
|
, _arg_size(method ? method->arg_size() : 0)
|
||||||
, _stack()
|
, _arg_local(_arena)
|
||||||
, _arg_local(_arg_size)
|
, _arg_stack(_arena)
|
||||||
, _arg_stack(_arg_size)
|
, _arg_returned(_arena)
|
||||||
, _arg_returned(_arg_size)
|
, _dirty(_arena)
|
||||||
, _dirty(_arg_size)
|
|
||||||
, _return_local(false)
|
, _return_local(false)
|
||||||
, _return_allocated(false)
|
, _return_allocated(false)
|
||||||
, _allocated_escapes(false)
|
, _allocated_escapes(false)
|
||||||
, _unknown_modified(false)
|
, _unknown_modified(false)
|
||||||
, _dependencies()
|
, _dependencies(_arena, 4, 0, NULL)
|
||||||
, _parent(parent)
|
, _parent(parent)
|
||||||
, _level(parent == NULL ? 0 : parent->level() + 1) {
|
, _level(parent == NULL ? 0 : parent->level() + 1) {
|
||||||
if (!_conservative) {
|
if (!_conservative) {
|
||||||
_arg_local.clear();
|
_arg_local.Clear();
|
||||||
_arg_stack.clear();
|
_arg_stack.Clear();
|
||||||
_arg_returned.clear();
|
_arg_returned.Clear();
|
||||||
_dirty.clear();
|
_dirty.Clear();
|
||||||
Arena* arena = CURRENT_ENV->arena();
|
Arena* arena = CURRENT_ENV->arena();
|
||||||
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
|
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
|
||||||
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
|
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
|
||||||
@ -1414,8 +1417,8 @@ void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) {
|
|||||||
deps->assert_evol_method(method());
|
deps->assert_evol_method(method());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < _dependencies.length(); i+=2) {
|
for (int i = 0; i < _dependencies.length(); i+=2) {
|
||||||
ciKlass *k = _dependencies[i]->as_klass();
|
ciKlass *k = _dependencies.at(i)->as_klass();
|
||||||
ciMethod *m = _dependencies[i+1]->as_method();
|
ciMethod *m = _dependencies.at(i+1)->as_method();
|
||||||
deps->assert_unique_concrete_method(k, m);
|
deps->assert_unique_concrete_method(k, m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define_array(ciObjectArray, ciObject*);
|
|
||||||
define_stack(ciObjectList, ciObjectArray);
|
|
||||||
|
|
||||||
// This class implements a fast, conservative analysis of effect of methods
|
// This class implements a fast, conservative analysis of effect of methods
|
||||||
// on the escape state of their arguments. The analysis is at the bytecode
|
// on the escape state of their arguments. The analysis is at the bytecode
|
||||||
// level.
|
// level.
|
||||||
@ -34,18 +31,17 @@ class ciBlock;
|
|||||||
|
|
||||||
class BCEscapeAnalyzer : public ResourceObj {
|
class BCEscapeAnalyzer : public ResourceObj {
|
||||||
private:
|
private:
|
||||||
|
Arena* _arena; // ciEnv arena
|
||||||
|
|
||||||
bool _conservative; // If true, return maximally
|
bool _conservative; // If true, return maximally
|
||||||
// conservative results.
|
// conservative results.
|
||||||
ciMethod* _method;
|
ciMethod* _method;
|
||||||
ciMethodData* _methodData;
|
ciMethodData* _methodData;
|
||||||
int _arg_size;
|
int _arg_size;
|
||||||
|
VectorSet _arg_local;
|
||||||
intStack _stack;
|
VectorSet _arg_stack;
|
||||||
|
VectorSet _arg_returned;
|
||||||
BitMap _arg_local;
|
VectorSet _dirty;
|
||||||
BitMap _arg_stack;
|
|
||||||
BitMap _arg_returned;
|
|
||||||
BitMap _dirty;
|
|
||||||
enum{ ARG_OFFSET_MAX = 31};
|
enum{ ARG_OFFSET_MAX = 31};
|
||||||
uint *_arg_modified;
|
uint *_arg_modified;
|
||||||
|
|
||||||
@ -54,7 +50,7 @@ class BCEscapeAnalyzer : public ResourceObj {
|
|||||||
bool _allocated_escapes;
|
bool _allocated_escapes;
|
||||||
bool _unknown_modified;
|
bool _unknown_modified;
|
||||||
|
|
||||||
ciObjectList _dependencies;
|
GrowableArray<ciObject *> _dependencies;
|
||||||
|
|
||||||
ciMethodBlocks *_methodBlocks;
|
ciMethodBlocks *_methodBlocks;
|
||||||
|
|
||||||
@ -68,20 +64,10 @@ class BCEscapeAnalyzer : public ResourceObj {
|
|||||||
private:
|
private:
|
||||||
// helper functions
|
// helper functions
|
||||||
bool is_argument(int i) { return i >= 0 && i < _arg_size; }
|
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);
|
void set_returned(ArgumentMap vars);
|
||||||
bool is_argument(ArgumentMap vars);
|
bool is_argument(ArgumentMap vars);
|
||||||
bool is_arg_stack(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_method_escape(ArgumentMap vars);
|
||||||
void set_global_escape(ArgumentMap vars);
|
void set_global_escape(ArgumentMap vars);
|
||||||
void set_dirty(ArgumentMap vars);
|
void set_dirty(ArgumentMap vars);
|
||||||
@ -116,25 +102,25 @@ class BCEscapeAnalyzer : public ResourceObj {
|
|||||||
ciMethodData* methodData() const { return _methodData; }
|
ciMethodData* methodData() const { return _methodData; }
|
||||||
BCEscapeAnalyzer* parent() const { return _parent; }
|
BCEscapeAnalyzer* parent() const { return _parent; }
|
||||||
int level() const { return _level; }
|
int level() const { return _level; }
|
||||||
ciObjectList* dependencies() { return &_dependencies; }
|
GrowableArray<ciObject *>* dependencies() { return &_dependencies; }
|
||||||
bool has_dependencies() const { return !_dependencies.is_empty(); }
|
bool has_dependencies() const { return !_dependencies.is_empty(); }
|
||||||
|
|
||||||
// retrieval of interprocedural escape information
|
// retrieval of interprocedural escape information
|
||||||
|
|
||||||
// The given argument does not escape the callee.
|
// The given argument does not escape the callee.
|
||||||
bool is_arg_local(int i) const {
|
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
|
// The given argument escapes the callee, but does not become globally
|
||||||
// reachable.
|
// reachable.
|
||||||
bool is_arg_stack(int i) const {
|
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.
|
// The given argument does not escape globally, and may be returned.
|
||||||
bool is_arg_returned(int i) const {
|
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.
|
// True iff only input arguments are returned.
|
||||||
bool is_return_local() const {
|
bool is_return_local() const {
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -44,9 +44,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
|
|||||||
_flags = ciFlags(access_flags);
|
_flags = ciFlags(access_flags);
|
||||||
_has_finalizer = access_flags.has_finalizer();
|
_has_finalizer = access_flags.has_finalizer();
|
||||||
_has_subklass = ik->subklass() != NULL;
|
_has_subklass = ik->subklass() != NULL;
|
||||||
_is_initialized = ik->is_initialized();
|
_init_state = (instanceKlass::ClassState)ik->get_init_state();
|
||||||
// Next line must follow and use the result of the previous line:
|
|
||||||
_is_linked = _is_initialized || ik->is_linked();
|
|
||||||
_nonstatic_field_size = ik->nonstatic_field_size();
|
_nonstatic_field_size = ik->nonstatic_field_size();
|
||||||
_has_nonstatic_fields = ik->has_nonstatic_fields();
|
_has_nonstatic_fields = ik->has_nonstatic_fields();
|
||||||
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
|
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
|
||||||
@ -91,8 +89,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
|
|||||||
: ciKlass(name, ciInstanceKlassKlass::make())
|
: ciKlass(name, ciInstanceKlassKlass::make())
|
||||||
{
|
{
|
||||||
assert(name->byte_at(0) != '[', "not an instance klass");
|
assert(name->byte_at(0) != '[', "not an instance klass");
|
||||||
_is_initialized = false;
|
_init_state = (instanceKlass::ClassState)0;
|
||||||
_is_linked = false;
|
|
||||||
_nonstatic_field_size = -1;
|
_nonstatic_field_size = -1;
|
||||||
_has_nonstatic_fields = false;
|
_has_nonstatic_fields = false;
|
||||||
_nonstatic_fields = NULL;
|
_nonstatic_fields = NULL;
|
||||||
@ -109,21 +106,10 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
|
|||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciInstanceKlass::compute_shared_is_initialized
|
// ciInstanceKlass::compute_shared_is_initialized
|
||||||
bool ciInstanceKlass::compute_shared_is_initialized() {
|
void ciInstanceKlass::compute_shared_init_state() {
|
||||||
GUARDED_VM_ENTRY(
|
GUARDED_VM_ENTRY(
|
||||||
instanceKlass* ik = get_instanceKlass();
|
instanceKlass* ik = get_instanceKlass();
|
||||||
_is_initialized = ik->is_initialized();
|
_init_state = (instanceKlass::ClassState)ik->get_init_state();
|
||||||
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;
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -39,9 +39,8 @@ private:
|
|||||||
jobject _loader;
|
jobject _loader;
|
||||||
jobject _protection_domain;
|
jobject _protection_domain;
|
||||||
|
|
||||||
|
instanceKlass::ClassState _init_state; // state of class
|
||||||
bool _is_shared;
|
bool _is_shared;
|
||||||
bool _is_initialized;
|
|
||||||
bool _is_linked;
|
|
||||||
bool _has_finalizer;
|
bool _has_finalizer;
|
||||||
bool _has_subklass;
|
bool _has_subklass;
|
||||||
bool _has_nonstatic_fields;
|
bool _has_nonstatic_fields;
|
||||||
@ -87,27 +86,34 @@ protected:
|
|||||||
|
|
||||||
bool is_shared() { return _is_shared; }
|
bool is_shared() { return _is_shared; }
|
||||||
|
|
||||||
bool compute_shared_is_initialized();
|
void compute_shared_init_state();
|
||||||
bool compute_shared_is_linked();
|
|
||||||
bool compute_shared_has_subklass();
|
bool compute_shared_has_subklass();
|
||||||
int compute_shared_nof_implementors();
|
int compute_shared_nof_implementors();
|
||||||
int compute_nonstatic_fields();
|
int compute_nonstatic_fields();
|
||||||
GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_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:
|
public:
|
||||||
// Has this klass been initialized?
|
// Has this klass been initialized?
|
||||||
bool is_initialized() {
|
bool is_initialized() {
|
||||||
if (_is_shared && !_is_initialized) {
|
update_if_shared(instanceKlass::fully_initialized);
|
||||||
return is_loaded() && compute_shared_is_initialized();
|
return _init_state == instanceKlass::fully_initialized;
|
||||||
}
|
}
|
||||||
return _is_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?
|
// Has this klass been linked?
|
||||||
bool is_linked() {
|
bool is_linked() {
|
||||||
if (_is_shared && !_is_linked) {
|
update_if_shared(instanceKlass::linked);
|
||||||
return is_loaded() && compute_shared_is_linked();
|
return _init_state >= instanceKlass::linked;
|
||||||
}
|
|
||||||
return _is_linked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// General klass information.
|
// General klass information.
|
||||||
|
@ -54,10 +54,10 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
|||||||
_code = NULL;
|
_code = NULL;
|
||||||
_exception_handlers = NULL;
|
_exception_handlers = NULL;
|
||||||
_liveness = NULL;
|
_liveness = NULL;
|
||||||
_bcea = NULL;
|
|
||||||
_method_blocks = NULL;
|
_method_blocks = NULL;
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
_flow = NULL;
|
_flow = NULL;
|
||||||
|
_bcea = NULL;
|
||||||
#endif // COMPILER2
|
#endif // COMPILER2
|
||||||
|
|
||||||
ciEnv *env = CURRENT_ENV;
|
ciEnv *env = CURRENT_ENV;
|
||||||
@ -121,11 +121,11 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
|
|||||||
_intrinsic_id = vmIntrinsics::_none;
|
_intrinsic_id = vmIntrinsics::_none;
|
||||||
_liveness = NULL;
|
_liveness = NULL;
|
||||||
_can_be_statically_bound = false;
|
_can_be_statically_bound = false;
|
||||||
_bcea = NULL;
|
|
||||||
_method_blocks = NULL;
|
_method_blocks = NULL;
|
||||||
_method_data = NULL;
|
_method_data = NULL;
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
_flow = NULL;
|
_flow = NULL;
|
||||||
|
_bcea = NULL;
|
||||||
#endif // COMPILER2
|
#endif // COMPILER2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,10 +1033,15 @@ bool ciMethod::is_accessor () const { FETCH_FLAG_FROM_VM(is_accessor)
|
|||||||
bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); }
|
bool ciMethod::is_initializer () const { FETCH_FLAG_FROM_VM(is_initializer); }
|
||||||
|
|
||||||
BCEscapeAnalyzer *ciMethod::get_bcea() {
|
BCEscapeAnalyzer *ciMethod::get_bcea() {
|
||||||
|
#ifdef COMPILER2
|
||||||
if (_bcea == NULL) {
|
if (_bcea == NULL) {
|
||||||
_bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
|
_bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
|
||||||
}
|
}
|
||||||
return _bcea;
|
return _bcea;
|
||||||
|
#else // COMPILER2
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return NULL;
|
||||||
|
#endif // COMPILER2
|
||||||
}
|
}
|
||||||
|
|
||||||
ciMethodBlocks *ciMethod::get_method_blocks() {
|
ciMethodBlocks *ciMethod::get_method_blocks() {
|
||||||
|
@ -48,7 +48,6 @@ class ciMethod : public ciObject {
|
|||||||
ciInstanceKlass* _holder;
|
ciInstanceKlass* _holder;
|
||||||
ciSignature* _signature;
|
ciSignature* _signature;
|
||||||
ciMethodData* _method_data;
|
ciMethodData* _method_data;
|
||||||
BCEscapeAnalyzer* _bcea;
|
|
||||||
ciMethodBlocks* _method_blocks;
|
ciMethodBlocks* _method_blocks;
|
||||||
|
|
||||||
// Code attributes.
|
// Code attributes.
|
||||||
@ -72,7 +71,8 @@ class ciMethod : public ciObject {
|
|||||||
// Optional liveness analyzer.
|
// Optional liveness analyzer.
|
||||||
MethodLiveness* _liveness;
|
MethodLiveness* _liveness;
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
ciTypeFlow* _flow;
|
ciTypeFlow* _flow;
|
||||||
|
BCEscapeAnalyzer* _bcea;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ciMethod(methodHandle h_m);
|
ciMethod(methodHandle h_m);
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -832,7 +832,6 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
|||||||
|
|
||||||
|
|
||||||
instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
|
instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
|
||||||
VTuneClassLoadMarker clm;
|
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
|
EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
|
||||||
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
|
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
|
||||||
|
@ -210,6 +210,7 @@ AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
|
|||||||
{
|
{
|
||||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
blob = new (size) AdapterBlob(size, cb);
|
blob = new (size) AdapterBlob(size, cb);
|
||||||
|
CodeCache::commit(blob);
|
||||||
}
|
}
|
||||||
// Track memory usage statistic after releasing CodeCache_lock
|
// Track memory usage statistic after releasing CodeCache_lock
|
||||||
MemoryService::track_code_cache_memory_usage();
|
MemoryService::track_code_cache_memory_usage();
|
||||||
@ -281,7 +282,6 @@ RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name,
|
|||||||
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub);
|
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub);
|
||||||
Disassembler::decode(stub->instructions_begin(), stub->instructions_end());
|
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());
|
Forte::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
@ -356,7 +356,6 @@ DeoptimizationBlob* DeoptimizationBlob::create(
|
|||||||
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
||||||
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
|
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());
|
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
@ -414,7 +413,6 @@ UncommonTrapBlob* UncommonTrapBlob::create(
|
|||||||
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
||||||
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
|
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());
|
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
@ -474,7 +472,6 @@ ExceptionBlob* ExceptionBlob::create(
|
|||||||
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
||||||
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
|
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());
|
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
@ -533,7 +530,6 @@ SafepointBlob* SafepointBlob::create(
|
|||||||
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
|
||||||
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
|
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());
|
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
|
@ -93,6 +93,8 @@ class CodeBlob_sizes {
|
|||||||
|
|
||||||
CodeHeap * CodeCache::_heap = new CodeHeap();
|
CodeHeap * CodeCache::_heap = new CodeHeap();
|
||||||
int CodeCache::_number_of_blobs = 0;
|
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;
|
int CodeCache::_number_of_nmethods_with_dependencies = 0;
|
||||||
bool CodeCache::_needs_cache_clean = false;
|
bool CodeCache::_needs_cache_clean = false;
|
||||||
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
|
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
|
||||||
@ -176,8 +178,14 @@ void CodeCache::free(CodeBlob* cb) {
|
|||||||
verify_if_often();
|
verify_if_often();
|
||||||
|
|
||||||
print_trace("free", cb);
|
print_trace("free", cb);
|
||||||
if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
|
if (cb->is_nmethod()) {
|
||||||
_number_of_nmethods_with_dependencies--;
|
_number_of_nmethods--;
|
||||||
|
if (((nmethod *)cb)->has_dependencies()) {
|
||||||
|
_number_of_nmethods_with_dependencies--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cb->is_adapter_blob()) {
|
||||||
|
_number_of_adapters--;
|
||||||
}
|
}
|
||||||
_number_of_blobs--;
|
_number_of_blobs--;
|
||||||
|
|
||||||
@ -191,9 +199,16 @@ void CodeCache::free(CodeBlob* cb) {
|
|||||||
void CodeCache::commit(CodeBlob* cb) {
|
void CodeCache::commit(CodeBlob* cb) {
|
||||||
// this is called by nmethod::nmethod, which must already own CodeCache_lock
|
// this is called by nmethod::nmethod, which must already own CodeCache_lock
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
|
if (cb->is_nmethod()) {
|
||||||
_number_of_nmethods_with_dependencies++;
|
_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
|
// flush the hardware I-cache
|
||||||
ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size());
|
ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size());
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -43,6 +43,8 @@ class CodeCache : AllStatic {
|
|||||||
// 4422213 or 4436291 for details.
|
// 4422213 or 4436291 for details.
|
||||||
static CodeHeap * _heap;
|
static CodeHeap * _heap;
|
||||||
static int _number_of_blobs;
|
static int _number_of_blobs;
|
||||||
|
static int _number_of_adapters;
|
||||||
|
static int _number_of_nmethods;
|
||||||
static int _number_of_nmethods_with_dependencies;
|
static int _number_of_nmethods_with_dependencies;
|
||||||
static bool _needs_cache_clean;
|
static bool _needs_cache_clean;
|
||||||
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
|
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
|
||||||
@ -105,6 +107,8 @@ class CodeCache : AllStatic {
|
|||||||
static nmethod* first_nmethod();
|
static nmethod* first_nmethod();
|
||||||
static nmethod* next_nmethod (CodeBlob* cb);
|
static nmethod* next_nmethod (CodeBlob* cb);
|
||||||
static int nof_blobs() { return _number_of_blobs; }
|
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
|
// GC support
|
||||||
static void gc_epilogue();
|
static void gc_epilogue();
|
||||||
|
@ -397,11 +397,6 @@ void nmethod::add_handler_for_exception_and_pc(Handle exception, address pc, add
|
|||||||
//-------------end of code for ExceptionCache--------------
|
//-------------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 {
|
int nmethod::total_size() const {
|
||||||
return
|
return
|
||||||
code_size() +
|
code_size() +
|
||||||
@ -419,8 +414,32 @@ const char* nmethod::compile_kind() const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// %%% This variable is no longer used?
|
// Fill in default values for various flag fields
|
||||||
int nmethod::_zombie_instruction_size = NativeJump::instruction_size;
|
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,
|
nmethod* nmethod::new_native_nmethod(methodHandle method,
|
||||||
@ -580,25 +599,16 @@ nmethod::nmethod(
|
|||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
|
||||||
NOT_PRODUCT(_has_debug_info = false);
|
init_defaults();
|
||||||
_oops_do_mark_link = NULL;
|
|
||||||
_method = method;
|
_method = method;
|
||||||
_entry_bci = InvocationEntryBci;
|
_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
|
// We have no exception handler or deopt handler make the
|
||||||
// values something that will never match a pc like the nmethod vtable entry
|
// values something that will never match a pc like the nmethod vtable entry
|
||||||
_exception_offset = 0;
|
_exception_offset = 0;
|
||||||
_deoptimize_offset = 0;
|
_deoptimize_offset = 0;
|
||||||
_deoptimize_mh_offset = 0;
|
_deoptimize_mh_offset = 0;
|
||||||
_orig_pc_offset = 0;
|
_orig_pc_offset = 0;
|
||||||
#ifdef HAVE_DTRACE_H
|
|
||||||
_trap_offset = 0;
|
|
||||||
#endif // def HAVE_DTRACE_H
|
|
||||||
_stub_offset = data_offset();
|
_stub_offset = data_offset();
|
||||||
_consts_offset = data_offset();
|
_consts_offset = data_offset();
|
||||||
_oops_offset = data_offset();
|
_oops_offset = data_offset();
|
||||||
@ -616,17 +626,9 @@ nmethod::nmethod(
|
|||||||
_exception_cache = NULL;
|
_exception_cache = NULL;
|
||||||
_pc_desc_cache.reset_to(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);
|
code_buffer->copy_oops_to(this);
|
||||||
debug_only(verify_scavenge_root_oops());
|
debug_only(verify_scavenge_root_oops());
|
||||||
CodeCache::commit(this);
|
CodeCache::commit(this);
|
||||||
VTune::create_nmethod(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
|
if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
|
||||||
@ -674,15 +676,9 @@ nmethod::nmethod(
|
|||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
|
||||||
NOT_PRODUCT(_has_debug_info = false);
|
init_defaults();
|
||||||
_oops_do_mark_link = NULL;
|
|
||||||
_method = method;
|
_method = method;
|
||||||
_entry_bci = InvocationEntryBci;
|
_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
|
// We have no exception handler or deopt handler make the
|
||||||
// values something that will never match a pc like the nmethod vtable entry
|
// values something that will never match a pc like the nmethod vtable entry
|
||||||
_exception_offset = 0;
|
_exception_offset = 0;
|
||||||
@ -708,17 +704,9 @@ nmethod::nmethod(
|
|||||||
_exception_cache = NULL;
|
_exception_cache = NULL;
|
||||||
_pc_desc_cache.reset_to(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);
|
code_buffer->copy_oops_to(this);
|
||||||
debug_only(verify_scavenge_root_oops());
|
debug_only(verify_scavenge_root_oops());
|
||||||
CodeCache::commit(this);
|
CodeCache::commit(this);
|
||||||
VTune::create_nmethod(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
|
if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
|
||||||
@ -783,21 +771,13 @@ nmethod::nmethod(
|
|||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
|
||||||
NOT_PRODUCT(_has_debug_info = false);
|
init_defaults();
|
||||||
_oops_do_mark_link = NULL;
|
|
||||||
_method = method;
|
_method = method;
|
||||||
_jmethod_id = NULL;
|
_entry_bci = entry_bci;
|
||||||
_compile_id = compile_id;
|
_compile_id = compile_id;
|
||||||
_comp_level = comp_level;
|
_comp_level = comp_level;
|
||||||
_entry_bci = entry_bci;
|
|
||||||
_osr_link = NULL;
|
|
||||||
_scavenge_root_link = NULL;
|
|
||||||
_scavenge_root_state = 0;
|
|
||||||
_compiler = compiler;
|
_compiler = compiler;
|
||||||
_orig_pc_offset = orig_pc_offset;
|
_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());
|
_stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
|
||||||
|
|
||||||
// Exception handler and deopt handler are in the stub section
|
// Exception handler and deopt handler are in the stub section
|
||||||
@ -824,15 +804,6 @@ nmethod::nmethod(
|
|||||||
_exception_cache = NULL;
|
_exception_cache = NULL;
|
||||||
_pc_desc_cache.reset_to(scopes_pcs_begin());
|
_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
|
// Copy contents of ScopeDescRecorder to nmethod
|
||||||
code_buffer->copy_oops_to(this);
|
code_buffer->copy_oops_to(this);
|
||||||
debug_info->copy_to(this);
|
debug_info->copy_to(this);
|
||||||
@ -844,8 +815,6 @@ nmethod::nmethod(
|
|||||||
|
|
||||||
CodeCache::commit(this);
|
CodeCache::commit(this);
|
||||||
|
|
||||||
VTune::create_nmethod(this);
|
|
||||||
|
|
||||||
// Copy contents of ExceptionHandlerTable to nmethod
|
// Copy contents of ExceptionHandlerTable to nmethod
|
||||||
handler_table->copy_to(this);
|
handler_table->copy_to(this);
|
||||||
nul_chk_table->copy_to(this);
|
nul_chk_table->copy_to(this);
|
||||||
@ -991,11 +960,6 @@ void nmethod::print_nmethod(bool printmethod) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void nmethod::set_version(int v) {
|
|
||||||
flags.version = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Promote one word from an assembly-time handle to a live embedded oop.
|
// Promote one word from an assembly-time handle to a live embedded oop.
|
||||||
inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
|
inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
|
||||||
if (handle == NULL ||
|
if (handle == NULL ||
|
||||||
@ -1142,6 +1106,8 @@ void nmethod::cleanup_inline_caches() {
|
|||||||
// This is a private interface with the sweeper.
|
// This is a private interface with the sweeper.
|
||||||
void nmethod::mark_as_seen_on_stack() {
|
void nmethod::mark_as_seen_on_stack() {
|
||||||
assert(is_not_entrant(), "must be a non-entrant method");
|
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());
|
set_stack_traversal_mark(NMethodSweeper::traversal_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,7 +1176,7 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
|
|||||||
// for later on.
|
// for later on.
|
||||||
CodeCache::set_needs_cache_clean(true);
|
CodeCache::set_needs_cache_clean(true);
|
||||||
}
|
}
|
||||||
flags.state = unloaded;
|
_state = unloaded;
|
||||||
|
|
||||||
// Log the unloading.
|
// Log the unloading.
|
||||||
log_state_change();
|
log_state_change();
|
||||||
@ -1236,21 +1202,21 @@ void nmethod::log_state_change() const {
|
|||||||
if (LogCompilation) {
|
if (LogCompilation) {
|
||||||
if (xtty != NULL) {
|
if (xtty != NULL) {
|
||||||
ttyLocker ttyl; // keep the following output all in one block
|
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 "'",
|
xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
|
||||||
os::current_thread_id());
|
os::current_thread_id());
|
||||||
} else {
|
} else {
|
||||||
xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
|
xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
|
||||||
os::current_thread_id(),
|
os::current_thread_id(),
|
||||||
(flags.state == zombie ? " zombie='1'" : ""));
|
(_state == zombie ? " zombie='1'" : ""));
|
||||||
}
|
}
|
||||||
log_identity(xtty);
|
log_identity(xtty);
|
||||||
xtty->stamp();
|
xtty->stamp();
|
||||||
xtty->end_elem();
|
xtty->end_elem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (PrintCompilation && flags.state != unloaded) {
|
if (PrintCompilation && _state != unloaded) {
|
||||||
print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
|
print_on(tty, _state == zombie ? "made zombie " : "made not entrant ");
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1261,8 +1227,9 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||||||
|
|
||||||
bool was_alive = false;
|
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);
|
nmethodLocker nml(this);
|
||||||
|
methodHandle the_method(method());
|
||||||
|
|
||||||
{
|
{
|
||||||
// If the method is already zombie there is nothing to do
|
// If the method is already zombie there is nothing to do
|
||||||
@ -1282,7 +1249,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||||||
// Enter critical section. Does not block for safepoint.
|
// Enter critical section. Does not block for safepoint.
|
||||||
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
if (flags.state == state) {
|
if (_state == state) {
|
||||||
// another thread already performed this transition so nothing
|
// another thread already performed this transition so nothing
|
||||||
// to do, but return false to indicate this.
|
// to do, but return false to indicate this.
|
||||||
return false;
|
return false;
|
||||||
@ -1293,17 +1260,37 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||||||
if (!is_osr_method() && !is_not_entrant()) {
|
if (!is_osr_method() && !is_not_entrant()) {
|
||||||
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
|
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
|
||||||
SharedRuntime::get_handle_wrong_method_stub());
|
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
|
// Change state
|
||||||
flags.state = state;
|
_state = state;
|
||||||
|
|
||||||
// Log the transition once
|
// Log the transition once
|
||||||
log_state_change();
|
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
|
} // leave critical region under Patching_lock
|
||||||
|
|
||||||
// When the nmethod becomes zombie it is no longer alive so the
|
// When the nmethod becomes zombie it is no longer alive so the
|
||||||
@ -1311,18 +1298,17 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||||||
// state will be flushed later when the transition to zombie
|
// state will be flushed later when the transition to zombie
|
||||||
// happens or they get unloaded.
|
// happens or they get unloaded.
|
||||||
if (state == zombie) {
|
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);
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
flush_dependencies(NULL);
|
flush_dependencies(NULL);
|
||||||
} else {
|
} else {
|
||||||
assert(state == not_entrant, "other cases may need to be handled differently");
|
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) {
|
if (TraceCreateZombies) {
|
||||||
tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
|
tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
|
||||||
}
|
}
|
||||||
@ -1330,47 +1316,6 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||||||
// Make sweeper aware that there is a zombie method that needs to be removed
|
// Make sweeper aware that there is a zombie method that needs to be removed
|
||||||
NMethodSweeper::notify(this);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2109,7 +2054,6 @@ address nmethod::continuation_for_implicit_exception(address pc) {
|
|||||||
|
|
||||||
void nmethod_init() {
|
void nmethod_init() {
|
||||||
// make sure you didn't forget to adjust the filler fields
|
// 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");
|
assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2345,7 +2289,6 @@ void nmethod::print() const {
|
|||||||
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
|
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
|
||||||
tty->print(" for method " INTPTR_FORMAT , (address)method());
|
tty->print(" for method " INTPTR_FORMAT , (address)method());
|
||||||
tty->print(" { ");
|
tty->print(" { ");
|
||||||
if (version()) tty->print("v%d ", version());
|
|
||||||
if (is_in_use()) tty->print("in_use ");
|
if (is_in_use()) tty->print("in_use ");
|
||||||
if (is_not_entrant()) tty->print("not_entrant ");
|
if (is_not_entrant()) tty->print("not_entrant ");
|
||||||
if (is_zombie()) tty->print("zombie ");
|
if (is_zombie()) tty->print("zombie ");
|
||||||
|
@ -78,29 +78,8 @@ class PcDescCache VALUE_OBJ_CLASS_SPEC {
|
|||||||
|
|
||||||
|
|
||||||
// nmethods (native methods) are the compiled code versions of Java methods.
|
// nmethods (native methods) are the compiled code versions of Java methods.
|
||||||
|
//
|
||||||
struct nmFlags {
|
// An nmethod contains:
|
||||||
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:
|
|
||||||
// - header (the nmethod structure)
|
// - header (the nmethod structure)
|
||||||
// [Relocation]
|
// [Relocation]
|
||||||
// - relocation information
|
// - relocation information
|
||||||
@ -131,8 +110,6 @@ class nmethod : public CodeBlob {
|
|||||||
friend class CodeCache; // non-perm oops
|
friend class CodeCache; // non-perm oops
|
||||||
private:
|
private:
|
||||||
// Shared fields for all nmethod's
|
// Shared fields for all nmethod's
|
||||||
static int _zombie_instruction_size;
|
|
||||||
|
|
||||||
methodOop _method;
|
methodOop _method;
|
||||||
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
|
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
|
||||||
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
|
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
|
||||||
@ -147,6 +124,11 @@ class nmethod : public CodeBlob {
|
|||||||
|
|
||||||
AbstractCompiler* _compiler; // The compiler which compiled this nmethod
|
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
|
// Offsets for different nmethod parts
|
||||||
int _exception_offset;
|
int _exception_offset;
|
||||||
// All deoptee's will resume execution at this location described by
|
// All deoptee's will resume execution at this location described by
|
||||||
@ -175,23 +157,31 @@ class nmethod : public CodeBlob {
|
|||||||
// pc during a deopt.
|
// pc during a deopt.
|
||||||
int _orig_pc_offset;
|
int _orig_pc_offset;
|
||||||
|
|
||||||
int _compile_id; // which compilation made this nmethod
|
int _compile_id; // which compilation made this nmethod
|
||||||
int _comp_level; // compilation level
|
int _comp_level; // compilation level
|
||||||
|
|
||||||
// offsets for entry points
|
// protected by CodeCache_lock
|
||||||
address _entry_point; // entry point with class check
|
bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
|
||||||
address _verified_entry_point; // entry point without class check
|
bool _speculatively_disconnected; // Marked for potential unload
|
||||||
address _osr_entry_point; // entry point for on stack replacement
|
|
||||||
|
bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
|
||||||
|
bool _marked_for_deoptimization; // Used for stack deoptimization
|
||||||
|
|
||||||
|
// used by jvmti to track if an unload event has been posted for this nmethod.
|
||||||
|
bool _unload_reported;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
nmFlags flags; // various flags to keep track of nmethod state
|
|
||||||
bool _markedForDeoptimization; // Used for stack deoptimization
|
|
||||||
enum { alive = 0,
|
enum { alive = 0,
|
||||||
not_entrant = 1, // uncommon trap has happened but activations may still exist
|
not_entrant = 1, // uncommon trap has happened but activations may still exist
|
||||||
zombie = 2,
|
zombie = 2,
|
||||||
unloaded = 3 };
|
unloaded = 3 };
|
||||||
|
|
||||||
// used by jvmti to track if an unload event has been posted for this nmethod.
|
|
||||||
bool _unload_reported;
|
|
||||||
|
|
||||||
jbyte _scavenge_root_state;
|
jbyte _scavenge_root_state;
|
||||||
|
|
||||||
@ -270,15 +260,15 @@ class nmethod : public CodeBlob {
|
|||||||
bool make_not_entrant_or_zombie(unsigned int state);
|
bool make_not_entrant_or_zombie(unsigned int state);
|
||||||
void inc_decompile_count();
|
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
|
// Used to manipulate the exception cache
|
||||||
void add_exception_cache_entry(ExceptionCache* new_entry);
|
void add_exception_cache_entry(ExceptionCache* new_entry);
|
||||||
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
|
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
|
||||||
|
|
||||||
// Inform external interfaces that a compiled method has been unloaded
|
// 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:
|
public:
|
||||||
// create nmethod with entry_bci
|
// create nmethod with entry_bci
|
||||||
@ -393,11 +383,11 @@ class nmethod : public CodeBlob {
|
|||||||
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
|
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
|
||||||
|
|
||||||
// flag accessing and manipulation
|
// flag accessing and manipulation
|
||||||
bool is_in_use() const { return flags.state == alive; }
|
bool is_in_use() const { return _state == alive; }
|
||||||
bool is_alive() const { return flags.state == alive || flags.state == not_entrant; }
|
bool is_alive() const { return _state == alive || _state == not_entrant; }
|
||||||
bool is_not_entrant() const { return flags.state == not_entrant; }
|
bool is_not_entrant() const { return _state == not_entrant; }
|
||||||
bool is_zombie() const { return flags.state == zombie; }
|
bool is_zombie() const { return _state == zombie; }
|
||||||
bool is_unloaded() const { return flags.state == unloaded; }
|
bool is_unloaded() const { return _state == unloaded; }
|
||||||
|
|
||||||
// Make the nmethod non entrant. The nmethod will continue to be
|
// Make the nmethod non entrant. The nmethod will continue to be
|
||||||
// alive. It is used when an uncommon trap happens. Returns true
|
// alive. It is used when an uncommon trap happens. Returns true
|
||||||
@ -410,37 +400,33 @@ class nmethod : public CodeBlob {
|
|||||||
bool unload_reported() { return _unload_reported; }
|
bool unload_reported() { return _unload_reported; }
|
||||||
void set_unload_reported() { _unload_reported = true; }
|
void set_unload_reported() { _unload_reported = true; }
|
||||||
|
|
||||||
bool is_marked_for_deoptimization() const { return _markedForDeoptimization; }
|
bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
|
||||||
void mark_for_deoptimization() { _markedForDeoptimization = true; }
|
void mark_for_deoptimization() { _marked_for_deoptimization = true; }
|
||||||
|
|
||||||
void make_unloaded(BoolObjectClosure* is_alive, oop cause);
|
void make_unloaded(BoolObjectClosure* is_alive, oop cause);
|
||||||
|
|
||||||
bool has_dependencies() { return dependencies_size() != 0; }
|
bool has_dependencies() { return dependencies_size() != 0; }
|
||||||
void flush_dependencies(BoolObjectClosure* is_alive);
|
void flush_dependencies(BoolObjectClosure* is_alive);
|
||||||
bool has_flushed_dependencies() { return flags.hasFlushedDependencies; }
|
bool has_flushed_dependencies() { return _has_flushed_dependencies; }
|
||||||
void set_has_flushed_dependencies() {
|
void set_has_flushed_dependencies() {
|
||||||
assert(!has_flushed_dependencies(), "should only happen once");
|
assert(!has_flushed_dependencies(), "should only happen once");
|
||||||
flags.hasFlushedDependencies = 1;
|
_has_flushed_dependencies = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_marked_for_reclamation() const { return flags.markedForReclamation; }
|
bool is_marked_for_reclamation() const { return _marked_for_reclamation; }
|
||||||
void mark_for_reclamation() { flags.markedForReclamation = 1; }
|
void mark_for_reclamation() { _marked_for_reclamation = 1; }
|
||||||
void unmark_for_reclamation() { flags.markedForReclamation = 0; }
|
|
||||||
|
|
||||||
bool has_unsafe_access() const { return flags.has_unsafe_access; }
|
bool has_unsafe_access() const { return _has_unsafe_access; }
|
||||||
void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
|
void set_has_unsafe_access(bool z) { _has_unsafe_access = z; }
|
||||||
|
|
||||||
bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
|
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
|
||||||
void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
|
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
|
||||||
|
|
||||||
bool is_speculatively_disconnected() const { return flags.speculatively_disconnected; }
|
bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
|
||||||
void set_speculatively_disconnected(bool z) { flags.speculatively_disconnected = z; }
|
void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
|
||||||
|
|
||||||
int comp_level() const { return _comp_level; }
|
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:
|
// Support for oops in scopes and relocs:
|
||||||
// Note: index 0 is reserved for null.
|
// Note: index 0 is reserved for null.
|
||||||
oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
|
oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -50,7 +50,6 @@ void* VtableStub::operator new(size_t size, int code_size) {
|
|||||||
}
|
}
|
||||||
_chunk = blob->instructions_begin();
|
_chunk = blob->instructions_begin();
|
||||||
_chunk_end = _chunk + bytes;
|
_chunk_end = _chunk + bytes;
|
||||||
VTune::register_stub("vtable stub", _chunk, _chunk_end);
|
|
||||||
Forte::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
|
// Notify JVMTI about this stub. The event will be recorded by the enclosing
|
||||||
// JvmtiDynamicCodeEventCollector and posted when this thread has released
|
// JvmtiDynamicCodeEventCollector and posted when this thread has released
|
||||||
|
@ -89,6 +89,21 @@ adlcVMDeps.hpp allocation.hpp
|
|||||||
|
|
||||||
allocation.hpp c2_globals.hpp
|
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 allocation.inline.hpp
|
||||||
block.cpp block.hpp
|
block.cpp block.hpp
|
||||||
block.cpp cfgnode.hpp
|
block.cpp cfgnode.hpp
|
||||||
@ -239,6 +254,7 @@ chaitin_<os_family>.cpp machnode.hpp
|
|||||||
ciEnv.cpp compileLog.hpp
|
ciEnv.cpp compileLog.hpp
|
||||||
ciEnv.cpp runtime.hpp
|
ciEnv.cpp runtime.hpp
|
||||||
|
|
||||||
|
ciMethod.cpp bcEscapeAnalyzer.hpp
|
||||||
ciMethod.cpp ciTypeFlow.hpp
|
ciMethod.cpp ciTypeFlow.hpp
|
||||||
ciMethod.cpp methodOop.hpp
|
ciMethod.cpp methodOop.hpp
|
||||||
|
|
||||||
|
@ -301,20 +301,6 @@ barrierSet.hpp oopsHierarchy.hpp
|
|||||||
barrierSet.inline.hpp barrierSet.hpp
|
barrierSet.inline.hpp barrierSet.hpp
|
||||||
barrierSet.inline.hpp cardTableModRefBS.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 biasedLocking.hpp
|
||||||
biasedLocking.cpp klass.inline.hpp
|
biasedLocking.cpp klass.inline.hpp
|
||||||
biasedLocking.cpp markOop.hpp
|
biasedLocking.cpp markOop.hpp
|
||||||
@ -665,7 +651,6 @@ ciKlassKlass.hpp ciSymbol.hpp
|
|||||||
|
|
||||||
ciMethod.cpp abstractCompiler.hpp
|
ciMethod.cpp abstractCompiler.hpp
|
||||||
ciMethod.cpp allocation.inline.hpp
|
ciMethod.cpp allocation.inline.hpp
|
||||||
ciMethod.cpp bcEscapeAnalyzer.hpp
|
|
||||||
ciMethod.cpp bitMap.inline.hpp
|
ciMethod.cpp bitMap.inline.hpp
|
||||||
ciMethod.cpp ciCallProfile.hpp
|
ciMethod.cpp ciCallProfile.hpp
|
||||||
ciMethod.cpp ciExceptionHandler.hpp
|
ciMethod.cpp ciExceptionHandler.hpp
|
||||||
@ -964,7 +949,6 @@ classLoader.cpp threadService.hpp
|
|||||||
classLoader.cpp timer.hpp
|
classLoader.cpp timer.hpp
|
||||||
classLoader.cpp universe.inline.hpp
|
classLoader.cpp universe.inline.hpp
|
||||||
classLoader.cpp vmSymbols.hpp
|
classLoader.cpp vmSymbols.hpp
|
||||||
classLoader.cpp vtune.hpp
|
|
||||||
|
|
||||||
classLoader.hpp classFileParser.hpp
|
classLoader.hpp classFileParser.hpp
|
||||||
classLoader.hpp perfData.hpp
|
classLoader.hpp perfData.hpp
|
||||||
@ -1004,7 +988,6 @@ codeBlob.cpp relocInfo.hpp
|
|||||||
codeBlob.cpp safepoint.hpp
|
codeBlob.cpp safepoint.hpp
|
||||||
codeBlob.cpp sharedRuntime.hpp
|
codeBlob.cpp sharedRuntime.hpp
|
||||||
codeBlob.cpp vframe.hpp
|
codeBlob.cpp vframe.hpp
|
||||||
codeBlob.cpp vtune.hpp
|
|
||||||
|
|
||||||
codeBlob.hpp codeBuffer.hpp
|
codeBlob.hpp codeBuffer.hpp
|
||||||
codeBlob.hpp frame.hpp
|
codeBlob.hpp frame.hpp
|
||||||
@ -2167,7 +2150,6 @@ interpreter.cpp sharedRuntime.hpp
|
|||||||
interpreter.cpp stubRoutines.hpp
|
interpreter.cpp stubRoutines.hpp
|
||||||
interpreter.cpp templateTable.hpp
|
interpreter.cpp templateTable.hpp
|
||||||
interpreter.cpp timer.hpp
|
interpreter.cpp timer.hpp
|
||||||
interpreter.cpp vtune.hpp
|
|
||||||
|
|
||||||
interpreter.hpp cppInterpreter.hpp
|
interpreter.hpp cppInterpreter.hpp
|
||||||
interpreter.hpp stubs.hpp
|
interpreter.hpp stubs.hpp
|
||||||
@ -2323,7 +2305,6 @@ java.cpp universe.hpp
|
|||||||
java.cpp vmError.hpp
|
java.cpp vmError.hpp
|
||||||
java.cpp vm_operations.hpp
|
java.cpp vm_operations.hpp
|
||||||
java.cpp vm_version_<arch>.hpp
|
java.cpp vm_version_<arch>.hpp
|
||||||
java.cpp vtune.hpp
|
|
||||||
|
|
||||||
java.hpp os.hpp
|
java.hpp os.hpp
|
||||||
|
|
||||||
@ -3050,7 +3031,6 @@ nmethod.cpp nmethod.hpp
|
|||||||
nmethod.cpp scopeDesc.hpp
|
nmethod.cpp scopeDesc.hpp
|
||||||
nmethod.cpp sharedRuntime.hpp
|
nmethod.cpp sharedRuntime.hpp
|
||||||
nmethod.cpp sweeper.hpp
|
nmethod.cpp sweeper.hpp
|
||||||
nmethod.cpp vtune.hpp
|
|
||||||
nmethod.cpp xmlstream.hpp
|
nmethod.cpp xmlstream.hpp
|
||||||
|
|
||||||
nmethod.hpp codeBlob.hpp
|
nmethod.hpp codeBlob.hpp
|
||||||
@ -3773,7 +3753,6 @@ sharedRuntime.cpp vframeArray.hpp
|
|||||||
sharedRuntime.cpp vmSymbols.hpp
|
sharedRuntime.cpp vmSymbols.hpp
|
||||||
sharedRuntime.cpp vmreg_<arch>.inline.hpp
|
sharedRuntime.cpp vmreg_<arch>.inline.hpp
|
||||||
sharedRuntime.cpp vtableStubs.hpp
|
sharedRuntime.cpp vtableStubs.hpp
|
||||||
sharedRuntime.cpp vtune.hpp
|
|
||||||
sharedRuntime.cpp xmlstream.hpp
|
sharedRuntime.cpp xmlstream.hpp
|
||||||
|
|
||||||
sharedRuntime.hpp allocation.hpp
|
sharedRuntime.hpp allocation.hpp
|
||||||
@ -3937,7 +3916,6 @@ stubCodeGenerator.cpp disassembler.hpp
|
|||||||
stubCodeGenerator.cpp forte.hpp
|
stubCodeGenerator.cpp forte.hpp
|
||||||
stubCodeGenerator.cpp oop.inline.hpp
|
stubCodeGenerator.cpp oop.inline.hpp
|
||||||
stubCodeGenerator.cpp stubCodeGenerator.hpp
|
stubCodeGenerator.cpp stubCodeGenerator.hpp
|
||||||
stubCodeGenerator.cpp vtune.hpp
|
|
||||||
|
|
||||||
stubCodeGenerator.hpp allocation.hpp
|
stubCodeGenerator.hpp allocation.hpp
|
||||||
stubCodeGenerator.hpp assembler.hpp
|
stubCodeGenerator.hpp assembler.hpp
|
||||||
@ -4458,7 +4436,6 @@ universe.cpp universe.hpp
|
|||||||
universe.cpp universe.inline.hpp
|
universe.cpp universe.inline.hpp
|
||||||
universe.cpp vmSymbols.hpp
|
universe.cpp vmSymbols.hpp
|
||||||
universe.cpp vm_operations.hpp
|
universe.cpp vm_operations.hpp
|
||||||
universe.cpp vtune.hpp
|
|
||||||
|
|
||||||
universe.hpp growableArray.hpp
|
universe.hpp growableArray.hpp
|
||||||
universe.hpp handles.hpp
|
universe.hpp handles.hpp
|
||||||
@ -4721,7 +4698,6 @@ vtableStubs.cpp mutexLocker.hpp
|
|||||||
vtableStubs.cpp resourceArea.hpp
|
vtableStubs.cpp resourceArea.hpp
|
||||||
vtableStubs.cpp sharedRuntime.hpp
|
vtableStubs.cpp sharedRuntime.hpp
|
||||||
vtableStubs.cpp vtableStubs.hpp
|
vtableStubs.cpp vtableStubs.hpp
|
||||||
vtableStubs.cpp vtune.hpp
|
|
||||||
|
|
||||||
vtableStubs.hpp allocation.hpp
|
vtableStubs.hpp allocation.hpp
|
||||||
|
|
||||||
@ -4735,11 +4711,6 @@ vtableStubs_<arch_model>.cpp sharedRuntime.hpp
|
|||||||
vtableStubs_<arch_model>.cpp vmreg_<arch>.inline.hpp
|
vtableStubs_<arch_model>.cpp vmreg_<arch>.inline.hpp
|
||||||
vtableStubs_<arch_model>.cpp vtableStubs.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 allocation.hpp
|
||||||
watermark.hpp globalDefinitions.hpp
|
watermark.hpp globalDefinitions.hpp
|
||||||
|
|
||||||
|
@ -99,11 +99,6 @@ void interpreter_init() {
|
|||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
// need to hit every safepoint in order to call zapping routine
|
// need to hit every safepoint in order to call zapping routine
|
||||||
// register the interpreter
|
// register the interpreter
|
||||||
VTune::register_stub(
|
|
||||||
"Interpreter",
|
|
||||||
AbstractInterpreter::code()->code_start(),
|
|
||||||
AbstractInterpreter::code()->code_end()
|
|
||||||
);
|
|
||||||
Forte::register_stub(
|
Forte::register_stub(
|
||||||
"Interpreter",
|
"Interpreter",
|
||||||
AbstractInterpreter::code()->code_start(),
|
AbstractInterpreter::code()->code_start(),
|
||||||
|
@ -343,7 +343,8 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
|
|||||||
// being initialized. Uncommon-trap for not-initialized static or
|
// being initialized. Uncommon-trap for not-initialized static or
|
||||||
// v-calls. Let interface calls happen.
|
// v-calls. Let interface calls happen.
|
||||||
ciInstanceKlass* holder_klass = dest_method->holder();
|
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()) {
|
!holder_klass->is_interface()) {
|
||||||
uncommon_trap(Deoptimization::Reason_uninitialized,
|
uncommon_trap(Deoptimization::Reason_uninitialized,
|
||||||
Deoptimization::Action_reinterpret,
|
Deoptimization::Action_reinterpret,
|
||||||
|
@ -480,6 +480,7 @@ class Parse : public GraphKit {
|
|||||||
bool push_constant(ciConstant con, bool require_constant = false);
|
bool push_constant(ciConstant con, bool require_constant = false);
|
||||||
|
|
||||||
// implementation of object creation bytecodes
|
// implementation of object creation bytecodes
|
||||||
|
void emit_guard_for_new(ciInstanceKlass* klass);
|
||||||
void do_new();
|
void do_new();
|
||||||
void do_newarray(BasicType elemtype);
|
void do_newarray(BasicType elemtype);
|
||||||
void do_anewarray();
|
void do_anewarray();
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -197,6 +197,43 @@ void Parse::array_store_check() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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-----------------------------------------
|
//------------------------------do_new-----------------------------------------
|
||||||
void Parse::do_new() {
|
void Parse::do_new() {
|
||||||
kill_dead_locals();
|
kill_dead_locals();
|
||||||
@ -206,7 +243,7 @@ void Parse::do_new() {
|
|||||||
assert(will_link, "_new: typeflow responsibility");
|
assert(will_link, "_new: typeflow responsibility");
|
||||||
|
|
||||||
// Should initialize, or throw an InstantiationError?
|
// 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->is_abstract() || klass->is_interface() ||
|
||||||
klass->name() == ciSymbol::java_lang_Class() ||
|
klass->name() == ciSymbol::java_lang_Class() ||
|
||||||
iter().is_unresolved_klass()) {
|
iter().is_unresolved_klass()) {
|
||||||
@ -215,6 +252,9 @@ void Parse::do_new() {
|
|||||||
klass);
|
klass);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (klass->is_being_initialized()) {
|
||||||
|
emit_guard_for_new(klass);
|
||||||
|
}
|
||||||
|
|
||||||
Node* kls = makecon(TypeKlassPtr::make(klass));
|
Node* kls = makecon(TypeKlassPtr::make(klass));
|
||||||
Node* obj = new_instance(kls);
|
Node* obj = new_instance(kls);
|
||||||
|
@ -118,7 +118,6 @@ void CodeBlobCollector::do_blob(CodeBlob* cb) {
|
|||||||
for (int i=0; i<_global_code_blobs->length(); i++) {
|
for (int i=0; i<_global_code_blobs->length(); i++) {
|
||||||
JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i);
|
JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i);
|
||||||
if (addr == scb->code_begin()) {
|
if (addr == scb->code_begin()) {
|
||||||
ShouldNotReachHere();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,11 +205,11 @@ jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* e
|
|||||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
nmethod* current = CodeCache::first_nmethod();
|
nmethod* current = CodeCache::first_nmethod();
|
||||||
while (current != NULL) {
|
while (current != NULL) {
|
||||||
// Lock the nmethod so it can't be freed
|
|
||||||
nmethodLocker nml(current);
|
|
||||||
|
|
||||||
// Only notify for live nmethods
|
// Only notify for live nmethods
|
||||||
if (current->is_alive()) {
|
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
|
// Don't hold the lock over the notify or jmethodID creation
|
||||||
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
current->get_and_cache_jmethod_id();
|
current->get_and_cache_jmethod_id();
|
||||||
|
@ -2541,9 +2541,6 @@ class CommandLineFlags {
|
|||||||
"Enable String cache capabilities on String.java") \
|
"Enable String cache capabilities on String.java") \
|
||||||
\
|
\
|
||||||
/* statistics */ \
|
/* statistics */ \
|
||||||
develop(bool, UseVTune, false, \
|
|
||||||
"enable support for Intel's VTune profiler") \
|
|
||||||
\
|
|
||||||
develop(bool, CountCompiledCalls, false, \
|
develop(bool, CountCompiledCalls, false, \
|
||||||
"counts method invocations") \
|
"counts method invocations") \
|
||||||
\
|
\
|
||||||
|
@ -34,7 +34,6 @@ void perfMemory_init();
|
|||||||
|
|
||||||
// Initialization done by Java thread in init_globals()
|
// Initialization done by Java thread in init_globals()
|
||||||
void management_init();
|
void management_init();
|
||||||
void vtune_init();
|
|
||||||
void bytecodes_init();
|
void bytecodes_init();
|
||||||
void classLoader_init();
|
void classLoader_init();
|
||||||
void codeCache_init();
|
void codeCache_init();
|
||||||
@ -82,7 +81,6 @@ void vm_init_globals() {
|
|||||||
jint init_globals() {
|
jint init_globals() {
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
management_init();
|
management_init();
|
||||||
vtune_init();
|
|
||||||
bytecodes_init();
|
bytecodes_init();
|
||||||
classLoader_init();
|
classLoader_init();
|
||||||
codeCache_init();
|
codeCache_init();
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -432,8 +432,6 @@ void before_exit(JavaThread * thread) {
|
|||||||
print_statistics();
|
print_statistics();
|
||||||
Universe::heap()->print_tracing_info();
|
Universe::heap()->print_tracing_info();
|
||||||
|
|
||||||
VTune::exit();
|
|
||||||
|
|
||||||
{ MutexLocker ml(BeforeExit_lock);
|
{ MutexLocker ml(BeforeExit_lock);
|
||||||
_before_exit_status = BEFORE_EXIT_DONE;
|
_before_exit_status = BEFORE_EXIT_DONE;
|
||||||
BeforeExit_lock->notify_all();
|
BeforeExit_lock->notify_all();
|
||||||
|
@ -2251,7 +2251,6 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) {
|
|||||||
B->name(),
|
B->name(),
|
||||||
fingerprint->as_string(),
|
fingerprint->as_string(),
|
||||||
B->instructions_begin());
|
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());
|
Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -132,7 +132,6 @@ StubCodeMark::~StubCodeMark() {
|
|||||||
_cdesc->set_end(_cgen->assembler()->pc());
|
_cdesc->set_end(_cgen->assembler()->pc());
|
||||||
assert(StubCodeDesc::_list == _cdesc, "expected order on list");
|
assert(StubCodeDesc::_list == _cdesc, "expected order on list");
|
||||||
_cgen->stub_epilog(_cdesc);
|
_cgen->stub_epilog(_cdesc);
|
||||||
VTune::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
|
|
||||||
Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
|
Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
|
||||||
|
|
||||||
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
if (JvmtiExport::should_post_dynamic_code_generated()) {
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
long NMethodSweeper::_traversals = 0; // No. of stack traversals performed
|
||||||
nmethod* NMethodSweeper::_current = NULL; // Current nmethod
|
nmethod* NMethodSweeper::_current = NULL; // Current nmethod
|
||||||
int NMethodSweeper::_seen = 0 ; // No. of blobs we have currently processed in current pass of CodeCache
|
int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache
|
||||||
int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
|
|
||||||
|
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::_locked_seen = 0;
|
||||||
jint NMethodSweeper::_not_entrant_seen_on_stack = 0;
|
jint NMethodSweeper::_not_entrant_seen_on_stack = 0;
|
||||||
bool NMethodSweeper::_rescan = false;
|
bool NMethodSweeper::_rescan = false;
|
||||||
bool NMethodSweeper::_do_sweep = false;
|
bool NMethodSweeper::_do_sweep = false;
|
||||||
jint NMethodSweeper::_sweep_started = 0;
|
|
||||||
bool NMethodSweeper::_was_full = false;
|
bool NMethodSweeper::_was_full = false;
|
||||||
jint NMethodSweeper::_advise_to_sweep = 0;
|
jint NMethodSweeper::_advise_to_sweep = 0;
|
||||||
jlong NMethodSweeper::_last_was_full = 0;
|
jlong NMethodSweeper::_last_was_full = 0;
|
||||||
@ -108,23 +109,14 @@ void NMethodSweeper::scan_stacks() {
|
|||||||
// code cache is filling up
|
// code cache is filling up
|
||||||
_last_was_full = os::javaTimeMillis();
|
_last_was_full = os::javaTimeMillis();
|
||||||
|
|
||||||
if (PrintMethodFlushing) {
|
log_sweep("restart_compiler");
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NMethodSweeper::possibly_sweep() {
|
void NMethodSweeper::possibly_sweep() {
|
||||||
|
assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
|
||||||
if ((!MethodFlushing) || (!_do_sweep)) return;
|
if ((!MethodFlushing) || (!_do_sweep)) return;
|
||||||
|
|
||||||
if (_invocations > 0) {
|
if (_invocations > 0) {
|
||||||
@ -133,32 +125,31 @@ void NMethodSweeper::possibly_sweep() {
|
|||||||
if (old != 0) {
|
if (old != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sweep_code_cache();
|
if (_invocations > 0) {
|
||||||
|
sweep_code_cache();
|
||||||
|
_invocations--;
|
||||||
|
}
|
||||||
|
_sweep_started = 0;
|
||||||
}
|
}
|
||||||
_sweep_started = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NMethodSweeper::sweep_code_cache() {
|
void NMethodSweeper::sweep_code_cache() {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
jlong sweep_start;
|
jlong sweep_start;
|
||||||
if(PrintMethodFlushing) {
|
if (PrintMethodFlushing) {
|
||||||
sweep_start = os::javaTimeMillis();
|
sweep_start = os::javaTimeMillis();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (PrintMethodFlushing && Verbose) {
|
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.
|
// We want to visit all nmethods after NmethodSweepFraction
|
||||||
// If invocation is 1 we do the rest
|
// invocations so divide the remaining number of nmethods by the
|
||||||
int todo = CodeCache::nof_blobs();
|
// remaining number of invocations. This is only an estimate since
|
||||||
if (_invocations > 1) {
|
// the number of nmethods changes during the sweep so the final
|
||||||
todo = (CodeCache::nof_blobs() - _seen) / _invocations;
|
// stage must iterate until it there are no more nmethods.
|
||||||
}
|
int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
|
||||||
|
|
||||||
// Compilers may check to sweep more often than stack scans happen,
|
|
||||||
// don't keep trying once it is all scanned
|
|
||||||
_invocations--;
|
|
||||||
|
|
||||||
assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
|
assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
|
||||||
assert(!CodeCache_lock->owned_by_self(), "just checking");
|
assert(!CodeCache_lock->owned_by_self(), "just checking");
|
||||||
@ -166,11 +157,12 @@ void NMethodSweeper::sweep_code_cache() {
|
|||||||
{
|
{
|
||||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
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.
|
// Since we will give up the CodeCache_lock, always skip ahead
|
||||||
// Other blobs can be deleted by other threads
|
// to the next nmethod. Other blobs can be deleted by other
|
||||||
// Read next before we potentially delete current
|
// threads but nmethods are only reclaimed by the sweeper.
|
||||||
nmethod* next = CodeCache::next_nmethod(_current);
|
nmethod* next = CodeCache::next_nmethod(_current);
|
||||||
|
|
||||||
// Now ready to process nmethod and give up CodeCache_lock
|
// Now ready to process nmethod and give up CodeCache_lock
|
||||||
@ -183,6 +175,8 @@ void NMethodSweeper::sweep_code_cache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
|
||||||
|
|
||||||
if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
|
if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
|
||||||
// we've completed a scan without making progress but there were
|
// we've completed a scan without making progress but there were
|
||||||
// nmethods we were unable to process either because they were
|
// nmethods we were unable to process either because they were
|
||||||
@ -201,6 +195,10 @@ void NMethodSweeper::sweep_code_cache() {
|
|||||||
tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
|
tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_invocations == 1) {
|
||||||
|
log_sweep("finished");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -223,7 +221,7 @@ void NMethodSweeper::process_nmethod(nmethod *nm) {
|
|||||||
if (nm->is_zombie()) {
|
if (nm->is_zombie()) {
|
||||||
// If it is first time, we see nmethod then we mark it. Otherwise,
|
// 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
|
// 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()) {
|
if (nm->is_marked_for_reclamation()) {
|
||||||
assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
|
assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
|
||||||
if (PrintMethodFlushing && Verbose) {
|
if (PrintMethodFlushing && Verbose) {
|
||||||
@ -320,16 +318,8 @@ void NMethodSweeper::handle_full_code_cache(bool is_full) {
|
|||||||
jlong curr_interval = now - _last_was_full;
|
jlong curr_interval = now - _last_was_full;
|
||||||
if (curr_interval < max_interval) {
|
if (curr_interval < max_interval) {
|
||||||
_rescan = true;
|
_rescan = true;
|
||||||
if (PrintMethodFlushing) {
|
log_sweep("disable_compiler", "flushing_interval='" UINT64_FORMAT "'",
|
||||||
tty->print_cr("### handle full too often, turning off compiler");
|
curr_interval/1000);
|
||||||
}
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,17 +339,7 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
|
|||||||
|
|
||||||
if ((!was_full()) && (is_full)) {
|
if ((!was_full()) && (is_full)) {
|
||||||
if (!CodeCache::needs_flushing()) {
|
if (!CodeCache::needs_flushing()) {
|
||||||
if (PrintMethodFlushing) {
|
log_sweep("restart_compiler");
|
||||||
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();
|
|
||||||
}
|
|
||||||
CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
|
CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -368,17 +348,7 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
|
|||||||
// Traverse the code cache trying to dump the oldest nmethods
|
// Traverse the code cache trying to dump the oldest nmethods
|
||||||
uint curr_max_comp_id = CompileBroker::get_compilation_id();
|
uint curr_max_comp_id = CompileBroker::get_compilation_id();
|
||||||
uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
|
uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
|
||||||
if (PrintMethodFlushing && Verbose) {
|
log_sweep("start_cleaning");
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
|
nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
|
||||||
jint disconnected = 0;
|
jint disconnected = 0;
|
||||||
@ -411,13 +381,9 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
|
|||||||
nm = CodeCache::alive_nmethod(CodeCache::next(nm));
|
nm = CodeCache::alive_nmethod(CodeCache::next(nm));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LogCompilation && (xtty != NULL)) {
|
log_sweep("stop_cleaning",
|
||||||
ttyLocker ttyl;
|
"disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "'",
|
||||||
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);
|
||||||
disconnected, made_not_entrant, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
|
|
||||||
xtty->stamp();
|
|
||||||
xtty->end_elem();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shut off compiler. Sweeper will start over with a new stack scan and
|
// 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.
|
// traversal cycle and turn it back on if it clears enough space.
|
||||||
@ -435,3 +401,38 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
|
|||||||
}
|
}
|
||||||
#endif
|
#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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,12 +31,13 @@ class NMethodSweeper : public AllStatic {
|
|||||||
static long _traversals; // Stack traversal count
|
static long _traversals; // Stack traversal count
|
||||||
static nmethod* _current; // Current nmethod
|
static nmethod* _current; // Current nmethod
|
||||||
static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache
|
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
|
static bool _rescan; // Indicates that we should do a full rescan of the
|
||||||
// of the code cache looking for work to do.
|
// 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 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 _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
|
static int _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack
|
||||||
|
|
||||||
@ -47,6 +48,9 @@ class NMethodSweeper : public AllStatic {
|
|||||||
static long _was_full_traversal; // trav number at last emergency unloading
|
static long _was_full_traversal; // trav number at last emergency unloading
|
||||||
|
|
||||||
static void process_nmethod(nmethod *nm);
|
static void process_nmethod(nmethod *nm);
|
||||||
|
|
||||||
|
static void log_sweep(const char* msg, const char* format = NULL, ...);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static long traversal_count() { return _traversals; }
|
static long traversal_count() { return _traversals; }
|
||||||
|
|
||||||
|
@ -614,7 +614,6 @@ static inline uint64_t cast_uint64_t(size_t x)
|
|||||||
/* NMethods (NOTE: incomplete, but only a little) */ \
|
/* NMethods (NOTE: incomplete, but only a little) */ \
|
||||||
/**************************************************/ \
|
/**************************************************/ \
|
||||||
\
|
\
|
||||||
static_field(nmethod, _zombie_instruction_size, int) \
|
|
||||||
nonstatic_field(nmethod, _method, methodOop) \
|
nonstatic_field(nmethod, _method, methodOop) \
|
||||||
nonstatic_field(nmethod, _entry_bci, int) \
|
nonstatic_field(nmethod, _entry_bci, int) \
|
||||||
nonstatic_field(nmethod, _osr_link, nmethod*) \
|
nonstatic_field(nmethod, _osr_link, nmethod*) \
|
||||||
|
@ -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(); }
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user