# HG changeset patch # User goetz # Date 1385087374 28800 # Node ID b0133e4187d300d5c8cf3fe0ccedd9cf299c32e6 # Parent da862781b5849c8de5358d274f96eb9e691d41d1 8028471: PPC64 (part 215): opto: Extend ImplicitNullCheck optimization. Summary: Fixed Implicit NULL check optimization for AIX, where the page at address '0' is only write-protected. Reviewed-by: kvn diff -r da862781b584 -r b0133e4187d3 src/cpu/ppc/vm/globals_ppc.hpp --- a/src/cpu/ppc/vm/globals_ppc.hpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/cpu/ppc/vm/globals_ppc.hpp Thu Nov 21 18:29:34 2013 -0800 @@ -92,7 +92,7 @@ /* Trap based checks use the ppc trap instructions to check certain */ \ /* conditions. This instruction raises a SIGTRAP caught by the */ \ /* exception handler of the VM. */ \ - product(bool, UseSIGTRAP, false, \ + product(bool, UseSIGTRAP, true, \ "Allow trap instructions that make use of SIGTRAP. Use this to " \ "switch off all optimizations requiring SIGTRAP.") \ product(bool, TrapBasedICMissChecks, true, \ diff -r da862781b584 -r b0133e4187d3 src/cpu/ppc/vm/macroAssembler_ppc.cpp --- a/src/cpu/ppc/vm/macroAssembler_ppc.cpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/cpu/ppc/vm/macroAssembler_ppc.cpp Thu Nov 21 18:29:34 2013 -0800 @@ -2433,7 +2433,7 @@ } 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) { trap_null_check(src); } diff -r da862781b584 -r b0133e4187d3 src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp --- a/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp Thu Nov 21 18:29:34 2013 -0800 @@ -269,7 +269,7 @@ // No support for compressed oops (base page of heap). Does not distinguish // loads and stores. 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) { assert(UseSIGTRAP, "sanity"); trap_null_check(a); @@ -286,7 +286,7 @@ } 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) { trap_null_check(s1); } @@ -297,7 +297,7 @@ // 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, Register s1) { - if ( NOT_LINUX(true)LINUX_ONLY(false) /*!os::zero_page_read_protected()*/) { + if ( !os::zero_page_read_protected()) { if (TrapBasedNullChecks) { trap_null_check(s1); } diff -r da862781b584 -r b0133e4187d3 src/cpu/ppc/vm/sharedRuntime_ppc.cpp --- a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Nov 21 18:29:34 2013 -0800 @@ -1128,7 +1128,7 @@ assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "klass offset should reach into any page"); // 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) { __ trap_null_check(R3_ARG1); } else { diff -r da862781b584 -r b0133e4187d3 src/cpu/ppc/vm/vtableStubs_ppc_64.cpp --- a/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp Thu Nov 21 18:29:34 2013 -0800 @@ -221,7 +221,7 @@ // Must do an explicit check if implicit checks are disabled. 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) { __ trap_null_check(R19_method); } else { diff -r da862781b584 -r b0133e4187d3 src/os/bsd/vm/os_bsd.hpp --- a/src/os/bsd/vm/os_bsd.hpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/os/bsd/vm/os_bsd.hpp Thu Nov 21 18:29:34 2013 -0800 @@ -27,6 +27,9 @@ // 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 */ typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); diff -r da862781b584 -r b0133e4187d3 src/os/linux/vm/os_linux.hpp --- a/src/os/linux/vm/os_linux.hpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/os/linux/vm/os_linux.hpp Thu Nov 21 18:29:34 2013 -0800 @@ -30,6 +30,9 @@ /* pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1 */ 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 { friend class os; friend class TestReserveMemorySpecial; diff -r da862781b584 -r b0133e4187d3 src/os/solaris/vm/os_solaris.hpp --- a/src/os/solaris/vm/os_solaris.hpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/os/solaris/vm/os_solaris.hpp Thu Nov 21 18:29:34 2013 -0800 @@ -27,6 +27,9 @@ // 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 { friend class os; diff -r da862781b584 -r b0133e4187d3 src/os/windows/vm/os_windows.hpp --- a/src/os/windows/vm/os_windows.hpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/os/windows/vm/os_windows.hpp Thu Nov 21 18:29:34 2013 -0800 @@ -26,6 +26,9 @@ #define OS_WINDOWS_VM_OS_WINDOWS_HPP // 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 { friend class os; diff -r da862781b584 -r b0133e4187d3 src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/share/vm/opto/callGenerator.cpp Thu Nov 21 18:29:34 2013 -0800 @@ -201,7 +201,7 @@ // Block::implicit_null_check() only looks for loads and stores, not calls. ciMethod *caller = kit.method(); ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data(); - if (!UseInlineCaches || !ImplicitNullChecks || + if (!UseInlineCaches || !ImplicitNullChecks || !os::zero_page_read_protected() || ((ImplicitNullCheckThreshold > 0) && caller_md && (caller_md->trap_count(Deoptimization::Reason_null_check) >= (uint)ImplicitNullCheckThreshold))) { diff -r da862781b584 -r b0133e4187d3 src/share/vm/opto/lcm.cpp --- a/src/share/vm/opto/lcm.cpp Thu Nov 21 12:30:35 2013 -0800 +++ b/src/share/vm/opto/lcm.cpp Thu Nov 21 18:29:34 2013 -0800 @@ -54,6 +54,43 @@ // 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---------------------------- // Detect implicit-null-check opportunities. Basically, find NULL checks // with suitable memory ops nearby. Use the memory op to do the NULL check. @@ -209,6 +246,14 @@ } 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 { intptr_t offset = 0;