Commit 4ca50e35 authored by Bartek Nowierski's avatar Bartek Nowierski Committed by Commit Bot

Initial CheckedPtr2 implementation

This code is currently unused, but is needed to evaluate performance
impact of the CheckedPtr initiative.
https://docs.google.com/document/d/1pnnOAIz_DMWDI4oIOFoMAqLnf_MZ2GsrJNb_dbQ3ZBg

The current implementation is an expensive no-op. It offers no run-time
verification of pointer correctness, but it performs work as if it did.
It is expected to have similar performance characteristics to the
designed CheckedPtr2. CHECKED_PTR2_PROTECTION_ENABLED and "TEST"
comments show how the actual code would look like had all needed
support been already implemented.

Bug: 1073933
Change-Id: I4fc6a1a3b6701dcae9bb38ff3fa01fd6276812fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2162493
Commit-Queue: Bartek Nowierski <bartekn@chromium.org>
Reviewed-by: default avatarBenoit L <lizeb@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772675}
parent 07dfc1a6
This diff is collapsed.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using testing::Test; using testing::Test;
...@@ -535,4 +536,94 @@ TEST_F(CheckedPtrTest, AssignmentFromNullptr) { ...@@ -535,4 +536,94 @@ TEST_F(CheckedPtrTest, AssignmentFromNullptr) {
EXPECT_EQ(g_get_for_dereference_cnt, 0); EXPECT_EQ(g_get_for_dereference_cnt, 0);
} }
#if defined(ARCH_CPU_64_BITS)
TEST(CheckedPtr2Impl, WrapNull) {
ASSERT_EQ(base::internal::CheckedPtr2Impl::GetWrappedNullPtr(), 0u);
ASSERT_EQ(base::internal::CheckedPtr2Impl::WrapRawPtr(nullptr), 0u);
}
TEST(CheckedPtr2Impl, SafelyUnwrapNull) {
ASSERT_EQ(base::internal::CheckedPtr2Impl::SafelyUnwrapPtrForExtraction(0),
nullptr);
}
TEST(CheckedPtr2Impl, WrapAndSafelyUnwrap) {
char bytes[] = {0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0xBA, 0x42, 0x78, 0x89};
#if !CHECKED_PTR2_PROTECTION_ENABLED
// If protection is disabled, wrap & unwrap will read at the pointer, not
// before it.
bytes[8] = bytes[6];
bytes[9] = bytes[7];
#endif
void* ptr = bytes + sizeof(uintptr_t);
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
uintptr_t set_top_bit = 0x0000000000000000;
uintptr_t mask = 0xFFFFFFFFFFFFFFFF;
#if CHECKED_PTR2_AVOID_BRANCH_WHEN_CHECKING_ENABLED
set_top_bit = 0x8000000000000000;
#if !CHECKED_PTR2_PROTECTION_ENABLED
mask = 0x0000FFFFFFFFFFFF;
#endif
#endif
uintptr_t wrapped = base::internal::CheckedPtr2Impl::WrapRawPtr(ptr);
// First 2 bytes in the preceding word will be used as generation (in reverse
// order due to little-endianness).
#if CHECKED_PTR2_USE_NO_OP_WRAPPER
ASSERT_EQ(wrapped, addr);
std::ignore = set_top_bit;
std::ignore = mask;
#else
ASSERT_EQ(wrapped, (addr | 0x42BA000000000000 | set_top_bit) & mask);
#endif
ASSERT_EQ(base::internal::CheckedPtr2Impl::SafelyUnwrapPtrInternal(wrapped),
addr);
bytes[7] |= 0x80;
#if !CHECKED_PTR2_PROTECTION_ENABLED
bytes[9] = bytes[7];
#endif
wrapped = base::internal::CheckedPtr2Impl::WrapRawPtr(ptr);
#if CHECKED_PTR2_USE_NO_OP_WRAPPER
ASSERT_EQ(wrapped, addr);
#else
ASSERT_EQ(wrapped, (addr | 0xC2BA000000000000 | set_top_bit) & mask);
#endif
ASSERT_EQ(base::internal::CheckedPtr2Impl::SafelyUnwrapPtrInternal(wrapped),
addr);
#if CHECKED_PTR2_AVOID_BRANCH_WHEN_DEREFERENCING
bytes[6] = 0;
bytes[7] = 0;
#if !CHECKED_PTR2_PROTECTION_ENABLED
bytes[8] = bytes[6];
bytes[9] = bytes[7];
#endif
mask = 0xFFFFFFFFFFFFFFFF;
#if CHECKED_PTR2_AVOID_BRANCH_WHEN_CHECKING_ENABLED
mask = 0x7FFFFFFFFFFFFFFF;
#if !CHECKED_PTR2_PROTECTION_ENABLED
mask = 0x0000FFFFFFFFFFFF;
#endif
#endif
// Mask out the top bit, because in some cases (not all), it may differ.
ASSERT_EQ(
base::internal::CheckedPtr2Impl::SafelyUnwrapPtrInternal(wrapped) & mask,
wrapped & mask);
#endif
}
TEST(CheckedPtr2Impl, SafelyUnwrapDisabled) {
char bytes[] = {0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0xBA, 0x42, 0x78, 0x89};
void* ptr = bytes + sizeof(uintptr_t);
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
ASSERT_EQ(base::internal::CheckedPtr2Impl::SafelyUnwrapPtrInternal(addr),
addr);
}
#endif // #if defined(ARCH_CPU_64_BITS)
} // namespace } // namespace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment