2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef CopiedAllocator_h
27 #define CopiedAllocator_h
29 #include "CopiedBlock.h"
30 #include <wtf/CheckedBoolean.h>
31 #include <wtf/DataLog.h>
35 class CopiedAllocator
{
39 bool fastPathShouldSucceed(size_t bytes
) const;
40 CheckedBoolean
tryAllocate(size_t bytes
, void** outPtr
);
41 CheckedBoolean
tryAllocateDuringCopying(size_t bytes
, void** outPtr
);
42 CheckedBoolean
tryReallocate(void *oldPtr
, size_t oldBytes
, size_t newBytes
);
43 void* forceAllocate(size_t bytes
);
44 CopiedBlock
* resetCurrentBlock();
45 void setCurrentBlock(CopiedBlock
*);
46 size_t currentCapacity();
48 bool isValid() { return !!m_currentBlock
; }
50 CopiedBlock
* currentBlock() { return m_currentBlock
; }
52 // Yes, these are public. No, that doesn't mean you can play with them.
53 // If I had made them private then I'd have to list off all of the JIT
54 // classes and functions that are entitled to modify these directly, and
55 // that would have been gross.
56 size_t m_currentRemaining
;
57 char* m_currentPayloadEnd
;
58 CopiedBlock
* m_currentBlock
;
61 inline CopiedAllocator::CopiedAllocator()
62 : m_currentRemaining(0)
63 , m_currentPayloadEnd(0)
68 inline bool CopiedAllocator::fastPathShouldSucceed(size_t bytes
) const
70 ASSERT(is8ByteAligned(reinterpret_cast<void*>(bytes
)));
72 return bytes
<= m_currentRemaining
;
75 inline CheckedBoolean
CopiedAllocator::tryAllocate(size_t bytes
, void** outPtr
)
77 ASSERT(is8ByteAligned(reinterpret_cast<void*>(bytes
)));
79 // This code is written in a gratuitously low-level manner, in order to
80 // serve as a kind of template for what the JIT would do. Note that the
81 // way it's written it ought to only require one register, which doubles
82 // as the result, provided that the compiler does a minimal amount of
83 // control flow simplification and the bytes argument is a constant.
85 size_t currentRemaining
= m_currentRemaining
;
86 if (bytes
> currentRemaining
)
88 currentRemaining
-= bytes
;
89 m_currentRemaining
= currentRemaining
;
90 *outPtr
= m_currentPayloadEnd
- currentRemaining
- bytes
;
92 ASSERT(is8ByteAligned(*outPtr
));
97 inline CheckedBoolean
CopiedAllocator::tryAllocateDuringCopying(size_t bytes
, void** outPtr
)
99 if (!tryAllocate(bytes
, outPtr
))
101 m_currentBlock
->reportLiveBytesDuringCopying(bytes
);
105 inline CheckedBoolean
CopiedAllocator::tryReallocate(
106 void* oldPtr
, size_t oldBytes
, size_t newBytes
)
108 ASSERT(is8ByteAligned(oldPtr
));
109 ASSERT(is8ByteAligned(reinterpret_cast<void*>(oldBytes
)));
110 ASSERT(is8ByteAligned(reinterpret_cast<void*>(newBytes
)));
112 ASSERT(newBytes
> oldBytes
);
114 size_t additionalBytes
= newBytes
- oldBytes
;
116 size_t currentRemaining
= m_currentRemaining
;
117 if (m_currentPayloadEnd
- currentRemaining
- oldBytes
!= static_cast<char*>(oldPtr
))
120 if (additionalBytes
> currentRemaining
)
123 m_currentRemaining
= currentRemaining
- additionalBytes
;
128 inline void* CopiedAllocator::forceAllocate(size_t bytes
)
130 void* result
= 0; // Needed because compilers don't realize this will always be assigned.
131 CheckedBoolean didSucceed
= tryAllocate(bytes
, &result
);
136 inline CopiedBlock
* CopiedAllocator::resetCurrentBlock()
138 CopiedBlock
* result
= m_currentBlock
;
140 result
->m_remaining
= m_currentRemaining
;
142 m_currentRemaining
= 0;
143 m_currentPayloadEnd
= 0;
148 inline void CopiedAllocator::setCurrentBlock(CopiedBlock
* newBlock
)
150 ASSERT(!m_currentBlock
);
151 m_currentBlock
= newBlock
;
153 m_currentRemaining
= newBlock
->m_remaining
;
154 m_currentPayloadEnd
= newBlock
->payloadEnd();
157 inline size_t CopiedAllocator::currentCapacity()
161 return m_currentBlock
->capacity();