aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgoetz <none@none>2013-11-21 18:29:34 -0800
committergoetz <none@none>2013-11-21 18:29:34 -0800
commit47fb5cfed83e8a379c850a213e770ac075a53a22 (patch)
treebedab213bb37800d0f8597f8d6c8c331e4fa31c6
parent24b95fe6010d2c8cd4c2a683d304f77e11cca4ae (diff)
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
-rw-r--r--src/cpu/ppc/vm/globals_ppc.hpp2
-rw-r--r--src/cpu/ppc/vm/macroAssembler_ppc.cpp2
-rw-r--r--src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp6
-rw-r--r--src/cpu/ppc/vm/sharedRuntime_ppc.cpp2
-rw-r--r--src/cpu/ppc/vm/vtableStubs_ppc_64.cpp2
-rw-r--r--src/os/bsd/vm/os_bsd.hpp3
-rw-r--r--src/os/linux/vm/os_linux.hpp3
-rw-r--r--src/os/solaris/vm/os_solaris.hpp3
-rw-r--r--src/os/windows/vm/os_windows.hpp3
-rw-r--r--src/share/vm/opto/callGenerator.cpp2
-rw-r--r--src/share/vm/opto/lcm.cpp45
11 files changed, 65 insertions, 8 deletions
diff --git a/src/cpu/ppc/vm/globals_ppc.hpp b/src/cpu/ppc/vm/globals_ppc.hpp
index 2dd4b1df1..b39151004 100644
--- a/src/cpu/ppc/vm/globals_ppc.hpp
+++ b/src/cpu/ppc/vm/globals_ppc.hpp
@@ -92,7 +92,7 @@ define_pd_global(uintx, TypeProfileLevel, 0);
/* 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 --git a/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/src/cpu/ppc/vm/macroAssembler_ppc.cpp
index eb716b5b8..f4b7c5e76 100644
--- a/src/cpu/ppc/vm/macroAssembler_ppc.cpp
+++ b/src/cpu/ppc/vm/macroAssembler_ppc.cpp
@@ -2433,7 +2433,7 @@ void MacroAssembler::load_klass(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) {
trap_null_check(src);
}
diff --git a/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp b/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
index d80e4ec44..529f82468 100644
--- a/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
+++ b/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
@@ -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
// 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::null_check_throw(Register a, int offset, Register te
}
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 @@ 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.
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 --git a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
index e9d217601..c2a971118 100644
--- a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
+++ b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
@@ -1128,7 +1128,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
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 --git a/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp
index 5323e4ae5..6a608e932 100644
--- a/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp
+++ b/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp
@@ -221,7 +221,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// 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 --git a/src/os/bsd/vm/os_bsd.hpp b/src/os/bsd/vm/os_bsd.hpp
index a906a30e9..c33968a0a 100644
--- a/src/os/bsd/vm/os_bsd.hpp
+++ b/src/os/bsd/vm/os_bsd.hpp
@@ -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 --git a/src/os/linux/vm/os_linux.hpp b/src/os/linux/vm/os_linux.hpp
index 5eed54f8c..829852f91 100644
--- a/src/os/linux/vm/os_linux.hpp
+++ b/src/os/linux/vm/os_linux.hpp
@@ -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 --git a/src/os/solaris/vm/os_solaris.hpp b/src/os/solaris/vm/os_solaris.hpp
index 330d4fbc5..048534691 100644
--- a/src/os/solaris/vm/os_solaris.hpp
+++ b/src/os/solaris/vm/os_solaris.hpp
@@ -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 --git a/src/os/windows/vm/os_windows.hpp b/src/os/windows/vm/os_windows.hpp
index 67ed8a4af..c9c4840bb 100644
--- a/src/os/windows/vm/os_windows.hpp
+++ b/src/os/windows/vm/os_windows.hpp
@@ -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 --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp
index adc27ac02..22807e2c7 100644
--- a/src/share/vm/opto/callGenerator.cpp
+++ b/src/share/vm/opto/callGenerator.cpp
@@ -201,7 +201,7 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
// 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 --git a/src/share/vm/opto/lcm.cpp b/src/share/vm/opto/lcm.cpp
index 8c4f339cd..dfdc663a2 100644
--- a/src/share/vm/opto/lcm.cpp
+++ b/src/share/vm/opto/lcm.cpp
@@ -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 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
}
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;