8028471: PPC64 (part 215): opto: Extend ImplicitNullCheck optimization.
authorgoetz
Thu, 21 Nov 2013 18:29:34 -0800
changeset 22852 1063026e8cee
parent 22851 4c4b6a45be43
child 22853 308672304981
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
hotspot/src/cpu/ppc/vm/globals_ppc.hpp
hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp
hotspot/src/os/bsd/vm/os_bsd.hpp
hotspot/src/os/linux/vm/os_linux.hpp
hotspot/src/os/solaris/vm/os_solaris.hpp
hotspot/src/os/windows/vm/os_windows.hpp
hotspot/src/share/vm/opto/callGenerator.cpp
hotspot/src/share/vm/opto/lcm.cpp
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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,                                \
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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);
     }
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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);
     }
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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 {
--- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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 {
--- a/hotspot/src/os/bsd/vm/os_bsd.hpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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 *);
 
--- a/hotspot/src/os/linux/vm/os_linux.hpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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;
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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;
 
--- a/hotspot/src/os/windows/vm/os_windows.hpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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;
 
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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))) {
--- a/hotspot/src/share/vm/opto/lcm.cpp	Thu Nov 21 12:30:35 2013 -0800
+++ b/hotspot/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;