Skip to content

Commit 9664c5b

Browse files
authored
feat: optimize string literal tostack behavior (#2945)
1 parent 7e2a62d commit 9664c5b

File tree

74 files changed

+3214
-17716
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+3214
-17716
lines changed

src/compiler.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ import {
5555
SideEffects,
5656
SwitchBuilder,
5757
ExpressionRunnerFlags,
58-
isConstZero,
5958
isConstNegZero,
6059
isConstExpressionNaN,
6160
ensureType,
62-
createType
61+
createType,
62+
getConstValueInteger
6363
} from "./module";
6464

6565
import {
@@ -451,6 +451,8 @@ export class Compiler extends DiagnosticEmitter {
451451
memorySegments: MemorySegment[] = [];
452452
/** Map of already compiled static string segments. */
453453
stringSegments: Map<string,MemorySegment> = new Map();
454+
/** Set of static GC object offsets. tostack is unnecessary for them. */
455+
staticGcObjectOffsets: Map<i32, Set<i32>> = new Map();
454456
/** Function table being compiled. First elem is blank. */
455457
functionTable: Function[] = [];
456458
/** Arguments length helper global. */
@@ -1939,7 +1941,16 @@ export class Compiler extends DiagnosticEmitter {
19391941
stringSegment = this.addRuntimeMemorySegment(buf);
19401942
segments.set(stringValue, stringSegment);
19411943
}
1942-
return i64_add(stringSegment.offset, i64_new(totalOverhead));
1944+
let stringOffset = i64_add(stringSegment.offset, i64_new(totalOverhead));
1945+
let staticGcObjectOffsets = this.staticGcObjectOffsets;
1946+
if (staticGcObjectOffsets.has(i64_high(stringOffset))) {
1947+
assert(staticGcObjectOffsets.get(i64_high(stringOffset))).add(i64_low(stringOffset));
1948+
} else {
1949+
let s = new Set<i32>();
1950+
s.add(i64_low(stringOffset));
1951+
staticGcObjectOffsets.set(i64_high(stringOffset), s);
1952+
}
1953+
return stringOffset;
19431954
}
19441955

19451956
/** Writes a series of static values of the specified type to a buffer. */
@@ -6754,6 +6765,21 @@ export class Compiler extends DiagnosticEmitter {
67546765
stub.set(CommonFlags.Compiled);
67556766
}
67566767

6768+
private needToStack(expr: ExpressionRef): bool {
6769+
const precomp = this.module.runExpression(expr, ExpressionRunnerFlags.Default);
6770+
// cannot precompute, so must go to stack
6771+
if (precomp == 0) return true;
6772+
const value = getConstValueInteger(precomp, this.options.isWasm64);
6773+
// zero constant doesn't need to go to stack
6774+
if (i64_eq(value, i64_zero)) return false;
6775+
// static GC objects doesn't need to go to stack
6776+
let staticGcObjectOffsets = this.staticGcObjectOffsets;
6777+
if (staticGcObjectOffsets.has(i64_high(value))) {
6778+
if (assert(staticGcObjectOffsets.get(i64_high(value))).has(i64_low(value))) return false;
6779+
}
6780+
return true;
6781+
}
6782+
67576783
/** Marks managed call operands for the shadow stack. */
67586784
private operandsTostack(signature: Signature, operands: ExpressionRef[]): void {
67596785
if (!this.options.stackSize) return;
@@ -6763,8 +6789,7 @@ export class Compiler extends DiagnosticEmitter {
67636789
if (thisType) {
67646790
if (thisType.isManaged) {
67656791
let operand = operands[0];
6766-
let precomp = module.runExpression(operand, ExpressionRunnerFlags.Default);
6767-
if (!precomp || !isConstZero(precomp)) { // otherwise unnecessary
6792+
if (this.needToStack(operand)) {
67686793
operands[operandIndex] = module.tostack(operand);
67696794
}
67706795
}
@@ -6777,8 +6802,7 @@ export class Compiler extends DiagnosticEmitter {
67776802
let paramType = parameterTypes[parameterIndex];
67786803
if (paramType.isManaged) {
67796804
let operand = operands[operandIndex];
6780-
let precomp = module.runExpression(operand, ExpressionRunnerFlags.Default);
6781-
if (!precomp || !isConstZero(precomp)) { // otherwise unnecessary
6805+
if (this.needToStack(operand)) {
67826806
operands[operandIndex] = module.tostack(operand);
67836807
}
67846808
}

src/module.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,6 +3038,18 @@ export function getConstValueI64High(expr: ExpressionRef): i32 {
30383038
return binaryen._BinaryenConstGetValueI64High(expr);
30393039
}
30403040

3041+
export function getConstValueInteger(expr: ExpressionRef, isWasm64: bool): i64 {
3042+
let lo: i32 = 0;
3043+
let hi: i32 = 0;
3044+
if (isWasm64) {
3045+
lo = getConstValueI64Low(expr);
3046+
hi = getConstValueI64High(expr);
3047+
} else {
3048+
lo = getConstValueI32(expr);
3049+
}
3050+
return i64_new(lo, hi);
3051+
}
3052+
30413053
export function getConstValueF32(expr: ExpressionRef): f32 {
30423054
return binaryen._BinaryenConstGetValueF32(expr);
30433055
}

tests/compiler/NonNullable.debug.wat

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -357,28 +357,15 @@
357357
(local $0 i32)
358358
(local $1 i32)
359359
global.get $~lib/memory/__stack_pointer
360-
i32.const 12
360+
i32.const 8
361361
i32.sub
362362
global.set $~lib/memory/__stack_pointer
363363
call $~stack_check
364364
global.get $~lib/memory/__stack_pointer
365365
i64.const 0
366366
i64.store
367-
global.get $~lib/memory/__stack_pointer
368-
i32.const 0
369-
i32.store offset=8
370367
i32.const 32
371-
local.set $1
372-
global.get $~lib/memory/__stack_pointer
373-
local.get $1
374-
i32.store
375-
local.get $1
376368
i32.const 32
377-
local.set $1
378-
global.get $~lib/memory/__stack_pointer
379-
local.get $1
380-
i32.store offset=4
381-
local.get $1
382369
call $~lib/string/String.__eq
383370
i32.eqz
384371
if
@@ -390,17 +377,7 @@
390377
unreachable
391378
end
392379
i32.const 112
393-
local.set $1
394-
global.get $~lib/memory/__stack_pointer
395-
local.get $1
396-
i32.store
397-
local.get $1
398380
i32.const 112
399-
local.set $1
400-
global.get $~lib/memory/__stack_pointer
401-
local.get $1
402-
i32.store offset=4
403-
local.get $1
404381
call $~lib/string/String.__eq
405382
i32.eqz
406383
if
@@ -412,17 +389,7 @@
412389
unreachable
413390
end
414391
i32.const 144
415-
local.set $1
416-
global.get $~lib/memory/__stack_pointer
417-
local.get $1
418-
i32.store
419-
local.get $1
420392
i32.const 144
421-
local.set $1
422-
global.get $~lib/memory/__stack_pointer
423-
local.get $1
424-
i32.store offset=4
425-
local.get $1
426393
call $~lib/string/String.__eq
427394
i32.eqz
428395
if
@@ -436,7 +403,7 @@
436403
global.get $~lib/memory/__stack_pointer
437404
global.get $NonNullable/z
438405
local.tee $0
439-
i32.store offset=8
406+
i32.store offset=4
440407
local.get $0
441408
if (result i32)
442409
local.get $0
@@ -462,7 +429,7 @@
462429
local.get $1
463430
call $NonNullable/safetyCheck<~lib/string/String|null>
464431
global.get $~lib/memory/__stack_pointer
465-
i32.const 12
432+
i32.const 8
466433
i32.add
467434
global.set $~lib/memory/__stack_pointer
468435
)

tests/compiler/NonNullable.release.wat

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
(start $~start)
2323
(func $~start
2424
global.get $~lib/memory/__stack_pointer
25-
i32.const 12
25+
i32.const 8
2626
i32.sub
2727
global.set $~lib/memory/__stack_pointer
2828
block $folding-inner0
@@ -33,15 +33,6 @@
3333
global.get $~lib/memory/__stack_pointer
3434
i64.const 0
3535
i64.store
36-
global.get $~lib/memory/__stack_pointer
37-
i32.const 0
38-
i32.store offset=8
39-
global.get $~lib/memory/__stack_pointer
40-
i32.const 1056
41-
i32.store
42-
global.get $~lib/memory/__stack_pointer
43-
i32.const 1056
44-
i32.store offset=4
4536
i32.const 1056
4637
i32.const 1056
4738
call $~lib/string/String.__eq
@@ -54,12 +45,6 @@
5445
call $~lib/builtins/abort
5546
unreachable
5647
end
57-
global.get $~lib/memory/__stack_pointer
58-
i32.const 1136
59-
i32.store
60-
global.get $~lib/memory/__stack_pointer
61-
i32.const 1136
62-
i32.store offset=4
6348
i32.const 1136
6449
i32.const 1136
6550
call $~lib/string/String.__eq
@@ -72,12 +57,6 @@
7257
call $~lib/builtins/abort
7358
unreachable
7459
end
75-
global.get $~lib/memory/__stack_pointer
76-
i32.const 1168
77-
i32.store
78-
global.get $~lib/memory/__stack_pointer
79-
i32.const 1168
80-
i32.store offset=4
8160
i32.const 1168
8261
i32.const 1168
8362
call $~lib/string/String.__eq
@@ -92,7 +71,7 @@
9271
end
9372
global.get $~lib/memory/__stack_pointer
9473
i32.const 1248
95-
i32.store offset=8
74+
i32.store offset=4
9675
global.get $~lib/memory/__stack_pointer
9776
i32.const 1248
9877
i32.store
@@ -126,7 +105,7 @@
126105
i32.add
127106
global.set $~lib/memory/__stack_pointer
128107
global.get $~lib/memory/__stack_pointer
129-
i32.const 12
108+
i32.const 8
130109
i32.add
131110
global.set $~lib/memory/__stack_pointer
132111
return

tests/compiler/bindings/esm.debug.wat

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,27 @@
124124
(export "functionFunction" (func $export:bindings/esm/functionFunction))
125125
(func $start:bindings/esm~anonymous|0
126126
)
127+
(func $start:bindings/esm
128+
i32.const 128
129+
i32.const 1
130+
f64.const 42
131+
f64.const 0
132+
f64.const 0
133+
f64.const 0
134+
f64.const 0
135+
call $~lib/builtins/trace
136+
i32.const 160
137+
call $~lib/bindings/dom/console.log
138+
global.get $~lib/bindings/dom/Math.E
139+
call $~lib/bindings/dom/Math.log
140+
drop
141+
global.get $bindings/esm/immutableGlobal
142+
drop
143+
global.get $bindings/esm/immutableGlobalNested
144+
drop
145+
call $bindings/esm/Date_getTimezoneOffset
146+
drop
147+
)
127148
(func $bindings/esm/plainFunction (param $a i32) (param $b i32) (result i32)
128149
local.get $a
129150
local.get $b
@@ -3081,50 +3102,6 @@
30813102
unreachable
30823103
end
30833104
)
3084-
(func $start:bindings/esm
3085-
(local $0 i32)
3086-
global.get $~lib/memory/__stack_pointer
3087-
i32.const 4
3088-
i32.sub
3089-
global.set $~lib/memory/__stack_pointer
3090-
call $~stack_check
3091-
global.get $~lib/memory/__stack_pointer
3092-
i32.const 0
3093-
i32.store
3094-
i32.const 128
3095-
local.set $0
3096-
global.get $~lib/memory/__stack_pointer
3097-
local.get $0
3098-
i32.store
3099-
local.get $0
3100-
i32.const 1
3101-
f64.const 42
3102-
f64.const 0
3103-
f64.const 0
3104-
f64.const 0
3105-
f64.const 0
3106-
call $~lib/builtins/trace
3107-
i32.const 160
3108-
local.set $0
3109-
global.get $~lib/memory/__stack_pointer
3110-
local.get $0
3111-
i32.store
3112-
local.get $0
3113-
call $~lib/bindings/dom/console.log
3114-
global.get $~lib/bindings/dom/Math.E
3115-
call $~lib/bindings/dom/Math.log
3116-
drop
3117-
global.get $bindings/esm/immutableGlobal
3118-
drop
3119-
global.get $bindings/esm/immutableGlobalNested
3120-
drop
3121-
call $bindings/esm/Date_getTimezoneOffset
3122-
drop
3123-
global.get $~lib/memory/__stack_pointer
3124-
i32.const 4
3125-
i32.add
3126-
global.set $~lib/memory/__stack_pointer
3127-
)
31283105
(func $bindings/esm/bufferFunction (param $a i32) (param $b i32) (result i32)
31293106
(local $aByteLength i32)
31303107
(local $bByteLength i32)

0 commit comments

Comments
 (0)