mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8028471: PPC64 (part 215): opto: Extend ImplicitNullCheck optimization
Fixed Implicit NULL check optimization for AIX, where the page at address '0' is only write-protected. Reviewed-by: kvn
This commit is contained in:
parent
aabed3781b
commit
a7c123880e
11 changed files with 65 additions and 8 deletions
|
@ -92,7 +92,7 @@ define_pd_global(uintx, TypeProfileLevel, 0);
|
||||||
/* Trap based checks use the ppc trap instructions to check certain */ \
|
/* Trap based checks use the ppc trap instructions to check certain */ \
|
||||||
/* conditions. This instruction raises a SIGTRAP caught by the */ \
|
/* conditions. This instruction raises a SIGTRAP caught by the */ \
|
||||||
/* exception handler of the VM. */ \
|
/* exception handler of the VM. */ \
|
||||||
product(bool, UseSIGTRAP, false, \
|
product(bool, UseSIGTRAP, true, \
|
||||||
"Allow trap instructions that make use of SIGTRAP. Use this to " \
|
"Allow trap instructions that make use of SIGTRAP. Use this to " \
|
||||||
"switch off all optimizations requiring SIGTRAP.") \
|
"switch off all optimizations requiring SIGTRAP.") \
|
||||||
product(bool, TrapBasedICMissChecks, true, \
|
product(bool, TrapBasedICMissChecks, true, \
|
||||||
|
|
|
@ -2433,7 +2433,7 @@ void MacroAssembler::load_klass(Register dst, Register src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroAssembler::load_klass_with_trap_null_check(Register dst, Register src) {
|
void MacroAssembler::load_klass_with_trap_null_check(Register dst, Register src) {
|
||||||
if (false NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) {
|
if (!os::zero_page_read_protected()) {
|
||||||
if (TrapBasedNullChecks) {
|
if (TrapBasedNullChecks) {
|
||||||
trap_null_check(src);
|
trap_null_check(src);
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@ inline void MacroAssembler::trap_ic_miss_check(Register a, Register b) {
|
||||||
// No support for compressed oops (base page of heap). Does not distinguish
|
// No support for compressed oops (base page of heap). Does not distinguish
|
||||||
// loads and stores.
|
// loads and stores.
|
||||||
inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg, address exception_entry) {
|
inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg, address exception_entry) {
|
||||||
if (!ImplicitNullChecks || needs_explicit_null_check(offset) NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) {
|
if (!ImplicitNullChecks || needs_explicit_null_check(offset) || !os::zero_page_read_protected()) {
|
||||||
if (TrapBasedNullChecks) {
|
if (TrapBasedNullChecks) {
|
||||||
assert(UseSIGTRAP, "sanity");
|
assert(UseSIGTRAP, "sanity");
|
||||||
trap_null_check(a);
|
trap_null_check(a);
|
||||||
|
@ -286,7 +286,7 @@ inline void MacroAssembler::null_check_throw(Register a, int offset, Register te
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Register s1) {
|
inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Register s1) {
|
||||||
if ( NOT_LINUX(true) LINUX_ONLY(false)/*!os::zero_page_read_protected()*/) {
|
if (!os::zero_page_read_protected()) {
|
||||||
if (TrapBasedNullChecks) {
|
if (TrapBasedNullChecks) {
|
||||||
trap_null_check(s1);
|
trap_null_check(s1);
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ inline void MacroAssembler::ld_with_trap_null_check(Register d, int si16, Regist
|
||||||
// Attention: No null check for loaded uncompressed OOP. Can be used for loading klass field.
|
// Attention: No null check for loaded uncompressed OOP. Can be used for loading klass field.
|
||||||
inline void MacroAssembler::load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant si16,
|
inline void MacroAssembler::load_heap_oop_with_trap_null_check(Register d, RegisterOrConstant si16,
|
||||||
Register s1) {
|
Register s1) {
|
||||||
if ( NOT_LINUX(true)LINUX_ONLY(false) /*!os::zero_page_read_protected()*/) {
|
if ( !os::zero_page_read_protected()) {
|
||||||
if (TrapBasedNullChecks) {
|
if (TrapBasedNullChecks) {
|
||||||
trap_null_check(s1);
|
trap_null_check(s1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1128,7 +1128,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()),
|
assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()),
|
||||||
"klass offset should reach into any page");
|
"klass offset should reach into any page");
|
||||||
// Check for NULL argument if we don't have implicit null checks.
|
// Check for NULL argument if we don't have implicit null checks.
|
||||||
if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) {
|
if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
|
||||||
if (TrapBasedNullChecks) {
|
if (TrapBasedNullChecks) {
|
||||||
__ trap_null_check(R3_ARG1);
|
__ trap_null_check(R3_ARG1);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -221,7 +221,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
|
|
||||||
// Must do an explicit check if implicit checks are disabled.
|
// Must do an explicit check if implicit checks are disabled.
|
||||||
assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity");
|
assert(!MacroAssembler::needs_explicit_null_check(in_bytes(Method::from_compiled_offset())), "sanity");
|
||||||
if (!ImplicitNullChecks NOT_LINUX(|| true) /*!os::zero_page_read_protected()*/) {
|
if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
|
||||||
if (TrapBasedNullChecks) {
|
if (TrapBasedNullChecks) {
|
||||||
__ trap_null_check(R19_method);
|
__ trap_null_check(R19_method);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
// Bsd_OS defines the interface to Bsd operating systems
|
// Bsd_OS defines the interface to Bsd operating systems
|
||||||
|
|
||||||
|
// Information about the protection of the page at address '0' on this os.
|
||||||
|
static bool zero_page_read_protected() { return true; }
|
||||||
|
|
||||||
/* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */
|
/* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */
|
||||||
typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
|
typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
/* pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1 */
|
/* pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1 */
|
||||||
typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
|
typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
|
||||||
|
|
||||||
|
// Information about the protection of the page at address '0' on this os.
|
||||||
|
static bool zero_page_read_protected() { return true; }
|
||||||
|
|
||||||
class Linux {
|
class Linux {
|
||||||
friend class os;
|
friend class os;
|
||||||
friend class TestReserveMemorySpecial;
|
friend class TestReserveMemorySpecial;
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
// Solaris_OS defines the interface to Solaris operating systems
|
// Solaris_OS defines the interface to Solaris operating systems
|
||||||
|
|
||||||
|
// Information about the protection of the page at address '0' on this os.
|
||||||
|
static bool zero_page_read_protected() { return true; }
|
||||||
|
|
||||||
class Solaris {
|
class Solaris {
|
||||||
friend class os;
|
friend class os;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#define OS_WINDOWS_VM_OS_WINDOWS_HPP
|
#define OS_WINDOWS_VM_OS_WINDOWS_HPP
|
||||||
// Win32_OS defines the interface to windows operating systems
|
// Win32_OS defines the interface to windows operating systems
|
||||||
|
|
||||||
|
// Information about the protection of the page at address '0' on this os.
|
||||||
|
static bool zero_page_read_protected() { return true; }
|
||||||
|
|
||||||
class win32 {
|
class win32 {
|
||||||
friend class os;
|
friend class os;
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
||||||
// Block::implicit_null_check() only looks for loads and stores, not calls.
|
// Block::implicit_null_check() only looks for loads and stores, not calls.
|
||||||
ciMethod *caller = kit.method();
|
ciMethod *caller = kit.method();
|
||||||
ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data();
|
ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data();
|
||||||
if (!UseInlineCaches || !ImplicitNullChecks ||
|
if (!UseInlineCaches || !ImplicitNullChecks || !os::zero_page_read_protected() ||
|
||||||
((ImplicitNullCheckThreshold > 0) && caller_md &&
|
((ImplicitNullCheckThreshold > 0) && caller_md &&
|
||||||
(caller_md->trap_count(Deoptimization::Reason_null_check)
|
(caller_md->trap_count(Deoptimization::Reason_null_check)
|
||||||
>= (uint)ImplicitNullCheckThreshold))) {
|
>= (uint)ImplicitNullCheckThreshold))) {
|
||||||
|
|
|
@ -54,6 +54,43 @@
|
||||||
|
|
||||||
// Optimization - Graph Style
|
// Optimization - Graph Style
|
||||||
|
|
||||||
|
// Check whether val is not-null-decoded compressed oop,
|
||||||
|
// i.e. will grab into the base of the heap if it represents NULL.
|
||||||
|
static bool accesses_heap_base_zone(Node *val) {
|
||||||
|
if (Universe::narrow_oop_base() > 0) { // Implies UseCompressedOops.
|
||||||
|
if (val && val->is_Mach()) {
|
||||||
|
if (val->as_Mach()->ideal_Opcode() == Op_DecodeN) {
|
||||||
|
// This assumes all Decodes with TypePtr::NotNull are matched to nodes that
|
||||||
|
// decode NULL to point to the heap base (Decode_NN).
|
||||||
|
if (val->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Must recognize load operation with Decode matched in memory operand.
|
||||||
|
// We should not reach here exept for PPC/AIX, as os::zero_page_read_protected()
|
||||||
|
// returns true everywhere else. On PPC, no such memory operands
|
||||||
|
// exist, therefore we did not yet implement a check for such operands.
|
||||||
|
NOT_AIX(Unimplemented());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool needs_explicit_null_check_for_read(Node *val) {
|
||||||
|
// On some OSes (AIX) the page at address 0 is only write protected.
|
||||||
|
// If so, only Store operations will trap.
|
||||||
|
if (os::zero_page_read_protected()) {
|
||||||
|
return false; // Implicit null check will work.
|
||||||
|
}
|
||||||
|
// Also a read accessing the base of a heap-based compressed heap will trap.
|
||||||
|
if (accesses_heap_base_zone(val) && // Hits the base zone page.
|
||||||
|
Universe::narrow_oop_use_implicit_null_checks()) { // Base zone page is protected.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------implicit_null_check----------------------------
|
//------------------------------implicit_null_check----------------------------
|
||||||
// Detect implicit-null-check opportunities. Basically, find NULL checks
|
// Detect implicit-null-check opportunities. Basically, find NULL checks
|
||||||
// with suitable memory ops nearby. Use the memory op to do the NULL check.
|
// with suitable memory ops nearby. Use the memory op to do the NULL check.
|
||||||
|
@ -209,6 +246,14 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On some OSes (AIX) the page at address 0 is only write protected.
|
||||||
|
// If so, only Store operations will trap.
|
||||||
|
// But a read accessing the base of a heap-based compressed heap will trap.
|
||||||
|
if (!was_store && needs_explicit_null_check_for_read(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// check if the offset is not too high for implicit exception
|
// check if the offset is not too high for implicit exception
|
||||||
{
|
{
|
||||||
intptr_t offset = 0;
|
intptr_t offset = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue