This commit is contained in:
Alejandro Murillo 2015-12-18 09:37:16 -08:00
commit 8a47e1f795
325 changed files with 5460 additions and 7341 deletions

View File

@ -49,7 +49,7 @@
#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
#endif
#ifdef ppc64
#if defined(ppc64) || defined(ppc64le)
#include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
#endif
@ -223,9 +223,12 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_at
verifyBitness(env, (char *) &buf);
CHECK_EXCEPTION;
char err_buf[200];
struct ps_prochandle* ph;
if ( (ph = Pgrab(jpid)) == NULL) {
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
if ( (ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) {
char msg[230];
snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf);
THROW_NEW_DEBUGGER_EXCEPTION(msg);
}
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
fillThreadsAndLoadObjects(env, this_obj, ph);
@ -349,7 +352,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
return (err == PS_OK)? array : 0;
}
#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(aarch64)
#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64)
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0
(JNIEnv *env, jobject this_obj, jint lwp_id) {
@ -377,7 +380,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
#if defined(sparc) || defined(sparcv9)
#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
#endif
#ifdef ppc64
#if defined(ppc64) || defined(ppc64le)
#define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG
#endif
@ -486,7 +489,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
}
#endif /* aarch64 */
#ifdef ppc64
#if defined(ppc64) || defined(ppc64le)
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg
regs[REG_INDEX(LR)] = gregs.link;

View File

@ -68,7 +68,8 @@ combination of ptrace and /proc calls.
*************************************************************************************/
#if defined(sparc) || defined(sparcv9) || defined(ppc64)
#if defined(sparc) || defined(sparcv9) || defined(ppc64) || defined(ppc64le)
#include <asm/ptrace.h>
#define user_regs_struct pt_regs
#endif
#if defined(aarch64)
@ -86,7 +87,7 @@ typedef int bool;
struct ps_prochandle;
// attach to a process
struct ps_prochandle* Pgrab(pid_t pid);
struct ps_prochandle* Pgrab(pid_t pid, char* err_buf, size_t err_buf_len);
// attach to a core dump
struct ps_prochandle* Pgrab_core(const char* execfile, const char* corefile);

View File

@ -215,9 +215,12 @@ static bool ptrace_waitpid(pid_t pid) {
}
// attach to a process/thread specified by "pid"
static bool ptrace_attach(pid_t pid) {
static bool ptrace_attach(pid_t pid, char* err_buf, size_t err_buf_len) {
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
char buf[200];
char* msg = strerror_r(errno, buf, sizeof(buf));
snprintf(err_buf, err_buf_len, "ptrace(PTRACE_ATTACH, ..) failed for %d: %s", pid, msg);
print_debug("%s\n", err_buf);
return false;
} else {
return ptrace_waitpid(pid);
@ -370,16 +373,17 @@ static ps_prochandle_ops process_ops = {
};
// attach to the process. One and only one exposed stuff
struct ps_prochandle* Pgrab(pid_t pid) {
struct ps_prochandle* Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
struct ps_prochandle* ph = NULL;
thread_info* thr = NULL;
if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
print_debug("can't allocate memory for ps_prochandle\n");
snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
print_debug("%s\n", err_buf);
return NULL;
}
if (ptrace_attach(pid) != true) {
if (ptrace_attach(pid, err_buf, err_buf_len) != true) {
free(ph);
return NULL;
}
@ -402,7 +406,7 @@ struct ps_prochandle* Pgrab(pid_t pid) {
thr = ph->threads;
while (thr) {
// don't attach to the main thread again
if (ph->pid != thr->lwp_id && ptrace_attach(thr->lwp_id) != true) {
if (ph->pid != thr->lwp_id && ptrace_attach(thr->lwp_id, err_buf, err_buf_len) != true) {
// even if one attach fails, we get return NULL
Prelease(ph);
return NULL;

View File

@ -125,10 +125,14 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
}
}
// close this tool without calling System.exit
protected void closeUI() {
workerThread.shutdown();
frame.dispose();
private class CloseUI extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
workerThread.shutdown();
frame.dispose();
}
}
public void run() {
@ -144,7 +148,8 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
frame = new JFrame("HSDB - HotSpot Debugger");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new CloseUI());
JMenuBar menuBar = new JMenuBar();
@ -207,7 +212,8 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
item = createMenuItem("Exit",
new ActionListener() {
public void actionPerformed(ActionEvent e) {
closeUI();
workerThread.shutdown();
frame.dispose();
}
});
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));

View File

@ -37,7 +37,7 @@ public class SAGetopt {
private boolean _optreset; // special handling of first call
public SAGetopt(String[] args) {
_argv = args;
_argv = args.clone();
_optind = 0;
_optopt = 1;
_optarg = null;

View File

@ -41,7 +41,8 @@ import sun.jvm.hotspot.types.TypeDataBase;
public class HeapRegionSetBase extends VMObject {
static private long countField;
// uint _length
static private CIntegerField lengthField;
static {
VM.registerVMInitializedObserver(new Observer() {
@ -54,13 +55,11 @@ public class HeapRegionSetBase extends VMObject {
static private synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("HeapRegionSetBase");
countField = type.getField("_count").getOffset();
lengthField = type.getCIntegerField("_length");
}
public HeapRegionSetCount count() {
Address countFieldAddr = addr.addOffsetTo(countField);
return (HeapRegionSetCount) VMObjectFactory.newObject(HeapRegionSetCount.class, countFieldAddr);
public long length() {
return lengthField.getValue(addr);
}
public HeapRegionSetBase(Address addr) {

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.gc.g1;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.runtime.VMObject;
import sun.jvm.hotspot.runtime.VMObjectFactory;
import sun.jvm.hotspot.types.AddressField;
import sun.jvm.hotspot.types.CIntegerField;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
// Mirror class for HeapRegionSetCount. Represents a group of regions.
public class HeapRegionSetCount extends VMObject {
static private CIntegerField lengthField;
static private CIntegerField capacityField;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
static private synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("HeapRegionSetCount");
lengthField = type.getCIntegerField("_length");
capacityField = type.getCIntegerField("_capacity");
}
public long length() {
return lengthField.getValue(addr);
}
public long capacity() {
return capacityField.getValue(addr);
}
public HeapRegionSetCount(Address addr) {
super(addr);
}
}

View File

@ -229,17 +229,17 @@ public class VM {
public String getValue() {
if (isBool()) {
return new Boolean(getBool()).toString();
return Boolean.toString(getBool());
} else if (isInt()) {
return new Long(getInt()).toString();
return Long.toString(getInt());
} else if (isUInt()) {
return new Long(getUInt()).toString();
return Long.toString(getUInt());
} else if (isIntx()) {
return new Long(getIntx()).toString();
return Long.toString(getIntx());
} else if (isUIntx()) {
return new Long(getUIntx()).toString();
return Long.toString(getUIntx());
} else if (isSizet()) {
return new Long(getSizet()).toString();
return Long.toString(getSizet());
} else {
return null;
}

View File

@ -112,8 +112,7 @@ public class HeapSummary extends Tool {
long survivorRegionNum = g1mm.survivorRegionNum();
HeapRegionSetBase oldSet = g1h.oldSet();
HeapRegionSetBase humongousSet = g1h.humongousSet();
long oldRegionNum = oldSet.count().length()
+ humongousSet.count().capacity() / HeapRegion.grainBytes();
long oldRegionNum = oldSet.length() + humongousSet.length();
printG1Space("G1 Heap:", g1h.n_regions(),
g1h.used(), g1h.capacity());
System.out.println("G1 Young Generation:");

View File

@ -1921,6 +1921,15 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
buf.link(genPCHref(addressToLong(pc)), pc.toString());
}
if (!method.isStatic() && !method.isNative()) {
OopHandle oopHandle = vf.getLocals().oopHandleAt(0);
if (oopHandle != null) {
buf.append(", oop = ");
buf.append(oopHandle.toString());
}
}
if (vf.isCompiledFrame()) {
buf.append(" (Compiled");
}

View File

@ -54,7 +54,7 @@ public class PlatformInfo {
public static boolean knownCPU(String cpu) {
final String[] KNOWN =
new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "aarch64"};
new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "ppc64le", "aarch64"};
for(String s : KNOWN) {
if(s.equals(cpu))
@ -98,6 +98,9 @@ public class PlatformInfo {
if (cpu.equals("x86_64"))
return "amd64";
if (cpu.equals("ppc64le"))
return "ppc64";
return cpu;
}

View File

@ -277,7 +277,7 @@ ifneq ($(OSNAME),windows)
# Use uname output for SRCARCH, but deal with platform differences. If ARCH
# is not explicitly listed below, it is treated as x86.
SRCARCH ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc ppc64 aarch64 zero,$(ARCH)))
SRCARCH ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc ppc64 ppc64le aarch64 zero,$(ARCH)))
ARCH/ = x86
ARCH/sparc = sparc
ARCH/sparc64= sparc
@ -285,6 +285,7 @@ ifneq ($(OSNAME),windows)
ARCH/amd64 = x86
ARCH/x86_64 = x86
ARCH/ppc64 = ppc
ARCH/ppc64le= ppc
ARCH/ppc = ppc
ARCH/aarch64= aarch64
ARCH/zero = zero
@ -309,8 +310,13 @@ ifneq ($(OSNAME),windows)
endif
endif
# LIBARCH is 1:1 mapping from BUILDARCH
LIBARCH ?= $(LIBARCH/$(BUILDARCH))
# LIBARCH is 1:1 mapping from BUILDARCH, except for ARCH=ppc64le
ifeq ($(ARCH),ppc64le)
LIBARCH ?= ppc64le
else
LIBARCH ?= $(LIBARCH/$(BUILDARCH))
endif
LIBARCH/i486 = i386
LIBARCH/amd64 = amd64
LIBARCH/sparc = sparc

View File

@ -58,14 +58,17 @@ define_pd_global(intx, InlineFrequencyCount, 100);
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
#define DEFAULT_STACK_RESERVED_PAGES (0)
#define MIN_STACK_YELLOW_PAGES 1
#define MIN_STACK_RED_PAGES 1
#define MIN_STACK_SHADOW_PAGES 1
#define MIN_STACK_RESERVED_PAGES (0)
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -36,4 +36,9 @@ const int StackAlignmentInBytes = 16;
// The PPC CPUs are NOT multiple-copy-atomic.
#define CPU_NOT_MULTIPLE_COPY_ATOMIC
#if defined(COMPILER2) && defined(AIX)
// Include Transactional Memory lock eliding optimization
#define INCLUDE_RTM_OPT 1
#endif
#endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP

View File

@ -44,14 +44,17 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs pas
#define DEFAULT_STACK_YELLOW_PAGES (6)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2))
#define DEFAULT_STACK_RESERVED_PAGES (0)
#define MIN_STACK_YELLOW_PAGES (1)
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES (1)
#define MIN_STACK_RESERVED_PAGES (0)
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
// Use large code-entry alignment.
define_pd_global(intx, CodeEntryAlignment, 128);

View File

@ -50,12 +50,29 @@
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
Unimplemented();
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
// There are more general problems with CDS on ppc, so I can not
// really test this. But having this instead of Unimplementd() allows
// us to pass TestOptionsWithRanges.java.
__ unimplemented();
}

View File

@ -210,12 +210,27 @@ void VM_Version::initialize() {
}
// Adjust RTM (Restricted Transactional Memory) flags.
if (!has_tcheck() && UseRTMLocking) {
if (UseRTMLocking) {
// If CPU or OS are too old:
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
// setting during arguments processing. See use_biased_locking().
// VM_Version_init() is executed after UseBiasedLocking is used
// in Thread::allocate().
vm_exit_during_initialization("RTM instructions are not available on this CPU");
if (!has_tcheck()) {
vm_exit_during_initialization("RTM instructions are not available on this CPU");
}
bool os_too_old = true;
#ifdef AIX
if (os::Aix::os_version() >= 0x0701031e) { // at least AIX 7.1.3.30
os_too_old = false;
}
#endif
#ifdef linux
// TODO: check kernel version (we currently have too old versions only)
#endif
if (os_too_old) {
vm_exit_during_initialization("RTM is not supported on this OS version.");
}
}
if (UseRTMLocking) {

View File

@ -1453,6 +1453,9 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
void LIR_Assembler::return_op(LIR_Opr result) {
if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
__ reserved_stack_check();
}
// the poll may need a register so just pick one that isn't the return register
#if defined(TIERED) && !defined(_LP64)
if (result->type_field() == LIR_OprDesc::long_type) {

View File

@ -632,7 +632,7 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
// stack frames shouldn't be much larger than max_stack elements
if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) {
if (fp() - unextended_sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) {
return false;
}

View File

@ -54,4 +54,8 @@ const int StackAlignmentInBytes = (2*wordSize);
#endif
#endif
#if defined(SOLARIS)
#define SUPPORT_RESERVED_STACK_AREA
#endif
#endif // CPU_SPARC_VM_GLOBALDEFINITIONS_SPARC_HPP

View File

@ -54,6 +54,7 @@ define_pd_global(intx, InlineSmallCode, 1500);
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_RESERVED_PAGES (SOLARIS_ONLY(1) NOT_SOLARIS(0))
#ifdef _LP64
// Stack slots are 2X larger in LP64 than in the 32 bit VM.
@ -69,10 +70,12 @@ define_pd_global(intx, VMThreadStackSize, 512);
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
#define MIN_STACK_RESERVED_PAGES (0)
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -1140,6 +1140,19 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
// save result (push state before jvmti call and pop it afterwards) and notify jvmti
notify_method_exit(false, state, NotifyJVMTI);
if (StackReservedPages > 0) {
// testing if Stack Reserved Area needs to be re-enabled
Label no_reserved_zone_enabling;
ld_ptr(G2_thread, JavaThread::reserved_stack_activation_offset(), G3_scratch);
cmp_and_brx_short(SP, G3_scratch, Assembler::lessUnsigned, Assembler::pt, no_reserved_zone_enabling);
call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), G2_thread);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError), G2_thread);
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
verify_thread();

View File

@ -3601,6 +3601,24 @@ void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp,
}
}
void MacroAssembler::reserved_stack_check() {
// testing if reserved zone needs to be enabled
Label no_reserved_zone_enabling;
ld_ptr(G2_thread, JavaThread::reserved_stack_activation_offset(), G4_scratch);
cmp_and_brx_short(SP, G4_scratch, Assembler::lessUnsigned, Assembler::pt, no_reserved_zone_enabling);
call_VM_leaf(L0, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), G2_thread);
AddressLiteral stub(StubRoutines::throw_delayed_StackOverflowError_entry());
jump_to(stub, G4_scratch);
delayed()->restore();
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
///////////////////////////////////////////////////////////////////////////////////
#if INCLUDE_ALL_GCS

View File

@ -1422,6 +1422,9 @@ public:
// stack overflow + shadow pages. Clobbers tsp and scratch registers.
void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch);
// Check for reserved stack access in method being exited (for JIT)
void reserved_stack_check();
virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset);
void verify_tlab();

View File

@ -1294,6 +1294,10 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ verify_thread();
if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
__ reserved_stack_check();
}
// If this does safepoint polling, then do it here
if(do_polling() && ra_->C->is_method_compilation()) {
AddressLiteral polling_page(os::get_polling_page());

View File

@ -5355,7 +5355,12 @@ class StubGenerator: public StubCodeGenerator {
#endif // COMPILER2 !=> _LP64
// Build this early so it's available for the interpreter.
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
StubRoutines::_throw_delayed_StackOverflowError_entry =
generate_throw_exception("delayed StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError));
if (UseCRC32Intrinsics) {
// set table address before stub generation which use it

View File

@ -35,7 +35,10 @@ const char* VM_Version::_features_str = "";
unsigned int VM_Version::_L2_data_cache_line_size = 0;
void VM_Version::initialize() {
_features = determine_features();
assert(_features != VM_Version::unknown_m, "System pre-initialization is not complete.");
guarantee(VM_Version::has_v9(), "only SPARC v9 is supported");
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
PrefetchFieldsAhead = prefetch_fields_ahead();
@ -60,8 +63,6 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1);
}
guarantee(VM_Version::has_v9(), "only SPARC v9 is supported");
UseSSE = 0; // Only on x86 and x64
_supports_cx8 = has_v9();

View File

@ -127,6 +127,8 @@ public:
// Initialization
static void initialize();
static void init_before_ergo() { _features = determine_features(); }
// Instruction support
static bool has_v8() { return (_features & v8_instructions_m) != 0; }
static bool has_v9() { return (_features & v9_instructions_m) != 0; }

View File

@ -518,6 +518,10 @@ void LIR_Assembler::return_op(LIR_Opr result) {
// Pop the stack before the safepoint code
__ remove_frame(initial_frame_size_in_bytes());
if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
__ reserved_stack_check();
}
bool result_is_oop = result->is_valid() ? result->is_oop() : false;
// Note: we do not need to round double result; float result has the right precision

View File

@ -57,4 +57,8 @@ const int StackAlignmentInBytes = 16;
#define INCLUDE_RTM_OPT 1
#endif
#if defined(LINUX) || defined(SOLARIS) || defined(__APPLE__)
#define SUPPORT_RESERVED_STACK_AREA
#endif
#endif // CPU_X86_VM_GLOBALDEFINITIONS_X86_HPP

View File

@ -57,9 +57,11 @@ define_pd_global(intx, InlineSmallCode, 1000);
#define DEFAULT_STACK_YELLOW_PAGES (NOT_WINDOWS(2) WINDOWS_ONLY(3))
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_RESERVED_PAGES (NOT_WINDOWS(1) WINDOWS_ONLY(0))
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_RESERVED_PAGES (0)
#ifdef AMD64
// Very large C++ stack frames using solaris-amd64 optimized builds
@ -76,6 +78,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -1023,6 +1023,25 @@ void InterpreterMacroAssembler::remove_activation(
// get sender sp
movptr(rbx,
Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize));
if (StackReservedPages > 0) {
// testing if reserved zone needs to be re-enabled
Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
Label no_reserved_zone_enabling;
NOT_LP64(get_thread(rthread);)
cmpptr(rbx, Address(rthread, JavaThread::reserved_stack_activation_offset()));
jcc(Assembler::lessEqual, no_reserved_zone_enabling);
call_VM_leaf(
CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
push(rthread);
call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_delayed_StackOverflowError));
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
leave(); // remove frame anchor
pop(ret_addr); // get return address
mov(rsp, rbx); // set sp to sender sp

View File

@ -1067,6 +1067,22 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) {
}
}
void MacroAssembler::reserved_stack_check() {
// testing if reserved zone needs to be enabled
Label no_reserved_zone_enabling;
Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread);
NOT_LP64(get_thread(rsi);)
cmpptr(rsp, Address(thread, JavaThread::reserved_stack_activation_offset()));
jcc(Assembler::below, no_reserved_zone_enabling);
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), thread);
jump(RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()));
should_not_reach_here();
bind(no_reserved_zone_enabling);
}
int MacroAssembler::biased_locking_enter(Register lock_reg,
Register obj_reg,
Register swap_reg,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -641,6 +641,9 @@ class MacroAssembler: public Assembler {
// stack overflow + shadow pages. Also, clobbers tmp
void bang_stack_size(Register size, Register tmp);
// Check for reserved stack access in method being exited (for JIT)
void reserved_stack_check();
virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp,
int offset);

View File

@ -3290,7 +3290,10 @@ class StubGenerator: public StubCodeGenerator {
CAST_FROM_FN_PTR(address, SharedRuntime::d2l));
// Build this early so it's available for the interpreter
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
StubRoutines::_throw_delayed_StackOverflowError_entry = generate_throw_exception("delayed StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError));
if (UseCRC32Intrinsics) {
// set table address before stub generation which use it

View File

@ -4410,6 +4410,11 @@ class StubGenerator: public StubCodeGenerator {
CAST_FROM_FN_PTR(address,
SharedRuntime::
throw_StackOverflowError));
StubRoutines::_throw_delayed_StackOverflowError_entry =
generate_throw_exception("delayed StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address,
SharedRuntime::
throw_delayed_StackOverflowError));
if (UseCRC32Intrinsics) {
// set table address before stub generation which use it
StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table;

View File

@ -541,8 +541,8 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
__ subptr(rax, stack_size);
// Use the maximum number of pages we might bang.
const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages :
(StackRedPages+StackYellowPages);
const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages+StackReservedPages) ? StackShadowPages :
(StackRedPages+StackYellowPages+StackReservedPages);
// add in the red and yellow zone sizes
__ addptr(rax, max_pages * page_size);

View File

@ -670,17 +670,16 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile *C = ra_->C;
MacroAssembler _masm(&cbuf);
if (C->max_vector_size() > 16) {
// Clear upper bits of YMM registers when current compiled code uses
// wide vectors to avoid AVX <-> SSE transition penalty during call.
MacroAssembler masm(&cbuf);
masm.vzeroupper();
_masm.vzeroupper();
}
// If method set FPU control word, restore to standard control word
if (C->in_24_bit_fp_mode()) {
MacroAssembler masm(&cbuf);
masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
_masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
}
int framesize = C->frame_size_in_bytes();
@ -702,6 +701,10 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
emit_opcode(cbuf, 0x58 | EBP_enc);
if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
__ reserved_stack_check();
}
if (do_polling() && C->is_method_compilation()) {
cbuf.relocate(cbuf.insts_end(), relocInfo::poll_return_type, 0);
emit_opcode(cbuf,0x85);
@ -729,6 +732,7 @@ uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
} else {
size += framesize ? 3 : 0;
}
size += 64; // added to support ReservedStackAccess
return size;
}

View File

@ -953,10 +953,11 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
Compile* C = ra_->C;
MacroAssembler _masm(&cbuf);
if (C->max_vector_size() > 16) {
// Clear upper bits of YMM registers when current compiled code uses
// wide vectors to avoid AVX <-> SSE transition penalty during call.
MacroAssembler _masm(&cbuf);
__ vzeroupper();
}
@ -984,6 +985,10 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
// popq rbp
emit_opcode(cbuf, 0x58 | RBP_enc);
if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
__ reserved_stack_check();
}
if (do_polling() && C->is_method_compilation()) {
MacroAssembler _masm(&cbuf);
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);

View File

@ -48,14 +48,17 @@ define_pd_global(intx, InlineSmallCode, 1000 );
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (5 LP64_ONLY(+1) DEBUG_ONLY(+3))
#define DEFAULT_STACK_RESERVED_PAGES (0)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
#define MIN_STACK_RESERVED_PAGES (0)
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -170,7 +170,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
* @return flags of this method
*/
private int getFlags() {
return UNSAFE.getByte(metaspaceMethod + config().methodFlagsOffset);
return UNSAFE.getShort(metaspaceMethod + config().methodFlagsOffset);
}
/**

View File

@ -1244,7 +1244,7 @@ public class HotSpotVMConfig {
@HotSpotVMField(name = "Method::_access_flags", type = "AccessFlags", get = HotSpotVMField.Type.OFFSET) @Stable public int methodAccessFlagsOffset;
@HotSpotVMField(name = "Method::_constMethod", type = "ConstMethod*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodConstMethodOffset;
@HotSpotVMField(name = "Method::_intrinsic_id", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int methodIntrinsicIdOffset;
@HotSpotVMField(name = "Method::_flags", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodFlagsOffset;
@HotSpotVMField(name = "Method::_flags", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int methodFlagsOffset;
@HotSpotVMField(name = "Method::_vtable_index", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodVtableIndexOffset;
@HotSpotVMConstant(name = "Method::_jfr_towrite") @Stable public int methodFlagsJfrTowrite;

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015, 2015 SAP AG. All rights reserved.
* 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 "libodm_aix.hpp"
#include "misc_aix.hpp"
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include "runtime/arguments.hpp"
dynamicOdm::dynamicOdm() {
const char *libodmname = "/usr/lib/libodm.a(shr_64.o)";
_libhandle = dlopen(libodmname, RTLD_MEMBER | RTLD_NOW);
if (!_libhandle) {
trcVerbose("Couldn't open %s", libodmname);
return;
}
_odm_initialize = (fun_odm_initialize )dlsym(_libhandle, "odm_initialize" );
_odm_set_path = (fun_odm_set_path )dlsym(_libhandle, "odm_set_path" );
_odm_mount_class = (fun_odm_mount_class)dlsym(_libhandle, "odm_mount_class");
_odm_get_obj = (fun_odm_get_obj )dlsym(_libhandle, "odm_get_obj" );
_odm_terminate = (fun_odm_terminate )dlsym(_libhandle, "odm_terminate" );
if (!_odm_initialize || !_odm_set_path || !_odm_mount_class || !_odm_get_obj || !_odm_terminate) {
trcVerbose("Couldn't find all required odm symbols from %s", libodmname);
dlclose(_libhandle);
_libhandle = NULL;
return;
}
}
dynamicOdm::~dynamicOdm() {
if (_libhandle) { dlclose(_libhandle); }
}
void odmWrapper::clean_data() { if (_data) { free(_data); _data = NULL; } }
int odmWrapper::class_offset(char *field, bool is_aix_5)
{
assert(has_class(), "initialization");
for (int i = 0; i < odm_class()->nelem; i++) {
if (strcmp(odm_class()->elem[i].elemname, field) == 0) {
int offset = odm_class()->elem[i].offset;
if (is_aix_5) { offset += LINK_VAL_OFFSET; }
return offset;
}
}
return -1;
}
void odmWrapper::determine_os_kernel_version(uint32_t* p_ver) {
int major_aix_version = ((*p_ver) >> 24) & 0xFF,
minor_aix_version = ((*p_ver) >> 16) & 0xFF;
assert(*p_ver, "must be initialized");
odmWrapper odm("product", "/usr/lib/objrepos"); // could also use "lpp"
if (!odm.has_class()) {
trcVerbose("try_determine_os_kernel_version: odm init problem");
return;
}
int voff, roff, moff, foff;
bool is_aix_5 = (major_aix_version == 5);
voff = odm.class_offset("ver", is_aix_5);
roff = odm.class_offset("rel", is_aix_5);
moff = odm.class_offset("mod", is_aix_5);
foff = odm.class_offset("fix", is_aix_5);
if (voff == -1 || roff == -1 || moff == -1 || foff == -1) {
trcVerbose("try_determine_os_kernel_version: could not get offsets");
return;
}
if (!odm.retrieve_obj("name='bos.mp64'")) {
trcVerbose("try_determine_os_kernel_version: odm_get_obj failed");
return;
}
int version, release, modification, fix_level;
do {
version = odm.read_short(voff);
release = odm.read_short(roff);
modification = odm.read_short(moff);
fix_level = odm.read_short(foff);
trcVerbose("odm found version: %d.%d.%d.%d", version, release, modification, fix_level);
if (version >> 8 != 0 || release >> 8 != 0 || modification >> 8 != 0 || fix_level >> 8 != 0) {
trcVerbose("8 bit numbers expected");
return;
}
} while (odm.retrieve_obj());
if (version != major_aix_version || release != minor_aix_version) {
trcVerbose("version determined by odm does not match uname");
return;
}
*p_ver = version << 24 | release << 16 | modification << 8 | fix_level;
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015, 2015 SAP AG. All rights reserved.
* 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.
*
*/
// Encapsulates the libodm library and provides more convenient interfaces.
#ifndef OS_AIX_VM_LIBODM_AIX_HPP
#define OS_AIX_VM_LIBODM_AIX_HPP
#include <odmi.h>
// The purpose of this code is to dynamically load the libodm library
// instead of statically linking against it. The library is AIX-specific.
// It only exists on AIX, not on PASE. In order to share binaries
// between AIX and PASE, we can't directly link against it.
typedef int (*fun_odm_initialize )(void);
typedef char* (*fun_odm_set_path )(char*);
typedef CLASS_SYMBOL (*fun_odm_mount_class)(char*);
typedef void* (*fun_odm_get_obj )(CLASS_SYMBOL, char*, void*, int);
typedef int (*fun_odm_terminate )(void);
class dynamicOdm {
void *_libhandle;
protected:
fun_odm_initialize _odm_initialize;
fun_odm_set_path _odm_set_path;
fun_odm_mount_class _odm_mount_class;
fun_odm_get_obj _odm_get_obj;
fun_odm_terminate _odm_terminate;
public:
dynamicOdm();
~dynamicOdm();
bool odm_loaded() {return _libhandle != NULL; }
};
// We provide a more convenient interface for odm access and
// especially to determine the exact AIX kernel version.
class odmWrapper : private dynamicOdm {
CLASS_SYMBOL _odm_class;
char *_data;
bool _initialized;
void clean_data();
public:
// Make sure everything gets initialized and cleaned up properly.
explicit odmWrapper(char* odm_class_name, char* odm_path = NULL) : _odm_class((CLASS_SYMBOL)-1),
_data(NULL), _initialized(false) {
if (!odm_loaded()) { return; }
_initialized = ((*_odm_initialize)() != -1);
if (_initialized) {
if (odm_path) { (*_odm_set_path)(odm_path); }
_odm_class = (*_odm_mount_class)(odm_class_name);
}
}
~odmWrapper() {
if (_initialized) { (*_odm_terminate)(); clean_data(); }
}
CLASS_SYMBOL odm_class() { return _odm_class; }
bool has_class() { return odm_class() != (CLASS_SYMBOL)-1; }
int class_offset(char *field, bool is_aix_5);
char* data() { return _data; }
char* retrieve_obj(char* name = NULL) {
clean_data();
char *cnp = (char*)(void*)(*_odm_get_obj)(odm_class(), name, NULL, (name == NULL) ? ODM_NEXT : ODM_FIRST);
if (cnp != (char*)-1) { _data = cnp; }
return data();
}
int read_short(int offs) {
short *addr = (short*)(data() + offs);
return *addr;
}
// Determine the exact AIX kernel version as 4 byte value.
// The high order 2 bytes must be initialized already. They can be determined by uname.
static void determine_os_kernel_version(uint32_t* p_ver);
};
#endif // OS_AIX_VM_LIBODM_AIX_HPP

View File

