Skip to content

Commit 9ba8162

Browse files
authored
Improve stub RT reallocation (AssemblyScript#790)
1 parent 9c2420b commit 9ba8162

39 files changed

+4175
-1575
lines changed

std/assembly/rt/stub.ts

+32-19
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,26 @@ var startOffset: usize = (__heap_base + AL_MASK) & ~AL_MASK;
88
@lazy
99
var offset: usize = startOffset;
1010

11-
// @ts-ignore: decorator
12-
@unsafe @global
13-
export function __alloc(size: usize, id: u32): usize {
14-
if (size > BLOCK_MAXSIZE) unreachable();
15-
var ptr = offset + BLOCK_OVERHEAD;
16-
var newPtr = (ptr + max<usize>(size, 1) + AL_MASK) & ~AL_MASK;
11+
function maybeGrowMemory(newOffset: usize): void {
12+
newOffset = (newOffset + AL_MASK) & ~AL_MASK;
1713
var pagesBefore = memory.size();
18-
if (newPtr > <usize>pagesBefore << 16) {
19-
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
14+
var maxOffset = <usize>pagesBefore << 16;
15+
if (newOffset > maxOffset) {
16+
let pagesNeeded = ((newOffset - maxOffset + 0xffff) & ~0xffff) >>> 16;
2017
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
2118
if (memory.grow(pagesWanted) < 0) {
2219
if (memory.grow(pagesNeeded) < 0) unreachable(); // out of memory
2320
}
2421
}
25-
offset = newPtr;
22+
offset = newOffset;
23+
}
24+
25+
// @ts-ignore: decorator
26+
@unsafe @global
27+
export function __alloc(size: usize, id: u32): usize {
28+
if (size > BLOCK_MAXSIZE) unreachable();
29+
var ptr = offset + BLOCK_OVERHEAD;
30+
maybeGrowMemory(ptr + max<usize>(size, 1));
2631
var block = changetype<BLOCK>(ptr - BLOCK_OVERHEAD);
2732
block.rtId = id;
2833
block.rtSize = size;
@@ -31,17 +36,25 @@ export function __alloc(size: usize, id: u32): usize {
3136

3237
// @ts-ignore: decorator
3338
@unsafe @global
34-
export function __realloc(ref: usize, size: usize): usize {
35-
var block = changetype<BLOCK>(ref - BLOCK_OVERHEAD);
36-
var oldSize = <usize>block.rtSize;
37-
if (size > oldSize) {
38-
let newRef = __alloc(size, block.rtId);
39-
memory.copy(newRef, ref, oldSize);
40-
ref = newRef;
41-
} else {
42-
block.rtSize = size;
39+
export function __realloc(ptr: usize, size: usize): usize {
40+
assert(ptr != 0 && !(ptr & AL_MASK)); // must exist and be aligned
41+
var block = changetype<BLOCK>(ptr - BLOCK_OVERHEAD);
42+
var actualSize = (<usize>block.rtSize + AL_MASK) & ~AL_MASK;
43+
var isLast = ptr + actualSize == offset;
44+
if (size > actualSize) {
45+
if (isLast) { // maybe grow
46+
if (size > BLOCK_MAXSIZE) unreachable();
47+
maybeGrowMemory(ptr + size);
48+
} else { // copy to new block at least double the size
49+
let newPtr = __alloc(max<usize>(size, actualSize << 1), block.rtId);
50+
memory.copy(newPtr, ptr, actualSize);
51+
block = changetype<BLOCK>((ptr = newPtr) - BLOCK_OVERHEAD);
52+
}
53+
} else if (isLast) { // shrink
54+
offset = (ptr + size + AL_MASK) & ~AL_MASK;
4355
}
44-
return ref;
56+
block.rtSize = size;
57+
return ptr;
4558
}
4659

4760
// @ts-ignore: decorator

tests/compiler/call-super.optimized.wat

+52-46
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
(type $FUNCSIG$v (func))
33
(type $FUNCSIG$ii (func (param i32) (result i32)))
44
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
5+
(type $FUNCSIG$vi (func (param i32)))
56
(type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
67
(type $FUNCSIG$i (func (result i32)))
78
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
@@ -11,59 +12,42 @@
1112
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
1213
(export "memory" (memory $0))
1314
(start $start)
14-
(func $~lib/rt/stub/__alloc (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
15+
(func $~lib/rt/stub/maybeGrowMemory (; 1 ;) (type $FUNCSIG$vi) (param $0 i32)
16+
(local $1 i32)
1517
(local $2 i32)
16-
(local $3 i32)
17-
(local $4 i32)
18-
(local $5 i32)
19-
local.get $0
20-
i32.const 1073741808
21-
i32.gt_u
22-
if
23-
unreachable
24-
end
25-
global.get $~lib/rt/stub/offset
26-
i32.const 16
27-
i32.add
28-
local.tee $3
29-
local.get $0
30-
i32.const 1
3118
local.get $0
32-
i32.const 1
33-
i32.gt_u
34-
select
35-
i32.add
3619
i32.const 15
3720
i32.add
3821
i32.const -16
3922
i32.and
40-
local.tee $2
23+
local.tee $0
4124
memory.size
42-
local.tee $4
25+
local.tee $2
4326
i32.const 16
4427
i32.shl
28+
local.tee $1
4529
i32.gt_u
4630
if
47-
local.get $4
4831
local.get $2
49-
local.get $3
32+
local.get $0
33+
local.get $1
5034
i32.sub
5135
i32.const 65535
5236
i32.add
5337
i32.const -65536
5438
i32.and
5539
i32.const 16
5640
i32.shr_u
57-
local.tee $5
58-
local.get $4
59-
local.get $5
41+
local.tee $1
42+
local.get $2
43+
local.get $1
6044
i32.gt_s
6145
select
6246
memory.grow
6347
i32.const 0
6448
i32.lt_s
6549
if
66-
local.get $5
50+
local.get $1
6751
memory.grow
6852
i32.const 0
6953
i32.lt_s
@@ -72,20 +56,42 @@
7256
end
7357
end
7458
end
75-
local.get $2
59+
local.get $0
7660
global.set $~lib/rt/stub/offset
77-
local.get $3
61+
)
62+
(func $~lib/rt/stub/__alloc (; 2 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
63+
(local $2 i32)
64+
(local $3 i32)
65+
local.get $0
66+
i32.const 1073741808
67+
i32.gt_u
68+
if
69+
unreachable
70+
end
71+
global.get $~lib/rt/stub/offset
7872
i32.const 16
79-
i32.sub
73+
i32.add
8074
local.tee $2
75+
local.get $0
76+
i32.const 1
77+
local.get $0
78+
i32.const 1
79+
i32.gt_u
80+
select
81+
i32.add
82+
call $~lib/rt/stub/maybeGrowMemory
83+
local.get $2
84+
i32.const 16
85+
i32.sub
86+
local.tee $3
8187
local.get $1
8288
i32.store offset=8
83-
local.get $2
89+
local.get $3
8490
local.get $0
8591
i32.store offset=12
86-
local.get $3
92+
local.get $2
8793
)
88-
(func $call-super/A#constructor (; 2 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
94+
(func $call-super/A#constructor (; 3 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
8995
local.get $0
9096
i32.eqz
9197
if
@@ -111,7 +117,7 @@
111117
end
112118
local.get $0
113119
)
114-
(func $call-super/B#constructor (; 3 ;) (type $FUNCSIG$i) (result i32)
120+
(func $call-super/B#constructor (; 4 ;) (type $FUNCSIG$i) (result i32)
115121
(local $0 i32)
116122
i32.const 8
117123
i32.const 4
@@ -146,7 +152,7 @@
146152
end
147153
local.get $0
148154
)
149-
(func $call-super/test1 (; 4 ;) (type $FUNCSIG$v)
155+
(func $call-super/test1 (; 5 ;) (type $FUNCSIG$v)
150156
(local $0 i32)
151157
call $call-super/B#constructor
152158
local.tee $0
@@ -174,7 +180,7 @@
174180
unreachable
175181
end
176182
)
177-
(func $call-super/D#constructor (; 5 ;) (type $FUNCSIG$i) (result i32)
183+
(func $call-super/D#constructor (; 6 ;) (type $FUNCSIG$i) (result i32)
178184
(local $0 i32)
179185
i32.const 8
180186
i32.const 6
@@ -219,7 +225,7 @@
219225
end
220226
local.get $0
221227
)
222-
(func $call-super/test2 (; 6 ;) (type $FUNCSIG$v)
228+
(func $call-super/test2 (; 7 ;) (type $FUNCSIG$v)
223229
(local $0 i32)
224230
call $call-super/D#constructor
225231
local.tee $0
@@ -247,7 +253,7 @@
247253
unreachable
248254
end
249255
)
250-
(func $call-super/E#constructor (; 7 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
256+
(func $call-super/E#constructor (; 8 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
251257
local.get $0
252258
i32.eqz
253259
if
@@ -273,7 +279,7 @@
273279
end
274280
local.get $0
275281
)
276-
(func $call-super/test3 (; 8 ;) (type $FUNCSIG$v)
282+
(func $call-super/test3 (; 9 ;) (type $FUNCSIG$v)
277283
(local $0 i32)
278284
i32.const 8
279285
i32.const 8
@@ -307,7 +313,7 @@
307313
unreachable
308314
end
309315
)
310-
(func $call-super/H#constructor (; 9 ;) (type $FUNCSIG$i) (result i32)
316+
(func $call-super/H#constructor (; 10 ;) (type $FUNCSIG$i) (result i32)
311317
(local $0 i32)
312318
i32.const 8
313319
i32.const 10
@@ -328,7 +334,7 @@
328334
i32.store offset=4
329335
local.get $0
330336
)
331-
(func $call-super/test4 (; 10 ;) (type $FUNCSIG$v)
337+
(func $call-super/test4 (; 11 ;) (type $FUNCSIG$v)
332338
(local $0 i32)
333339
call $call-super/H#constructor
334340
local.tee $0
@@ -356,7 +362,7 @@
356362
unreachable
357363
end
358364
)
359-
(func $call-super/J#constructor (; 11 ;) (type $FUNCSIG$i) (result i32)
365+
(func $call-super/J#constructor (; 12 ;) (type $FUNCSIG$i) (result i32)
360366
(local $0 i32)
361367
i32.const 8
362368
i32.const 12
@@ -377,7 +383,7 @@
377383
i32.store offset=4
378384
local.get $0
379385
)
380-
(func $call-super/test5 (; 12 ;) (type $FUNCSIG$v)
386+
(func $call-super/test5 (; 13 ;) (type $FUNCSIG$v)
381387
(local $0 i32)
382388
call $call-super/J#constructor
383389
local.tee $0
@@ -405,7 +411,7 @@
405411
unreachable
406412
end
407413
)
408-
(func $start (; 13 ;) (type $FUNCSIG$v)
414+
(func $start (; 14 ;) (type $FUNCSIG$v)
409415
i32.const 64
410416
global.set $~lib/rt/stub/startOffset
411417
global.get $~lib/rt/stub/startOffset
@@ -416,7 +422,7 @@
416422
call $call-super/test4
417423
call $call-super/test5
418424
)
419-
(func $null (; 14 ;) (type $FUNCSIG$v)
425+
(func $null (; 15 ;) (type $FUNCSIG$v)
420426
nop
421427
)
422428
)

0 commit comments

Comments
 (0)