Optimize stack unwinding by reducing `AddressIsReadable` calls.

PiperOrigin-RevId: 822738922
Change-Id: Ifd784d16ffb8ae810900b11e41a74ac1f263ed89
diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc
index bf6e5ab..27ee32a 100644
--- a/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -245,6 +245,7 @@
   }
 #endif
 
+  const size_t page_size = static_cast<size_t>(getpagesize());
   const uintptr_t old_fp_u = reinterpret_cast<uintptr_t>(old_fp);
   const uintptr_t new_fp_u = reinterpret_cast<uintptr_t>(new_fp);
 
@@ -273,8 +274,7 @@
     // so we assume the large frame is legit if we know the real stack bounds
     // and are within the stack.
     if (new_fp_u <= old_fp_u || new_fp_u - old_fp_u > kMaxFrameBytes) {
-      if (stack_high < kUnknownStackEnd &&
-          static_cast<size_t>(getpagesize()) < stack_low) {
+      if (stack_high < kUnknownStackEnd && page_size < stack_low) {
         // Stack bounds are known.
         if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
           // new_fp_u is not within the known stack.
@@ -311,7 +311,12 @@
   if (new_fp_u >= 0xffffe000) return nullptr;
 #endif
 #if !defined(_WIN32)
-  if (!STRICT_UNWINDING) {
+  const uintptr_t old_fp_page = old_fp_u & ~(page_size - 1);
+  const uintptr_t new_fp_page = new_fp_u & ~(page_size - 1);
+  if (old_fp_page == new_fp_page && (new_fp_u & (sizeof(void*) - 1)) == 0) {
+    // We dereferenced the old_fp above, so it is safe to dereference
+    // new_fp if it's on the same page as the old_fp and is aligned.
+  } else if (!STRICT_UNWINDING) {
     // Lax sanity checks cause a crash in 32-bit tcmalloc/crash_reason_test
     // on AMD-based machines with VDSO-enabled kernels.
     // Make an extra sanity check to insure new_fp is readable.