< prev index next >

src/cpu/ppc/vm/vm_version_ppc.cpp

Print this page
rev 8107 : 8077838: Recent developments for ppc.

*** 30,45 **** #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "utilities/defaultStream.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 const char* VM_Version::_features_str = ""; bool VM_Version::_is_determine_features_test_running = false; #define MSG(flag) \ --- 30,46 ---- #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #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 = 32; // pessimistic init value const char* VM_Version::_features_str = ""; bool VM_Version::_is_determine_features_test_running = false; #define MSG(flag) \
*** 53,75 **** // Test which instructions are supported and measure cache line size. determine_features(); // If PowerArchitecturePPC64 hasn't been specified explicitly determine from features. if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) { ! if (VM_Version::has_popcntw()) { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7); } else if (VM_Version::has_cmpb()) { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 6); } else if (VM_Version::has_popcntb()) { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 5); } else { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 0); } } guarantee(PowerArchitecturePPC64 == 0 || PowerArchitecturePPC64 == 5 || ! PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7, ! "PowerArchitecturePPC64 should be 0, 5, 6 or 7"); if (!UseSIGTRAP) { MSG(TrapBasedICMissChecks); MSG(TrapBasedNotEntrantChecks); MSG(TrapBasedNullChecks); --- 54,84 ---- // Test which instructions are supported and measure cache line size. determine_features(); // If PowerArchitecturePPC64 hasn't been specified explicitly determine from features. if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) { ! 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); } else if (VM_Version::has_popcntb()) { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 5); } else { FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 0); } } guarantee(PowerArchitecturePPC64 == 0 || PowerArchitecturePPC64 == 5 || ! 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); MSG(TrapBasedNotEntrantChecks); MSG(TrapBasedNullChecks);
*** 95,118 **** #endif // 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", (has_fsqrt() ? " fsqrt" : ""), (has_isel() ? " isel" : ""), (has_lxarxeh() ? " lxarxeh" : ""), (has_cmpb() ? " cmpb" : ""), //(has_mftgpr()? " mftgpr" : ""), (has_popcntb() ? " popcntb" : ""), (has_popcntw() ? " popcntw" : ""), (has_fcfids() ? " fcfids" : ""), ! (has_vand() ? " vand" : "") // Make sure number of %s matches num_features! ); _features_str = os::strdup(buf); ! NOT_PRODUCT(if (Verbose) print_features();); // PPC64 supports 8-byte compare-exchange operations (see // Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr) // and 'atomic long memory ops' (see Unsafe_GetLongVolatile). _supports_cx8 = true; --- 104,133 ---- #endif // 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%s%s%s%s", (has_fsqrt() ? " fsqrt" : ""), (has_isel() ? " isel" : ""), (has_lxarxeh() ? " lxarxeh" : ""), (has_cmpb() ? " cmpb" : ""), //(has_mftgpr()? " mftgpr" : ""), (has_popcntb() ? " popcntb" : ""), (has_popcntw() ? " popcntw" : ""), (has_fcfids() ? " fcfids" : ""), ! (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); ! if (Verbose) { ! print_features(); ! } // PPC64 supports 8-byte compare-exchange operations (see // Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr) // and 'atomic long memory ops' (see Unsafe_GetLongVolatile). _supports_cx8 = true;
*** 169,187 **** --- 184,275 ---- warning("SHA intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); 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) { if (!FLAG_IS_DEFAULT(UseUnalignedAccesses)) warning("Unaligned memory access is not available on this CPU"); FLAG_SET_DEFAULT(UseUnalignedAccesses, false); } } + 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()); } #ifdef COMPILER2
*** 445,460 **** // 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->blr(); // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->function_entry(); a->dcbz(R3_ARG1); // R3_ARG1 = addr --- 533,551 ---- // 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] -> 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. void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->function_entry(); a->dcbz(R3_ARG1); // R3_ARG1 = addr
*** 489,503 **** if (code[feature_cntr++]) features |= fsqrt_m; if (code[feature_cntr++]) features |= fsqrts_m; 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; // Print the detection code. if (PrintAssembly) { ttyLocker ttyl; tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " after execution:", p2i(code)); --- 580,597 ---- if (code[feature_cntr++]) features |= fsqrt_m; if (code[feature_cntr++]) features |= fsqrts_m; 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 |= 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) { ttyLocker ttyl; tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " after execution:", p2i(code));
*** 505,514 **** --- 599,671 ---- } _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; void VM_Version::allow_all() { saved_features = _features;
< prev index next >