Skip to content

Commit eddf08c

Browse files
authored
Optimize expandType for JS target (AssemblyScript#2148)
1 parent 9bdeb8b commit eddf08c

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

src/module.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010

1111
import { BuiltinNames } from "./builtins";
1212
import { Target } from "./common";
13-
import {
14-
isHighSurrogate,
15-
isLowSurrogate,
16-
combineSurrogates,
17-
SURROGATE_HIGH,
18-
SURROGATE_LOW
13+
import {
14+
isHighSurrogate,
15+
isLowSurrogate,
16+
combineSurrogates,
17+
SURROGATE_HIGH,
18+
SURROGATE_LOW
1919
} from "./util";
2020
import * as binaryen from "./glue/binaryen";
2121

@@ -2619,8 +2619,15 @@ export function expandType(type: TypeRef): TypeRef[] {
26192619
var cArr = binaryen._malloc(<usize>arity << 2);
26202620
binaryen._BinaryenTypeExpand(type, cArr);
26212621
var types = new Array<TypeRef>(arity);
2622-
for (let i: u32 = 0; i < arity; ++i) {
2623-
types[i] = binaryen.__i32_load(cArr + (<usize>i << 2));
2622+
if (!ASC_TARGET) {
2623+
let ptr = cArr >>> 2;
2624+
for (let i: u32 = 0; i < arity; ++i) {
2625+
types[i] = binaryen.HEAPU32[ptr + i];
2626+
}
2627+
} else {
2628+
for (let i: u32 = 0; i < arity; ++i) {
2629+
types[i] = binaryen.__i32_load(cArr + (<usize>i << 2));
2630+
}
26242631
}
26252632
binaryen._free(cArr);
26262633
return types;

src/passes/shadowstack.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,52 @@
11
/**
22
* @fileoverview Shadow stack instrumentation for a precise GC.
3-
*
3+
*
44
* Instruments function arguments and local assignments marked with a 'tostack'
55
* call to also do stores to a shadow stack of managed values only.
6-
*
6+
*
77
* Consider a simple call to a function looking like the following, taking
88
* managed arguments, plus assigning managed values to locals:
9-
*
9+
*
1010
* function foo(a: Obj, b: Obj): Obj {
1111
* var c = __tostack(a) // slot 2
1212
* __collect()
1313
* return b
1414
* }
15-
*
15+
*
1616
* foo(__tostack(a), __tostack(b)) // slot 0, 1
17-
*
17+
*
1818
* At the call to `__collect()` the 32-bit stack frame of the function is:
19-
*
19+
*
2020
* Offset | Value stored
2121
* -------|----------------------------
2222
* 0 | First managed argument 'a'
2323
* 4 | Second managed argument 'b'
2424
* -------|----------------------------
2525
* 8 | First managed local 'c'
26-
*
26+
*
2727
* We are splitting the frame in two halves as annotated since both halves are
2828
* only known separately for indirect calls, with the first half becoming an
2929
* extension of the calling function's stack frame by means of treating the
3030
* arguments as if these were locals beyond the caller's `numLocals`. Function
3131
* arguments stay a bit longer on the stack than usually, but we also don't have
3232
* to modify the stack pointer pre-call at all this way. The caller's amended
3333
* stack frame when assuming one managed local may look like this:
34-
*
34+
*
3535
* Offset | Value stored
3636
* -------|----------------------------
3737
* 0 | First managed local '?'
3838
* 4 | Extended with first managed argument 'a'
3939
* 8 | Extended with second managed argument 'b'
40-
*
40+
*
4141
* with the callee's stack frame becoming just:
42-
*
42+
*
4343
* Offset | Value stored
4444
* -------|----------------------------
4545
* 0 | First managed local 'c'
46-
*
46+
*
4747
* Instrumentation added below looks about like the following, with the stack
4848
* growing downwards and 't' and 'r' being new temporary locals:
49-
*
49+
*
5050
* // callee frameSize = 1 * sizeof<usize>()
5151
* function foo(a: usize, b: usize): usize {
5252
* memory.fill(__stack_pointer -= frameSize, 0, frameSize)
@@ -56,7 +56,7 @@
5656
* __stack_pointer += frameSize
5757
* return r
5858
* }
59-
*
59+
*
6060
* // caller frameSize = (numLocalSlots + 2 [by extension]) * sizeof<usize>()
6161
* (
6262
* r = foo(
@@ -69,14 +69,14 @@
6969
* ),
7070
* r
7171
* )
72-
*
72+
*
7373
* Also note that we have to `memory.fill` the second half because the first
7474
* assignment to a local may happen at a later point within the function. The
7575
* invariant we need to maintain for a precise GC is that it only sees zeroes
7676
* or valid pointers, but never an invalid pointer left on the stack earlier.
7777
* Since most frames are small, we unroll a sequence of `store`s up to a frame
7878
* size of 16 bytes, and `memory.fill`, if available, beyond.
79-
*
79+
*
8080
* @license Apache-2.0
8181
*/
8282

@@ -155,7 +155,10 @@ type TempMap = Map<TypeRef,LocalIndex>;
155155

156156
/** Attempts to match the `__tostack(value)` pattern. Returns `value` if a match, otherwise `0`. */
157157
function matchPattern(module: Module, expr: ExpressionRef): ExpressionRef {
158-
if (_BinaryenExpressionGetId(expr) == ExpressionId.Call && module.readStringCached(_BinaryenCallGetTarget(expr)) == BuiltinNames.tostack) {
158+
if (
159+
_BinaryenExpressionGetId(expr) == ExpressionId.Call &&
160+
module.readStringCached(_BinaryenCallGetTarget(expr)) == BuiltinNames.tostack
161+
) {
159162
assert(_BinaryenCallGetNumOperands(expr) == 1);
160163
return _BinaryenCallGetOperandAt(expr, 0);
161164
}
@@ -320,7 +323,10 @@ export class ShadowStackPass extends Pass {
320323
module.global_get(BuiltinNames.stack_pointer, this.ptrType),
321324
module.global_get(BuiltinNames.data_end, this.ptrType)
322325
),
323-
this.compiler.makeStaticAbort(this.compiler.ensureStaticString("stack overflow"), this.compiler.program.nativeSource)
326+
this.compiler.makeStaticAbort(
327+
this.compiler.ensureStaticString("stack overflow"),
328+
this.compiler.program.nativeSource
329+
)
324330
)
325331
);
326332
}
@@ -579,7 +585,7 @@ export class ShadowStackPass extends Pass {
579585
);
580586
// memory.fill(__stack_pointer, 0, frameSize)
581587
this.makeStackFill(frameSize, stmts);
582-
588+
583589
// Handle implicit return
584590
let body = _BinaryenFunctionGetBody(func);
585591
let bodyType = _BinaryenExpressionGetType(body);
@@ -675,4 +681,4 @@ class InstrumentReturns extends Pass {
675681
);
676682
this.replaceCurrent(module.flatten(stmts, TypeRef.Unreachable));
677683
}
678-
}
684+
}

0 commit comments

Comments
 (0)