Skip to content

Commit 57e3130

Browse files
committed
reduce size of Array!T from 32 to 16 bytes
- allocates a maximum of uint.max entries - overlaps single entry with pointer to array
1 parent e0ef787 commit 57e3130

2 files changed

Lines changed: 58 additions & 45 deletions

File tree

compiler/src/dmd/root/array.d

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,24 @@ debug
2929

3030
extern (C++) struct Array(T)
3131
{
32-
size_t length;
32+
size_t length() const { return data.used; }
33+
void length(size_t len) { data.used = cast(uint)len; }
3334

3435
private:
35-
T[] data;
3636
enum SMALLARRAYCAP = 1;
37-
T[SMALLARRAYCAP] smallarray; // inline storage for small arrays
38-
37+
struct A
38+
{
39+
uint allocated = SMALLARRAYCAP;
40+
uint used;
41+
union
42+
{
43+
T[SMALLARRAYCAP] smallarray; // inline storage for small arrays
44+
T* _ptr;
45+
}
46+
extern(D) inout(T)* ptr() inout { return allocated <= SMALLARRAYCAP ? smallarray.ptr : _ptr; }
47+
}
48+
A data;
49+
3950
public:
4051
/*******************
4152
* Params:
@@ -44,7 +55,7 @@ public:
4455
this(size_t dim) pure nothrow scope
4556
{
4657
reserve(dim);
47-
this.length = dim;
58+
this.data.used = cast(uint)dim;
4859
}
4960

5061
@disable this(this);
@@ -54,12 +65,13 @@ public:
5465
debug (stomp)
5566
{
5667
if (data.ptr)
57-
memset(data.ptr, 0xFF, data.length * T.sizeof);
68+
memset(data.ptr, 0xFF, data.allocated * T.sizeof);
5869
}
59-
if (data.ptr && data.ptr != &smallarray[0])
70+
if (data.allocated > SMALLARRAYCAP)
6071
mem.xfree(data.ptr);
6172
}
6273

74+
@trusted:
6375
// this is using a template constraint because of ambiguity with this(size_t) when T is
6476
// int, and c++ header generation doesn't accept wrapping this in static if
6577
extern(D) this()(T[] elems ...) pure nothrow if (is(T == struct) || is(T == class))
@@ -94,7 +106,7 @@ public:
94106
}
95107
else
96108
{
97-
buf[u] = toStringFunc(a.data[u]);
109+
buf[u] = toStringFunc(a.data.ptr[u]);
98110
}
99111

100112
len += buf[u].length + seplen;
@@ -144,7 +156,7 @@ public:
144156
ref Array push(T ptr) return pure nothrow
145157
{
146158
reserve(1);
147-
data[length++] = ptr;
159+
data.ptr[data.used++] = ptr;
148160
return this;
149161
}
150162

@@ -164,31 +176,32 @@ public:
164176

165177
void reserve(size_t nentries) pure nothrow
166178
{
167-
//printf("Array::reserve: length = %d, data.length = %d, nentries = %d\n", cast(int)length, cast(int)data.length, cast(int)nentries);
179+
//printf("Array::reserve: length = %d, data.allocated = %d, nentries = %d\n", cast(int)length, cast(int)data.allocated, cast(int)nentries);
168180

169181
// Cold path
170182
void enlarge(size_t nentries)
171183
{
184+
static if (uint.max < size_t.max)
185+
assert(data.used + nentries <= uint.max);
186+
172187
pragma(inline, false); // never inline cold path
173-
if (data.length == 0)
188+
if (data.allocated == 0)
174189
{
175190
// Not properly initialized, someone memset it to zero
176-
if (nentries <= SMALLARRAYCAP)
177-
{
178-
data = SMALLARRAYCAP ? smallarray[] : null;
179-
}
180-
else
191+
if (nentries > SMALLARRAYCAP)
181192
{
182193
auto p = cast(T*)mem.xmalloc(nentries * T.sizeof);
183-
data = p[0 .. nentries];
194+
data._ptr = p;
184195
}
196+
data.allocated = cast(uint)nentries;
185197
}
186-
else if (data.length == SMALLARRAYCAP)
198+
else if (data.allocated <= SMALLARRAYCAP)
187199
{
188200
const allocdim = length + nentries;
189201
auto p = cast(T*)mem.xmalloc(allocdim * T.sizeof);
190-
memcpy(p, smallarray.ptr, length * T.sizeof);
191-
data = p[0 .. allocdim];
202+
memcpy(p, data.smallarray.ptr, length * T.sizeof);
203+
data._ptr = p;
204+
data.allocated = cast(uint)allocdim;
192205
}
193206
else
194207
{
@@ -203,23 +216,23 @@ public:
203216
// always move using allocate-copy-stomp-free
204217
auto p = cast(T*)mem.xmalloc(allocdim * T.sizeof);
205218
memcpy(p, data.ptr, length * T.sizeof);
206-
memset(data.ptr, 0xFF, data.length * T.sizeof);
219+
memset(data.ptr, 0xFF, data.allocated * T.sizeof);
207220
mem.xfree(data.ptr);
208-
data = p[0 .. allocdim];
209221
}
210222
else
211223
{
212224
auto p = cast(T*)mem.xrealloc(data.ptr, allocdim * T.sizeof);
213-
data = p[0 .. allocdim];
214225
}
226+
data._ptr = p;
227+
data.allocated = cast(uint)allocdim;
215228
}
216229

217230
debug (stomp)
218231
{
219232
if (data.ptr)
220233
{
221-
if (length < data.length)
222-
memset(data.ptr + length, 0xFF, (data.length - length) * T.sizeof);
234+
if (length < data.allocated)
235+
memset(data.ptr + length, 0xFF, (data.allocated - length) * T.sizeof);
223236
}
224237
}
225238
else
@@ -228,22 +241,22 @@ public:
228241
{
229242
if (data.ptr)
230243
{
231-
if (length < data.length)
232-
memset(data.ptr + length, 0xFF, (data.length - length) * T.sizeof);
244+
if (length < data.allocated)
245+
memset(data.ptr + length, 0xFF, (data.allocated - length) * T.sizeof);
233246
}
234247
}
235248
}
236249
}
237250

238-
if (data.length - length < nentries) // false means hot path
251+
if (data.allocated - length < nentries) // false means hot path
239252
enlarge(nentries);
240253
}
241254

242255
void remove(size_t i) pure nothrow @nogc
243256
{
244257
if (length - i - 1)
245258
memmove(data.ptr + i, data.ptr + i + 1, (length - i - 1) * T.sizeof);
246-
length--;
259+
data.used--;
247260
debug (stomp) memset(data.ptr + length, 0xFF, T.sizeof);
248261
}
249262

@@ -256,7 +269,7 @@ public:
256269
if (length != index)
257270
memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof);
258271
memcpy(data.ptr + index, a.data.ptr, d * T.sizeof);
259-
length += d;
272+
data.used += d;
260273
}
261274
}
262275

@@ -267,15 +280,15 @@ public:
267280
if (length != index)
268281
memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof);
269282
memcpy(data.ptr + index, a.ptr, d * T.sizeof);
270-
length += d;
283+
data.used += d;
271284
}
272285

273286
void insert(size_t index, T ptr) pure nothrow
274287
{
275288
reserve(1);
276289
memmove(data.ptr + index + 1, data.ptr + index, (length - index) * T.sizeof);
277-
data[index] = ptr;
278-
length++;
290+
data.ptr[index] = ptr;
291+
data.used++;
279292
}
280293

281294
/// Insert 'count' copies of 'value' at 'index' position
@@ -286,8 +299,8 @@ public:
286299
reserve(count);
287300
if (length != index)
288301
memmove(data.ptr + index + count, data.ptr + index, (length - index) * T.sizeof);
289-
data[index .. index + count] = value;
290-
length += count;
302+
data.ptr[index .. index + count] = value;
303+
data.used += count;
291304
}
292305

293306
void setDim(size_t newdim) pure nothrow
@@ -296,13 +309,13 @@ public:
296309
{
297310
reserve(newdim - length);
298311
}
299-
length = newdim;
312+
data.used = cast(uint)newdim;
300313
}
301314

302315
size_t find(T ptr) const nothrow pure
303316
{
304317
foreach (i; 0 .. length)
305-
if (data[i] is ptr)
318+
if (data.ptr[i] is ptr)
306319
return i;
307320
return size_t.max;
308321
}
@@ -338,13 +351,13 @@ public:
338351
{
339352
reserve(1);
340353
memmove(data.ptr + 1, data.ptr, length * T.sizeof);
341-
data[0] = ptr;
342-
length++;
354+
data.ptr[0] = ptr;
355+
data.used++;
343356
}
344357

345358
void zero() nothrow pure @nogc
346359
{
347-
data[0 .. length] = T.init;
360+
data.ptr[0 .. length] = T.init;
348361
}
349362

350363
T pop() nothrow pure @nogc
@@ -357,18 +370,18 @@ public:
357370
return result;
358371
}
359372
else
360-
return data[--length];
373+
return data.ptr[--data.used];
361374
}
362375

363376
extern (D) inout(T)[] opSlice() inout nothrow pure @nogc
364377
{
365-
return data[0 .. length];
378+
return data.ptr[0 .. length];
366379
}
367380

368381
extern (D) inout(T)[] opSlice(size_t a, size_t b) inout nothrow pure @nogc
369382
{
370383
assert(a <= b && b <= length);
371-
return data[a .. b];
384+
return data.ptr[a .. b];
372385
}
373386

374387
/**

compiler/src/dmd/templatesem.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6688,9 +6688,9 @@ private MATCH deduceParentInstance(Scope* sc, Dsymbol sym, TypeInstance tpi,
66886688
if (!tparent)
66896689
return MATCH.nomatch;
66906690

6691-
tpi.idents.length--;
6691+
tpi.idents.pop();
66926692
auto m = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
6693-
tpi.idents.length++;
6693+
tpi.idents.push(id);
66946694
return m;
66956695
}
66966696

0 commit comments

Comments
 (0)