8213199: GC abstraction for Assembler::needs_explicit_null_check()
Reviewed-by: adinn, eosterlund
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -582,6 +582,7 @@
virtual void null_check(Register reg, int offset = -1);
static bool needs_explicit_null_check(intptr_t offset);
+ static bool uses_implicit_null_check(void* address);
static address target_addr_for_insn(address insn_addr, unsigned insn);
static address target_addr_for_insn(address insn_addr) {
--- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -358,6 +358,7 @@
void zero_memory(Register start, Register end, Register tmp);
static bool needs_explicit_null_check(intptr_t offset);
+ static bool uses_implicit_null_check(void* address);
void arm_stack_overflow_check(int frame_size_in_bytes, Register tmp);
void arm_stack_overflow_check(Register Rsize, Register tmp);
@@ -1095,4 +1096,3 @@
#endif // CPU_ARM_VM_MACROASSEMBLER_ARM_HPP
-
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -659,6 +659,7 @@
void get_vm_result_2(Register metadata_result);
static bool needs_explicit_null_check(intptr_t offset);
+ static bool uses_implicit_null_check(void* address);
// Trap-instruction-based checks.
// Range checks can be distinguished from zero checks as they check 32 bit,
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -772,6 +772,7 @@
void null_check(Register reg, Register tmp = Z_R0, int64_t offset = -1);
static bool needs_explicit_null_check(intptr_t offset); // Implemented in shared file ?!
+ static bool uses_implicit_null_check(void* address);
// Klass oop manipulations if compressed.
void encode_klass_not_null(Register dst, Register src = noreg);
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -575,6 +575,7 @@
void null_check(Register reg, int offset = -1);
static bool needs_explicit_null_check(intptr_t offset);
+ static bool uses_implicit_null_check(void* address);
// support for delayed instructions
MacroAssembler* delayed() { Assembler::delayed(); return this; }
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -96,6 +96,7 @@
void null_check(Register reg, int offset = -1);
static bool needs_explicit_null_check(intptr_t offset);
+ static bool uses_implicit_null_check(void* address);
// Required platform-specific helpers for Label::patch_instructions.
// They _shadow_ the declarations in AbstractAssembler, which are undefined.
--- a/src/hotspot/os/windows/os_windows.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os/windows/os_windows.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -2492,7 +2492,7 @@
#endif
{
// Null pointer exception.
- if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr)) {
+ if (MacroAssembler::uses_implicit_null_check((void*)addr)) {
address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
if (stub != NULL) return Handle_Exception(exceptionInfo, stub);
}
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -409,7 +409,7 @@
// SIGSEGV-based implicit null check in compiled code.
else if (sig == SIGSEGV && ImplicitNullChecks &&
CodeCache::contains((void*) pc) &&
- !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) {
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
if (TraceTraps) {
tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc);
}
@@ -612,5 +612,3 @@
AixNativeCallstack::print_callstack_for_context(st, (const ucontext_t*)context, true, buf, (size_t) buf_size);
return true;
}
-
-
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -580,7 +580,7 @@
// 64-bit Darwin may also use a SIGBUS (seen with compressed oops).
// Catching SIGBUS here prevents the implicit SIGBUS NULL check below from
// being called, so only do so if the implicit NULL check is not necessary.
- } else if (sig == SIGBUS && MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ } else if (sig == SIGBUS && !MacroAssembler::uses_implicit_null_check(info->si_addr)) {
#else
} else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
#endif
@@ -655,7 +655,7 @@
}
#endif // AMD64
} else if ((sig == SIGSEGV || sig == SIGBUS) &&
- !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
// Determination of interpreter/vtable stub/compiled code null exception
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -357,10 +357,15 @@
}
#endif
+ address addr = (address) info->si_addr;
+
+ // Make sure the high order byte is sign extended, as it may be masked away by the hardware.
+ if ((uintptr_t(addr) & (uintptr_t(1) << 55)) != 0) {
+ addr = address(uintptr_t(addr) | (uintptr_t(0xFF) << 56));
+ }
+
// Handle ALL stack overflow variations here
if (sig == SIGSEGV) {
- address addr = (address) info->si_addr;
-
// check if fault address is within thread stack
if (thread->on_local_stack(addr)) {
// stack overflow
@@ -456,7 +461,7 @@
SharedRuntime::
IMPLICIT_DIVIDE_BY_ZERO);
} else if (sig == SIGSEGV &&
- !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ MacroAssembler::uses_implicit_null_check((void*)addr)) {
// Determination of interpreter/vtable stub/compiled code null exception
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -384,7 +384,8 @@
if (nm != NULL && nm->has_unsafe_access()) {
unsafe_access = true;
}
- } else if (sig == SIGSEGV && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ } else if (sig == SIGSEGV &&
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
// Determination of interpreter/vtable stub/compiled code null exception
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
if (cb != NULL) {
@@ -682,4 +683,3 @@
// ARM does not require an additional stack bang.
return 0;
}
-
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -431,7 +431,7 @@
// SIGSEGV-based implicit null check in compiled code.
else if (sig == SIGSEGV && ImplicitNullChecks &&
CodeCache::contains((void*) pc) &&
- !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) {
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
if (TraceTraps) {
tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
}
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -418,7 +418,7 @@
else if (sig == SIGSEGV && ImplicitNullChecks &&
CodeCache::contains((void*) pc) &&
- !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) {
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
if (TraceTraps) {
tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
}
--- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -416,9 +416,9 @@
return false;
}
-inline static bool checkNullPointer(address pc, intptr_t fault,
+inline static bool checkNullPointer(address pc, void* fault,
JavaThread* thread, address* stub) {
- if (!MacroAssembler::needs_explicit_null_check(fault)) {
+ if (MacroAssembler::uses_implicit_null_check(fault)) {
// Determination of interpreter/vtable stub/compiled code null
// exception
*stub =
@@ -586,7 +586,7 @@
}
if ((sig == SIGSEGV) &&
- checkNullPointer(pc, (intptr_t)info->si_addr, thread, &stub)) {
+ checkNullPointer(pc, info->si_addr, thread, &stub)) {
break;
}
} while (0);
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -479,7 +479,7 @@
}
#endif // AMD64
} else if (sig == SIGSEGV &&
- !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
// Determination of interpreter/vtable stub/compiled code null exception
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
--- a/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -505,7 +505,7 @@
}
#endif // COMPILER2
- else if (sig == SIGSEGV && info->si_code > 0 && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ else if (sig == SIGSEGV && info->si_code > 0 && MacroAssembler::uses_implicit_null_check(info->si_addr)) {
// Determination of interpreter/vtable stub/compiled code null exception
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
--- a/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -579,7 +579,8 @@
// QQQ It doesn't seem that we need to do this on x86 because we should be able
// to return properly from the handler without this extra stuff on the back side.
- else if (sig == SIGSEGV && info->si_code > 0 && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
+ else if (sig == SIGSEGV && info->si_code > 0 &&
+ MacroAssembler::uses_implicit_null_check(info->si_addr)) {
// Determination of interpreter/vtable stub/compiled code null exception
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
--- a/src/hotspot/share/asm/assembler.cpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/share/asm/assembler.cpp Thu Nov 08 23:31:08 2018 +0100
@@ -26,6 +26,7 @@
#include "asm/codeBuffer.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/collectedHeap.hpp"
#include "runtime/atomic.hpp"
#include "runtime/icache.hpp"
#include "runtime/os.hpp"
@@ -307,21 +308,32 @@
return NULL;
}
-bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
+bool MacroAssembler::uses_implicit_null_check(void* address) {
// Exception handler checks the nmethod's implicit null checks table
// only when this method returns false.
+ intptr_t int_address = reinterpret_cast<intptr_t>(address);
+ intptr_t cell_header_size = Universe::heap()->cell_header_size();
+ size_t region_size = os::vm_page_size() + cell_header_size;
#ifdef _LP64
if (UseCompressedOops && Universe::narrow_oop_base() != NULL) {
- assert (Universe::heap() != NULL, "java heap should be initialized");
- // The first page after heap_base is unmapped and
- // the 'offset' is equal to [heap_base + offset] for
- // narrow oop implicit null checks.
- uintptr_t base = (uintptr_t)Universe::narrow_oop_base();
- if ((uintptr_t)offset >= base) {
- // Normalize offset for the next check.
- offset = (intptr_t)(pointer_delta((void*)offset, (void*)base, 1));
+ // A SEGV can legitimately happen in C2 code at address
+ // (heap_base + offset) if Matcher::narrow_oop_use_complex_address
+ // is configured to allow narrow oops field loads to be implicitly
+ // null checked
+ intptr_t start = ((intptr_t)Universe::narrow_oop_base()) - cell_header_size;
+ intptr_t end = start + region_size;
+ if (int_address >= start && int_address < end) {
+ return true;
}
}
#endif
- return offset < 0 || os::vm_page_size() <= offset;
+ intptr_t start = -cell_header_size;
+ intptr_t end = start + region_size;
+ return int_address >= start && int_address < end;
}
+
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
+ // Check if offset is outside of [-cell_header_size, os::vm_page_size)
+ return offset < -Universe::heap()->cell_header_size() ||
+ offset >= os::vm_page_size();
+}
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Nov 08 18:10:15 2018 -0300
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Nov 08 23:31:08 2018 +0100
@@ -580,6 +580,11 @@
virtual size_t obj_size(oop obj) const;
+ // Cells are memory slices allocated by the allocator. Objects are initialized
+ // in cells. The cell itself may have a header, found at a negative offset of
+ // oops. Usually, the size of the cell header is 0, but it may be larger.
+ virtual ptrdiff_t cell_header_size() const { return 0; }
+
// Non product verification and debugging.
#ifndef PRODUCT
// Support for PromotionFailureALot. Return true if it's time to cause a