Skip to content

Commit 048bcad

Browse files
authored
Avoid new blocks in binary reading/writing (#1165)
* don't emit a toplevel block if we don't need to, as in wasm it is a list context * don't create unnecessary blocks in wasm reading
1 parent c672940 commit 048bcad

39 files changed

Lines changed: 2290 additions & 2596 deletions

src/wasm-binary.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -906,8 +906,10 @@ class WasmBinaryBuilder {
906906
BinaryConsts::ASTNodes readExpression(Expression*& curr);
907907
void pushBlockElements(Block* curr, size_t start, size_t end);
908908
void visitBlock(Block *curr);
909-
Expression* getMaybeBlock(WasmType type);
910-
Expression* getBlock(WasmType type);
909+
910+
// Gets a block of expressions. If it's just one, return that singleton.
911+
Expression* getBlockOrSingleton(WasmType type);
912+
911913
void visitIf(If *curr);
912914
void visitLoop(Loop *curr);
913915
BreakTarget getBreakTarget(int32_t offset);

src/wasm/wasm-binary.cpp

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ void WasmBinaryWriter::writeFunctions() {
271271
if (numLocalsByType[f32]) o << U32LEB(numLocalsByType[f32]) << binaryWasmType(f32);
272272
if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64);
273273

274-
writeExpression(function->body);
274+
recursePossibleBlockContents(function->body);
275275
o << int8_t(BinaryConsts::End);
276276
size_t size = o.size() - start;
277277
assert(size <= std::numeric_limits<uint32_t>::max());
@@ -1633,7 +1633,7 @@ void WasmBinaryBuilder::readFunctions() {
16331633
breakStack.emplace_back(RETURN_BREAK, func->result != none); // the break target for the function scope
16341634
assert(expressionStack.empty());
16351635
assert(depth == 0);
1636-
func->body = getMaybeBlock(func->result);
1636+
func->body = getBlockOrSingleton(func->result);
16371637
assert(depth == 0);
16381638
assert(breakStack.size() == 1);
16391639
breakStack.pop_back();
@@ -2225,38 +2225,34 @@ void WasmBinaryBuilder::visitBlock(Block *curr) {
22252225
}
22262226
}
22272227

2228-
Expression* WasmBinaryBuilder::getMaybeBlock(WasmType type) {
2228+
Expression* WasmBinaryBuilder::getBlockOrSingleton(WasmType type) {
2229+
Name label = getNextLabel();
2230+
breakStack.push_back({label, type != none && type != unreachable});
22292231
auto start = expressionStack.size();
22302232
processExpressions();
22312233
size_t end = expressionStack.size();
2232-
if (start - end == 1) {
2233-
return popExpression();
2234-
}
2235-
if (start > end) {
2236-
throw ParseException("block cannot pop from outside");
2237-
}
2234+
breakStack.pop_back();
22382235
auto* block = allocator.alloc<Block>();
22392236
pushBlockElements(block, start, end);
2237+
block->name = label;
22402238
block->finalize(type);
2241-
return block;
2242-
}
2243-
2244-
Expression* WasmBinaryBuilder::getBlock(WasmType type) {
2245-
Name label = getNextLabel();
2246-
breakStack.push_back({label, type != none && type != unreachable});
2247-
auto* block = Builder(wasm).blockify(getMaybeBlock(type));
2248-
breakStack.pop_back();
2249-
block->cast<Block>()->name = label;
2239+
// maybe we don't need a block here?
2240+
if (!brokenTo(block)) {
2241+
block->name = Name();
2242+
if (block->list.size() == 1) {
2243+
return block->list[0];
2244+
}
2245+
}
22502246
return block;
22512247
}
22522248

22532249
void WasmBinaryBuilder::visitIf(If *curr) {
22542250
if (debug) std::cerr << "zz node: If" << std::endl;
22552251
curr->type = getWasmType();
22562252
curr->condition = popNonVoidExpression();
2257-
curr->ifTrue = getBlock(curr->type);
2253+
curr->ifTrue = getBlockOrSingleton(curr->type);
22582254
if (lastSeparator == BinaryConsts::Else) {
2259-
curr->ifFalse = getBlock(curr->type);
2255+
curr->ifFalse = getBlockOrSingleton(curr->type);
22602256
}
22612257
curr->finalize(curr->type);
22622258
if (lastSeparator != BinaryConsts::End) {
@@ -2269,7 +2265,25 @@ void WasmBinaryBuilder::visitLoop(Loop *curr) {
22692265
curr->type = getWasmType();
22702266
curr->name = getNextLabel();
22712267
breakStack.push_back({curr->name, 0});
2272-
curr->body = getMaybeBlock(curr->type);
2268+
// find the expressions in the block, and create the body
2269+
// a loop may have a list of instructions in wasm, much like
2270+
// a block, but it only has a label at the top of the loop,
2271+
// so even if we need a block (if there is more than 1
2272+
// expression) we never need a label on the block.
2273+
auto start = expressionStack.size();
2274+
processExpressions();
2275+
size_t end = expressionStack.size();
2276+
if (end - start == 1) {
2277+
curr->body = popExpression();
2278+
} else {
2279+
if (start > end) {
2280+
throw ParseException("block cannot pop from outside");
2281+
}
2282+
auto* block = allocator.alloc<Block>();
2283+
pushBlockElements(block, start, end);
2284+
block->finalize(curr->type);
2285+
curr->body = block;
2286+
}
22732287
breakStack.pop_back();
22742288
curr->finalize(curr->type);
22752289
}

test/atomics.wast.fromBinary

Lines changed: 116 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -4,165 +4,157 @@
44
(func $atomic-loadstore (type $0)
55
(local $var$0 i32)
66
(local $var$1 i64)
7-
(block $label$0
8-
(drop
9-
(i32.atomic.load8_u offset=4
10-
(get_local $var$0)
11-
)
7+
(drop
8+
(i32.atomic.load8_u offset=4
9+
(get_local $var$0)
1210
)
13-
(drop
14-
(i32.atomic.load16_u offset=4
15-
(get_local $var$0)
16-
)
11+
)
12+
(drop
13+
(i32.atomic.load16_u offset=4
14+
(get_local $var$0)
1715
)
18-
(drop
19-
(i32.atomic.load offset=4
20-
(get_local $var$0)
21-
)
16+
)
17+
(drop
18+
(i32.atomic.load offset=4
19+
(get_local $var$0)
2220
)
23-
(drop
24-
(i64.atomic.load8_u
25-
(get_local $var$0)
26-
)
21+
)
22+
(drop
23+
(i64.atomic.load8_u
24+
(get_local $var$0)
2725
)
28-
(drop
29-
(i64.atomic.load16_u
30-
(get_local $var$0)
31-
)
26+
)
27+
(drop
28+
(i64.atomic.load16_u
29+
(get_local $var$0)
3230
)
33-
(drop
34-
(i64.atomic.load32_u
35-
(get_local $var$0)
36-
)
31+
)
32+
(drop
33+
(i64.atomic.load32_u
34+
(get_local $var$0)
3735
)
38-
(drop
39-
(i64.atomic.load
40-
(get_local $var$0)
41-
)
36+
)
37+
(drop
38+
(i64.atomic.load
39+
(get_local $var$0)
4240
)
43-
(i32.atomic.store offset=4
41+
)
42+
(i32.atomic.store offset=4
43+
(get_local $var$0)
44+
(get_local $var$0)
45+
)
46+
(i32.atomic.store8 offset=4
47+
(get_local $var$0)
48+
(get_local $var$0)
49+
)
50+
(i32.atomic.store16 offset=4
51+
(get_local $var$0)
52+
(get_local $var$0)
53+
)
54+
(i64.atomic.store offset=4
55+
(get_local $var$0)
56+
(get_local $var$1)
57+
)
58+
(i64.atomic.store8 offset=4
59+
(get_local $var$0)
60+
(get_local $var$1)
61+
)
62+
(i64.atomic.store16 offset=4
63+
(get_local $var$0)
64+
(get_local $var$1)
65+
)
66+
(i64.atomic.store32 offset=4
67+
(get_local $var$0)
68+
(get_local $var$1)
69+
)
70+
)
71+
(func $atomic-rmw (type $0)
72+
(local $var$0 i32)
73+
(local $var$1 i64)
74+
(drop
75+
(i32.atomic.rmw.add offset=4
4476
(get_local $var$0)
4577
(get_local $var$0)
4678
)
47-
(i32.atomic.store8 offset=4
79+
)
80+
(drop
81+
(i32.atomic.rmw8_u.add offset=4
4882
(get_local $var$0)
4983
(get_local $var$0)
5084
)
51-
(i32.atomic.store16 offset=4
85+
)
86+
(drop
87+
(i32.atomic.rmw16_u.and
5288
(get_local $var$0)
5389
(get_local $var$0)
5490
)
55-
(i64.atomic.store offset=4
91+
)
92+
(drop
93+
(i64.atomic.rmw32_u.or
5694
(get_local $var$0)
5795
(get_local $var$1)
5896
)
59-
(i64.atomic.store8 offset=4
97+
)
98+
(drop
99+
(i32.atomic.rmw8_u.xchg
100+
(get_local $var$0)
60101
(get_local $var$0)
61-
(get_local $var$1)
62102
)
63-
(i64.atomic.store16 offset=4
103+
)
104+
)
105+
(func $atomic-cmpxchg (type $0)
106+
(local $var$0 i32)
107+
(local $var$1 i64)
108+
(drop
109+
(i32.atomic.rmw.cmpxchg offset=4
110+
(get_local $var$0)
111+
(get_local $var$0)
112+
(get_local $var$0)
113+
)
114+
)
115+
(drop
116+
(i32.atomic.rmw8_u.cmpxchg
117+
(get_local $var$0)
118+
(get_local $var$0)
64119
(get_local $var$0)
120+
)
121+
)
122+
(drop
123+
(i64.atomic.rmw.cmpxchg offset=4
124+
(get_local $var$0)
125+
(get_local $var$1)
65126
(get_local $var$1)
66127
)
67-
(i64.atomic.store32 offset=4
128+
)
129+
(drop
130+
(i64.atomic.rmw32_u.cmpxchg
68131
(get_local $var$0)
69132
(get_local $var$1)
133+
(get_local $var$1)
70134
)
71135
)
72136
)
73-
(func $atomic-rmw (type $0)
137+
(func $atomic-wait-wake (type $0)
74138
(local $var$0 i32)
75139
(local $var$1 i64)
76-
(block $label$0
77-
(drop
78-
(i32.atomic.rmw.add offset=4
79-
(get_local $var$0)
80-
(get_local $var$0)
81-
)
82-
)
83-
(drop
84-
(i32.atomic.rmw8_u.add offset=4
85-
(get_local $var$0)
86-
(get_local $var$0)
87-
)
88-
)
89-
(drop
90-
(i32.atomic.rmw16_u.and
91-
(get_local $var$0)
92-
(get_local $var$0)
93-
)
94-
)
95-
(drop
96-
(i64.atomic.rmw32_u.or
97-
(get_local $var$0)
98-
(get_local $var$1)
99-
)
100-
)
101-
(drop
102-
(i32.atomic.rmw8_u.xchg
103-
(get_local $var$0)
104-
(get_local $var$0)
105-
)
140+
(drop
141+
(i32.wait
142+
(get_local $var$0)
143+
(get_local $var$0)
144+
(get_local $var$1)
106145
)
107146
)
108-
)
109-
(func $atomic-cmpxchg (type $0)
110-
(local $var$0 i32)
111-
(local $var$1 i64)
112-
(block $label$0
113-
(drop
114-
(i32.atomic.rmw.cmpxchg offset=4
115-
(get_local $var$0)
116-
(get_local $var$0)
117-
(get_local $var$0)
118-
)
119-
)
120-
(drop
121-
(i32.atomic.rmw8_u.cmpxchg
122-
(get_local $var$0)
123-
(get_local $var$0)
124-
(get_local $var$0)
125-
)
126-
)
127-
(drop
128-
(i64.atomic.rmw.cmpxchg offset=4
129-
(get_local $var$0)
130-
(get_local $var$1)
131-
(get_local $var$1)
132-
)
133-
)
134-
(drop
135-
(i64.atomic.rmw32_u.cmpxchg
136-
(get_local $var$0)
137-
(get_local $var$1)
138-
(get_local $var$1)
139-
)
147+
(drop
148+
(wake
149+
(get_local $var$0)
150+
(get_local $var$0)
140151
)
141152
)
142-
)
143-
(func $atomic-wait-wake (type $0)
144-
(local $var$0 i32)
145-
(local $var$1 i64)
146-
(block $label$0
147-
(drop
148-
(i32.wait
149-
(get_local $var$0)
150-
(get_local $var$0)
151-
(get_local $var$1)
152-
)
153-
)
154-
(drop
155-
(wake
156-
(get_local $var$0)
157-
(get_local $var$0)
158-
)
159-
)
160-
(drop
161-
(i64.wait
162-
(get_local $var$0)
163-
(get_local $var$1)
164-
(get_local $var$1)
165-
)
153+
(drop
154+
(i64.wait
155+
(get_local $var$0)
156+
(get_local $var$1)
157+
(get_local $var$1)
166158
)
167159
)
168160
)

0 commit comments

Comments
 (0)