mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-28 05:38:06 +00:00
Cleaned up & fixed buffer alignment handling.
- Fixed ForceVectorAlignment (and possibly other call-sites) not setting minalign_. - Fixed flipped alignment parameters in CopyTable (reflection). - Made aligment for FlatBufferBuilder internal buffer configurable (useful when reading a constructed buffer directly). - Ensured Alignment rounding is always up. Change-Id: I33ca4887d92a09cb11a369c14a109f4b07ae707a Tested: on Linux.
This commit is contained in:
@@ -525,12 +525,14 @@ class DetachedBuffer {
|
|||||||
// Essentially, this supports 2 std::vectors in a single buffer.
|
// Essentially, this supports 2 std::vectors in a single buffer.
|
||||||
class vector_downward {
|
class vector_downward {
|
||||||
public:
|
public:
|
||||||
explicit vector_downward(size_t initial_size = 1024,
|
explicit vector_downward(size_t initial_size,
|
||||||
Allocator *allocator = nullptr,
|
Allocator *allocator,
|
||||||
bool own_allocator = false)
|
bool own_allocator,
|
||||||
|
size_t buffer_minalign)
|
||||||
: allocator_(allocator ? allocator : &DefaultAllocator::instance()),
|
: allocator_(allocator ? allocator : &DefaultAllocator::instance()),
|
||||||
own_allocator_(own_allocator),
|
own_allocator_(own_allocator),
|
||||||
initial_size_(initial_size),
|
initial_size_(initial_size),
|
||||||
|
buffer_minalign_(buffer_minalign),
|
||||||
reserved_(0),
|
reserved_(0),
|
||||||
buf_(nullptr),
|
buf_(nullptr),
|
||||||
cur_(nullptr),
|
cur_(nullptr),
|
||||||
@@ -580,11 +582,6 @@ class vector_downward {
|
|||||||
return fb;
|
return fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t growth_policy(size_t bytes) {
|
|
||||||
return (bytes == 0) ? initial_size_
|
|
||||||
: ((bytes / 2) & ~(AlignOf<largest_scalar_t>() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ensure_space(size_t len) {
|
size_t ensure_space(size_t len) {
|
||||||
assert(cur_ >= scratch_ && scratch_ >= buf_);
|
assert(cur_ >= scratch_ && scratch_ >= buf_);
|
||||||
if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
|
if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
|
||||||
@@ -667,6 +664,7 @@ class vector_downward {
|
|||||||
Allocator *allocator_;
|
Allocator *allocator_;
|
||||||
bool own_allocator_;
|
bool own_allocator_;
|
||||||
size_t initial_size_;
|
size_t initial_size_;
|
||||||
|
size_t buffer_minalign_;
|
||||||
size_t reserved_;
|
size_t reserved_;
|
||||||
uint8_t *buf_;
|
uint8_t *buf_;
|
||||||
uint8_t *cur_; // Points at location between empty (below) and used (above).
|
uint8_t *cur_; // Points at location between empty (below) and used (above).
|
||||||
@@ -677,9 +675,9 @@ class vector_downward {
|
|||||||
auto old_reserved = reserved_;
|
auto old_reserved = reserved_;
|
||||||
auto old_size = size();
|
auto old_size = size();
|
||||||
auto old_scratch_size = scratch_size();
|
auto old_scratch_size = scratch_size();
|
||||||
reserved_ += (std::max)(len, growth_policy(old_reserved));
|
reserved_ += (std::max)(len,
|
||||||
FLATBUFFERS_CONSTEXPR size_t alignment = AlignOf<largest_scalar_t>();
|
old_reserved ? old_reserved / 2 : initial_size_);
|
||||||
reserved_ = (reserved_ + alignment - 1) & ~(alignment - 1);
|
reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
|
||||||
if (buf_) {
|
if (buf_) {
|
||||||
buf_ = allocator_->reallocate_downward(buf_, old_reserved, reserved_,
|
buf_ = allocator_->reallocate_downward(buf_, old_reserved, reserved_,
|
||||||
old_size, old_scratch_size);
|
old_size, old_scratch_size);
|
||||||
@@ -726,10 +724,16 @@ class FlatBufferBuilder {
|
|||||||
/// a `DefaultAllocator`.
|
/// a `DefaultAllocator`.
|
||||||
/// @param[in] own_allocator Whether the builder/vector should own the
|
/// @param[in] own_allocator Whether the builder/vector should own the
|
||||||
/// allocator. Defaults to / `false`.
|
/// allocator. Defaults to / `false`.
|
||||||
|
/// @param[in] buffer_minalign Force the buffer to be aligned to the given
|
||||||
|
/// minimum alignment upon reallocation. Only needed if you intend to store
|
||||||
|
/// types with custom alignment AND you wish to read the buffer in-place
|
||||||
|
/// directly after creation.
|
||||||
explicit FlatBufferBuilder(size_t initial_size = 1024,
|
explicit FlatBufferBuilder(size_t initial_size = 1024,
|
||||||
Allocator *allocator = nullptr,
|
Allocator *allocator = nullptr,
|
||||||
bool own_allocator = false)
|
bool own_allocator = false,
|
||||||
: buf_(initial_size, allocator, own_allocator),
|
size_t buffer_minalign =
|
||||||
|
AlignOf<largest_scalar_t>())
|
||||||
|
: buf_(initial_size, allocator, own_allocator, buffer_minalign),
|
||||||
num_field_loc(0),
|
num_field_loc(0),
|
||||||
max_voffset_(0),
|
max_voffset_(0),
|
||||||
nested(false),
|
nested(false),
|
||||||
@@ -827,8 +831,12 @@ class FlatBufferBuilder {
|
|||||||
/// @cond FLATBUFFERS_INTERNAL
|
/// @cond FLATBUFFERS_INTERNAL
|
||||||
void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
|
void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
|
||||||
|
|
||||||
void Align(size_t elem_size) {
|
void TrackMinAlign(size_t elem_size) {
|
||||||
if (elem_size > minalign_) minalign_ = elem_size;
|
if (elem_size > minalign_) minalign_ = elem_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Align(size_t elem_size) {
|
||||||
|
TrackMinAlign(elem_size);
|
||||||
buf_.fill(PaddingBytes(buf_.size(), elem_size));
|
buf_.fill(PaddingBytes(buf_.size(), elem_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1023,6 +1031,7 @@ class FlatBufferBuilder {
|
|||||||
// Aligns such that when "len" bytes are written, an object can be written
|
// Aligns such that when "len" bytes are written, an object can be written
|
||||||
// after it with "alignment" without padding.
|
// after it with "alignment" without padding.
|
||||||
void PreAlign(size_t len, size_t alignment) {
|
void PreAlign(size_t len, size_t alignment) {
|
||||||
|
TrackMinAlign(alignment);
|
||||||
buf_.fill(PaddingBytes(GetSize() + len, alignment));
|
buf_.fill(PaddingBytes(GetSize() + len, alignment));
|
||||||
}
|
}
|
||||||
template<typename T> void PreAlign(size_t len) {
|
template<typename T> void PreAlign(size_t len) {
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
|||||||
auto element_size = GetTypeSize(element_base_type);
|
auto element_size = GetTypeSize(element_base_type);
|
||||||
if (elemobjectdef && elemobjectdef->is_struct())
|
if (elemobjectdef && elemobjectdef->is_struct())
|
||||||
element_size = elemobjectdef->bytesize();
|
element_size = elemobjectdef->bytesize();
|
||||||
fbb.StartVector(element_size, vec->size());
|
fbb.StartVector(vec->size(), element_size);
|
||||||
fbb.PushBytes(vec->Data(), element_size * vec->size());
|
fbb.PushBytes(vec->Data(), element_size * vec->size());
|
||||||
offset = fbb.EndVector(vec->size());
|
offset = fbb.EndVector(vec->size());
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user