@ -38,6 +38,7 @@
#include "jvm_aix.h"
#include "libo4.hpp"
#include "libperfstat_aix.hpp"
#include "libodm_aix.hpp"
#include "loadlib_aix.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
@ -197,9 +198,13 @@ int os::Aix::_page_size = -1;
// -1 = uninitialized, 0 if AIX, 1 if OS/400 pase
int os::Aix::_on_pase = -1;
// -1 = uninitialized, otherwise os version in the form 0xMMmm - MM:major, mm:minor
// E.g. 0x0601 for AIX 6.1 or 0x0504 for OS/400 V5R4
int os::Aix::_os_version = -1;
// 0 = uninitialized, otherwise 32 bit number:
// 0xVVRRTTSS
// VV - major version
// RR - minor version
// TT - tech level, if known, 0 otherwise
// SS - service pack, if known, 0 otherwise
uint32_t os::Aix::_os_version = 0;
int os::Aix::_stack_page_size = -1;
@ -358,7 +363,7 @@ static char cpu_arch[] = "ppc64";
// Wrap the function "vmgetinfo" which is not available on older OS releases.
static int checked_vmgetinfo(void *out, int command, int arg) {
if (os::Aix::on_pase() && os::Aix::os_version() < 0x0601) {
if (os::Aix::on_pase() && os::Aix::os_version_short() < 0x0601) {
guarantee(false, "cannot call vmgetinfo on AS/400 older than V6R1");
}
return ::vmgetinfo(out, command, arg);
@ -367,7 +372,7 @@ static int checked_vmgetinfo(void *out, int command, int arg) {
// Given an address, returns the size of the page backing that address.
size_t os::Aix::query_pagesize(void* addr) {
if (os::Aix::on_pase() && os::Aix::os_version() < 0x0601) {
if (os::Aix::on_pase() && os::Aix::os_version_short() < 0x0601) {
// AS/400 older than V6R1: no vmgetinfo here, default to 4K
return SIZE_4K;
}
@ -1211,7 +1216,7 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core, void* siginfo, void* context) {
void os::abort(bool dump_core, void* siginfo, const void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT
@ -1491,6 +1496,10 @@ void os::print_os_info(outputStream* st) {
st->print(name.machine);
st->cr();
uint32_t ver = os::Aix::os_version();
st->print_cr("AIX kernel version %u.%u.%u.%u",
(ver >> 24) & 0xFF, (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
// rlimit
st->print("rlimit:");
struct rlimit rlim;
@ -3806,7 +3815,7 @@ void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Aix::ucontext_get_pc((ucontext_t *) context.ucontext());
_epc = os::Aix::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread.
guarantee(thread->is_VM_thread(), "can only be called for VMThread");
@ -4255,7 +4264,7 @@ bool os::Aix::is_primordial_thread() {
// one of Aix::on_pase(), Aix::os_version() static
void os::Aix::initialize_os_info() {
assert(_on_pase == -1 && _os_version == -1, "already called.");
assert(_on_pase == -1 && _os_version == 0, "already called.");
struct utsname uts;
memset(&uts, 0, sizeof(uts));
@ -4271,28 +4280,34 @@ void os::Aix::initialize_os_info() {
assert(major > 0, "invalid OS version");
const int minor = atoi(uts.release);
assert(minor > 0, "invalid OS release");
_os_version = (major << 8) | minor;
_os_version = (major << 24) | (minor << 16);
char ver_str[20] = {0};
char *name_str = "unknown OS";
if (strcmp(uts.sysname, "OS400") == 0) {
// We run on AS/400 PASE. We do not support versions older than V5R4M0.
_on_pase = 1;
if (_os_version < 0x0504) {
if (os_version_short() < 0x0504) {
trcVerbose("OS/400 releases older than V5R4M0 not supported.");
assert(false, "OS/400 release too old.");
} else {
trcVerbose("We run on OS/400 (pase) V%dR%d", major, minor);
}
name_str = "OS/400 (pase)";
jio_snprintf(ver_str, sizeof(ver_str), "%u.%u", major, minor);
} else if (strcmp(uts.sysname, "AIX") == 0) {
// We run on AIX. We do not support versions older than AIX 5.3.
_on_pase = 0;
if (_os_version < 0x0503) {
// Determine detailed AIX version: Version, Release, Modification, Fix Level.
odmWrapper::determine_os_kernel_version(&_os_version);
if (os_version_short() < 0x0503) {
trcVerbose("AIX release older than AIX 5.3 not supported.");
assert(false, "AIX release too old.");
} else {
trcVerbose("We run on AIX %d.%d", major, minor);
}
name_str = "AIX";
jio_snprintf(ver_str, sizeof(ver_str), "%u.%u.%u.%u",
major, minor, (_os_version >> 8) & 0xFF, _os_version & 0xFF);
} else {
assert(false, "unknown OS");
assert(false, name_str);
}
trcVerbose("We run on %s %s", name_str, ver_str);
}
guarantee(_on_pase != -1 && _os_version, "Could not determine AIX/OS400 release");
@ -4357,7 +4372,7 @@ void os::Aix::scan_environment() {
p = ::getenv("LDR_CNTRL");
trcVerbose("LDR_CNTRL=%s.", p ? p : "<unset>");
if (os::Aix::on_pase() && os::Aix::os_version() == 0x0701) {
if (os::Aix::on_pase() && os::Aix::os_version_short() == 0x0701) {
if (p && ::strstr(p, "TEXTPSIZE")) {
trcVerbose("*** WARNING - LDR_CNTRL contains TEXTPSIZE. "
"you may experience hangs or crashes on OS/400 V7R1.");
@ -5016,7 +5031,7 @@ void TestReserveMemorySpecial_test() {
}
#endif
bool os::start_debugging(char *buf, int buflen) {
bool os::start_debugging(char *buf, int buflen) {
int len = (int)strlen(buf);
char *p = &buf[len];

View File

@ -55,15 +55,12 @@ class Aix {
// -1 = uninitialized, 0 = AIX, 1 = OS/400 (PASE)
static int _on_pase;
// -1 = uninitialized, otherwise 16 bit number:
// 0 = uninitialized, otherwise 16 bit number:
// lower 8 bit - minor version
// higher 8 bit - major version
// For AIX, e.g. 0x0601 for AIX 6.1
// for OS/400 e.g. 0x0504 for OS/400 V5R4
static int _os_version;
// 4 Byte kernel version: Version, Release, Tech Level, Service Pack.
static unsigned int _os_kernel_version;
static uint32_t _os_version;
// -1 = uninitialized,
// 0 - SPEC1170 not requested (XPG_SUS_ENV is OFF or not set)
@ -126,8 +123,8 @@ class Aix {
static int vm_default_page_size(void ) { return 8*K; }
static address ucontext_get_pc(const ucontext_t* uc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static intptr_t* ucontext_get_fp(ucontext_t* uc);
static intptr_t* ucontext_get_sp(const ucontext_t* uc);
static intptr_t* ucontext_get_fp(const ucontext_t* uc);
// Set PC into context. Needed for continuation after signal.
static void ucontext_set_pc(ucontext_t* uc, address pc);
@ -175,32 +172,31 @@ class Aix {
return _on_pase ? false : true;
}
// -1 = uninitialized, otherwise 16 bit number:
// Get 4 byte AIX kernel version number:
// highest 2 bytes: Version, Release
// if available: lowest 2 bytes: Tech Level, Service Pack.
static uint32_t os_version() {
assert(_os_version != 0, "not initialized");
return _os_version;
}
// 0 = uninitialized, otherwise 16 bit number:
// lower 8 bit - minor version
// higher 8 bit - major version
// For AIX, e.g. 0x0601 for AIX 6.1
// for OS/400 e.g. 0x0504 for OS/400 V5R4
static int os_version () {
assert(_os_version != -1, "not initialized");
return _os_version;
}
// Get 4 byte AIX kernel version number:
// highest 2 bytes: Version, Release
// if available: lowest 2 bytes: Tech Level, Service Pack.
static unsigned int os_kernel_version() {
if (_os_kernel_version) return _os_kernel_version;
return os_version() << 16;
static int os_version_short() {
return os_version() >> 16;
}
// Convenience method: returns true if running on PASE V5R4 or older.
static bool on_pase_V5R4_or_older() {
return on_pase() && os_version() <= 0x0504;
return on_pase() && os_version_short() <= 0x0504;
}
// Convenience method: returns true if running on AIX 5.3 or older.
static bool on_aix_53_or_older() {
return on_aix() && os_version() <= 0x0503;
return on_aix() && os_version_short() <= 0x0503;
}
// Returns true if we run in SPEC1170 compliant mode (XPG_SUS_ENV=ON).

View File

@ -1077,7 +1077,7 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core, void* siginfo, void* context) {
void os::abort(bool dump_core, void* siginfo, const void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT
@ -3497,7 +3497,7 @@ jint os::init_2(void) {
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
os::Bsd::min_stack_allowed = MAX2(os::Bsd::min_stack_allowed,
(size_t)(StackYellowPages+StackRedPages+StackShadowPages+
(size_t)(StackReservedPages+StackYellowPages+StackRedPages+StackShadowPages+
2*BytesPerWord COMPILER2_PRESENT(+1)) * Bsd::page_size());
size_t threadStackSizeInBytes = ThreadStackSize * K;
@ -3643,7 +3643,7 @@ void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Bsd::ucontext_get_pc((ucontext_t *) context.ucontext());
_epc = os::Bsd::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread
guarantee(thread->is_VM_thread(), "can only be called for VMThread");

View File

@ -86,19 +86,21 @@ class Bsd {
static int page_size(void) { return _page_size; }
static void set_page_size(int val) { _page_size = val; }
static address ucontext_get_pc(ucontext_t* uc);
static address ucontext_get_pc(const ucontext_t* uc);
static void ucontext_set_pc(ucontext_t* uc, address pc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static intptr_t* ucontext_get_fp(ucontext_t* uc);
static intptr_t* ucontext_get_sp(const ucontext_t* uc);
static intptr_t* ucontext_get_fp(const ucontext_t* uc);
// For Analyzer Forte AsyncGetCallTrace profiling support:
//
// This interface should be declared in os_bsd_i486.hpp, but
// that file provides extensions to the os class and not the
// Bsd class.
static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
static ExtendedPC fetch_frame_from_ucontext(Thread* thread, const ucontext_t* uc,
intptr_t** ret_sp, intptr_t** ret_fp);
static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_bsd_signal, harmlessly.
static bool signal_handlers_are_installed;

View File

@ -1341,7 +1341,7 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core, void* siginfo, void* context) {
void os::abort(bool dump_core, void* siginfo, const void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT
@ -1733,7 +1733,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
#if defined(VM_LITTLE_ENDIAN)
{EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2LSB, (char*)"Power PC 64"},
#else
{EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
{EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64 LE"},
#endif
{EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
{EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"},
@ -1861,8 +1861,8 @@ void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf,
JavaThread *jt = Threads::first();
while (jt) {
if (!jt->stack_guard_zone_unused() && // Stack not yet fully initialized
jt->stack_yellow_zone_enabled()) { // No pending stack overflow exceptions
if (!jt->stack_guard_zone_unused() && // Stack not yet fully initialized
jt->stack_guards_enabled()) { // No pending stack overflow exceptions
if (!os::guard_memory((char *) jt->stack_red_zone_base() - jt->stack_red_zone_size(),
jt->stack_yellow_zone_size() + jt->stack_red_zone_size())) {
warning("Attempt to reguard stack yellow zone failed.");
@ -2177,6 +2177,8 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
const char* search_string = "model name";
#elif defined(SPARC)
const char* search_string = "cpu";
#elif defined(PPC64)
const char* search_string = "cpu";
#else
const char* search_string = "Processor";
#endif
@ -4603,6 +4605,11 @@ void os::init(void) {
if (vm_page_size() > (int)Linux::vm_default_page_size()) {
StackYellowPages = 1;
StackRedPages = 1;
#if defined(IA32) || defined(IA64)
StackReservedPages = 1;
#else
StackReservedPages = 0;
#endif
StackShadowPages = round_to((StackShadowPages*Linux::vm_default_page_size()), vm_page_size()) / vm_page_size();
}
@ -4664,7 +4671,7 @@ jint os::init_2(void) {
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
os::Linux::min_stack_allowed = MAX2(os::Linux::min_stack_allowed,
(size_t)(StackYellowPages+StackRedPages+StackShadowPages) * Linux::page_size() +
(size_t)(StackReservedPages+StackYellowPages+StackRedPages+StackShadowPages) * Linux::page_size() +
(2*BytesPerWord COMPILER2_PRESENT(+1)) * Linux::vm_default_page_size());
size_t threadStackSizeInBytes = ThreadStackSize * K;
@ -4846,7 +4853,7 @@ void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Linux::ucontext_get_pc((ucontext_t *) context.ucontext());
_epc = os::Linux::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread
guarantee(thread->is_VM_thread(), "can only be called for VMThread");

View File

@ -123,19 +123,21 @@ class Linux {
static int vm_default_page_size(void) { return _vm_default_page_size; }
static address ucontext_get_pc(ucontext_t* uc);
static address ucontext_get_pc(const ucontext_t* uc);
static void ucontext_set_pc(ucontext_t* uc, address pc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static intptr_t* ucontext_get_fp(ucontext_t* uc);
static intptr_t* ucontext_get_sp(const ucontext_t* uc);
static intptr_t* ucontext_get_fp(const ucontext_t* uc);
// For Analyzer Forte AsyncGetCallTrace profiling support:
//
// This interface should be declared in os_linux_i486.hpp, but
// that file provides extensions to the os class and not the
// Linux class.
static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
static ExtendedPC fetch_frame_from_ucontext(Thread* thread, const ucontext_t* uc,
intptr_t** ret_sp, intptr_t** ret_fp);
static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_linux_signal, harmlessly.
static bool signal_handlers_are_installed;

View File

@ -736,12 +736,12 @@ bool os::Posix::is_valid_signal(int sig) {
}
// Returns:
// "invalid (<num>)" for an invalid signal number
// NULL for an invalid signal number
// "SIG<num>" for a valid but unknown signal number
// signal name otherwise.
const char* os::exception_name(int sig, char* buf, size_t size) {
if (!os::Posix::is_valid_signal(sig)) {
jio_snprintf(buf, size, "invalid (%d)", sig);
return NULL;
}
const char* const name = os::Posix::get_signal_name(sig, buf, size);
if (strcmp(name, "UNKNOWN") == 0) {
@ -1031,7 +1031,7 @@ int os::Posix::unblock_thread_signal_mask(const sigset_t *set) {
return pthread_sigmask(SIG_UNBLOCK, set, NULL);
}
address os::Posix::ucontext_get_pc(ucontext_t* ctx) {
address os::Posix::ucontext_get_pc(const ucontext_t* ctx) {
#ifdef TARGET_OS_FAMILY_linux
return Linux::ucontext_get_pc(ctx);
#elif defined(TARGET_OS_FAMILY_solaris)

View File

@ -76,7 +76,7 @@ public:
// A POSIX conform, platform-independend siginfo print routine.
static void print_siginfo_brief(outputStream* os, const siginfo_t* si);
static address ucontext_get_pc(ucontext_t* ctx);
static address ucontext_get_pc(const ucontext_t* ctx);
// Set PC into context. Needed for continuation after signal.
static void ucontext_set_pc(ucontext_t* ctx, address pc);
};

View File

@ -1380,7 +1380,7 @@ void os::shutdown() {
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
void os::abort(bool dump_core, void* siginfo, void* context) {
void os::abort(bool dump_core, void* siginfo, const void* context) {
os::shutdown();
if (dump_core) {
#ifndef PRODUCT
@ -3736,7 +3736,7 @@ void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) {
Thread* thread = context.thread();
OSThread* osthread = thread->osthread();
if (osthread->ucontext() != NULL) {
_epc = os::Solaris::ucontext_get_pc((ucontext_t *) context.ucontext());
_epc = os::Solaris::ucontext_get_pc((const ucontext_t *) context.ucontext());
} else {
// NULL context is unexpected, double-check this is the VMThread
guarantee(thread->is_VM_thread(), "can only be called for VMThread");
@ -4382,6 +4382,7 @@ void os::init(void) {
if (vm_page_size() > 8*K) {
StackYellowPages = 1;
StackRedPages = 1;
StackReservedPages = 1;
StackShadowPages = round_to((StackShadowPages*8*K), vm_page_size()) / vm_page_size();
}
}
@ -4438,7 +4439,7 @@ jint os::init_2(void) {
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
os::Solaris::min_stack_allowed = MAX2(os::Solaris::min_stack_allowed,
(size_t)(StackYellowPages+StackRedPages+StackShadowPages+
(size_t)(StackReservedPages+StackYellowPages+StackRedPages+StackShadowPages+
2*BytesPerWord COMPILER2_PRESENT(+1)) * page_size);
size_t threadStackSizeInBytes = ThreadStackSize * K;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -130,15 +130,15 @@ class Solaris {
static address handler_start, handler_end; // start and end pc of thr_sighndlrinfo
static bool valid_stack_address(Thread* thread, address sp);
static bool valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect);
static ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
ucontext_t* uc);
static bool valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect);
static const ucontext_t* get_valid_uc_in_signal_handler(Thread* thread,
const ucontext_t* uc);
static ExtendedPC ucontext_get_ExtendedPC(ucontext_t* uc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static ExtendedPC ucontext_get_ExtendedPC(const ucontext_t* uc);
static intptr_t* ucontext_get_sp(const ucontext_t* uc);
// ucontext_get_fp() is only used by Solaris X86 (see note below)
static intptr_t* ucontext_get_fp(ucontext_t* uc);
static address ucontext_get_pc(ucontext_t* uc);
static intptr_t* ucontext_get_fp(const ucontext_t* uc);
static address ucontext_get_pc(const ucontext_t* uc);
static void ucontext_set_pc(ucontext_t* uc, address pc);
// For Analyzer Forte AsyncGetCallTrace profiling support:
@ -147,9 +147,11 @@ class Solaris {
// We should have different declarations of this interface in
// os_solaris_i486.hpp and os_solaris_sparc.hpp, but that file
// provides extensions to the os class and not the Solaris class.
static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
static ExtendedPC fetch_frame_from_ucontext(Thread* thread, const ucontext_t* uc,
intptr_t** ret_sp, intptr_t** ret_fp);
static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
static void hotspot_sigmask(Thread* thread);
// SR_handler

View File

@ -1028,7 +1028,7 @@ void os::check_dump_limit(char* buffer, size_t buffsz) {
VMError::record_coredump_status(buffer, status);
}
void os::abort(bool dump_core, void* siginfo, void* context) {
void os::abort(bool dump_core, void* siginfo, const void* context) {
HINSTANCE dbghelp;
EXCEPTION_POINTERS ep;
MINIDUMP_EXCEPTION_INFORMATION mei;
@ -2374,6 +2374,39 @@ static inline void report_error(Thread* t, DWORD exception_code,
// somewhere where we can find it in the minidump.
}
bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread,
struct _EXCEPTION_POINTERS* exceptionInfo, address pc, frame* fr) {
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
address addr = (address) exceptionRecord->ExceptionInformation[1];
if (Interpreter::contains(pc)) {
*fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// more complex code with compiled code
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling
return false;
} else {
*fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);
// in compiled code, the stack banging is performed just after the return pc
// has been pushed on the stack
*fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp()));
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
//-----------------------------------------------------------------------------
LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH;
@ -2550,7 +2583,16 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW));
}
#endif
if (thread->stack_yellow_zone_enabled()) {
if (thread->stack_guards_enabled()) {
if (_thread_in_Java) {
frame fr;
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
address addr = (address) exceptionRecord->ExceptionInformation[1];
if (os::win32::get_frame_at_stack_banging_point(thread, exceptionInfo, pc, &fr)) {
assert(fr.is_java_frame(), "Must be a Java frame");
SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
}
}
// Yellow zone violation. The o/s has unprotected the first yellow
// zone page for us. Note: must call disable_stack_yellow_zone to
// update the enabled status, even if the zone contains only one page.
@ -5529,8 +5571,6 @@ bool os::start_debugging(char *buf, int buflen) {
return yes;
}
#ifndef JDK6_OR_EARLIER
void os::Kernel32Dll::initialize() {
initializeCommon();
}
@ -5705,261 +5745,6 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name,
return agent_entry_name;
}
#else
// Kernel32 API
typedef BOOL (WINAPI* SwitchToThread_Fn)(void);
typedef HANDLE (WINAPI* CreateToolhelp32Snapshot_Fn)(DWORD, DWORD);
typedef BOOL (WINAPI* Module32First_Fn)(HANDLE, LPMODULEENTRY32);
typedef BOOL (WINAPI* Module32Next_Fn)(HANDLE, LPMODULEENTRY32);
typedef void (WINAPI* GetNativeSystemInfo_Fn)(LPSYSTEM_INFO);
SwitchToThread_Fn os::Kernel32Dll::_SwitchToThread = NULL;
CreateToolhelp32Snapshot_Fn os::Kernel32Dll::_CreateToolhelp32Snapshot = NULL;
Module32First_Fn os::Kernel32Dll::_Module32First = NULL;
Module32Next_Fn os::Kernel32Dll::_Module32Next = NULL;
GetNativeSystemInfo_Fn os::Kernel32Dll::_GetNativeSystemInfo = NULL;
void os::Kernel32Dll::initialize() {
if (!initialized) {
HMODULE handle = ::GetModuleHandle("Kernel32.dll");
assert(handle != NULL, "Just check");
_SwitchToThread = (SwitchToThread_Fn)::GetProcAddress(handle, "SwitchToThread");
_CreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_Fn)
::GetProcAddress(handle, "CreateToolhelp32Snapshot");
_Module32First = (Module32First_Fn)::GetProcAddress(handle, "Module32First");
_Module32Next = (Module32Next_Fn)::GetProcAddress(handle, "Module32Next");
_GetNativeSystemInfo = (GetNativeSystemInfo_Fn)::GetProcAddress(handle, "GetNativeSystemInfo");
initializeCommon(); // resolve the functions that always need resolving
initialized = TRUE;
}
}
BOOL os::Kernel32Dll::SwitchToThread() {
assert(initialized && _SwitchToThread != NULL,
"SwitchToThreadAvailable() not yet called");
return _SwitchToThread();
}
BOOL os::Kernel32Dll::SwitchToThreadAvailable() {
if (!initialized) {
initialize();
}
return _SwitchToThread != NULL;
}
// Help tools
BOOL os::Kernel32Dll::HelpToolsAvailable() {
if (!initialized) {
initialize();
}
return _CreateToolhelp32Snapshot != NULL &&
_Module32First != NULL &&
_Module32Next != NULL;
}
HANDLE os::Kernel32Dll::CreateToolhelp32Snapshot(DWORD dwFlags,
DWORD th32ProcessId) {
assert(initialized && _CreateToolhelp32Snapshot != NULL,
"HelpToolsAvailable() not yet called");
return _CreateToolhelp32Snapshot(dwFlags, th32ProcessId);
}
BOOL os::Kernel32Dll::Module32First(HANDLE hSnapshot,LPMODULEENTRY32 lpme) {
assert(initialized && _Module32First != NULL,
"HelpToolsAvailable() not yet called");
return _Module32First(hSnapshot, lpme);
}
inline BOOL os::Kernel32Dll::Module32Next(HANDLE hSnapshot,
LPMODULEENTRY32 lpme) {
assert(initialized && _Module32Next != NULL,
"HelpToolsAvailable() not yet called");
return _Module32Next(hSnapshot, lpme);
}
BOOL os::Kernel32Dll::GetNativeSystemInfoAvailable() {
if (!initialized) {
initialize();
}
return _GetNativeSystemInfo != NULL;
}
void os::Kernel32Dll::GetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo) {
assert(initialized && _GetNativeSystemInfo != NULL,
"GetNativeSystemInfoAvailable() not yet called");
_GetNativeSystemInfo(lpSystemInfo);
}
// PSAPI API
typedef BOOL (WINAPI *EnumProcessModules_Fn)(HANDLE, HMODULE *, DWORD, LPDWORD);
typedef BOOL (WINAPI *GetModuleFileNameEx_Fn)(HANDLE, HMODULE, LPTSTR, DWORD);
typedef BOOL (WINAPI *GetModuleInformation_Fn)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
EnumProcessModules_Fn os::PSApiDll::_EnumProcessModules = NULL;
GetModuleFileNameEx_Fn os::PSApiDll::_GetModuleFileNameEx = NULL;
GetModuleInformation_Fn os::PSApiDll::_GetModuleInformation = NULL;
BOOL os::PSApiDll::initialized = FALSE;
void os::PSApiDll::initialize() {
if (!initialized) {
HMODULE handle = os::win32::load_Windows_dll("PSAPI.DLL", NULL, 0);
if (handle != NULL) {
_EnumProcessModules = (EnumProcessModules_Fn)::GetProcAddress(handle,
"EnumProcessModules");
_GetModuleFileNameEx = (GetModuleFileNameEx_Fn)::GetProcAddress(handle,
"GetModuleFileNameExA");
_GetModuleInformation = (GetModuleInformation_Fn)::GetProcAddress(handle,
"GetModuleInformation");
}
initialized = TRUE;
}
}
BOOL os::PSApiDll::EnumProcessModules(HANDLE hProcess, HMODULE *lpModule,
DWORD cb, LPDWORD lpcbNeeded) {
assert(initialized && _EnumProcessModules != NULL,
"PSApiAvailable() not yet called");
return _EnumProcessModules(hProcess, lpModule, cb, lpcbNeeded);
}
DWORD os::PSApiDll::GetModuleFileNameEx(HANDLE hProcess, HMODULE hModule,
LPTSTR lpFilename, DWORD nSize) {
assert(initialized && _GetModuleFileNameEx != NULL,
"PSApiAvailable() not yet called");
return _GetModuleFileNameEx(hProcess, hModule, lpFilename, nSize);
}
BOOL os::PSApiDll::GetModuleInformation(HANDLE hProcess, HMODULE hModule,
LPMODULEINFO lpmodinfo, DWORD cb) {
assert(initialized && _GetModuleInformation != NULL,
"PSApiAvailable() not yet called");
return _GetModuleInformation(hProcess, hModule, lpmodinfo, cb);
}
BOOL os::PSApiDll::PSApiAvailable() {
if (!initialized) {
initialize();
}
return _EnumProcessModules != NULL &&
_GetModuleFileNameEx != NULL &&
_GetModuleInformation != NULL;
}
// WinSock2 API
typedef int (PASCAL FAR* WSAStartup_Fn)(WORD, LPWSADATA);
typedef struct hostent *(PASCAL FAR *gethostbyname_Fn)(...);
WSAStartup_Fn os::WinSock2Dll::_WSAStartup = NULL;
gethostbyname_Fn os::WinSock2Dll::_gethostbyname = NULL;
BOOL os::WinSock2Dll::initialized = FALSE;
void os::WinSock2Dll::initialize() {
if (!initialized) {
HMODULE handle = os::win32::load_Windows_dll("ws2_32.dll", NULL, 0);
if (handle != NULL) {
_WSAStartup = (WSAStartup_Fn)::GetProcAddress(handle, "WSAStartup");
_gethostbyname = (gethostbyname_Fn)::GetProcAddress(handle, "gethostbyname");
}
initialized = TRUE;
}
}
BOOL os::WinSock2Dll::WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) {
assert(initialized && _WSAStartup != NULL,
"WinSock2Available() not yet called");
return _WSAStartup(wVersionRequested, lpWSAData);
}
struct hostent* os::WinSock2Dll::gethostbyname(const char *name) {
assert(initialized && _gethostbyname != NULL,
"WinSock2Available() not yet called");
return _gethostbyname(name);
}
BOOL os::WinSock2Dll::WinSock2Available() {
if (!initialized) {
initialize();
}
return _WSAStartup != NULL &&
_gethostbyname != NULL;
}
typedef BOOL (WINAPI *AdjustTokenPrivileges_Fn)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
typedef BOOL (WINAPI *OpenProcessToken_Fn)(HANDLE, DWORD, PHANDLE);
typedef BOOL (WINAPI *LookupPrivilegeValue_Fn)(LPCTSTR, LPCTSTR, PLUID);
AdjustTokenPrivileges_Fn os::Advapi32Dll::_AdjustTokenPrivileges = NULL;
OpenProcessToken_Fn os::Advapi32Dll::_OpenProcessToken = NULL;
LookupPrivilegeValue_Fn os::Advapi32Dll::_LookupPrivilegeValue = NULL;
BOOL os::Advapi32Dll::initialized = FALSE;
void os::Advapi32Dll::initialize() {
if (!initialized) {
HMODULE handle = os::win32::load_Windows_dll("advapi32.dll", NULL, 0);
if (handle != NULL) {
_AdjustTokenPrivileges = (AdjustTokenPrivileges_Fn)::GetProcAddress(handle,
"AdjustTokenPrivileges");
_OpenProcessToken = (OpenProcessToken_Fn)::GetProcAddress(handle,
"OpenProcessToken");
_LookupPrivilegeValue = (LookupPrivilegeValue_Fn)::GetProcAddress(handle,
"LookupPrivilegeValueA");
}
initialized = TRUE;
}
}
BOOL os::Advapi32Dll::AdjustTokenPrivileges(HANDLE TokenHandle,
BOOL DisableAllPrivileges,
PTOKEN_PRIVILEGES NewState,
DWORD BufferLength,
PTOKEN_PRIVILEGES PreviousState,
PDWORD ReturnLength) {
assert(initialized && _AdjustTokenPrivileges != NULL,
"AdvapiAvailable() not yet called");
return _AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges, NewState,
BufferLength, PreviousState, ReturnLength);
}
BOOL os::Advapi32Dll::OpenProcessToken(HANDLE ProcessHandle,
DWORD DesiredAccess,
PHANDLE TokenHandle) {
assert(initialized && _OpenProcessToken != NULL,
"AdvapiAvailable() not yet called");
return _OpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle);
}
BOOL os::Advapi32Dll::LookupPrivilegeValue(LPCTSTR lpSystemName,
LPCTSTR lpName, PLUID lpLuid) {
assert(initialized && _LookupPrivilegeValue != NULL,
"AdvapiAvailable() not yet called");
return _LookupPrivilegeValue(lpSystemName, lpName, lpLuid);
}
BOOL os::Advapi32Dll::AdvapiAvailable() {
if (!initialized) {
initialize();
}
return _AdjustTokenPrivileges != NULL &&
_OpenProcessToken != NULL &&
_LookupPrivilegeValue != NULL;
}
#endif
#ifndef PRODUCT
// test the code path in reserve_memory_special() that tries to allocate memory in a single
@ -5976,7 +5761,7 @@ BOOL os::Advapi32Dll::AdvapiAvailable() {
void TestReserveMemorySpecial_test() {
if (!UseLargePages) {
if (VerboseInternalVMTests) {
gclog_or_tty->print("Skipping test because large pages are disabled");
tty->print("Skipping test because large pages are disabled");
}
return;
}
@ -5992,7 +5777,7 @@ void TestReserveMemorySpecial_test() {
char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), NULL, false);
if (result == NULL) {
if (VerboseInternalVMTests) {
gclog_or_tty->print("Failed to allocate control block with size " SIZE_FORMAT ". Skipping remainder of test.",
tty->print("Failed to allocate control block with size " SIZE_FORMAT ". Skipping remainder of test.",
large_allocation_size);
}
} else {
@ -6005,7 +5790,7 @@ void TestReserveMemorySpecial_test() {
char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), expected_location, false);
if (actual_location == NULL) {
if (VerboseInternalVMTests) {
gclog_or_tty->print("Failed to allocate any memory at " PTR_FORMAT " size " SIZE_FORMAT ". Skipping remainder of test.",
tty->print("Failed to allocate any memory at " PTR_FORMAT " size " SIZE_FORMAT ". Skipping remainder of test.",
expected_location, large_allocation_size);
}
} else {

View File

@ -110,6 +110,10 @@ class win32 {
// Default stack size for the current process.
static size_t default_stack_size() { return _default_stack_size; }
static bool get_frame_at_stack_banging_point(JavaThread* thread,
struct _EXCEPTION_POINTERS* exceptionInfo,
address pc, frame* fr);
#ifndef _WIN64
// A wrapper to install a structured exception handler for fast JNI accesors.
static address fast_jni_accessor_wrapper(BasicType);
@ -183,26 +187,11 @@ class PlatformParker : public CHeapObj<mtInternal> {
} ;
// JDK7 requires VS2010
#if _MSC_VER < 1600
#define JDK6_OR_EARLIER 1
#endif
class WinSock2Dll: AllStatic {
public:
static BOOL WSAStartup(WORD, LPWSADATA);
static struct hostent* gethostbyname(const char *name);
static BOOL WinSock2Available();
#ifdef JDK6_OR_EARLIER
private:
static int (PASCAL FAR* _WSAStartup)(WORD, LPWSADATA);
static struct hostent *(PASCAL FAR *_gethostbyname)(...);
static BOOL initialized;
static void initialize();
#endif
};
class Kernel32Dll: AllStatic {
@ -244,16 +233,6 @@ private:
static void initialize();
static void initializeCommon();
#ifdef JDK6_OR_EARLIER
private:
static BOOL (WINAPI *_SwitchToThread)(void);
static HANDLE (WINAPI* _CreateToolhelp32Snapshot)(DWORD,DWORD);
static BOOL (WINAPI* _Module32First)(HANDLE,LPMODULEENTRY32);
static BOOL (WINAPI* _Module32Next)(HANDLE,LPMODULEENTRY32);
static void (WINAPI *_GetNativeSystemInfo)(LPSYSTEM_INFO);
#endif
};
class Advapi32Dll: AllStatic {
@ -263,16 +242,6 @@ public:
static BOOL LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID);
static BOOL AdvapiAvailable();
#ifdef JDK6_OR_EARLIER
private:
static BOOL (WINAPI *_AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
static BOOL (WINAPI *_OpenProcessToken)(HANDLE, DWORD, PHANDLE);
static BOOL (WINAPI *_LookupPrivilegeValue)(LPCTSTR, LPCTSTR, PLUID);
static BOOL initialized;
static void initialize();
#endif
};
class PSApiDll: AllStatic {
@ -282,16 +251,6 @@ public:
static BOOL GetModuleInformation(HANDLE, HMODULE, LPMODULEINFO, DWORD);
static BOOL PSApiAvailable();
#ifdef JDK6_OR_EARLIER
private:
static BOOL (WINAPI *_EnumProcessModules)(HANDLE, HMODULE *, DWORD, LPDWORD);
static BOOL (WINAPI *_GetModuleFileNameEx)(HANDLE, HMODULE, LPTSTR, DWORD);;
static BOOL (WINAPI *_GetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
static BOOL initialized;
static void initialize();
#endif
};
#endif // OS_WINDOWS_VM_OS_WINDOWS_HPP

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#ifdef _WIN64
// These are copied defines from fdlibm.h, this allows us to keep the code
// the same as in the JDK, for easier maintenance.
#define __HI(x) *(1+(int*)&x)
#define __LO(x) *(int*)&x
// This code is a copy of __ieee754_fmod() from the JDK's libfdlibm and is
// used as a workaround for issues with the Windows x64 CRT implementation
// of fmod. Microsoft has acknowledged that this is an issue in Visual Studio
// 2012 and forward, but has not provided a time frame for a fix other than that
// it'll not be fixed in Visual Studio 2013 or 2015.
static const double one = 1.0, Zero[] = { 0.0, -0.0, };
double SharedRuntime::fmod_winx64(double x, double y)
{
int n, hx, hy, hz, ix, iy, sx, i;
unsigned lx, ly, lz;
hx = __HI(x); /* high word of x */
lx = __LO(x); /* low word of x */
hy = __HI(y); /* high word of y */
ly = __LO(y); /* low word of y */
sx = hx & 0x80000000; /* sign of x */
hx ^= sx; /* |x| */
hy &= 0x7fffffff; /* |y| */
#pragma warning( disable : 4146 )
/* purge off exception values */
if ((hy | ly) == 0 || (hx >= 0x7ff00000) || /* y=0,or x not finite */
((hy | ((ly | -ly) >> 31))>0x7ff00000)) /* or y is NaN */
#pragma warning( default : 4146 )
return (x*y) / (x*y);
if (hx <= hy) {
if ((hx<hy) || (lx<ly)) return x; /* |x|<|y| return x */
if (lx == ly)
return Zero[(unsigned)sx >> 31]; /* |x|=|y| return x*0*/
}
/* determine ix = ilogb(x) */
if (hx<0x00100000) { /* subnormal x */
if (hx == 0) {
for (ix = -1043, i = lx; i>0; i <<= 1) ix -= 1;
}
else {
for (ix = -1022, i = (hx << 11); i>0; i <<= 1) ix -= 1;
}
}
else ix = (hx >> 20) - 1023;
/* determine iy = ilogb(y) */
if (hy<0x00100000) { /* subnormal y */
if (hy == 0) {
for (iy = -1043, i = ly; i>0; i <<= 1) iy -= 1;
}
else {
for (iy = -1022, i = (hy << 11); i>0; i <<= 1) iy -= 1;
}
}
else iy = (hy >> 20) - 1023;
/* set up {hx,lx}, {hy,ly} and align y to x */
if (ix >= -1022)
hx = 0x00100000 | (0x000fffff & hx);
else { /* subnormal x, shift x to normal */
n = -1022 - ix;
if (n <= 31) {
hx = (hx << n) | (lx >> (32 - n));
lx <<= n;
}
else {
hx = lx << (n - 32);
lx = 0;
}
}
if (iy >= -1022)
hy = 0x00100000 | (0x000fffff & hy);
else { /* subnormal y, shift y to normal */
n = -1022 - iy;
if (n <= 31) {
hy = (hy << n) | (ly >> (32 - n));
ly <<= n;
}
else {
hy = ly << (n - 32);
ly = 0;
}
}
/* fix point fmod */
n = ix - iy;
while (n--) {
hz = hx - hy; lz = lx - ly; if (lx<ly) hz -= 1;
if (hz<0){ hx = hx + hx + (lx >> 31); lx = lx + lx; }
else {
if ((hz | lz) == 0) /* return sign(x)*0 */
return Zero[(unsigned)sx >> 31];
hx = hz + hz + (lz >> 31); lx = lz + lz;
}
}
hz = hx - hy; lz = lx - ly; if (lx<ly) hz -= 1;
if (hz >= 0) { hx = hz; lx = lz; }
/* convert back to floating value and restore the sign */
if ((hx | lx) == 0) /* return sign(x)*0 */
return Zero[(unsigned)sx >> 31];
while (hx<0x00100000) { /* normalize x */
hx = hx + hx + (lx >> 31); lx = lx + lx;
iy -= 1;
}
if (iy >= -1022) { /* normalize output */
hx = ((hx - 0x00100000) | ((iy + 1023) << 20));
__HI(x) = hx | sx;
__LO(x) = lx;
}
else { /* subnormal output */
n = -1022 - iy;
if (n <= 20) {
lx = (lx >> n) | ((unsigned)hx << (32 - n));
hx >>= n;
}
else if (n <= 31) {
lx = (hx << (32 - n)) | (lx >> n); hx = sx;
}
else {
lx = hx >> (n - 32); hx = sx;
}
__HI(x) = hx | sx;
__LO(x) = lx;
x *= one; /* create necessary signal */
}
return x; /* exact output */
}
#endif

View File

@ -291,6 +291,71 @@ inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
}
#define VM_HAS_SPECIALIZED_CMPXCHG_BYTE
inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a a 'fence_cmpxchg_acquire'
// (see atomic.hpp).
// Using 32 bit internally.
volatile int *dest_base = (volatile int*)((uintptr_t)dest & ~3);
#ifdef VM_LITTLE_ENDIAN
const unsigned int shift_amount = ((uintptr_t)dest & 3) * 8;
#else
const unsigned int shift_amount = ((~(uintptr_t)dest) & 3) * 8;
#endif
const unsigned int masked_compare_val = ((unsigned int)(unsigned char)compare_value),
masked_exchange_val = ((unsigned int)(unsigned char)exchange_value),
xor_value = (masked_compare_val ^ masked_exchange_val) << shift_amount;
unsigned int old_value, value32;
__asm__ __volatile__ (
/* fence */
strasm_sync
/* simple guard */
" lbz %[old_value], 0(%[dest]) \n"
" cmpw %[masked_compare_val], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" lwarx %[value32], 0, %[dest_base] \n"
/* extract byte and compare */
" srd %[old_value], %[value32], %[shift_amount] \n"
" clrldi %[old_value], %[old_value], 56 \n"
" cmpw %[masked_compare_val], %[old_value] \n"
" bne- 2f \n"
/* replace byte and try to store */
" xor %[value32], %[xor_value], %[value32] \n"
" stwcx. %[value32], 0, %[dest_base] \n"
" bne- 1b \n"
/* acquire */
strasm_sync
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value),
[value32] "=&r" (value32),
"=m" (*dest),
"=m" (*dest_base)
/* in */
: [dest] "b" (dest),
[dest_base] "b" (dest_base),
[shift_amount] "r" (shift_amount),
[masked_compare_val] "r" (masked_compare_val),
[xor_value] "r" (xor_value),
"m" (*dest),
"m" (*dest_base)
/* clobber */
: "cc",
"memory"
);
return (jbyte)(unsigned char)old_value;
}
inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) {
// Note that cmpxchg guarantees a two-way memory barrier across

View File

@ -98,12 +98,12 @@ address os::Aix::ucontext_get_pc(const ucontext_t * uc) {
return (address)uc->uc_mcontext.jmp_context.iar;
}
intptr_t* os::Aix::ucontext_get_sp(ucontext_t * uc) {
intptr_t* os::Aix::ucontext_get_sp(const ucontext_t * uc) {
// gpr1 holds the stack pointer on aix
return (intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/];
}
intptr_t* os::Aix::ucontext_get_fp(ucontext_t * uc) {
intptr_t* os::Aix::ucontext_get_fp(const ucontext_t * uc) {
return NULL;
}
@ -111,11 +111,11 @@ void os::Aix::ucontext_set_pc(ucontext_t* uc, address new_pc) {
uc->uc_mcontext.jmp_context.iar = (uint64_t) new_pc;
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t* uc = (ucontext_t*)ucVoid;
const ucontext_t* uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC(os::Aix::ucontext_get_pc(uc));
@ -131,7 +131,7 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
@ -507,10 +507,10 @@ size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t* uc = (ucontext_t*)context;
const ucontext_t* uc = (const ucontext_t*)context;
st->print_cr("Registers:");
st->print("pc =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.iar);
@ -544,9 +544,23 @@ void os::print_context(outputStream *st, void *context) {
st->cr();
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
st->print("Not ported - print_register_info\n");
ucontext_t *uc = (ucontext_t*)context;
st->print_cr("Register to memory mapping:");
st->cr();
st->print("pc ="); print_location(st, (intptr_t)uc->uc_mcontext.jmp_context.iar);
st->print("lr ="); print_location(st, (intptr_t)uc->uc_mcontext.jmp_context.lr);
st->print("sp ="); print_location(st, (intptr_t)os::Aix::ucontext_get_sp(uc));
for (int i = 0; i < 32; i++) {
st->print("r%-2d=", i);
print_location(st, (intptr_t)uc->uc_mcontext.jmp_context.gpr[i]);
}
st->cr();
}
extern "C" {
@ -565,3 +579,4 @@ int os::extra_bang_size_in_bytes() {
// PPC does not require the additional stack bang.
return 0;
}

View File

@ -304,7 +304,7 @@ void os::initialize_thread(Thread* thr) {
// Nothing to do.
}
address os::Bsd::ucontext_get_pc(ucontext_t * uc) {
address os::Bsd::ucontext_get_pc(const ucontext_t * uc) {
return (address)uc->context_pc;
}
@ -312,11 +312,11 @@ void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) {
uc->context_pc = (intptr_t)pc ;
}
intptr_t* os::Bsd::ucontext_get_sp(ucontext_t * uc) {
intptr_t* os::Bsd::ucontext_get_sp(const ucontext_t * uc) {
return (intptr_t*)uc->context_sp;
}
intptr_t* os::Bsd::ucontext_get_fp(ucontext_t * uc) {
intptr_t* os::Bsd::ucontext_get_fp(const ucontext_t * uc) {
return (intptr_t*)uc->context_fp;
}
@ -325,8 +325,9 @@ intptr_t* os::Bsd::ucontext_get_fp(ucontext_t * uc) {
// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
// frames. Currently we don't do that on Bsd, so it's the same as
// os::fetch_frame_from_context().
// This method is also used for stack overflow signal handling.
ExtendedPC os::Bsd::fetch_frame_from_ucontext(Thread* thread,
ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
assert(thread != NULL, "just checking");
assert(ret_sp != NULL, "just checking");
@ -335,11 +336,11 @@ ExtendedPC os::Bsd::fetch_frame_from_ucontext(Thread* thread,
return os::fetch_frame_from_context(uc, ret_sp, ret_fp);
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t* uc = (ucontext_t*)ucVoid;
const ucontext_t* uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC(os::Bsd::ucontext_get_pc(uc));
@ -355,13 +356,55 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = os::Bsd::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
address pc = (address) os::Bsd::ucontext_get_pc(uc);
if (Interpreter::contains(pc)) {
// interpreter performs stack banging after the fixed frame header has
// been generated while the compilers perform it before. To maintain
// semantic consistency between interpreted and compiled frames, the
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// more complex code with compiled code
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling
return false;
} else {
*fr = os::fetch_frame_from_ucontext(thread, uc);
// in compiled code, the stack banging is performed just after the return pc
// has been pushed on the stack
*fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp()));
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
// By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
// turned off by -fomit-frame-pointer,
frame os::get_sender_for_C_frame(frame* fr) {
@ -479,13 +522,31 @@ JVM_handle_bsd_signal(int sig,
addr >= thread->stack_base() - thread->stack_size()) {
// stack overflow
if (thread->in_stack_yellow_zone(addr)) {
thread->disable_stack_yellow_zone();
if (thread->thread_state() == _thread_in_Java) {
if (thread->in_stack_reserved_zone(addr)) {
frame fr;
if (os::Bsd::get_frame_at_stack_banging_point(thread, uc, &fr)) {
assert(fr.is_java_frame(), "Must be a Java frame");
frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
if (activation.sp() != NULL) {
thread->disable_stack_reserved_zone();
if (activation.is_interpreted_frame()) {
thread->set_reserved_stack_activation((address)(
activation.fp() + frame::interpreter_frame_initial_sp_offset));
} else {
thread->set_reserved_stack_activation((address)activation.unextended_sp());
}
return 1;
}
}
}
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
thread->disable_stack_yellow_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
thread->disable_stack_yellow_zone();
return 1;
}
} else if (thread->in_stack_red_zone(addr)) {
@ -910,10 +971,10 @@ size_t os::current_stack_size() {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Registers:");
#ifdef AMD64
st->print( "RAX=" INTPTR_FORMAT, uc->context_rax);
@ -971,10 +1032,10 @@ void os::print_context(outputStream *st, void *context) {
print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Register to memory mapping:");
st->cr();

View File

@ -106,7 +106,7 @@ void os::initialize_thread(Thread* thr) {
// Nothing to do.
}
address os::Bsd::ucontext_get_pc(ucontext_t* uc) {
address os::Bsd::ucontext_get_pc(const ucontext_t* uc) {
ShouldNotCallThis();
return NULL;
}
@ -115,14 +115,14 @@ void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) {
ShouldNotCallThis();
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp,
intptr_t** ret_fp) {
ShouldNotCallThis();
return ExtendedPC();
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
ShouldNotCallThis();
return frame();
}
@ -374,11 +374,11 @@ size_t os::current_stack_size() {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream* st, void* context) {
void os::print_context(outputStream* st, const void* context) {
ShouldNotCallThis();
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
ShouldNotCallThis();
}

View File

@ -109,7 +109,7 @@ char* os::non_memory_address_word() {
void os::initialize_thread(Thread *thr) {
}
address os::Linux::ucontext_get_pc(ucontext_t * uc) {
address os::Linux::ucontext_get_pc(const ucontext_t * uc) {
#ifdef BUILTIN_SIM
return (address)uc->uc_mcontext.gregs[REG_PC];
#else
@ -125,7 +125,7 @@ void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
#endif
}
intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) {
#ifdef BUILTIN_SIM
return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
#else
@ -133,7 +133,7 @@ intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
#endif
}
intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) {
#ifdef BUILTIN_SIM
return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
#else
@ -147,7 +147,7 @@ intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
// frames. Currently we don't do that on Linux, so it's the same as
// os::fetch_frame_from_context().
ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
assert(thread != NULL, "just checking");
assert(ret_sp != NULL, "just checking");
@ -156,11 +156,11 @@ ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
return os::fetch_frame_from_context(uc, ret_sp, ret_fp);
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t* uc = (ucontext_t*)ucVoid;
const ucontext_t* uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
@ -176,7 +176,7 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
@ -591,10 +591,10 @@ size_t os::current_stack_size() {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Registers:");
#ifdef BUILTIN_SIM
st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
@ -643,10 +643,10 @@ void os::print_context(outputStream *st, void *context) {
print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Register to memory mapping:");
st->cr();

View File

@ -291,6 +291,71 @@ inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
}
#define VM_HAS_SPECIALIZED_CMPXCHG_BYTE
inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a a 'fence_cmpxchg_acquire'
// (see atomic.hpp).
// Using 32 bit internally.
volatile int *dest_base = (volatile int*)((uintptr_t)dest & ~3);
#ifdef VM_LITTLE_ENDIAN
const unsigned int shift_amount = ((uintptr_t)dest & 3) * 8;
#else
const unsigned int shift_amount = ((~(uintptr_t)dest) & 3) * 8;
#endif
const unsigned int masked_compare_val = ((unsigned int)(unsigned char)compare_value),
masked_exchange_val = ((unsigned int)(unsigned char)exchange_value),
xor_value = (masked_compare_val ^ masked_exchange_val) << shift_amount;
unsigned int old_value, value32;
__asm__ __volatile__ (
/* fence */
strasm_sync
/* simple guard */
" lbz %[old_value], 0(%[dest]) \n"
" cmpw %[masked_compare_val], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" lwarx %[value32], 0, %[dest_base] \n"
/* extract byte and compare */
" srd %[old_value], %[value32], %[shift_amount] \n"
" clrldi %[old_value], %[old_value], 56 \n"
" cmpw %[masked_compare_val], %[old_value] \n"
" bne- 2f \n"
/* replace byte and try to store */
" xor %[value32], %[xor_value], %[value32] \n"
" stwcx. %[value32], 0, %[dest_base] \n"
" bne- 1b \n"
/* acquire */
strasm_sync
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value),
[value32] "=&r" (value32),
"=m" (*dest),
"=m" (*dest_base)
/* in */
: [dest] "b" (dest),
[dest_base] "b" (dest_base),
[shift_amount] "r" (shift_amount),
[masked_compare_val] "r" (masked_compare_val),
[xor_value] "r" (xor_value),
"m" (*dest),
"m" (*dest_base)
/* clobber */
: "cc",
"memory"
);
return (jbyte)(unsigned char)old_value;
}
inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) {
// Note that cmpxchg guarantees a two-way memory barrier across

View File

@ -99,7 +99,7 @@ void os::initialize_thread(Thread *thread) { }
// Frame information (pc, sp, fp) retrieved via ucontext
// always looks like a C-frame according to the frame
// conventions in frame_ppc64.hpp.
address os::Linux::ucontext_get_pc(ucontext_t * uc) {
address os::Linux::ucontext_get_pc(const ucontext_t * uc) {
// On powerpc64, ucontext_t is not selfcontained but contains
// a pointer to an optional substructure (mcontext_t.regs) containing the volatile
// registers - NIP, among others.
@ -122,19 +122,19 @@ void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
uc->uc_mcontext.regs->nip = (unsigned long)pc;
}
intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) {
return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
}
intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) {
return NULL;
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t* uc = (ucontext_t*)ucVoid;
const ucontext_t* uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
@ -150,7 +150,7 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
@ -564,10 +564,10 @@ size_t os::current_stack_size() {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t* uc = (ucontext_t*)context;
const ucontext_t* uc = (const ucontext_t*)context;
st->print_cr("Registers:");
st->print("pc =" INTPTR_FORMAT " ", uc->uc_mcontext.regs->nip);
@ -595,10 +595,10 @@ void os::print_context(outputStream *st, void *context) {
st->cr();
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Register to memory mapping:");
st->cr();

View File

@ -92,7 +92,7 @@ enum {
// signal frames. Currently we don't do that on Linux, so it's the
// same as os::fetch_frame_from_context().
ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
ucontext_t* uc,
const ucontext_t* uc,
intptr_t** ret_sp,
intptr_t** ret_fp) {
assert(thread != NULL, "just checking");
@ -102,10 +102,10 @@ ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
return os::fetch_frame_from_context(uc, ret_sp, ret_fp);
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp,
intptr_t** ret_fp) {
ucontext_t* uc = (ucontext_t*) ucVoid;
const ucontext_t* uc = (const ucontext_t*) ucVoid;
ExtendedPC epc;
if (uc != NULL) {
@ -130,7 +130,7 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, NULL);
return frame(sp, frame::unpatchable, epc.pc());
@ -213,10 +213,10 @@ char* os::non_memory_address_word() {
void os::initialize_thread(Thread* thr) {}
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t* uc = (ucontext_t*)context;
const ucontext_t* uc = (const ucontext_t*)context;
sigcontext* sc = (sigcontext*)context;
st->print_cr("Registers:");
@ -291,11 +291,11 @@ void os::print_context(outputStream *st, void *context) {
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
sigcontext* sc = (sigcontext*)context;
const ucontext_t *uc = (const ucontext_t*)context;
const sigcontext* sc = (const sigcontext*)context;
intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);
st->print_cr("Register to memory mapping:");
@ -343,7 +343,7 @@ void os::print_register_info(outputStream *st, void *context) {
}
address os::Linux::ucontext_get_pc(ucontext_t* uc) {
address os::Linux::ucontext_get_pc(const ucontext_t* uc) {
return (address) SIG_PC((sigcontext*)uc);
}
@ -353,13 +353,13 @@ void os::Linux::ucontext_set_pc(ucontext_t* uc, address pc) {
SIG_NPC(ctx) = (intptr_t)(pc+4);
}
intptr_t* os::Linux::ucontext_get_sp(ucontext_t *uc) {
intptr_t* os::Linux::ucontext_get_sp(const ucontext_t *uc) {
return (intptr_t*)
((intptr_t)SIG_REGS((sigcontext*)uc).u_regs[CON_O6] + STACK_BIAS);
}
// not used on Sparc
intptr_t* os::Linux::ucontext_get_fp(ucontext_t *uc) {
intptr_t* os::Linux::ucontext_get_fp(const ucontext_t *uc) {
ShouldNotReachHere();
return NULL;
}
@ -684,7 +684,7 @@ JVM_handle_linux_signal(int sig,
}
if (pc == NULL && uc != NULL) {
pc = os::Linux::ucontext_get_pc((ucontext_t*)uc);
pc = os::Linux::ucontext_get_pc((const ucontext_t*)uc);
}
// unmask current signal

View File

@ -117,7 +117,7 @@ void os::initialize_thread(Thread* thr) {
// Nothing to do.
}
address os::Linux::ucontext_get_pc(ucontext_t * uc) {
address os::Linux::ucontext_get_pc(const ucontext_t * uc) {
return (address)uc->uc_mcontext.gregs[REG_PC];
}
@ -125,11 +125,11 @@ void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
uc->uc_mcontext.gregs[REG_PC] = (intptr_t)pc;
}
intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) {
return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
}
intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) {
return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
}
@ -138,8 +138,9 @@ intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
// frames. Currently we don't do that on Linux, so it's the same as
// os::fetch_frame_from_context().
// This method is also used for stack overflow signal handling.
ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
assert(thread != NULL, "just checking");
assert(ret_sp != NULL, "just checking");
@ -148,11 +149,11 @@ ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
return os::fetch_frame_from_context(uc, ret_sp, ret_fp);
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t* uc = (ucontext_t*)ucVoid;
const ucontext_t* uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
@ -168,13 +169,57 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = os::Linux::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
address pc = (address) os::Linux::ucontext_get_pc(uc);
if (Interpreter::contains(pc)) {
// interpreter performs stack banging after the fixed frame header has
// been generated while the compilers perform it before. To maintain
// semantic consistency between interpreted and compiled frames, the
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// more complex code with compiled code
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling
return false;
} else {
// in compiled code, the stack banging is performed just after the return pc
// has been pushed on the stack
intptr_t* fp = os::Linux::ucontext_get_fp(uc);
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
*fr = frame(sp + 1, fp, (address)*sp);
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
assert(!fr->is_first_frame(), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
// By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
// turned off by -fomit-frame-pointer,
frame os::get_sender_for_C_frame(frame* fr) {
@ -305,13 +350,32 @@ JVM_handle_linux_signal(int sig,
addr >= thread->stack_base() - thread->stack_size()) {
// stack overflow
if (thread->in_stack_yellow_zone(addr)) {
thread->disable_stack_yellow_zone();
if (thread->thread_state() == _thread_in_Java) {
if (thread->in_stack_reserved_zone(addr)) {
frame fr;
if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
assert(fr.is_java_frame(), "Must be a Java frame");
frame activation =
SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
if (activation.sp() != NULL) {
thread->disable_stack_reserved_zone();
if (activation.is_interpreted_frame()) {
thread->set_reserved_stack_activation((address)(
activation.fp() + frame::interpreter_frame_initial_sp_offset));
} else {
thread->set_reserved_stack_activation((address)activation.unextended_sp());
}
return 1;
}
}
}
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
thread->disable_stack_yellow_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
thread->disable_stack_yellow_zone();
return 1;
}
} else if (thread->in_stack_red_zone(addr)) {
@ -720,10 +784,10 @@ size_t os::current_stack_size() {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Registers:");
#ifdef AMD64
st->print( "RAX=" INTPTR_FORMAT, (intptr_t)uc->uc_mcontext.gregs[REG_RAX]);
@ -783,10 +847,10 @@ void os::print_context(outputStream *st, void *context) {
print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Register to memory mapping:");
st->cr();
@ -868,7 +932,7 @@ void os::workaround_expand_exec_shield_cs_limit() {
* we don't have much control or understanding of the address space, just let it slide.
*/
char* hint = (char*) (Linux::initial_thread_stack_bottom() -
((StackYellowPages + StackRedPages + 1) * page_size));
((StackReservedPages + StackYellowPages + StackRedPages + 1) * page_size));
char* codebuf = os::attempt_reserve_memory_at(page_size, hint);
if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) {
return; // No matter, we tried, best effort.

View File

@ -100,7 +100,7 @@ void os::initialize_thread(Thread * thr){
// Nothing to do.
}
address os::Linux::ucontext_get_pc(ucontext_t* uc) {
address os::Linux::ucontext_get_pc(const ucontext_t* uc) {
ShouldNotCallThis();
}
@ -108,13 +108,13 @@ void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
ShouldNotCallThis();
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp,
intptr_t** ret_fp) {
ShouldNotCallThis();
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
ShouldNotCallThis();
}
@ -406,11 +406,11 @@ size_t os::current_stack_size() {
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
void os::print_context(outputStream* st, void* context) {
void os::print_context(outputStream* st, const void* context) {
ShouldNotCallThis();
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
ShouldNotCallThis();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -121,7 +121,7 @@ char* os::non_memory_address_word() {
// There are issues with libthread giving out uc_links for different threads
// on the same uc_link chain and bad or circular links.
//
bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect) {
bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect) {
if (valid >= suspect ||
valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags ||
valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp ||
@ -148,10 +148,10 @@ bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t*
// We will only follow one level of uc_link since there are libthread
// issues with ucontext linking and it is better to be safe and just
// let caller retry later.
ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
ucontext_t *uc) {
const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
const ucontext_t *uc) {
ucontext_t *retuc = NULL;
const ucontext_t *retuc = NULL;
// Sometimes the topmost register windows are not properly flushed.
// i.e., if the kernel would have needed to take a page fault
@ -179,7 +179,7 @@ ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
}
// Assumes ucontext is valid
ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) {
ExtendedPC os::Solaris::ucontext_get_ExtendedPC(const ucontext_t *uc) {
address pc = (address)uc->uc_mcontext.gregs[REG_PC];
// set npc to zero to avoid using it for safepoint, good for profiling only
return ExtendedPC(pc);
@ -191,17 +191,17 @@ void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) {
}
// Assumes ucontext is valid
intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) {
return (intptr_t*)((intptr_t)uc->uc_mcontext.gregs[REG_SP] + STACK_BIAS);
}
// Solaris X86 only
intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) {
intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) {
ShouldNotReachHere();
return NULL;
}
address os::Solaris::ucontext_get_pc(ucontext_t *uc) {
address os::Solaris::ucontext_get_pc(const ucontext_t *uc) {
return (address) uc->uc_mcontext.gregs[REG_PC];
}
@ -213,25 +213,26 @@ address os::Solaris::ucontext_get_pc(ucontext_t *uc) {
//
// The difference between this and os::fetch_frame_from_context() is that
// here we try to skip nested signal frames.
// This method is also used for stack overflow signal handling.
ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
assert(thread != NULL, "just checking");
assert(ret_sp != NULL, "just checking");
assert(ret_fp == NULL, "just checking");
ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
const ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
return os::fetch_frame_from_context(luc, ret_sp, ret_fp);
}
// ret_fp parameter is only used by Solaris X86.
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t *uc = (ucontext_t*)ucVoid;
const ucontext_t *uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = os::Solaris::ucontext_get_ExtendedPC(uc);
@ -245,13 +246,48 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
return frame(sp, frame::unpatchable, epc.pc());
}
frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
intptr_t* sp;
ExtendedPC epc = os::Solaris::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, NULL);
return frame(sp, frame::unpatchable, epc.pc());
}
bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
address pc = (address) os::Solaris::ucontext_get_pc(uc);
if (Interpreter::contains(pc)) {
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// more complex code with compiled code
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling
return false;
} else {
*fr = os::fetch_frame_from_ucontext(thread, uc);
*fr = frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
}
@ -367,17 +403,32 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
address addr = (address) info->si_addr;
if (thread->in_stack_yellow_zone(addr)) {
thread->disable_stack_yellow_zone();
// Sometimes the register windows are not properly flushed.
if(uc->uc_mcontext.gwins != NULL) {
::handle_unflushed_register_windows(uc->uc_mcontext.gwins);
}
if (thread->thread_state() == _thread_in_Java) {
if (thread->in_stack_reserved_zone(addr)) {
frame fr;
if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
assert(fr.is_java_frame(), "Must be a Java frame");
frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
if (activation.sp() != NULL) {
thread->disable_stack_reserved_zone();
RegisterMap map(thread);
int frame_size = activation.frame_size(&map);
thread->set_reserved_stack_activation((address)(((address)activation.sp()) - STACK_BIAS));
return true;
}
}
}
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
thread->disable_stack_yellow_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
thread->disable_stack_yellow_zone();
return true;
}
} else if (thread->in_stack_red_zone(addr)) {
@ -554,10 +605,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
return false;
}
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Registers:");
st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT
@ -631,10 +682,10 @@ void os::print_context(outputStream *st, void *context) {
print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
st->print_cr("Register to memory mapping:");

View File

@ -121,7 +121,7 @@ char* os::non_memory_address_word() {
// There are issues with libthread giving out uc_links for different threads
// on the same uc_link chain and bad or circular links.
//
bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect) {
bool os::Solaris::valid_ucontext(Thread* thread, const ucontext_t* valid, const ucontext_t* suspect) {
if (valid >= suspect ||
valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags ||
valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp ||
@ -146,10 +146,10 @@ bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t*
// We will only follow one level of uc_link since there are libthread
// issues with ucontext linking and it is better to be safe and just
// let caller retry later.
ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
ucontext_t *uc) {
const ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
const ucontext_t *uc) {
ucontext_t *retuc = NULL;
const ucontext_t *retuc = NULL;
if (uc != NULL) {
if (uc->uc_link == NULL) {
@ -171,7 +171,7 @@ ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
}
// Assumes ucontext is valid
ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) {
ExtendedPC os::Solaris::ucontext_get_ExtendedPC(const ucontext_t *uc) {
return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]);
}
@ -180,16 +180,16 @@ void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) {
}
// Assumes ucontext is valid
intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
intptr_t* os::Solaris::ucontext_get_sp(const ucontext_t *uc) {
return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
}
// Assumes ucontext is valid
intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) {
intptr_t* os::Solaris::ucontext_get_fp(const ucontext_t *uc) {
return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
}
address os::Solaris::ucontext_get_pc(ucontext_t *uc) {
address os::Solaris::ucontext_get_pc(const ucontext_t *uc) {
return (address) uc->uc_mcontext.gregs[REG_PC];
}
@ -198,22 +198,23 @@ address os::Solaris::ucontext_get_pc(ucontext_t *uc) {
//
// The difference between this and os::fetch_frame_from_context() is that
// here we try to skip nested signal frames.
// This method is also used for stack overflow signal handling.
ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
assert(thread != NULL, "just checking");
assert(ret_sp != NULL, "just checking");
assert(ret_fp != NULL, "just checking");
ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
const ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
return os::fetch_frame_from_context(luc, ret_sp, ret_fp);
}
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
ucontext_t *uc = (ucontext_t*)ucVoid;
const ucontext_t *uc = (const ucontext_t*)ucVoid;
if (uc != NULL) {
epc = os::Solaris::ucontext_get_ExtendedPC(uc);
@ -229,13 +230,56 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = os::Solaris::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp);
return frame(sp, fp, epc.pc());
}
bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
address pc = (address) os::Solaris::ucontext_get_pc(uc);
if (Interpreter::contains(pc)) {
// interpreter performs stack banging after the fixed frame header has
// been generated while the compilers perform it before. To maintain
// semantic consistency between interpreted and compiled frames, the
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
} else {
// more complex code with compiled code
assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
// Not sure where the pc points to, fallback to default
// stack overflow handling
return false;
} else {
// in compiled code, the stack banging is performed just after the return pc
// has been pushed on the stack
intptr_t* fp = os::Solaris::ucontext_get_fp(uc);
intptr_t* sp = os::Solaris::ucontext_get_sp(uc);
*fr = frame(sp + 1, fp, (address)*sp);
if (!fr->is_java_frame()) {
assert(fr->safe_for_sender(thread), "Safety check");
*fr = fr->java_sender();
}
}
}
assert(fr->is_java_frame(), "Safety check");
return true;
}
frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
@ -422,13 +466,31 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
address addr = (address) info->si_addr;
if (thread->in_stack_yellow_zone(addr)) {
thread->disable_stack_yellow_zone();
if (thread->thread_state() == _thread_in_Java) {
if (thread->in_stack_reserved_zone(addr)) {
frame fr;
if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
assert(fr.is_java_frame(), "Must be Java frame");
frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
if (activation.sp() != NULL) {
thread->disable_stack_reserved_zone();
if (activation.is_interpreted_frame()) {
thread->set_reserved_stack_activation((address)(
activation.fp() + frame::interpreter_frame_initial_sp_offset));
} else {
thread->set_reserved_stack_activation((address)activation.unextended_sp());
}
return true;
}
}
}
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
thread->disable_stack_yellow_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
thread->disable_stack_yellow_zone();
return true;
}
} else if (thread->in_stack_red_zone(addr)) {
@ -712,10 +774,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
return false;
}
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Registers:");
#ifdef AMD64
st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
@ -771,10 +833,10 @@ void os::print_context(outputStream *st, void *context) {
print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
ucontext_t *uc = (ucontext_t*)context;
const ucontext_t *uc = (const ucontext_t*)context;
st->print_cr("Register to memory mapping:");
st->cr();

View File

@ -359,7 +359,7 @@ cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_boot
* while (...) {... fr = os::get_sender_for_C_frame(&fr); }
* loop in vmError.cpp. We need to roll our own loop.
*/
bool os::platform_print_native_stack(outputStream* st, void* context,
bool os::platform_print_native_stack(outputStream* st, const void* context,
char *buf, int buf_size)
{
CONTEXT ctx;
@ -435,7 +435,7 @@ bool os::platform_print_native_stack(outputStream* st, void* context,
}
#endif // AMD64
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
ExtendedPC epc;
@ -455,7 +455,7 @@ ExtendedPC os::fetch_frame_from_context(void* ucVoid,
return epc;
}
frame os::fetch_frame_from_context(void* ucVoid) {
frame os::fetch_frame_from_context(const void* ucVoid) {
intptr_t* sp;
intptr_t* fp;
ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
@ -527,10 +527,10 @@ frame os::current_frame() {
}
}
void os::print_context(outputStream *st, void *context) {
void os::print_context(outputStream *st, const void *context) {
if (context == NULL) return;
CONTEXT* uc = (CONTEXT*)context;
const CONTEXT* uc = (const CONTEXT*)context;
st->print_cr("Registers:");
#ifdef AMD64
@ -588,10 +588,10 @@ void os::print_context(outputStream *st, void *context) {
}
void os::print_register_info(outputStream *st, void *context) {
void os::print_register_info(outputStream *st, const void *context) {
if (context == NULL) return;
CONTEXT* uc = (CONTEXT*)context;
const CONTEXT* uc = (const CONTEXT*)context;
st->print_cr("Register to memory mapping:");
st->cr();

View File

@ -66,7 +66,7 @@
#ifdef AMD64
#define PLATFORM_PRINT_NATIVE_STACK 1
static bool platform_print_native_stack(outputStream* st, void* context,
static bool platform_print_native_stack(outputStream* st, const void* context,
char *buf, int buf_size);
#endif

View File

@ -70,12 +70,12 @@ CONFIGURE_ARGS= --host=$(MINGW) --target=$(MINGW)
else #linux
CPU = $(shell uname -m)
ARCH1=$(CPU:x86_64=amd64)
ARCH2=$(ARCH1:i686=i386)
ARCH=$(ARCH2:ppc64le=ppc64)
ARCH=$(ARCH1:i686=i386)
ifdef LP64
CFLAGS/sparcv9 += -m64
CFLAGS/amd64 += -m64
CFLAGS/ppc64 += -m64
CFLAGS/ppc64le += -m64 -DABI_ELFv2
else
ARCH=$(ARCH1:amd64=i386)
CFLAGS/i386 += -m32

View File

@ -66,7 +66,7 @@ int main(int ac, char** av) {
printf("...And now for something completely different:\n");
void *start = (void*) &main;
void *end = (void*) &end_of_file;
#if defined(__ia64) || defined(__powerpc__)
#if defined(__ia64) || (defined(__powerpc__) && !defined(ABI_ELFv2))
/* On IA64 and PPC function pointers are pointers to function descriptors */
start = *((void**)start);
end = *((void**)end);

View File

@ -461,7 +461,7 @@ static const char* native_arch_name() {
#ifdef LIBARCH_sparcv9
res = "sparc:v9b";
#endif
#ifdef LIBARCH_ppc64
#if defined(LIBARCH_ppc64) || defined(LIBARCH_ppc64le)
res = "powerpc:common64";
#endif
#ifdef LIBARCH_aarch64

View File

@ -8,7 +8,6 @@
prepend in front of bootstrap class path
-Xnoclassgc disable class garbage collection
-Xlog:<opts> control JVM logging, use -Xlog:help for details
-Xloggc:<file> log GC status to a file with time stamps
-Xbatch disable background compilation
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size

View File

@ -551,6 +551,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
, _would_profile(false)
, _has_unsafe_access(false)
, _has_method_handle_invokes(false)
, _has_reserved_stack_access(method->has_reserved_stack_access())
, _bailout_msg(NULL)
, _exception_info_list(NULL)
, _allocator(NULL)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -81,6 +81,7 @@ class Compilation: public StackObj {
bool _has_unsafe_access;
bool _would_profile;
bool _has_method_handle_invokes; // True if this method has MethodHandle invokes.
bool _has_reserved_stack_access;
const char* _bailout_msg;
ExceptionInfoList* _exception_info_list;
ExceptionHandlerTable _exception_handler_table;
@ -171,6 +172,9 @@ class Compilation: public StackObj {
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
bool has_reserved_stack_access() const { return _has_reserved_stack_access; }
void set_has_reserved_stack_access(bool z) { _has_reserved_stack_access = z; }
DebugInformationRecorder* debug_info_recorder() const; // = _env->debug_info();
Dependencies* dependency_recorder() const; // = _env->dependencies()
ImplicitExceptionTable* implicit_exception_table() { return &_implicit_exception_table; }

View File

@ -3322,7 +3322,13 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co
// method handle invokes
if (callee->is_method_handle_intrinsic()) {
return try_method_handle_inline(callee);
if (try_method_handle_inline(callee)) {
if (callee->has_reserved_stack_access()) {
compilation()->set_has_reserved_stack_access(true);
}
return true;
}
return false;
}
// handle intrinsics
@ -3330,6 +3336,9 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co
(CheckIntrinsics ? callee->intrinsic_candidate() : true)) {
if (try_inline_intrinsics(callee)) {
print_inlining(callee, "intrinsic");
if (callee->has_reserved_stack_access()) {
compilation()->set_has_reserved_stack_access(true);
}
return true;
}
// try normal inlining
@ -3346,8 +3355,12 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co
if (bc == Bytecodes::_illegal) {
bc = code();
}
if (try_inline_full(callee, holder_known, bc, receiver))
if (try_inline_full(callee, holder_known, bc, receiver)) {
if (callee->has_reserved_stack_access()) {
compilation()->set_has_reserved_stack_access(true);
}
return true;
}
// Entire compilation could fail during try_inline_full call.
// In that case printing inlining decision info is useless.

View File

@ -502,7 +502,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// Check the stack guard pages and reenable them if necessary and there is
// enough space on the stack to do so. Use fast exceptions only if the guard
// pages are enabled.
bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
bool guard_pages_enabled = thread->stack_guards_enabled();
if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
if (JvmtiExport::can_post_on_exceptions()) {

View File

@ -91,6 +91,7 @@ ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
_balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
_is_c1_compilable = !h_m()->is_not_c1_compilable();
_is_c2_compilable = !h_m()->is_not_c2_compilable();
_has_reserved_stack_access = h_m()->has_reserved_stack_access();
// Lazy fields, filled in on demand. Require allocation.
_code = NULL;
_exception_handlers = NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -81,6 +81,7 @@ class ciMethod : public ciMetadata {
bool _is_c1_compilable;
bool _is_c2_compilable;
bool _can_be_statically_bound;
bool _has_reserved_stack_access;
// Lazy fields, filled in on demand
address _code;
@ -316,6 +317,7 @@ class ciMethod : public ciMetadata {
bool is_accessor () const;
bool is_initializer () const;
bool can_be_statically_bound() const { return _can_be_statically_bound; }
bool has_reserved_stack_access() const { return _has_reserved_stack_access; }
bool is_boxing_method() const;
bool is_unboxing_method() const;

View File

@ -946,6 +946,7 @@ public:
_method_HotSpotIntrinsicCandidate,
_jdk_internal_vm_annotation_Contended,
_field_Stable,
_jdk_internal_vm_annotation_ReservedStackAccess,
_annotation_LIMIT
};
const Location _location;
@ -2016,6 +2017,11 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
}
return _jdk_internal_vm_annotation_Contended;
}
case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ReservedStackAccess_signature): {
if (_location != _in_method) break; // only allow for methods
if (RestrictReservedStack && !privileged) break; // honor privileges
return _jdk_internal_vm_annotation_ReservedStackAccess;
}
default: {
break;
}
@ -2051,6 +2057,8 @@ void MethodAnnotationCollector::apply_to(methodHandle m) {
m->set_hidden(true);
if (has_annotation(_method_HotSpotIntrinsicCandidate) && !m->is_synthetic())
m->set_intrinsic_candidate(true);
if (has_annotation(_jdk_internal_vm_annotation_ReservedStackAccess))
m->set_has_reserved_stack_access(true);
}
void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) {

View File

@ -212,6 +212,7 @@
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
template(jdk_internal_vm_annotation_Contended_signature, "Ljdk/internal/vm/annotation/Contended;") \
template(jdk_internal_vm_annotation_ReservedStackAccess_signature, "Ljdk/internal/vm/annotation/ReservedStackAccess;") \
\
/* class symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \

View File

@ -26,6 +26,7 @@
#define SHARE_VM_GC_CMS_ALLOCATIONSTATS_HPP
#include "gc/shared/gcUtil.hpp"
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
@ -119,11 +120,9 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC {
ssize_t old_desired = _desired;
float delta_ise = (CMSExtrapolateSweep ? intra_sweep_estimate : 0.0);
_desired = (ssize_t)(new_rate * (inter_sweep_estimate + delta_ise));
if (PrintFLSStatistics > 1) {
gclog_or_tty->print_cr("demand: " SSIZE_FORMAT ", old_rate: %f, current_rate: %f, "
"new_rate: %f, old_desired: " SSIZE_FORMAT ", new_desired: " SSIZE_FORMAT,
demand, old_rate, rate, new_rate, old_desired, _desired);
}
log_trace(gc, freelist)("demand: " SSIZE_FORMAT ", old_rate: %f, current_rate: %f, "
"new_rate: %f, old_desired: " SSIZE_FORMAT ", new_desired: " SSIZE_FORMAT,
demand, old_rate, rate, new_rate, old_desired, _desired);
}
}

View File

@ -400,17 +400,16 @@ void CompactibleFreeListSpace::print_on(outputStream* st) const {
void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st)
const {
reportIndexedFreeListStatistics();
gclog_or_tty->print_cr("Layout of Indexed Freelists");
gclog_or_tty->print_cr("---------------------------");
reportIndexedFreeListStatistics(st);
st->print_cr("Layout of Indexed Freelists");
st->print_cr("---------------------------");
AdaptiveFreeList<FreeChunk>::print_labels_on(st, "size");
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
_indexedFreeList[i].print_on(gclog_or_tty);
for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
fc = fc->next()) {
gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
p2i(fc), p2i((HeapWord*)fc + i),
fc->cantCoalesce() ? "\t CC" : "");
_indexedFreeList[i].print_on(st);
for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; fc = fc->next()) {
st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
p2i(fc), p2i((HeapWord*)fc + i),
fc->cantCoalesce() ? "\t CC" : "");
}
}
}
@ -422,7 +421,7 @@ const {
void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st)
const {
_dictionary->report_statistics();
_dictionary->report_statistics(st);
st->print_cr("Layout of Freelists in Tree");
st->print_cr("---------------------------");
_dictionary->print_free_lists(st);
@ -472,54 +471,58 @@ size_t BlkPrintingClosure::do_blk(HeapWord* addr) {
return sz;
}
void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c,
outputStream* st) {
st->print_cr("\n=========================");
void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st) {
st->print_cr("=========================");
st->print_cr("Block layout in CMS Heap:");
st->print_cr("=========================");
BlkPrintingClosure bpcl(c, this, c->markBitMap(), st);
blk_iterate(&bpcl);
st->print_cr("\n=======================================");
st->print_cr("=======================================");
st->print_cr("Order & Layout of Promotion Info Blocks");
st->print_cr("=======================================");
print_promo_info_blocks(st);
st->print_cr("\n===========================");
st->print_cr("===========================");
st->print_cr("Order of Indexed Free Lists");
st->print_cr("=========================");
print_indexed_free_lists(st);
st->print_cr("\n=================================");
st->print_cr("=================================");
st->print_cr("Order of Free Lists in Dictionary");
st->print_cr("=================================");
print_dictionary_free_lists(st);
}
void CompactibleFreeListSpace::reportFreeListStatistics() const {
void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const {
assert_lock_strong(&_freelistLock);
assert(PrintFLSStatistics != 0, "Reporting error");
_dictionary->report_statistics();
if (PrintFLSStatistics > 1) {
reportIndexedFreeListStatistics();
LogHandle(gc, freelist, stats) log;
if (!log.is_debug()) {
return;
}
log.debug("%s", title);
_dictionary->report_statistics(log.debug_stream());
if (log.is_trace()) {
ResourceMark rm;
reportIndexedFreeListStatistics(log.trace_stream());
size_t total_size = totalSizeInIndexedFreeLists() +
_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
gclog_or_tty->print(" free=" SIZE_FORMAT " frag=%1.4f\n", total_size, flsFrag());
log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag());
}
}
void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const {
void CompactibleFreeListSpace::reportIndexedFreeListStatistics(outputStream* st) const {
assert_lock_strong(&_freelistLock);
gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
"--------------------------------\n");
st->print_cr("Statistics for IndexedFreeLists:");
st->print_cr("--------------------------------");
size_t total_size = totalSizeInIndexedFreeLists();
size_t free_blocks = numFreeBlocksInIndexedFreeLists();
gclog_or_tty->print("Total Free Space: " SIZE_FORMAT "\n", total_size);
gclog_or_tty->print("Max Chunk Size: " SIZE_FORMAT "\n", maxChunkSizeInIndexedFreeLists());
gclog_or_tty->print("Number of Blocks: " SIZE_FORMAT "\n", free_blocks);
size_t free_blocks = numFreeBlocksInIndexedFreeLists();
st->print_cr("Total Free Space: " SIZE_FORMAT, total_size);
st->print_cr("Max Chunk Size: " SIZE_FORMAT, maxChunkSizeInIndexedFreeLists());
st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks);
if (free_blocks != 0) {
gclog_or_tty->print("Av. Block Size: " SIZE_FORMAT "\n", total_size/free_blocks);
st->print_cr("Av. Block Size: " SIZE_FORMAT, total_size/free_blocks);
}
}
@ -1824,10 +1827,7 @@ CompactibleFreeListSpace::sweep_completed() {
void
CompactibleFreeListSpace::gc_prologue() {
assert_locked();
if (PrintFLSStatistics != 0) {
gclog_or_tty->print("Before GC:\n");
reportFreeListStatistics();
}
reportFreeListStatistics("Before GC:");
refillLinearAllocBlocksIfNeeded();
}
@ -1837,11 +1837,7 @@ CompactibleFreeListSpace::gc_epilogue() {
assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
_promoInfo.stopTrackingPromotions();
repairLinearAllocationBlocks();
// Print Space's stats
if (PrintFLSStatistics != 0) {
gclog_or_tty->print("After GC:\n");
reportFreeListStatistics();
}
reportFreeListStatistics("After GC:");
}
// Iteration support, mostly delegated from a CMS generation
@ -2014,9 +2010,7 @@ void CompactibleFreeListSpace::beginSweepFLCensus(
size_t i;
for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
AdaptiveFreeList<FreeChunk>* fl = &_indexedFreeList[i];
if (PrintFLSStatistics > 1) {
gclog_or_tty->print("size[" SIZE_FORMAT "] : ", i);
}
log_trace(gc, freelist)("size[" SIZE_FORMAT "] : ", i);
fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
fl->set_before_sweep(fl->count());
@ -2065,16 +2059,10 @@ void CompactibleFreeListSpace::clearFLCensus() {
}
void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
if (PrintFLSStatistics > 0) {
HeapWord* largestAddr = (HeapWord*) dictionary()->find_largest_dict();
gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
p2i(largestAddr));
}
log_debug(gc, freelist)("CMS: Large block " PTR_FORMAT, p2i(dictionary()->find_largest_dict()));
setFLSurplus();
setFLHints();
if (PrintGC && PrintFLSCensus > 0) {
printFLCensus(sweep_count);
}
printFLCensus(sweep_count);
clearFLCensus();
assert_locked();
_dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent);
@ -2213,14 +2201,15 @@ class VerifyAllBlksClosure: public BlkClosure {
}
}
if (res == 0) {
gclog_or_tty->print_cr("Livelock: no rank reduction!");
gclog_or_tty->print_cr(
" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n"
" Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n",
LogHandle(gc, verify) log;
log.info("Livelock: no rank reduction!");
log.info(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n"
" Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n",
p2i(addr), res, was_obj ?"true":"false", was_live ?"true":"false",
p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false");
_sp->print_on(gclog_or_tty);
guarantee(false, "Seppuku!");
ResourceMark rm;
_sp->print_on(log.info_stream());
guarantee(false, "Verification failed.");
}
_last_addr = addr;
_last_size = res;
@ -2386,17 +2375,23 @@ void CompactibleFreeListSpace::check_free_list_consistency() const {
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
assert_lock_strong(&_freelistLock);
LogHandle(gc, freelist, census) log;
if (!log.is_debug()) {
return;
}
AdaptiveFreeList<FreeChunk> total;
gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
log.debug("end sweep# " SIZE_FORMAT, sweep_count);
ResourceMark rm;
outputStream* out = log.debug_stream();
AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size");
size_t total_free = 0;
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
const AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
total_free += fl->count() * fl->size();
if (i % (40*IndexSetStride) == 0) {
AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
AdaptiveFreeList<FreeChunk>::print_labels_on(out, "size");
}
fl->print_on(gclog_or_tty);
fl->print_on(out);
total.set_bfr_surp( total.bfr_surp() + fl->bfr_surp() );
total.set_surplus( total.surplus() + fl->surplus() );
total.set_desired( total.desired() + fl->desired() );
@ -2408,14 +2403,13 @@ void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
total.set_split_births(total.split_births() + fl->split_births());
total.set_split_deaths(total.split_deaths() + fl->split_deaths());
}
total.print_on(gclog_or_tty, "TOTAL");
gclog_or_tty->print_cr("Total free in indexed lists "
SIZE_FORMAT " words", total_free);
gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n",
(double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
(total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
(double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
_dictionary->print_dict_census();
total.print_on(out, "TOTAL");
log.debug("Total free in indexed lists " SIZE_FORMAT " words", total_free);
log.debug("growth: %8.5f deficit: %8.5f",
(double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
(total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
(double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
_dictionary->print_dict_census(out);
}
///////////////////////////////////////////////////////////////////////////
@ -2544,10 +2538,7 @@ void CFLS_LAB::compute_desired_plab_size() {
// Reset counters for next round
_global_num_workers[i] = 0;
_global_num_blocks[i] = 0;
if (PrintOldPLAB) {
gclog_or_tty->print_cr("[" SIZE_FORMAT "]: " SIZE_FORMAT,
i, (size_t)_blocks_to_claim[i].average());
}
log_trace(gc, plab)("[" SIZE_FORMAT "]: " SIZE_FORMAT, i, (size_t)_blocks_to_claim[i].average());
}
}
}
@ -2584,10 +2575,8 @@ void CFLS_LAB::retire(int tid) {
_indexedFreeList[i].set_size(i);
}
}
if (PrintOldPLAB) {
gclog_or_tty->print_cr("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT,
tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
}
log_trace(gc, plab)("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT,
tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
// Reset stats for next round
_num_blocks[i] = 0;
}

View File

@ -29,6 +29,7 @@
#include "gc/cms/promotionInfo.hpp"
#include "gc/shared/blockOffsetTable.hpp"
#include "gc/shared/space.hpp"
#include "logging/log.hpp"
#include "memory/binaryTreeDictionary.hpp"
#include "memory/freeList.hpp"
@ -275,8 +276,8 @@ class CompactibleFreeListSpace: public CompactibleSpace {
void verify_objects_initialized() const;
// Statistics reporting helper functions
void reportFreeListStatistics() const;
void reportIndexedFreeListStatistics() const;
void reportFreeListStatistics(const char* title) const;
void reportIndexedFreeListStatistics(outputStream* st) const;
size_t maxChunkSizeInIndexedFreeLists() const;
size_t numFreeBlocksInIndexedFreeLists() const;
// Accessor
@ -450,11 +451,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
void save_sweep_limit() {
_sweep_limit = BlockOffsetArrayUseUnallocatedBlock ?
unallocated_block() : end();
if (CMSTraceSweeper) {
gclog_or_tty->print_cr(">>>>> Saving sweep limit " PTR_FORMAT
" for space [" PTR_FORMAT "," PTR_FORMAT ") <<<<<<",
p2i(_sweep_limit), p2i(bottom()), p2i(end()));
}
log_develop_trace(gc, sweep)(">>>>> Saving sweep limit " PTR_FORMAT
" for space [" PTR_FORMAT "," PTR_FORMAT ") <<<<<<",
p2i(_sweep_limit), p2i(bottom()), p2i(end()));
}
NOT_PRODUCT(
void clear_sweep_limit() { _sweep_limit = NULL; }

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
#include "gc/shared/generationCounters.hpp"
#include "gc/shared/space.hpp"
#include "gc/shared/taskqueue.hpp"
#include "logging/log.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/iterator.hpp"
#include "memory/virtualspace.hpp"
@ -308,9 +309,8 @@ class ChunkArray: public CHeapObj<mtGC> {
void reset() {
_index = 0;
if (_overflows > 0 && PrintCMSStatistics > 1) {
warning("CMS: ChunkArray[" SIZE_FORMAT "] overflowed " SIZE_FORMAT " times",
_capacity, _overflows);
if (_overflows > 0) {
log_trace(gc)("CMS: ChunkArray[" SIZE_FORMAT "] overflowed " SIZE_FORMAT " times", _capacity, _overflows);
}
_overflows = 0;
}
@ -451,7 +451,7 @@ class CMSStats VALUE_OBJ_CLASS_SPEC {
// Debugging.
void print_on(outputStream* st) const PRODUCT_RETURN;
void print() const { print_on(gclog_or_tty); }
void print() const { print_on(tty); }
};
// A closure related to weak references processing which
@ -935,7 +935,7 @@ class CMSCollector: public CHeapObj<mtGC> {
void startTimer() { assert(!_timer.is_active(), "Error"); _timer.start(); }
void stopTimer() { assert( _timer.is_active(), "Error"); _timer.stop(); }
void resetTimer() { assert(!_timer.is_active(), "Error"); _timer.reset(); }
double timerValue() { assert(!_timer.is_active(), "Error"); return _timer.seconds(); }
jlong timerTicks() { assert(!_timer.is_active(), "Error"); return _timer.ticks(); }
int yields() { return _numYields; }
void resetYields() { _numYields = 0; }
@ -961,7 +961,7 @@ class CMSCollector: public CHeapObj<mtGC> {
// Debugging
void verify();
bool verify_after_remark(bool silent = VerifySilently);
bool verify_after_remark();
void verify_ok_to_terminate() const PRODUCT_RETURN;
void verify_work_stacks_empty() const PRODUCT_RETURN;
void verify_overflow_empty() const PRODUCT_RETURN;
@ -1234,7 +1234,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
const char* name() const;
virtual const char* short_name() const { return "CMS"; }
void print() const;
void printOccupancy(const char* s);
// Resize the generation after a compacting GC. The
// generation can be treated as a contiguous space

View File

@ -34,7 +34,7 @@
#include "gc/shared/gcHeapSummary.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/generation.hpp"
@ -45,6 +45,7 @@
#include "gc/shared/strongRootsScope.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "gc/shared/workgroup.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
@ -270,9 +271,9 @@ void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, size_t word_sz) {
}
void ParScanThreadState::print_promotion_failure_size() {
if (_promotion_failed_info.has_failed() && PrintPromotionFailure) {
gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
_thread_num, _promotion_failed_info.first_size());
if (_promotion_failed_info.has_failed()) {
log_trace(gc, promotion)(" (%d: promotion failure size = " SIZE_FORMAT ") ",
_thread_num, _promotion_failed_info.first_size());
}
}
@ -298,11 +299,11 @@ public:
#if TASKQUEUE_STATS
static void
print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
void print_termination_stats(outputStream* const st = gclog_or_tty);
print_termination_stats_hdr(outputStream* const st);
void print_termination_stats();
static void
print_taskqueue_stats_hdr(outputStream* const st = gclog_or_tty);
void print_taskqueue_stats(outputStream* const st = gclog_or_tty);
print_taskqueue_stats_hdr(outputStream* const st);
void print_taskqueue_stats();
void reset_stats();
#endif // TASKQUEUE_STATS
@ -383,7 +384,15 @@ void ParScanThreadStateSet::print_termination_stats_hdr(outputStream* const st)
st->print_raw_cr("--- --------- --------- ------ --------- ------ --------");
}
void ParScanThreadStateSet::print_termination_stats(outputStream* const st) {
void ParScanThreadStateSet::print_termination_stats() {
LogHandle(gc, task, stats) log;
if (!log.is_debug()) {
return;
}
ResourceMark rm;
outputStream* st = log.debug_stream();
print_termination_stats_hdr(st);
for (int i = 0; i < length(); ++i) {
@ -404,7 +413,13 @@ void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) {
st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
}
void ParScanThreadStateSet::print_taskqueue_stats(outputStream* const st) {
void ParScanThreadStateSet::print_taskqueue_stats() {
if (!develop_log_is_enabled(Trace, gc, task, stats)) {
return;
}
LogHandle(gc, task, stats) log;
ResourceMark rm;
outputStream* st = log.trace_stream();
print_taskqueue_stats_hdr(st);
TaskQueueStats totals;
@ -823,9 +838,7 @@ void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThr
_promo_failure_scan_stack.clear(true); // Clear cached segments.
remove_forwarding_pointers();
if (PrintGCDetails) {
gclog_or_tty->print(" (promotion failed)");
}
log_info(gc, promotion)("Promotion failed");
// All the spaces are in play for mark-sweep.
swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
from()->set_next_compaction_space(to());
@ -882,9 +895,7 @@ void ParNewGeneration::collect(bool full,
size_policy->minor_collection_begin();
}
GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL);
// Capture heap used before collection (for printing).
size_t gch_prev_used = gch->used();
GCTraceTime(Trace, gc) t1("ParNew", NULL, gch->gc_cause());
age_table()->clear();
to()->clear(SpaceDecorator::Mangle);
@ -990,12 +1001,8 @@ void ParNewGeneration::collect(bool full,
plab_stats()->adjust_desired_plab_sz();
}
if (PrintGC && !PrintGCDetails) {
gch->print_heap_change(gch_prev_used);
}
TASKQUEUE_STATS_ONLY(if (PrintTerminationStats) thread_state_set.print_termination_stats());
TASKQUEUE_STATS_ONLY(if (PrintTaskqueue) thread_state_set.print_taskqueue_stats());
TASKQUEUE_STATS_ONLY(thread_state_set.print_termination_stats());
TASKQUEUE_STATS_ONLY(thread_state_set.print_taskqueue_stats());
if (UseAdaptiveSizePolicy) {
size_policy->minor_collection_end(gch->gc_cause());
@ -1150,11 +1157,9 @@ oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state,
// This code must come after the CAS test, or it will print incorrect
// information.
if (TraceScavenge) {
gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}",
is_in_reserved(new_obj) ? "copying" : "tenuring",
new_obj->klass()->internal_name(), p2i(old), p2i(new_obj), new_obj->size());
}
log_develop_trace(gc, scavenge)("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}",
is_in_reserved(new_obj) ? "copying" : "tenuring",
new_obj->klass()->internal_name(), p2i(old), p2i(new_obj), new_obj->size());
if (forward_ptr == NULL) {
oop obj_to_push = new_obj;
@ -1176,9 +1181,7 @@ oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state,
)
if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) {
// Add stats for overflow pushes.
if (Verbose && PrintGCDetails) {
gclog_or_tty->print("queue overflow!\n");
}
log_develop_trace(gc)("Queue Overflow");
push_on_overflow_list(old, par_scan_state);
TASKQUEUE_STATS_ONLY(par_scan_state->taskqueue_stats().record_overflow(0));
}

View File

@ -30,6 +30,7 @@
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "logging/log.hpp"
template <class T> inline void ParScanWeakRefClosure::do_oop_work(T* p) {
assert (!oopDesc::is_null(*p), "null weak reference?");
@ -108,11 +109,9 @@ inline void ParScanClosure::do_oop_work(T* p,
if (m->is_marked()) { // Contains forwarding pointer.
new_obj = ParNewGeneration::real_forwardee(obj);
oopDesc::encode_store_heap_oop_not_null(p, new_obj);
if (TraceScavenge) {
gclog_or_tty->print_cr("{%s %s ( " PTR_FORMAT " ) " PTR_FORMAT " -> " PTR_FORMAT " (%d)}",
"forwarded ",
new_obj->klass()->internal_name(), p2i(p), p2i((void *)obj), p2i((void *)new_obj), new_obj->size());
}
log_develop_trace(gc, scavenge)("{%s %s ( " PTR_FORMAT " ) " PTR_FORMAT " -> " PTR_FORMAT " (%d)}",
"forwarded ",
new_obj->klass()->internal_name(), p2i(p), p2i((void *)obj), p2i((void *)new_obj), new_obj->size());
} else {
size_t obj_sz = obj->size_given_klass(objK);
new_obj = _g->copy_to_survivor_space(_par_scan_state, obj, obj_sz, m);

View File

@ -132,7 +132,7 @@ class SpoolBlock: public FreeChunk {
}
void print_on(outputStream* st) const;
void print() const { print_on(gclog_or_tty); }
void print() const { print_on(tty); }
};
class PromotionInfo VALUE_OBJ_CLASS_SPEC {

View File

@ -28,7 +28,7 @@
#include "gc/cms/vmCMSOperations.hpp"
#include "gc/shared/gcLocker.inline.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTraceTime.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/isGCActiveMark.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp"
@ -58,7 +58,7 @@ void VM_CMS_Operation::release_and_notify_pending_list_lock() {
void VM_CMS_Operation::verify_before_gc() {
if (VerifyBeforeGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm);
GCTraceTime(Info, gc, verify) tm("Verify Before", _collector->_gc_timer_cm);
HandleMark hm;
FreelistLocker x(_collector);
MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
@ -70,7 +70,7 @@ void VM_CMS_Operation::verify_before_gc() {
void VM_CMS_Operation::verify_after_gc() {
if (VerifyAfterGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm);
GCTraceTime(Info, gc, verify) tm("Verify After", _collector->_gc_timer_cm);
HandleMark hm;
FreelistLocker x(_collector);
MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);

View File

@ -26,7 +26,6 @@
#include "gc/g1/collectionSetChooser.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1ErgoVerbose.hpp"
#include "gc/shared/space.inline.hpp"
#include "runtime/atomic.inline.hpp"
@ -136,8 +135,8 @@ void CollectionSetChooser::sort_regions() {
assert(regions_at(i) != NULL, "Should be true by sorting!");
}
#endif // ASSERT
if (G1PrintRegionLivenessInfo) {
G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Sorting");
if (log_is_enabled(Trace, gc, liveness)) {
G1PrintRegionLivenessInfoClosure cl("Post-Sorting");
for (uint i = 0; i < _end; ++i) {
HeapRegion* r = regions_at(i);
cl.doHeapRegion(r);

View File

@ -28,6 +28,7 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/suspendibleThreadSet.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
@ -88,11 +89,8 @@ bool ConcurrentG1RefineThread::is_active() {
void ConcurrentG1RefineThread::activate() {
MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
if (!is_primary()) {
if (G1TraceConcRefinement) {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
_worker_id, _threshold, (int)dcqs.completed_buffers_num());
}
log_debug(gc, refine)("G1-Refine-activated worker %d, on threshold %d, current %d",
_worker_id, _threshold, JavaThread::dirty_card_queue_set().completed_buffers_num());
set_active(true);
} else {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
@ -104,11 +102,8 @@ void ConcurrentG1RefineThread::activate() {
void ConcurrentG1RefineThread::deactivate() {
MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
if (!is_primary()) {
if (G1TraceConcRefinement) {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
_worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num());
}
log_debug(gc, refine)("G1-Refine-deactivated worker %d, off threshold %d, current %d",
_worker_id, _deactivation_threshold, JavaThread::dirty_card_queue_set().completed_buffers_num());
set_active(false);
} else {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
@ -174,9 +169,7 @@ void ConcurrentG1RefineThread::run_service() {
}
}
if (G1TraceConcRefinement) {
gclog_or_tty->print_cr("G1-Refine-stop");
}
log_debug(gc, refine)("G1-Refine-stop");
}
void ConcurrentG1RefineThread::stop() {
@ -199,4 +192,4 @@ void ConcurrentG1RefineThread::stop() {
void ConcurrentG1RefineThread::stop_service() {
MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
_monitor->notify();
}
}

View File

@ -31,8 +31,6 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1CollectorState.hpp"
#include "gc/g1/g1ErgoVerbose.hpp"
#include "gc/g1/g1Log.hpp"
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/g1StringDedup.hpp"
@ -44,12 +42,13 @@
#include "gc/shared/gcId.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/strongRootsScope.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "gc/shared/vmGCOperations.hpp"
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
@ -232,9 +231,7 @@ void CMMarkStack::expand() {
// Clear expansion flag
_should_expand = false;
if (_capacity == (jint) MarkStackSizeMax) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr(" (benign) Can't expand marking stack capacity, at max size limit");
}
log_trace(gc)("(benign) Can't expand marking stack capacity, at max size limit");
return;
}
// Double capacity if possible
@ -254,12 +251,9 @@ void CMMarkStack::expand() {
_index = 0;
_capacity = new_capacity;
} else {
if (PrintGCDetails && Verbose) {
// Failed to double capacity, continue;
gclog_or_tty->print(" (benign) Failed to expand marking stack capacity from "
SIZE_FORMAT "K to " SIZE_FORMAT "K",
_capacity / K, new_capacity / K);
}
// Failed to double capacity, continue;
log_trace(gc)("(benign) Failed to expand marking stack capacity from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
_capacity / K, new_capacity / K);
}
}
@ -848,10 +842,7 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
// marking.
reset_marking_state(true /* clear_overflow */);
if (G1Log::fine()) {
gclog_or_tty->gclog_stamp();
gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]");
}
log_info(gc)("Concurrent Mark reset for overflow");
}
}
@ -987,8 +978,6 @@ public:
};
void ConcurrentMark::scanRootRegions() {
double scan_start = os::elapsedTime();
// Start of concurrent marking.
ClassLoaderDataGraph::clear_claimed_marks();
@ -996,10 +985,7 @@ void ConcurrentMark::scanRootRegions() {
// at least one root region to scan. So, if it's false, we
// should not attempt to do any further work.
if (root_regions()->scan_in_progress()) {
if (G1Log::fine()) {
gclog_or_tty->gclog_stamp();
gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]");
}
GCTraceConcTime(Info, gc) tt("Concurrent Root Region Scan");
_parallel_marking_threads = calc_parallel_marking_threads();
assert(parallel_marking_threads() <= max_parallel_marking_threads(),
@ -1010,11 +996,6 @@ void ConcurrentMark::scanRootRegions() {
_parallel_workers->set_active_workers(active_workers);
_parallel_workers->run_task(&task);
if (G1Log::fine()) {
gclog_or_tty->gclog_stamp();
gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]", os::elapsedTime() - scan_start);
}
// It's possible that has_aborted() is true here without actually
// aborting the survivor scan earlier. This is OK as it's
// mainly used for sanity checking.
@ -1049,22 +1030,6 @@ void ConcurrentMark::markFromRoots() {
print_stats();
}
// Helper class to get rid of some boilerplate code.
class G1CMTraceTime : public StackObj {
GCTraceTimeImpl _gc_trace_time;
static bool doit_and_prepend(bool doit) {
if (doit) {
gclog_or_tty->put(' ');
}
return doit;
}
public:
G1CMTraceTime(const char* title, bool doit)
: _gc_trace_time(title, doit_and_prepend(doit), false, G1CollectedHeap::heap()->gc_timer_cm()) {
}
};
void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
// world is stopped at this checkpoint
assert(SafepointSynchronize::is_at_safepoint(),
@ -1083,8 +1048,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
if (VerifyDuringGC) {
HandleMark hm; // handle scope
g1h->prepare_for_verify();
Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(before)");
Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (before)");
}
g1h->check_bitmaps("Remark Start");
@ -1102,16 +1066,13 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
if (has_overflown()) {
// Oops. We overflowed. Restart concurrent marking.
_restart_for_overflow = true;
if (G1TraceMarkStackOverflow) {
gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
}
log_develop_trace(gc)("Remark led to restart for overflow.");
// Verify the heap w.r.t. the previous marking bitmap.
if (VerifyDuringGC) {
HandleMark hm; // handle scope
g1h->prepare_for_verify();
Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(overflow)");
Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (overflow)");
}
// Clear the marking state because we will be restarting
@ -1119,7 +1080,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
reset_marking_state();
} else {
{
G1CMTraceTime trace("GC aggregate-data", G1Log::finer());
GCTraceTime(Debug, gc) trace("GC Aggregate Data", g1h->gc_timer_cm());
// Aggregate the per-task counting data that we have accumulated
// while marking.
@ -1136,8 +1097,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
if (VerifyDuringGC) {
HandleMark hm; // handle scope
g1h->prepare_for_verify();
Universe::verify(VerifyOption_G1UseNextMarking,
" VerifyDuringGC:(after)");
Universe::verify(VerifyOption_G1UseNextMarking, "During GC (after)");
}
g1h->check_bitmaps("Remark End");
assert(!restart_for_overflow(), "sanity");
@ -1523,8 +1483,8 @@ class G1NoteEndOfConcMarkClosure : public HeapRegionClosure {
G1CollectedHeap* _g1;
size_t _freed_bytes;
FreeRegionList* _local_cleanup_list;
HeapRegionSetCount _old_regions_removed;
HeapRegionSetCount _humongous_regions_removed;
uint _old_regions_removed;
uint _humongous_regions_removed;
HRRSCleanupTask* _hrrs_cleanup_task;
public:
@ -1534,13 +1494,13 @@ public:
_g1(g1),
_freed_bytes(0),
_local_cleanup_list(local_cleanup_list),
_old_regions_removed(),
_humongous_regions_removed(),
_old_regions_removed(0),
_humongous_regions_removed(0),
_hrrs_cleanup_task(hrrs_cleanup_task) { }
size_t freed_bytes() { return _freed_bytes; }
const HeapRegionSetCount& old_regions_removed() { return _old_regions_removed; }
const HeapRegionSetCount& humongous_regions_removed() { return _humongous_regions_removed; }
const uint old_regions_removed() { return _old_regions_removed; }
const uint humongous_regions_removed() { return _humongous_regions_removed; }
bool doHeapRegion(HeapRegion *hr) {
if (hr->is_archive()) {
@ -1555,10 +1515,10 @@ public:
_freed_bytes += hr->used();
hr->set_containing_set(NULL);
if (hr->is_humongous()) {
_humongous_regions_removed.increment(1u, hr->capacity());
_humongous_regions_removed++;
_g1->free_humongous_region(hr, _local_cleanup_list, true);
} else {
_old_regions_removed.increment(1u, hr->capacity());
_old_regions_removed++;
_g1->free_region(hr, _local_cleanup_list, true);
}
} else {
@ -1656,8 +1616,7 @@ void ConcurrentMark::cleanup() {
if (VerifyDuringGC) {
HandleMark hm; // handle scope
g1h->prepare_for_verify();
Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(before)");
Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (before)");
}
g1h->check_bitmaps("Cleanup Start");
@ -1699,8 +1658,8 @@ void ConcurrentMark::cleanup() {
double this_final_counting_time = (count_end - start);
_total_counting_time += this_final_counting_time;
if (G1PrintRegionLivenessInfo) {
G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Marking");
if (log_is_enabled(Trace, gc, liveness)) {
G1PrintRegionLivenessInfoClosure cl("Post-Marking");
_g1h->heap_region_iterate(&cl);
}
@ -1743,10 +1702,6 @@ void ConcurrentMark::cleanup() {
double end = os::elapsedTime();
_cleanup_times.add((end - start) * 1000.0);
if (G1Log::fine()) {
g1h->g1_policy()->print_heap_transition(start_used_bytes);
}
// Clean up will have freed any regions completely full of garbage.
// Update the soft reference policy with the new heap occupancy.
Universe::update_heap_info_at_gc();
@ -1754,8 +1709,7 @@ void ConcurrentMark::cleanup() {
if (VerifyDuringGC) {
HandleMark hm; // handle scope
g1h->prepare_for_verify();
Universe::verify(VerifyOption_G1UsePrevMarking,
" VerifyDuringGC:(after)");
Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (after)");
}
g1h->check_bitmaps("Cleanup End");
@ -1788,11 +1742,9 @@ void ConcurrentMark::completeCleanup() {
_cleanup_list.verify_optional();
FreeRegionList tmp_free_list("Tmp Free List");
if (G1ConcRegionFreeingVerbose) {
gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
"cleanup list has %u entries",
_cleanup_list.length());
}
log_develop_trace(gc, freelist)("G1ConcRegionFreeing [complete cleanup] : "
"cleanup list has %u entries",
_cleanup_list.length());
// No one else should be accessing the _cleanup_list at this point,
// so it is not necessary to take any locks
@ -1810,13 +1762,11 @@ void ConcurrentMark::completeCleanup() {
// region from the _cleanup_list).
if ((tmp_free_list.length() % G1SecondaryFreeListAppendLength == 0) ||
_cleanup_list.is_empty()) {
if (G1ConcRegionFreeingVerbose) {
gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
"appending %u entries to the secondary_free_list, "
"cleanup list still has %u entries",
tmp_free_list.length(),
_cleanup_list.length());
}
log_develop_trace(gc, freelist)("G1ConcRegionFreeing [complete cleanup] : "
"appending %u entries to the secondary_free_list, "
"cleanup list still has %u entries",
tmp_free_list.length(),
_cleanup_list.length());
{
MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
@ -2073,7 +2023,7 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
// Inner scope to exclude the cleaning of the string and symbol
// tables from the displayed time.
{
G1CMTraceTime t("GC ref-proc", G1Log::finer());
GCTraceTime(Debug, gc) trace("GC Ref Proc", g1h->gc_timer_cm());
ReferenceProcessor* rp = g1h->ref_processor_cm();
@ -2163,24 +2113,24 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
// Unload Klasses, String, Symbols, Code Cache, etc.
{
G1CMTraceTime trace("Unloading", G1Log::finer());
GCTraceTime(Debug, gc) trace("Unloading", g1h->gc_timer_cm());
if (ClassUnloadingWithConcurrentMark) {
bool purged_classes;
{
G1CMTraceTime trace("System Dictionary Unloading", G1Log::finest());
GCTraceTime(Trace, gc) trace("System Dictionary Unloading", g1h->gc_timer_cm());
purged_classes = SystemDictionary::do_unloading(&g1_is_alive, false /* Defer klass cleaning */);
}
{
G1CMTraceTime trace("Parallel Unloading", G1Log::finest());
GCTraceTime(Trace, gc) trace("Parallel Unloading", g1h->gc_timer_cm());
weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
}
}
if (G1StringDedup::is_enabled()) {
G1CMTraceTime trace("String Deduplication Unlink", G1Log::finest());
GCTraceTime(Trace, gc) trace("String Deduplication Unlink", g1h->gc_timer_cm());
G1StringDedup::unlink(&g1_is_alive);
}
}
@ -2301,7 +2251,7 @@ void ConcurrentMark::checkpointRootsFinalWork() {
HandleMark hm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
G1CMTraceTime trace("Finalize Marking", G1Log::finer());
GCTraceTime(Debug, gc) trace("Finalize Marking", g1h->gc_timer_cm());
g1h->ensure_parsability(false);
@ -2614,12 +2564,13 @@ void ConcurrentMark::clear_all_count_data() {
}
void ConcurrentMark::print_stats() {
if (G1MarkingVerboseLevel > 0) {
gclog_or_tty->print_cr("---------------------------------------------------------------------");
for (size_t i = 0; i < _active_tasks; ++i) {
_tasks[i]->print_stats();
gclog_or_tty->print_cr("---------------------------------------------------------------------");
}
if (!log_is_enabled(Debug, gc, stats)) {
return;
}
log_debug(gc, stats)("---------------------------------------------------------------------");
for (size_t i = 0; i < _active_tasks; ++i) {
_tasks[i]->print_stats();
log_debug(gc, stats)("---------------------------------------------------------------------");
}
}
@ -2663,16 +2614,21 @@ void ConcurrentMark::abort() {
static void print_ms_time_info(const char* prefix, const char* name,
NumberSeq& ns) {
gclog_or_tty->print_cr("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).",
log_trace(gc, marking)("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).",
prefix, ns.num(), name, ns.sum()/1000.0, ns.avg());
if (ns.num() > 0) {
gclog_or_tty->print_cr("%s [std. dev = %8.2f ms, max = %8.2f ms]",
log_trace(gc, marking)("%s [std. dev = %8.2f ms, max = %8.2f ms]",
prefix, ns.sd(), ns.maximum());
}
}
void ConcurrentMark::print_summary_info() {
gclog_or_tty->print_cr(" Concurrent marking:");
LogHandle(gc, marking) log;
if (!log.is_trace()) {
return;
}
log.trace(" Concurrent marking:");
print_ms_time_info(" ", "init marks", _init_times);
print_ms_time_info(" ", "remarks", _remark_times);
{
@ -2681,25 +2637,16 @@ void ConcurrentMark::print_summary_info() {
}
print_ms_time_info(" ", "cleanups", _cleanup_times);
gclog_or_tty->print_cr(" Final counting total time = %8.2f s (avg = %8.2f ms).",
_total_counting_time,
(_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 /
(double)_cleanup_times.num()
: 0.0));
log.trace(" Final counting total time = %8.2f s (avg = %8.2f ms).",
_total_counting_time, (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / (double)_cleanup_times.num() : 0.0));
if (G1ScrubRemSets) {
gclog_or_tty->print_cr(" RS scrub total time = %8.2f s (avg = %8.2f ms).",
_total_rs_scrub_time,
(_cleanup_times.num() > 0 ? _total_rs_scrub_time * 1000.0 /
(double)_cleanup_times.num()
: 0.0));
log.trace(" RS scrub total time = %8.2f s (avg = %8.2f ms).",
_total_rs_scrub_time, (_cleanup_times.num() > 0 ? _total_rs_scrub_time * 1000.0 / (double)_cleanup_times.num() : 0.0));
}
gclog_or_tty->print_cr(" Total stop_world time = %8.2f s.",
(_init_times.sum() + _remark_times.sum() +
_cleanup_times.sum())/1000.0);
gclog_or_tty->print_cr(" Total concurrent time = %8.2f s "
"(%8.2f s marking).",
cmThread()->vtime_accum(),
cmThread()->vtime_mark_accum());
log.trace(" Total stop_world time = %8.2f s.",
(_init_times.sum() + _remark_times.sum() + _cleanup_times.sum())/1000.0);
log.trace(" Total concurrent time = %8.2f s (%8.2f s marking).",
cmThread()->vtime_accum(), cmThread()->vtime_mark_accum());
}
void ConcurrentMark::print_worker_threads_on(outputStream* st) const {
@ -3079,15 +3026,15 @@ void CMTask::drain_satb_buffers() {
}
void CMTask::print_stats() {
gclog_or_tty->print_cr("Marking Stats, task = %u, calls = %d",
_worker_id, _calls);
gclog_or_tty->print_cr(" Elapsed time = %1.2lfms, Termination time = %1.2lfms",
_elapsed_time_ms, _termination_time_ms);
gclog_or_tty->print_cr(" Step Times (cum): num = %d, avg = %1.2lfms, sd = %1.2lfms",
_step_times_ms.num(), _step_times_ms.avg(),
_step_times_ms.sd());
gclog_or_tty->print_cr(" max = %1.2lfms, total = %1.2lfms",
_step_times_ms.maximum(), _step_times_ms.sum());
log_debug(gc, stats)("Marking Stats, task = %u, calls = %d",
_worker_id, _calls);
log_debug(gc, stats)(" Elapsed time = %1.2lfms, Termination time = %1.2lfms",
_elapsed_time_ms, _termination_time_ms);
log_debug(gc, stats)(" Step Times (cum): num = %d, avg = %1.2lfms, sd = %1.2lfms",
_step_times_ms.num(), _step_times_ms.avg(),
_step_times_ms.sd());
log_debug(gc, stats)(" max = %1.2lfms, total = %1.2lfms",
_step_times_ms.maximum(), _step_times_ms.sum());
}
bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) {
@ -3587,9 +3534,8 @@ CMTask::CMTask(uint worker_id,
#define G1PPRL_SUM_MB_PERC_FORMAT(tag) G1PPRL_SUM_MB_FORMAT(tag) " / %1.2f %%"
G1PrintRegionLivenessInfoClosure::
G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name)
: _out(out),
_total_used_bytes(0), _total_capacity_bytes(0),
G1PrintRegionLivenessInfoClosure(const char* phase_name)
: _total_used_bytes(0), _total_capacity_bytes(0),
_total_prev_live_bytes(0), _total_next_live_bytes(0),
_hum_used_bytes(0), _hum_capacity_bytes(0),
_hum_prev_live_bytes(0), _hum_next_live_bytes(0),
@ -3599,38 +3545,37 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name)
double now = os::elapsedTime();
// Print the header of the output.
_out->cr();
_out->print_cr(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now);
_out->print_cr(G1PPRL_LINE_PREFIX" HEAP"
G1PPRL_SUM_ADDR_FORMAT("reserved")
G1PPRL_SUM_BYTE_FORMAT("region-size"),
p2i(g1_reserved.start()), p2i(g1_reserved.end()),
HeapRegion::GrainBytes);
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_H_FORMAT
G1PPRL_ADDR_BASE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_DOUBLE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT,
"type", "address-range",
"used", "prev-live", "next-live", "gc-eff",
"remset", "code-roots");
_out->print_cr(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_H_FORMAT
G1PPRL_ADDR_BASE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_DOUBLE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT,
"", "",
"(bytes)", "(bytes)", "(bytes)", "(bytes/ms)",
"(bytes)", "(bytes)");
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now);
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX" HEAP"
G1PPRL_SUM_ADDR_FORMAT("reserved")
G1PPRL_SUM_BYTE_FORMAT("region-size"),
p2i(g1_reserved.start()), p2i(g1_reserved.end()),
HeapRegion::GrainBytes);
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX);
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_H_FORMAT
G1PPRL_ADDR_BASE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_DOUBLE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT,
"type", "address-range",
"used", "prev-live", "next-live", "gc-eff",
"remset", "code-roots");
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_H_FORMAT
G1PPRL_ADDR_BASE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_DOUBLE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT,
"", "",
"(bytes)", "(bytes)", "(bytes)", "(bytes/ms)",
"(bytes)", "(bytes)");
}
// It takes as a parameter a reference to one of the _hum_* fields, it
@ -3701,18 +3646,18 @@ bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
_total_strong_code_roots_bytes += strong_code_roots_bytes;
// Print a line for this particular region.
_out->print_cr(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_FORMAT
G1PPRL_ADDR_BASE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_DOUBLE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT,
type, p2i(bottom), p2i(end),
used_bytes, prev_live_bytes, next_live_bytes, gc_eff,
remset_bytes, strong_code_roots_bytes);
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_FORMAT
G1PPRL_ADDR_BASE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_DOUBLE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT,
type, p2i(bottom), p2i(end),
used_bytes, prev_live_bytes, next_live_bytes, gc_eff,
remset_bytes, strong_code_roots_bytes);
return false;
}
@ -3721,23 +3666,22 @@ G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() {
// add static memory usages to remembered set sizes
_total_remset_bytes += HeapRegionRemSet::fl_mem_size() + HeapRegionRemSet::static_mem_size();
// Print the footer of the output.
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
" SUMMARY"
G1PPRL_SUM_MB_FORMAT("capacity")
G1PPRL_SUM_MB_PERC_FORMAT("used")
G1PPRL_SUM_MB_PERC_FORMAT("prev-live")
G1PPRL_SUM_MB_PERC_FORMAT("next-live")
G1PPRL_SUM_MB_FORMAT("remset")
G1PPRL_SUM_MB_FORMAT("code-roots"),
bytes_to_mb(_total_capacity_bytes),
bytes_to_mb(_total_used_bytes),
perc(_total_used_bytes, _total_capacity_bytes),
bytes_to_mb(_total_prev_live_bytes),
perc(_total_prev_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_next_live_bytes),
perc(_total_next_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_remset_bytes),
bytes_to_mb(_total_strong_code_roots_bytes));
_out->cr();
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX);
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX
" SUMMARY"
G1PPRL_SUM_MB_FORMAT("capacity")
G1PPRL_SUM_MB_PERC_FORMAT("used")
G1PPRL_SUM_MB_PERC_FORMAT("prev-live")
G1PPRL_SUM_MB_PERC_FORMAT("next-live")
G1PPRL_SUM_MB_FORMAT("remset")
G1PPRL_SUM_MB_FORMAT("code-roots"),
bytes_to_mb(_total_capacity_bytes),
bytes_to_mb(_total_used_bytes),
perc(_total_used_bytes, _total_capacity_bytes),
bytes_to_mb(_total_prev_live_bytes),
perc(_total_prev_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_next_live_bytes),
perc(_total_next_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_remset_bytes),
bytes_to_mb(_total_strong_code_roots_bytes));
}

View File

@ -978,8 +978,6 @@ public:
// after we sort the old regions at the end of the cleanup operation.
class G1PrintRegionLivenessInfoClosure: public HeapRegionClosure {
private:
outputStream* _out;
// Accumulators for these values.
size_t _total_used_bytes;
size_t _total_capacity_bytes;
@ -1024,7 +1022,7 @@ private:
public:
// The header and footer are printed in the constructor and
// destructor respectively.
G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name);
G1PrintRegionLivenessInfoClosure(const char* phase_name);
virtual bool doHeapRegion(HeapRegion* r);
~G1PrintRegionLivenessInfoClosure();
};

View File

@ -26,12 +26,13 @@
#include "gc/g1/concurrentMarkThread.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1Log.hpp"
#include "gc/g1/g1MMUTracker.hpp"
#include "gc/g1/suspendibleThreadSet.hpp"
#include "gc/g1/vm_operations_g1.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/vmThread.hpp"
@ -78,20 +79,6 @@ public:
}
};
// We want to avoid that the logging from the concurrent thread is mixed
// with the logging from a STW GC. So, if necessary join the STS to ensure
// that the logging is done either before or after the STW logging.
void ConcurrentMarkThread::cm_log(bool doit, bool join_sts, const char* fmt, ...) {
if (doit) {
SuspendibleThreadSetJoiner sts_joiner(join_sts);
va_list args;
va_start(args, fmt);
gclog_or_tty->gclog_stamp();
gclog_or_tty->vprint_cr(fmt, args);
va_end(args);
}
}
// Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU.
void ConcurrentMarkThread::delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool remark) {
if (g1_policy->adaptive_young_list_length()) {
@ -143,8 +130,11 @@ void ConcurrentMarkThread::run_service() {
_cm->scanRootRegions();
}
double mark_start_sec = os::elapsedTime();
cm_log(G1Log::fine(), true, "[GC concurrent-mark-start]");
// It would be nice to use the GCTraceConcTime class here but
// the "end" logging is inside the loop and not at the end of
// a scope. Mimicking the same log output as GCTraceConcTime instead.
jlong mark_start = os::elapsed_counter();
log_info(gc)("Concurrent Mark (%.3fs)", TimeHelper::counter_to_seconds(mark_start));
int iter = 0;
do {
@ -154,20 +144,22 @@ void ConcurrentMarkThread::run_service() {
}
double mark_end_time = os::elapsedVTime();
double mark_end_sec = os::elapsedTime();
jlong mark_end = os::elapsed_counter();
_vtime_mark_accum += (mark_end_time - cycle_start);
if (!cm()->has_aborted()) {
delay_to_keep_mmu(g1_policy, true /* remark */);
cm_log(G1Log::fine(), true, "[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec);
log_info(gc)("Concurrent Mark (%.3fs, %.3fs) %.3fms",
TimeHelper::counter_to_seconds(mark_start),
TimeHelper::counter_to_seconds(mark_end),
TimeHelper::counter_to_millis(mark_end - mark_start));
CMCheckpointRootsFinalClosure final_cl(_cm);
VM_CGC_Operation op(&final_cl, "GC remark", true /* needs_pll */);
VM_CGC_Operation op(&final_cl, "Pause Remark", true /* needs_pll */);
VMThread::execute(&op);
}
if (cm()->restart_for_overflow()) {
cm_log(G1TraceMarkStackOverflow, true, "Restarting conc marking because of MS overflow in remark (restart #%d).", iter);
cm_log(G1Log::fine(), true, "[GC concurrent-mark-restart-for-overflow]");
log_debug(gc)("Restarting conc marking because of MS overflow in remark (restart #%d).", iter);
log_info(gc)("Concurrent Mark restart for overflow");
}
} while (cm()->restart_for_overflow());
@ -181,7 +173,7 @@ void ConcurrentMarkThread::run_service() {
delay_to_keep_mmu(g1_policy, false /* cleanup */);
CMCleanUp cl_cl(_cm);
VM_CGC_Operation op(&cl_cl, "GC cleanup", false /* needs_pll */);
VM_CGC_Operation op(&cl_cl, "Pause Cleanup", false /* needs_pll */);
VMThread::execute(&op);
} else {
// We don't want to update the marking status if a GC pause
@ -201,8 +193,7 @@ void ConcurrentMarkThread::run_service() {
// place, it would wait for us to process the regions
// reclaimed by cleanup.
double cleanup_start_sec = os::elapsedTime();
cm_log(G1Log::fine(), false, "[GC concurrent-cleanup-start]");
GCTraceConcTime(Info, gc) tt("Concurrent Cleanup");
// Now do the concurrent cleanup operation.
_cm->completeCleanup();
@ -217,9 +208,6 @@ void ConcurrentMarkThread::run_service() {
// while it's trying to join the STS, which is conditional on
// the GC workers finishing.
g1h->reset_free_regions_coming();
double cleanup_end_sec = os::elapsedTime();
cm_log(G1Log::fine(), true, "[GC concurrent-cleanup-end, %1.7lf secs]", cleanup_end_sec - cleanup_start_sec);
}
guarantee(cm()->cleanup_list_is_empty(),
"at this point there should be no regions on the cleanup list");
@ -253,7 +241,7 @@ void ConcurrentMarkThread::run_service() {
if (!cm()->has_aborted()) {
g1_policy->record_concurrent_mark_cleanup_completed();
} else {
cm_log(G1Log::fine(), false, "[GC concurrent-mark-abort]");
log_info(gc)("Concurrent Mark abort");
}
}

View File

@ -40,7 +40,6 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
double _vtime_accum; // Accumulated virtual time.
double _vtime_mark_accum;
void cm_log(bool doit, bool join_sts, const char* fmt, ...) ATTRIBUTE_PRINTF(4, 5);
public:
virtual void run();

View File

@ -112,7 +112,7 @@ void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl,
fl_owner);
set_buffer_size(G1UpdateBufferSize);
_shared_dirty_card_queue.set_lock(lock);
_free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
_free_ids = new FreeIdSet(num_par_ids(), _cbl_mon);
}
void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {

View File

@ -353,7 +353,7 @@ bool G1ArchiveAllocator::alloc_new_region() {
assert(hr->is_empty(), "expected empty region (index %u)", hr->hrm_index());
hr->set_archive();
_g1h->old_set_add(hr);
_g1h->hr_printer()->alloc(hr, G1HRPrinter::Archive);
_g1h->hr_printer()->alloc(hr);
_allocated_regions.append(hr);
_allocation_region = hr;

Some files were not shown because too many files have changed in this diff Show More