@@ -54,55 +54,39 @@ size_t SmallString::UsedThreadLocal() {
5454
5555static_assert (sizeof (SmallString) == 16 );
5656
57- // we should use only for sizes greater than kPrefLen
5857size_t SmallString::Assign (std::string_view s) {
5958 DCHECK_GT (s.size (), kPrefLen );
60-
59+ DCHECK ( CanAllocate (s. size ()));
6160 uint8_t * realptr = nullptr ;
6261
63- if (size_ == 0 ) {
64- // packed structs can not be tied here.
65- auto [sp, rp] = tl.seg_alloc ->Allocate (s.size () - kPrefLen );
62+ // reallocate if we need a larger allocation or it becomes space-inefficient
63+ size_t heap_len = s.size () - kPrefLen ;
64+ if (size_t available = MallocUsed (); available < heap_len || heap_len * 2 < available) {
65+ Free ();
66+
67+ auto [sp, rp] = tl.seg_alloc ->Allocate (heap_len);
6668 small_ptr_ = sp;
6769 realptr = rp;
68- size_ = s.size ();
69- } else if (s.size () <= size_) {
70- realptr = tl.seg_alloc ->Translate (small_ptr_);
71-
72- if (s.size () < size_) {
73- size_t capacity = mi_usable_size (realptr);
74- if (s.size () * 2 < capacity) {
75- tl.seg_alloc ->Free (small_ptr_);
76- auto [sp, rp] = tl.seg_alloc ->Allocate (s.size () - kPrefLen );
77- small_ptr_ = sp;
78- realptr = rp;
79- }
80- size_ = s.size ();
81- }
8270 } else {
83- LOG (FATAL) << " TBD: Bad usage " ;
71+ realptr = tl. seg_alloc -> Translate (small_ptr_) ;
8472 }
8573
74+ size_ = s.size ();
8675 memcpy (prefix_, s.data (), kPrefLen );
87- memcpy (realptr, s.data () + kPrefLen , s.size () - kPrefLen );
88-
76+ memcpy (realptr, s.data () + kPrefLen , heap_len);
8977 return mi_malloc_usable_size (realptr);
9078}
9179
9280void SmallString::Free () {
93- if (size_ <= kPrefLen )
94- return ;
95-
96- tl.seg_alloc ->Free (small_ptr_);
81+ if (size_)
82+ tl.seg_alloc ->Free (small_ptr_);
9783 size_ = 0 ;
9884}
9985
10086uint16_t SmallString::MallocUsed () const {
101- if (size_ <= kPrefLen )
102- return 0 ;
103- auto * realptr = tl.seg_alloc ->Translate (small_ptr_);
104-
105- return mi_malloc_usable_size (realptr);
87+ if (size_)
88+ return mi_malloc_usable_size (tl.seg_alloc ->Translate (small_ptr_));
89+ return 0 ;
10690}
10791
10892bool SmallString::Equal (std::string_view o) const {
@@ -112,13 +96,10 @@ bool SmallString::Equal(std::string_view o) const {
11296 if (size_ == 0 )
11397 return true ;
11498
115- DCHECK_GT (size_, kPrefLen );
116-
11799 if (memcmp (prefix_, o.data (), kPrefLen ) != 0 )
118100 return false ;
119101
120102 uint8_t * realp = tl.seg_alloc ->Translate (small_ptr_);
121-
122103 return memcmp (realp, o.data () + kPrefLen , size_ - kPrefLen ) == 0 ;
123104}
124105
@@ -127,21 +108,16 @@ bool SmallString::Equal(const SmallString& os) const {
127108 return false ;
128109
129110 string_view me[2 ], other[2 ];
130- unsigned n1 = GetV (me);
131- unsigned n2 = os.GetV (other);
132-
133- if (n1 != n2)
134- return false ;
111+ Get (me);
112+ os.Get (other);
135113
136114 return me[0 ] == other[0 ] && me[1 ] == other[1 ];
137115}
138116
139117uint64_t SmallString::HashCode () const {
140- DCHECK_GT (size_, kPrefLen );
141-
142118 string_view slice[2 ];
119+ Get (slice);
143120
144- GetV (slice);
145121 XXH3_state_t* state = tl.xxh_state .get ();
146122 XXH3_64bits_reset_withSeed (state, kHashSeed );
147123 XXH3_64bits_update (state, slice[0 ].data (), slice[0 ].size ());
@@ -150,41 +126,35 @@ uint64_t SmallString::HashCode() const {
150126 return XXH3_64bits_digest (state);
151127}
152128
153- void SmallString::Get (std::string* dest) const {
154- dest->resize (size_);
155- if (size_) {
156- DCHECK_GT (size_, kPrefLen );
157- memcpy (dest->data (), prefix_, kPrefLen );
158- uint8_t * ptr = tl.seg_alloc ->Translate (small_ptr_);
159- memcpy (dest->data () + kPrefLen , ptr, size_ - kPrefLen );
160- }
161- }
162-
163- unsigned SmallString::GetV (string_view dest[2 ]) const {
164- DCHECK_GT (size_, kPrefLen );
165- if (size_ <= kPrefLen ) {
166- dest[0 ] = string_view{prefix_, size_};
167- return 1 ;
168- }
129+ void SmallString::Get (string_view dest[2 ]) const {
130+ DCHECK (size_);
169131
170132 dest[0 ] = string_view{prefix_, kPrefLen };
171133 uint8_t * ptr = tl.seg_alloc ->Translate (small_ptr_);
172134 dest[1 ] = string_view{reinterpret_cast <char *>(ptr), size_ - kPrefLen };
173- return 2 ;
174135}
175136
176- bool SmallString::DefragIfNeeded (PageUsage* page_usage) {
177- DCHECK_GT (size_, kPrefLen );
178- if (size_ <= kPrefLen ) {
179- return false ;
180- }
137+ void SmallString::Get (char * out) const {
138+ string_view strs[2 ];
139+ Get (strs);
140+ memcpy (out, strs[0 ].data (), strs[0 ].size ());
141+ memcpy (out + strs[0 ].size (), strs[1 ].data (), strs[1 ].size ());
142+ }
181143
144+ void SmallString::Get (std::string* dest) const {
145+ dest->resize (size_);
146+ Get (dest->data ());
147+ }
148+
149+ bool SmallString::DefragIfNeeded (PageUsage* page_usage) {
182150 uint8_t * cur_real_ptr = tl.seg_alloc ->Translate (small_ptr_);
183151 if (!page_usage->IsPageForObjectUnderUtilized (tl.seg_alloc ->heap (), cur_real_ptr))
184152 return false ;
185153
186- auto [sp, rp] = tl.seg_alloc ->Allocate (size_ - kPrefLen );
154+ if (!CanAllocate (size_ - kPrefLen )) // Forced
155+ return false ;
187156
157+ auto [sp, rp] = tl.seg_alloc ->Allocate (size_ - kPrefLen );
188158 memcpy (rp, cur_real_ptr, size_ - kPrefLen );
189159 tl.seg_alloc ->Free (small_ptr_);
190160 small_ptr_ = sp;
0 commit comments