Skip to content

Commit

Permalink
Merge pull request #510 from romange/Pr2
Browse files Browse the repository at this point in the history
fix: avoid over-allocating memory for 8 byte alignment or less
  • Loading branch information
danielaparker authored May 20, 2024
2 parents f5cc67c + 07e3315 commit 0be3e70
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions include/jsoncons/detail/heap_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <memory> // std::allocator
#include <jsoncons/config/compiler_support.hpp>

namespace jsoncons {
namespace jsoncons {
namespace detail {

inline char*
Expand All @@ -30,8 +30,8 @@ namespace detail {
{
Extra extra_;
Allocator alloc_;
Allocator& get_allocator()

Allocator& get_allocator()
{
return alloc_;
}
Expand All @@ -53,15 +53,16 @@ namespace detail {
struct heap_string : public heap_string_base<Extra,Allocator>
{
using char_type = CharT;
using allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<CharT>;
using allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<CharT>;
using allocator_traits_type = std::allocator_traits<allocator_type>;
using pointer = typename allocator_traits_type::pointer;

pointer p_;
std::size_t length_;
uint8_t offset_;
uint8_t align_pad_;

~heap_string() noexcept = default;
~heap_string() noexcept = default;

const char_type* c_str() const { return extension_traits::to_plain_pointer(p_); }
const char_type* data() const { return extension_traits::to_plain_pointer(p_); }
Expand Down Expand Up @@ -110,10 +111,10 @@ namespace detail {
using heap_string_type = heap_string<CharT,Extra,Allocator>;
private:

using byte_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
using byte_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
using byte_pointer = typename std::allocator_traits<byte_allocator_type>::pointer;

using heap_string_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<heap_string_type>;
using heap_string_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<heap_string_type>;
public:
using pointer = typename std::allocator_traits<heap_string_allocator_type>::pointer;

Expand All @@ -136,27 +137,41 @@ namespace detail {
std::size_t len = aligned_size(length*sizeof(char_type));

std::size_t align = alignof(storage_type);
std::size_t mem_len = (align-1)+len;

char* q = nullptr;
char* storage = nullptr;
byte_allocator_type byte_alloc(alloc);
byte_pointer ptr = byte_alloc.allocate(mem_len);
uint8_t align_pad = 0;

char* q = extension_traits::to_plain_pointer(ptr);
if (align <= 8) {
byte_pointer ptr = byte_alloc.allocate(len);
q = extension_traits::to_plain_pointer(ptr);

char* storage = align_up(q, align);
if (reinterpret_cast<uintptr_t>(q) % align == 0) {
storage = q;
} else {
byte_alloc.deallocate(ptr, len);
}
}

JSONCONS_ASSERT(storage >= q);
if (storage == nullptr) {
align_pad = uint8_t(align-1);
byte_pointer ptr = byte_alloc.allocate(align_pad+len);
q = extension_traits::to_plain_pointer(ptr);
storage = align_up(q, align);
JSONCONS_ASSERT(storage >= q);
}

heap_string_type* ps = new(storage)heap_string_type(extra, byte_alloc);

auto psa = launder_cast<storage_t*>(storage);
auto psa = launder_cast<storage_t*>(storage);

CharT* p = new(&psa->c)char_type[length + 1];
std::memcpy(p, s, length*sizeof(char_type));
p[length] = 0;
ps->p_ = std::pointer_traits<typename heap_string_type::pointer>::pointer_to(*p);
ps->length_ = length;
ps->offset_ = (uint8_t)(storage - q);
ps->align_pad_ = align_pad;
return std::pointer_traits<pointer>::pointer_to(*ps);
}

Expand All @@ -170,7 +185,7 @@ namespace detail {

char* p = q - ptr->offset_;

std::size_t mem_size = (alignof(storage_type)-1)+ aligned_size(ptr->length_*sizeof(char_type));
std::size_t mem_size = ptr->align_pad_ + aligned_size(ptr->length_*sizeof(char_type));
byte_allocator_type byte_alloc(ptr->get_allocator());
byte_alloc.deallocate(p,mem_size + ptr->offset_);
}
Expand Down

0 comments on commit 0be3e70

Please sign in to comment.