@ -42,14 +42,34 @@ static constexpr size_t kMinFlatSize = 32;
static constexpr size_t kMaxFlatSize = 4096 ;
static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead ;
static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead ;
static constexpr size_t kMaxLargeFlatSize = 256 * 1024 ;
static constexpr size_t kMaxLargeFlatLength = kMaxLargeFlatSize - kFlatOverhead ;
// kTagBase should make the Size <--> Tag computation resilient
// against changes to the value of FLAT when we add a new tag..
static constexpr uint8_t kTagBase = FLAT - 4 ;
// Converts the provided rounded size to the corresponding tag
constexpr uint8_t AllocatedSizeToTagUnchecked ( size_t size ) {
return static_cast < uint8_t > ( ( size < = 1024 ) ? size / 8 + 2
: 130 + size / 32 - 1024 / 32 ) ;
return static_cast < uint8_t > ( size < = 512 ? kTagBase + size / 8
: size < = 8192
? kTagBase + 512 / 8 + size / 64 - 512 / 64
: kTagBase + 512 / 8 + ( ( 8192 - 512 ) / 64 ) +
size / 4096 - 8192 / 4096 ) ;
}
static_assert ( kMinFlatSize / 8 + 2 > = FLAT , " " ) ;
static_assert ( AllocatedSizeToTagUnchecked ( kMaxFlatSize ) < = MAX_FLAT_TAG , " " ) ;
// Converts the provided tag to the corresponding allocated size
constexpr size_t TagToAllocatedSize ( uint8_t tag ) {
return ( tag < = kTagBase + 512 / 8 ) ? tag * 8 - kTagBase * 8
: ( tag < = kTagBase + ( 512 / 8 ) + ( ( 8192 - 512 ) / 64 ) )
? 512 + tag * 64 - kTagBase * 64 - 512 / 8 * 64
: 8192 + tag * 4096 - kTagBase * 4096 -
( ( 512 / 8 ) + ( ( 8192 - 512 ) / 64 ) ) * 4096 ;
}
static_assert ( AllocatedSizeToTagUnchecked ( kMinFlatSize ) = = FLAT , " " ) ;
static_assert ( AllocatedSizeToTagUnchecked ( kMaxLargeFlatSize ) = = MAX_FLAT_TAG ,
" " ) ;
// Helper functions for rounded div, and rounding to exact sizes.
constexpr size_t DivUp ( size_t n , size_t m ) { return ( n + m - 1 ) / m ; }
@ -58,7 +78,7 @@ constexpr size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
// Returns the size to the nearest equal or larger value that can be
// expressed exactly as a tag value.
inline size_t RoundUpForTag ( size_t size ) {
return RoundUp ( size , ( size < = 10 24 ) ? 8 : 32 ) ;
return RoundUp ( size , ( size < = 5 12) ? 8 : ( size < = 8192 ? 64 : 4096 ) ) ;
}
// Converts the allocated size to a tag, rounding down if the size
@ -71,26 +91,26 @@ inline uint8_t AllocatedSizeToTag(size_t size) {
return tag ;
}
// Converts the provided tag to the corresponding allocated size
constexpr size_t TagToAllocatedSize ( uint8_t tag ) {
return ( tag < = 130 ) ? ( ( tag - 2 ) * 8 ) : ( 1024 + ( tag - 130 ) * 32 ) ;
}
// Converts the provided tag to the corresponding available data length
constexpr size_t TagToLength ( uint8_t tag ) {
return TagToAllocatedSize ( tag ) - kFlatOverhead ;
}
// Enforce that kMaxFlatSize maps to a well-known exact tag value.
static_assert ( TagToAllocatedSize ( 226 ) = = kMaxFlatSize , " Bad tag logic " ) ;
static_assert ( TagToAllocatedSize ( MAX_FLAT_TAG ) = = kMaxLargeFlatSize ,
" Bad tag logic " ) ;
struct CordRepFlat : public CordRep {
// Tag for explicit 'large flat' allocation
struct Large { } ;
// Creates a new flat node.
static CordRepFlat * New ( size_t len ) {
template < size_t max_flat_size >
static CordRepFlat * NewImpl ( size_t len ) {
if ( len < = kMinFlatLength ) {
len = kMinFlatLength ;
} else if ( len > kMaxFlatLength ) {
len = kMaxFlatLength ;
} else if ( len > max_flat_size - kFlatOverhead ) {
len = max_flat_size - kFlatOverhead ;
}
// Round size up so it matches a size we can exactly express in a tag.
@ -101,6 +121,12 @@ struct CordRepFlat : public CordRep {
return rep ;
}
static CordRepFlat * New ( size_t len ) { return NewImpl < kMaxFlatSize > ( len ) ; }
static CordRepFlat * New ( Large , size_t len ) {
return NewImpl < kMaxLargeFlatSize > ( len ) ;
}
// Deletes a CordRepFlat instance created previously through a call to New().
// Flat CordReps are allocated and constructed with raw ::operator new and
// placement new, and must be destructed and deallocated accordingly.