commit
87084d39ef
201 changed files with 12349 additions and 21398 deletions
@ -1,3 +1,3 @@ |
|||||||
PROTOC_VERSION = '21.7' |
PROTOC_VERSION = "21.7" |
||||||
PROTOBUF_JAVA_VERSION = '3.21.7' |
PROTOBUF_JAVA_VERSION = "3.21.7" |
||||||
PROTOBUF_PYTHON_VERSION = '4.21.7' |
PROTOBUF_PYTHON_VERSION = "4.21.7" |
||||||
|
@ -0,0 +1,155 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// This file provides alignment utilities for use in arenas.
|
||||||
|
//
|
||||||
|
// `ArenaAlign` constains a single `align` data member and provides
|
||||||
|
// the below functions which operate on the given alignment.
|
||||||
|
//
|
||||||
|
// Ceil(size_t n) - rounds `n` up to the nearest `align` boundary.
|
||||||
|
// Floor(size_t n) - rounds `n` down to the nearest `align` boundary.
|
||||||
|
// Ceil(T* P) - rounds `p` up to the nearest `align` boundary.
|
||||||
|
// IsAligned(size_t n) - returns true if `n` is aligned to `align`
|
||||||
|
// IsAligned(T* p) - returns true if `p` is aligned to `align`
|
||||||
|
// CheckAligned(T* p) - returns `p`. Checks alignment of `p` in debug.
|
||||||
|
//
|
||||||
|
// Additionally there is an optimized `CeilDefaultAligned(T*)` method which is
|
||||||
|
// equivalent to `Ceil(ArenaAlignDefault().CheckAlign(p))` but more efficiently
|
||||||
|
// implemented as a 'check only' for ArenaAlignDefault.
|
||||||
|
//
|
||||||
|
// These classes allow for generic arena logic using 'alignment policies'.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// template <Align>
|
||||||
|
// void* NaiveAlloc(size_t n, Align align) {
|
||||||
|
// align.CheckAligned(n);
|
||||||
|
// uint8_t* ptr = align.CeilDefaultAligned(ptr_);
|
||||||
|
// ptr_ += n;
|
||||||
|
// return ptr;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void CallSites() {
|
||||||
|
// void *p1 = NaiveAlloc(n, ArenaAlignDefault());
|
||||||
|
// void *p2 = NaiveAlloc(n, ArenaAlignAs(32));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
#ifndef GOOGLE_PROTOBUF_ARENA_ALIGN_H__ |
||||||
|
#define GOOGLE_PROTOBUF_ARENA_ALIGN_H__ |
||||||
|
|
||||||
|
#include <cstddef> |
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
#include "google/protobuf/stubs/logging.h" |
||||||
|
#include "google/protobuf/stubs/common.h" |
||||||
|
#include "absl/numeric/bits.h" |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace internal { |
||||||
|
|
||||||
|
struct ArenaAlignDefault { |
||||||
|
static constexpr size_t align = 8; // NOLINT
|
||||||
|
|
||||||
|
static constexpr bool IsAligned(size_t n) { return (n & (align - 1)) == 0; } |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
static bool IsAligned(T* ptr) { |
||||||
|
return (reinterpret_cast<uintptr_t>(ptr) & (align - 1)) == 0; |
||||||
|
} |
||||||
|
|
||||||
|
static constexpr size_t Ceil(size_t n) { return (n + align - 1) & -align; } |
||||||
|
static constexpr size_t Floor(size_t n) { return (n & ~(align - 1)); } |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
T* Ceil(T* ptr) const { |
||||||
|
uintptr_t intptr = reinterpret_cast<uintptr_t>(ptr); |
||||||
|
return reinterpret_cast<T*>((intptr + align - 1) & -align); |
||||||
|
} |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
T* CeilDefaultAligned(T* ptr) const { |
||||||
|
return ArenaAlignDefault().CheckAligned(ptr); |
||||||
|
} |
||||||
|
|
||||||
|
// Address sanitizer enabled alignment check
|
||||||
|
template <typename T> |
||||||
|
static T* CheckAligned(T* ptr) { |
||||||
|
GOOGLE_DCHECK(IsAligned(ptr)) << static_cast<void*>(ptr); |
||||||
|
return ptr; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
struct ArenaAlign { |
||||||
|
static constexpr bool IsDefault() { return false; }; |
||||||
|
|
||||||
|
size_t align = 8; |
||||||
|
|
||||||
|
constexpr bool IsAligned(size_t n) const { return (n & (align - 1)) == 0; } |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
bool IsAligned(T* ptr) const { |
||||||
|
return (reinterpret_cast<uintptr_t>(ptr) & (align - 1)) == 0; |
||||||
|
} |
||||||
|
|
||||||
|
constexpr size_t Ceil(size_t n) const { return (n + align - 1) & -align; } |
||||||
|
constexpr size_t Floor(size_t n) const { return (n & ~(align - 1)); } |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
T* Ceil(T* ptr) const { |
||||||
|
uintptr_t intptr = reinterpret_cast<uintptr_t>(ptr); |
||||||
|
return reinterpret_cast<T*>((intptr + align - 1) & -align); |
||||||
|
} |
||||||
|
|
||||||
|
template <typename T> |
||||||
|
T* CeilDefaultAligned(T* ptr) const { |
||||||
|
return Ceil(ArenaAlignDefault().CheckAligned(ptr)); |
||||||
|
} |
||||||
|
|
||||||
|
// Address sanitizer enabled alignment check
|
||||||
|
template <typename T> |
||||||
|
T* CheckAligned(T* ptr) const { |
||||||
|
GOOGLE_DCHECK(IsAligned(ptr)) << static_cast<void*>(ptr); |
||||||
|
return ptr; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
inline ArenaAlign ArenaAlignAs(size_t align) { |
||||||
|
// align must be a non zero power of 2 >= 8
|
||||||
|
GOOGLE_DCHECK_NE(align, 0); |
||||||
|
GOOGLE_DCHECK(absl::has_single_bit(align)) << "Invalid alignment " << align; |
||||||
|
return ArenaAlign{align}; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
#endif // GOOGLE_PROTOBUF_ARENA_ALIGN_H__
|
@ -0,0 +1,215 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "google/protobuf/arena_align.h" |
||||||
|
|
||||||
|
#include <gmock/gmock.h> |
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace internal { |
||||||
|
namespace { |
||||||
|
|
||||||
|
using ::testing::Eq; |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, Align) { |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_THAT(align_default.align, Eq(8)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, Floor) { |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_THAT(align_default.Floor(0), Eq(0)); |
||||||
|
EXPECT_THAT(align_default.Floor(1), Eq(0)); |
||||||
|
EXPECT_THAT(align_default.Floor(7), Eq(0)); |
||||||
|
EXPECT_THAT(align_default.Floor(8), Eq(8)); |
||||||
|
EXPECT_THAT(align_default.Floor(9), Eq(8)); |
||||||
|
EXPECT_THAT(align_default.Floor(15), Eq(8)); |
||||||
|
EXPECT_THAT(align_default.Floor(16), Eq(16)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, Ceil) { |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_THAT(align_default.Ceil(0), Eq(0)); |
||||||
|
EXPECT_THAT(align_default.Ceil(1), Eq(8)); |
||||||
|
EXPECT_THAT(align_default.Ceil(7), Eq(8)); |
||||||
|
EXPECT_THAT(align_default.Ceil(8), Eq(8)); |
||||||
|
EXPECT_THAT(align_default.Ceil(9), Eq(16)); |
||||||
|
EXPECT_THAT(align_default.Ceil(15), Eq(16)); |
||||||
|
EXPECT_THAT(align_default.Ceil(16), Eq(16)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, CeilPtr) { |
||||||
|
char p[17] = {0}; |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 0), Eq(p + 0)); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 1), Eq(p + 8)); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 7), Eq(p + 8)); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 8), Eq(p + 8)); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 9), Eq(p + 16)); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 15), Eq(p + 16)); |
||||||
|
EXPECT_THAT(align_default.Ceil(p + 16), Eq(p + 16)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, CheckAligned) { |
||||||
|
char p[17] = {0}; |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_THAT(align_default.CheckAligned(p + 0), Eq(p + 0)); |
||||||
|
EXPECT_THAT(align_default.CheckAligned(p + 8), Eq(p + 8)); |
||||||
|
EXPECT_THAT(align_default.CheckAligned(p + 16), Eq(p + 16)); |
||||||
|
#ifdef PROTOBUF_HAS_DEATH_TEST |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 1), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 7), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 9), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 15), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 17), ".*"); |
||||||
|
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, CeilDefaultAligned) { |
||||||
|
char p[17] = {0}; |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_THAT(align_default.CeilDefaultAligned(p + 0), Eq(p + 0)); |
||||||
|
EXPECT_THAT(align_default.CeilDefaultAligned(p + 8), Eq(p + 8)); |
||||||
|
EXPECT_THAT(align_default.CeilDefaultAligned(p + 16), Eq(p + 16)); |
||||||
|
#ifdef PROTOBUF_HAS_DEATH_TEST |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 1), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 7), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 9), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 15), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 17), ".*"); |
||||||
|
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlignDefault, IsAligned) { |
||||||
|
auto align_default = ArenaAlignDefault(); |
||||||
|
EXPECT_TRUE(align_default.IsAligned(0)); |
||||||
|
EXPECT_FALSE(align_default.IsAligned(1)); |
||||||
|
EXPECT_FALSE(align_default.IsAligned(7)); |
||||||
|
EXPECT_TRUE(align_default.IsAligned(8)); |
||||||
|
EXPECT_FALSE(align_default.IsAligned(9)); |
||||||
|
EXPECT_FALSE(align_default.IsAligned(15)); |
||||||
|
EXPECT_TRUE(align_default.IsAligned(16)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, Align) { |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_THAT(align_64.align, Eq(64)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, Floor) { |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_THAT(align_64.Floor(0), Eq(0)); |
||||||
|
EXPECT_THAT(align_64.Floor(1), Eq(0)); |
||||||
|
EXPECT_THAT(align_64.Floor(63), Eq(0)); |
||||||
|
EXPECT_THAT(align_64.Floor(64), Eq(64)); |
||||||
|
EXPECT_THAT(align_64.Floor(65), Eq(64)); |
||||||
|
EXPECT_THAT(align_64.Floor(127), Eq(64)); |
||||||
|
EXPECT_THAT(align_64.Floor(128), Eq(128)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, Ceil) { |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_THAT(align_64.Ceil(0), Eq(0)); |
||||||
|
EXPECT_THAT(align_64.Ceil(1), Eq(64)); |
||||||
|
EXPECT_THAT(align_64.Ceil(63), Eq(64)); |
||||||
|
EXPECT_THAT(align_64.Ceil(64), Eq(64)); |
||||||
|
EXPECT_THAT(align_64.Ceil(65), Eq(128)); |
||||||
|
EXPECT_THAT(align_64.Ceil(127), Eq(128)); |
||||||
|
EXPECT_THAT(align_64.Ceil(128), Eq(128)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, CeilPtr) { |
||||||
|
alignas(64) char p[129] = {0}; |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 0), Eq(p)); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 1), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 63), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 64), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 65), Eq(p + 128)); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 127), Eq(p + 128)); |
||||||
|
EXPECT_THAT(align_64.Ceil(p + 128), Eq(p + 128)); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, CheckAligned) { |
||||||
|
alignas(128) char p[129] = {0}; |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_THAT(align_64.CheckAligned(p + 0), Eq(p)); |
||||||
|
EXPECT_THAT(align_64.CheckAligned(p + 64), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.CheckAligned(p + 128), Eq(p + 128)); |
||||||
|
#ifdef PROTOBUF_HAS_DEATH_TEST |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 1), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 7), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 8), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 56), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 63), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 65), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 72), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 120), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 129), ".*"); |
||||||
|
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, CeilDefaultAligned) { |
||||||
|
alignas(128) char p[129] = {0}; |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 0), Eq(p)); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 8), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 56), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 64), Eq(p + 64)); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 72), Eq(p + 128)); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 120), Eq(p + 128)); |
||||||
|
EXPECT_THAT(align_64.CeilDefaultAligned(p + 128), Eq(p + 128)); |
||||||
|
#ifdef PROTOBUF_HAS_DEATH_TEST |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 1), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 7), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 63), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 65), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 127), ".*"); |
||||||
|
EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 129), ".*"); |
||||||
|
#endif // PROTOBUF_HAS_DEATH_TEST
|
||||||
|
} |
||||||
|
|
||||||
|
TEST(ArenaAlign, IsAligned) { |
||||||
|
auto align_64 = ArenaAlignAs(64); |
||||||
|
EXPECT_TRUE(align_64.IsAligned(0)); |
||||||
|
EXPECT_FALSE(align_64.IsAligned(1)); |
||||||
|
EXPECT_FALSE(align_64.IsAligned(63)); |
||||||
|
EXPECT_TRUE(align_64.IsAligned(64)); |
||||||
|
EXPECT_FALSE(align_64.IsAligned(65)); |
||||||
|
EXPECT_FALSE(align_64.IsAligned(127)); |
||||||
|
EXPECT_TRUE(align_64.IsAligned(128)); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
@ -0,0 +1,126 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__ |
||||||
|
#define GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__ |
||||||
|
|
||||||
|
#include <cstddef> |
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
#include "google/protobuf/arena_config.h" |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace internal { |
||||||
|
|
||||||
|
// `AllocationPolicy` defines `Arena` allocation policies. Applications can
|
||||||
|
// customize the inital and maximum sizes for arena allocation, as well as set
|
||||||
|
// custom allocation and deallocation functions. `AllocationPolicy` is for
|
||||||
|
// protocol buffer internal use only, and typically created from a user facing
|
||||||
|
// public configuration class such as `ArenaOptions`.
|
||||||
|
struct AllocationPolicy { |
||||||
|
static constexpr size_t kDefaultStartBlockSize = 256; |
||||||
|
|
||||||
|
size_t start_block_size = kDefaultStartBlockSize; |
||||||
|
size_t max_block_size = GetDefaultArenaMaxBlockSize(); |
||||||
|
|
||||||
|
void* (*block_alloc)(size_t) = nullptr; |
||||||
|
void (*block_dealloc)(void*, size_t) = nullptr; |
||||||
|
|
||||||
|
bool IsDefault() const { |
||||||
|
return start_block_size == kDefaultStartBlockSize && |
||||||
|
max_block_size == GetDefaultArenaMaxBlockSize() && |
||||||
|
block_alloc == nullptr && block_dealloc == nullptr; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// Tagged pointer to an AllocationPolicy.
|
||||||
|
class TaggedAllocationPolicyPtr { |
||||||
|
public: |
||||||
|
constexpr TaggedAllocationPolicyPtr() : policy_(0) {} |
||||||
|
|
||||||
|
explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy) |
||||||
|
: policy_(reinterpret_cast<uintptr_t>(policy)) {} |
||||||
|
|
||||||
|
void set_policy(AllocationPolicy* policy) { |
||||||
|
auto bits = policy_ & kTagsMask; |
||||||
|
policy_ = reinterpret_cast<uintptr_t>(policy) | bits; |
||||||
|
} |
||||||
|
|
||||||
|
AllocationPolicy* get() { |
||||||
|
return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask); |
||||||
|
} |
||||||
|
const AllocationPolicy* get() const { |
||||||
|
return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask); |
||||||
|
} |
||||||
|
|
||||||
|
AllocationPolicy& operator*() { return *get(); } |
||||||
|
const AllocationPolicy& operator*() const { return *get(); } |
||||||
|
|
||||||
|
AllocationPolicy* operator->() { return get(); } |
||||||
|
const AllocationPolicy* operator->() const { return get(); } |
||||||
|
|
||||||
|
bool is_user_owned_initial_block() const { |
||||||
|
return static_cast<bool>(get_mask<kUserOwnedInitialBlock>()); |
||||||
|
} |
||||||
|
void set_is_user_owned_initial_block(bool v) { |
||||||
|
set_mask<kUserOwnedInitialBlock>(v); |
||||||
|
} |
||||||
|
|
||||||
|
uintptr_t get_raw() const { return policy_; } |
||||||
|
|
||||||
|
private: |
||||||
|
enum : uintptr_t { |
||||||
|
kUserOwnedInitialBlock = 1, |
||||||
|
}; |
||||||
|
|
||||||
|
static constexpr uintptr_t kTagsMask = 7; |
||||||
|
static constexpr uintptr_t kPtrMask = ~kTagsMask; |
||||||
|
|
||||||
|
template <uintptr_t kMask> |
||||||
|
uintptr_t get_mask() const { |
||||||
|
return policy_ & kMask; |
||||||
|
} |
||||||
|
template <uintptr_t kMask> |
||||||
|
void set_mask(bool v) { |
||||||
|
if (v) { |
||||||
|
policy_ |= kMask; |
||||||
|
} else { |
||||||
|
policy_ &= ~kMask; |
||||||
|
} |
||||||
|
} |
||||||
|
uintptr_t policy_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
#endif // GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__
|
@ -0,0 +1,189 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef GOOGLE_PROTOBUF_ARENA_CLEANUP_H__ |
||||||
|
#define GOOGLE_PROTOBUF_ARENA_CLEANUP_H__ |
||||||
|
|
||||||
|
#include <cstddef> |
||||||
|
#include <cstdint> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include "google/protobuf/stubs/logging.h" |
||||||
|
#include "google/protobuf/stubs/common.h" |
||||||
|
#include "absl/base/attributes.h" |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace internal { |
||||||
|
namespace cleanup { |
||||||
|
|
||||||
|
// Helper function invoking the destructor of `object`
|
||||||
|
template <typename T> |
||||||
|
void arena_destruct_object(void* object) { |
||||||
|
reinterpret_cast<T*>(object)->~T(); |
||||||
|
} |
||||||
|
|
||||||
|
// Tag defines the type of cleanup / cleanup object. This tag is stored in the
|
||||||
|
// lowest 2 bits of the `elem` value identifying the type of node. All node
|
||||||
|
// types must start with a `uintptr_t` that stores `Tag` in its low two bits.
|
||||||
|
enum class Tag : uintptr_t { |
||||||
|
kDynamic = 0, // DynamicNode
|
||||||
|
kString = 1, // StringNode (std::string)
|
||||||
|
}; |
||||||
|
|
||||||
|
// DynamicNode contains the object (`elem`) that needs to be
|
||||||
|
// destroyed, and the function to destroy it (`destructor`)
|
||||||
|
// elem must be aligned at minimum on a 4 byte boundary.
|
||||||
|
struct DynamicNode { |
||||||
|
uintptr_t elem; |
||||||
|
void (*destructor)(void*); |
||||||
|
}; |
||||||
|
|
||||||
|
// StringNode contains a `std::string` object (`elem`) that needs to be
|
||||||
|
// destroyed. The lowest 2 bits of `elem` contain the non-zero kString tag.
|
||||||
|
struct StringNode { |
||||||
|
uintptr_t elem; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// EnableSpecializedTags() return true if the alignment of tagged objects
|
||||||
|
// such as std::string allow us to poke tags in the 2 LSB bits.
|
||||||
|
inline constexpr bool EnableSpecializedTags() { |
||||||
|
// For now we require 2 bits
|
||||||
|
return alignof(std::string) >= 8; |
||||||
|
} |
||||||
|
|
||||||
|
// Adds a cleanup entry identified by `tag` at memory location `pos`.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CreateNode(Tag tag, void* pos, |
||||||
|
const void* elem_raw, |
||||||
|
void (*destructor)(void*)) { |
||||||
|
auto elem = reinterpret_cast<uintptr_t>(elem_raw); |
||||||
|
if (EnableSpecializedTags()) { |
||||||
|
GOOGLE_DCHECK_EQ(elem & 3, 0ULL); // Must be aligned
|
||||||
|
switch (tag) { |
||||||
|
case Tag::kString: { |
||||||
|
StringNode n = {elem | static_cast<uintptr_t>(Tag::kString)}; |
||||||
|
memcpy(pos, &n, sizeof(n)); |
||||||
|
return; |
||||||
|
} |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
DynamicNode n = {elem, destructor}; |
||||||
|
memcpy(pos, &n, sizeof(n)); |
||||||
|
} |
||||||
|
|
||||||
|
// Optimization: performs a prefetch on `elem_address`.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void PrefetchNode( |
||||||
|
const void* elem_address) { |
||||||
|
(void)elem_address; |
||||||
|
} |
||||||
|
|
||||||
|
// Destroys the node idenitfied by `tag` stored at memory location `pos`.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void DestroyNode(Tag tag, const void* pos) { |
||||||
|
if (EnableSpecializedTags()) { |
||||||
|
switch (tag) { |
||||||
|
case Tag::kString: { |
||||||
|
StringNode n; |
||||||
|
memcpy(&n, pos, sizeof(n)); |
||||||
|
auto* s = reinterpret_cast<std::string*>(n.elem & ~0x7ULL); |
||||||
|
// Some compilers don't like fully qualified explicit dtor calls,
|
||||||
|
// so use an alias to avoid having to type `::`.
|
||||||
|
using string_type = std::string; |
||||||
|
s->~string_type(); |
||||||
|
return; |
||||||
|
} |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
DynamicNode n; |
||||||
|
memcpy(&n, pos, sizeof(n)); |
||||||
|
n.destructor(reinterpret_cast<void*>(n.elem)); |
||||||
|
} |
||||||
|
|
||||||
|
// Returns the `tag` identifying the type of object for `destructor` or
|
||||||
|
// kDynamic if `destructor` does not identify a well know object type.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE Tag Type(void (*destructor)(void*)) { |
||||||
|
if (EnableSpecializedTags()) { |
||||||
|
if (destructor == &arena_destruct_object<std::string>) { |
||||||
|
return Tag::kString; |
||||||
|
} |
||||||
|
} |
||||||
|
return Tag::kDynamic; |
||||||
|
} |
||||||
|
|
||||||
|
// Returns the `tag` identifying the type of object stored at memory location
|
||||||
|
// `elem`, which represents the first uintptr_t value in the node.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE Tag Type(void* raw) { |
||||||
|
if (!EnableSpecializedTags()) return Tag::kDynamic; |
||||||
|
|
||||||
|
uintptr_t elem; |
||||||
|
memcpy(&elem, raw, sizeof(elem)); |
||||||
|
switch (static_cast<Tag>(elem & 0x7ULL)) { |
||||||
|
case Tag::kDynamic: |
||||||
|
return Tag::kDynamic; |
||||||
|
case Tag::kString: |
||||||
|
return Tag::kString; |
||||||
|
default: |
||||||
|
GOOGLE_LOG(FATAL) << "Corrupted cleanup tag: " << (elem & 0x7ULL); |
||||||
|
return Tag::kDynamic; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Returns the required size in bytes off the node type identified by `tag`.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE size_t Size(Tag tag) { |
||||||
|
if (!EnableSpecializedTags()) return sizeof(DynamicNode); |
||||||
|
|
||||||
|
switch (tag) { |
||||||
|
case Tag::kDynamic: |
||||||
|
return sizeof(DynamicNode); |
||||||
|
case Tag::kString: |
||||||
|
return sizeof(StringNode); |
||||||
|
default: |
||||||
|
GOOGLE_LOG(FATAL) << "Corrupted cleanup tag: " << static_cast<int>(tag); |
||||||
|
return sizeof(DynamicNode); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Returns the required size in bytes off the node type for `destructor`.
|
||||||
|
inline ABSL_ATTRIBUTE_ALWAYS_INLINE size_t Size(void (*destructor)(void*)) { |
||||||
|
return destructor == nullptr ? 0 : Size(Type(destructor)); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace cleanup
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
#endif // GOOGLE_PROTOBUF_ARENA_CLEANUP_H__
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue