1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "mojo/public/bindings/lib/buffer.h"
13 #include "mojo/public/bindings/lib/bindings_serialization.h"
14 #include "mojo/public/environment/buffer_tls.h"
16 // Scrub memory in debug builds to help catch use-after-free bugs.
18 #define DEBUG_SCRUB(address, size) (void) (address), (void) (size)
20 #define DEBUG_SCRUB(address, size) memset(address, 0xCD, size)
25 //-----------------------------------------------------------------------------
28 previous_ = internal::SetCurrentBuffer(this);
32 Buffer* buf MOJO_ALLOW_UNUSED = internal::SetCurrentBuffer(previous_);
36 Buffer* Buffer::current() {
37 return internal::GetCurrentBuffer();
40 //-----------------------------------------------------------------------------
44 ScratchBuffer::ScratchBuffer()
47 fixed_.cursor = fixed_data_;
48 fixed_.end = fixed_data_ + kMinSegmentSize;
51 ScratchBuffer::~ScratchBuffer() {
52 // Invoke destructors in reverse order to mirror allocation order.
53 std::deque<PendingDestructor>::reverse_iterator it;
54 for (it = pending_dtors_.rbegin(); it != pending_dtors_.rend(); ++it)
55 it->func(it->address);
58 Segment* doomed = overflow_;
59 overflow_ = overflow_->next;
60 DEBUG_SCRUB(doomed, doomed->end - reinterpret_cast<char*>(doomed));
63 DEBUG_SCRUB(fixed_data_, sizeof(fixed_data_));
66 void* ScratchBuffer::Allocate(size_t delta, Destructor func) {
67 delta = internal::Align(delta);
69 void* result = AllocateInSegment(&fixed_, delta);
72 result = AllocateInSegment(overflow_, delta);
75 AddOverflowSegment(delta);
76 result = AllocateInSegment(overflow_, delta);
81 PendingDestructor dtor;
83 dtor.address = result;
84 pending_dtors_.push_back(dtor);
89 void* ScratchBuffer::AllocateInSegment(Segment* segment, size_t delta) {
91 if (static_cast<size_t>(segment->end - segment->cursor) >= delta) {
92 result = segment->cursor;
93 memset(result, 0, delta);
94 segment->cursor += delta;
101 void ScratchBuffer::AddOverflowSegment(size_t delta) {
102 if (delta < kMinSegmentSize)
103 delta = kMinSegmentSize;
105 // Ensure segment buffer is aligned.
106 size_t segment_size = internal::Align(sizeof(Segment)) + delta;
108 Segment* segment = static_cast<Segment*>(malloc(segment_size));
109 segment->next = overflow_;
110 segment->cursor = reinterpret_cast<char*>(segment + 1);
111 segment->end = segment->cursor + delta;
116 //-----------------------------------------------------------------------------
118 FixedBuffer::FixedBuffer(size_t size)
121 size_(internal::Align(size)) {
122 ptr_ = static_cast<char*>(calloc(size_, 1));
125 FixedBuffer::~FixedBuffer() {
129 void* FixedBuffer::Allocate(size_t delta, Destructor dtor) {
132 delta = internal::Align(delta);
134 // TODO(darin): Using <assert.h> is probably not going to cut it.
136 assert(cursor_ + delta <= size_);
137 if (cursor_ + delta > size_)
140 char* result = ptr_ + cursor_;
146 void* FixedBuffer::Leak() {
154 } // namespace internal