--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Apr 22 19:10:03 2015 +0300
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Apr 15 12:44:56 2015 +0200
@@ -32,12 +32,13 @@
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "utilities/defaultStream.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "vm_version_ppc.hpp"
# include <sys/sysinfo.h>
int VM_Version::_features = VM_Version::unknown_m;
-int VM_Version::_measured_cache_line_size = 128; // default value
+int VM_Version::_measured_cache_line_size = 32; // pessimistic init value
const char* VM_Version::_features_str = "";
bool VM_Version::_is_determine_features_test_running = false;
@@ -55,7 +56,9 @@
// If PowerArchitecturePPC64 hasn't been specified explicitly determine from features.
if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) {
- if (VM_Version::has_popcntw()) {
+ if (VM_Version::has_lqarx()) {
+ FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 8);
+ } else if (VM_Version::has_popcntw()) {
FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7);
} else if (VM_Version::has_cmpb()) {
FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 6);
@@ -66,8 +69,14 @@
}
}
guarantee(PowerArchitecturePPC64 == 0 || PowerArchitecturePPC64 == 5 ||
- PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7,
- "PowerArchitecturePPC64 should be 0, 5, 6 or 7");
+ PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7 ||
+ PowerArchitecturePPC64 == 8,
+ "PowerArchitecturePPC64 should be 0, 5, 6, 7, or 8");
+
+ // Power 8: Configure Data Stream Control Register.
+ if (PowerArchitecturePPC64 >= 8) {
+ config_dscr();
+ }
if (!UseSIGTRAP) {
MSG(TrapBasedICMissChecks);
@@ -97,7 +106,7 @@
// Create and print feature-string.
char buf[(num_features+1) * 16]; // Max 16 chars per feature.
jio_snprintf(buf, sizeof(buf),
- "ppc64%s%s%s%s%s%s%s%s",
+ "ppc64%s%s%s%s%s%s%s%s%s%s%s%s",
(has_fsqrt() ? " fsqrt" : ""),
(has_isel() ? " isel" : ""),
(has_lxarxeh() ? " lxarxeh" : ""),
@@ -106,11 +115,17 @@
(has_popcntb() ? " popcntb" : ""),
(has_popcntw() ? " popcntw" : ""),
(has_fcfids() ? " fcfids" : ""),
- (has_vand() ? " vand" : "")
+ (has_vand() ? " vand" : ""),
+ (has_lqarx() ? " lqarx" : ""),
+ (has_vcipher() ? " vcipher" : ""),
+ (has_vpmsumb() ? " vpmsumb" : ""),
+ (has_tcheck() ? " tcheck" : "")
// Make sure number of %s matches num_features!
);
_features_str = os::strdup(buf);
- NOT_PRODUCT(if (Verbose) print_features(););
+ if (Verbose) {
+ print_features();
+ }
// PPC64 supports 8-byte compare-exchange operations (see
// Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr)
@@ -171,6 +186,58 @@
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
+ // Adjust RTM (Restricted Transactional Memory) flags.
+ if (!has_tcheck() && UseRTMLocking) {
+ // 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 (UseRTMLocking) {
+#if INCLUDE_RTM_OPT
+ if (!UnlockExperimentalVMOptions) {
+ vm_exit_during_initialization("UseRTMLocking is only available as experimental option on this platform. "
+ "It must be enabled via -XX:+UnlockExperimentalVMOptions flag.");
+ } else {
+ warning("UseRTMLocking is only available as experimental option on this platform.");
+ }
+ if (!FLAG_IS_CMDLINE(UseRTMLocking)) {
+ // RTM locking should be used only for applications with
+ // high lock contention. For now we do not use it by default.
+ vm_exit_during_initialization("UseRTMLocking flag should be only set on command line");
+ }
+ if (!is_power_of_2(RTMTotalCountIncrRate)) {
+ warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64");
+ FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64);
+ }
+ if (RTMAbortRatio < 0 || RTMAbortRatio > 100) {
+ warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
+ FLAG_SET_DEFAULT(RTMAbortRatio, 50);
+ }
+ FLAG_SET_ERGO(bool, UseNewFastLockPPC64, false); // Does not implement TM.
+ guarantee(RTMSpinLoopCount > 0, "unsupported");
+#else
+ // Only C2 does RTM locking optimization.
+ // Can't continue because UseRTMLocking affects UseBiasedLocking flag
+ // setting during arguments processing. See use_biased_locking().
+ vm_exit_during_initialization("RTM locking optimization is not supported in this VM");
+#endif
+ } else { // !UseRTMLocking
+ if (UseRTMForStackLocks) {
+ if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) {
+ warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off");
+ }
+ FLAG_SET_DEFAULT(UseRTMForStackLocks, false);
+ }
+ if (UseRTMDeopt) {
+ FLAG_SET_DEFAULT(UseRTMDeopt, false);
+ }
+ if (PrintPreciseRTMLockingStatistics) {
+ FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false);
+ }
+ }
// This machine does not allow unaligned memory accesses
if (UseUnalignedAccesses) {
@@ -180,6 +247,27 @@
}
}
+bool VM_Version::use_biased_locking() {
+#if INCLUDE_RTM_OPT
+ // RTM locking is most useful when there is high lock contention and
+ // low data contention. With high lock contention the lock is usually
+ // inflated and biased locking is not suitable for that case.
+ // RTM locking code requires that biased locking is off.
+ // Note: we can't switch off UseBiasedLocking in get_processor_features()
+ // because it is used by Thread::allocate() which is called before
+ // VM_Version::initialize().
+ if (UseRTMLocking && UseBiasedLocking) {
+ if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
+ FLAG_SET_DEFAULT(UseBiasedLocking, false);
+ } else {
+ warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
+ UseBiasedLocking = false;
+ }
+ }
+#endif
+ return UseBiasedLocking;
+}
+
void VM_Version::print_features() {
tty->print_cr("Version: %s cache_line_size = %d", cpu_features(), (int) get_cache_line_size());
}
@@ -443,16 +531,19 @@
// Don't use R0 in ldarx.
// Keep R3_ARG1 unmodified, it contains &field (see below).
// Keep R4_ARG2 unmodified, it contains offset = 0 (see below).
- a->fsqrt(F3, F4); // code[0] -> fsqrt_m
- a->fsqrts(F3, F4); // code[1] -> fsqrts_m
- a->isel(R7, R5, R6, 0); // code[2] -> isel_m
- a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m
- a->cmpb(R7, R5, R6); // code[4] -> bcmp
- //a->mftgpr(R7, F3); // code[5] -> mftgpr
- a->popcntb(R7, R5); // code[6] -> popcntb
- a->popcntw(R7, R5); // code[7] -> popcntw
- a->fcfids(F3, F4); // code[8] -> fcfids
- a->vand(VR0, VR0, VR0); // code[9] -> vand
+ a->fsqrt(F3, F4); // code[0] -> fsqrt_m
+ a->fsqrts(F3, F4); // code[1] -> fsqrts_m
+ a->isel(R7, R5, R6, 0); // code[2] -> isel_m
+ a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m
+ a->cmpb(R7, R5, R6); // code[4] -> cmpb
+ a->popcntb(R7, R5); // code[5] -> popcntb
+ a->popcntw(R7, R5); // code[6] -> popcntw
+ a->fcfids(F3, F4); // code[7] -> fcfids
+ a->vand(VR0, VR0, VR0); // code[8] -> vand
+ a->lqarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[9] -> lqarx_m
+ a->vcipher(VR0, VR1, VR2); // code[10] -> vcipher
+ a->vpmsumb(VR0, VR1, VR2); // code[11] -> vpmsumb
+ a->tcheck(0); // code[12] -> tcheck
a->blr();
// Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
@@ -491,11 +582,14 @@
if (code[feature_cntr++]) features |= isel_m;
if (code[feature_cntr++]) features |= lxarxeh_m;
if (code[feature_cntr++]) features |= cmpb_m;
- //if(code[feature_cntr++])features |= mftgpr_m;
if (code[feature_cntr++]) features |= popcntb_m;
if (code[feature_cntr++]) features |= popcntw_m;
if (code[feature_cntr++]) features |= fcfids_m;
if (code[feature_cntr++]) features |= vand_m;
+ if (code[feature_cntr++]) features |= lqarx_m;
+ if (code[feature_cntr++]) features |= vcipher_m;
+ if (code[feature_cntr++]) features |= vpmsumb_m;
+ if (code[feature_cntr++]) features |= tcheck_m;
// Print the detection code.
if (PrintAssembly) {
@@ -507,6 +601,69 @@
_features = features;
}
+// Power 8: Configure Data Stream Control Register.
+void VM_Version::config_dscr() {
+ assert(has_tcheck(), "Only execute on Power 8 or later!");
+
+ // 7 InstWords for each call (function descriptor + blr instruction).
+ const int code_size = (2+2*7)*BytesPerInstWord;
+
+ // Allocate space for the code.
+ ResourceMark rm;
+ CodeBuffer cb("config_dscr", code_size, 0);
+ MacroAssembler* a = new MacroAssembler(&cb);
+
+ // Emit code.
+ uint64_t (*get_dscr)() = (uint64_t(*)())(void *)a->emit_fd();
+ uint32_t *code = (uint32_t *)a->pc();
+ a->mfdscr(R3);
+ a->blr();
+
+ void (*set_dscr)(long) = (void(*)(long))(void *)a->emit_fd();
+ a->mtdscr(R3);
+ a->blr();
+
+ uint32_t *code_end = (uint32_t *)a->pc();
+ a->flush();
+
+ // Print the detection code.
+ if (PrintAssembly) {
+ ttyLocker ttyl;
+ tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", code);
+ Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
+ }
+
+ // Apply the configuration if needed.
+ uint64_t dscr_val = (*get_dscr)();
+ if (Verbose) {
+ tty->print_cr("dscr value was 0x%lx" , dscr_val);
+ }
+ bool change_requested = false;
+ if (DSCR_PPC64 != (uintx)-1) {
+ dscr_val = DSCR_PPC64;
+ change_requested = true;
+ }
+ if (DSCR_DPFD_PPC64 <= 7) {
+ uint64_t mask = 0x7;
+ if ((dscr_val & mask) != DSCR_DPFD_PPC64) {
+ dscr_val = (dscr_val & ~mask) | (DSCR_DPFD_PPC64);
+ change_requested = true;
+ }
+ }
+ if (DSCR_URG_PPC64 <= 7) {
+ uint64_t mask = 0x7 << 6;
+ if ((dscr_val & mask) != DSCR_DPFD_PPC64 << 6) {
+ dscr_val = (dscr_val & ~mask) | (DSCR_URG_PPC64 << 6);
+ change_requested = true;
+ }
+ }
+ if (change_requested) {
+ (*set_dscr)(dscr_val);
+ if (Verbose) {
+ tty->print_cr("dscr was set to 0x%lx" , (*get_dscr)());
+ }
+ }
+}
static int saved_features = 0;