Skip to content

Commit e08a264

Browse files
authored
Slightly optimize interop with binaryen (#2108)
1 parent ca18f25 commit e08a264

File tree

2 files changed

+91
-51
lines changed

2 files changed

+91
-51
lines changed

src/glue/binaryen.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,11 @@ export declare function _BinaryenSetAllowInliningFunctionsWithLoops(enabled: boo
643643

644644
// Helpers
645645

646+
// Binaryen.js only (ASC_TARGET = 0)
647+
export declare const HEAPU8: Uint8Array;
648+
export declare const HEAPU32: Uint32Array;
649+
export declare const HEAP32: Int32Array;
650+
646651
export declare function _malloc(size: usize): usize;
647652
export declare function _free(ptr: usize): void;
648653
export declare function __i32_store8(ptr: usize, value: number): void;

src/module.ts

Lines changed: 86 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,7 +2507,7 @@ export class Module {
25072507
// avoid quite a bit of unnecessary garbage.
25082508
if (ptr == 0) return null;
25092509
var cached = this.cachedPointersToStrings;
2510-
if (cached.has(ptr)) return changetype<string>(this.cachedPointersToStrings.get(ptr));
2510+
if (cached.has(ptr)) return changetype<string>(cached.get(ptr));
25112511
var str = readString(ptr);
25122512
cached.set(ptr, str);
25132513
return str;
@@ -3035,8 +3035,12 @@ function allocU8Array(u8s: Uint8Array | null): usize {
30353035
if (!u8s) return 0;
30363036
var len = u8s.length;
30373037
var ptr = binaryen._malloc(len);
3038-
for (let i = 0; i < len; ++i) {
3039-
binaryen.__i32_store8(ptr + i, u8s[i]);
3038+
if (!ASC_TARGET) {
3039+
binaryen.HEAPU8.set(u8s, ptr);
3040+
} else {
3041+
for (let i = 0; i < len; ++i) {
3042+
binaryen.__i32_store8(ptr + i, u8s[i]);
3043+
}
30403044
}
30413045
return ptr;
30423046
}
@@ -3045,11 +3049,15 @@ function allocI32Array(i32s: i32[] | null): usize {
30453049
if (!i32s) return 0;
30463050
var len = i32s.length;
30473051
var ptr = binaryen._malloc(len << 2);
3048-
var idx = ptr;
3049-
for (let i = 0; i < len; ++i) {
3050-
let val = i32s[i];
3051-
binaryen.__i32_store(idx, val);
3052-
idx += 4;
3052+
if (!ASC_TARGET) {
3053+
binaryen.HEAP32.set(i32s, ptr >>> 2);
3054+
} else {
3055+
var idx = ptr;
3056+
for (let i = 0; i < len; ++i) {
3057+
let val = i32s[i];
3058+
binaryen.__i32_store(idx, val);
3059+
idx += 4;
3060+
}
30533061
}
30543062
return ptr;
30553063
}
@@ -3058,11 +3066,15 @@ function allocU32Array(u32s: u32[] | null): usize {
30583066
if (!u32s) return 0;
30593067
var len = u32s.length;
30603068
var ptr = binaryen._malloc(len << 2);
3061-
var idx = ptr;
3062-
for (let i = 0; i < len; ++i) {
3063-
let val = u32s[i];
3064-
binaryen.__i32_store(idx, val);
3065-
idx += 4;
3069+
if (!ASC_TARGET) {
3070+
binaryen.HEAPU32.set(u32s, ptr >>> 2);
3071+
} else {
3072+
var idx = ptr;
3073+
for (let i = 0; i < len; ++i) {
3074+
let val = u32s[i];
3075+
binaryen.__i32_store(idx, val);
3076+
idx += 4;
3077+
}
30663078
}
30673079
return ptr;
30683080
}
@@ -3073,72 +3085,95 @@ export function allocPtrArray(ptrs: usize[] | null): usize {
30733085
assert(ASC_TARGET != Target.WASM64);
30743086
var len = ptrs.length;
30753087
var ptr = binaryen._malloc(len << 2);
3076-
var idx = ptr;
3077-
for (let i = 0, k = len; i < k; ++i) {
3078-
let val = ptrs[i];
3079-
binaryen.__i32_store(idx, <i32>val);
3080-
idx += 4;
3088+
if (!ASC_TARGET) {
3089+
binaryen.HEAPU32.set(ptrs, ptr >>> 2);
3090+
} else {
3091+
var idx = ptr;
3092+
for (let i = 0, k = len; i < k; ++i) {
3093+
let val = ptrs[i];
3094+
binaryen.__i32_store(idx, <i32>val);
3095+
idx += 4;
3096+
}
30813097
}
30823098
return ptr;
30833099
}
30843100

30853101
function stringLengthUTF8(str: string): usize {
30863102
var len = 0;
30873103
for (let i = 0, k = str.length; i < k; ++i) {
3088-
let u = str.charCodeAt(i);
3089-
if (u >= 0xD800 && u <= 0xDFFF && i + 1 < k) {
3090-
u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
3091-
}
3104+
let u = str.charCodeAt(i) >>> 0;
30923105
if (u <= 0x7F) {
30933106
len += 1;
30943107
} else if (u <= 0x7FF) {
30953108
len += 2;
3096-
} else if (u <= 0xFFFF) {
3097-
len += 3;
3098-
} else {
3109+
} else if (u >= 0xD800 && u <= 0xDFFF && i + 1 < k) {
3110+
u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
30993111
len += 4;
3112+
} else {
3113+
len += 3;
31003114
}
31013115
}
31023116
return len;
31033117
}
31043118

31053119
function allocString(str: string | null): usize {
31063120
if (str === null) return 0;
3107-
var ptr = binaryen._malloc(stringLengthUTF8(str) + 1) >>> 0;
3108-
// the following is based on Emscripten's stringToUTF8Array
3121+
var len = stringLengthUTF8(str);
3122+
var ptr = binaryen._malloc(len + 1) >>> 0;
31093123
var idx = ptr;
3110-
for (let i = 0, k = str.length; i < k; ++i) {
3111-
let u = str.charCodeAt(i);
3112-
if (u >= 0xD800 && u <= 0xDFFF && i + 1 < k) {
3113-
u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
3114-
}
3115-
if (u <= 0x7F) {
3116-
binaryen.__i32_store8(idx++, u as u8);
3117-
} else if (u <= 0x7FF) {
3118-
binaryen.__i32_store8(idx++, (0xC0 | (u >>> 6) ) as u8);
3119-
binaryen.__i32_store8(idx++, (0x80 | ( u & 63)) as u8);
3120-
} else if (u <= 0xFFFF) {
3121-
binaryen.__i32_store8(idx++, (0xE0 | (u >>> 12) ) as u8);
3122-
binaryen.__i32_store8(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
3123-
binaryen.__i32_store8(idx++, (0x80 | ( u & 63)) as u8);
3124+
if (len === str.length) {
3125+
// fast path when all chars are ascii
3126+
if (!ASC_TARGET) {
3127+
for (let i = 0, k = str.length; i < k; ++i) {
3128+
binaryen.HEAPU8[idx++] = str.charCodeAt(i);
3129+
}
31243130
} else {
3125-
assert(u < 0x200000, "Invalid Unicode code point during allocString");
3126-
binaryen.__i32_store8(idx++, (0xF0 | (u >>> 18) ) as u8);
3127-
binaryen.__i32_store8(idx++, (0x80 | ((u >>> 12) & 63)) as u8);
3128-
binaryen.__i32_store8(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
3129-
binaryen.__i32_store8(idx++, (0x80 | ( u & 63)) as u8);
3131+
for (let i = 0, k = str.length; i < k; ++i) {
3132+
let u = str.charCodeAt(i) >>> 0;
3133+
binaryen.__i32_store8(idx++, u as u8);
3134+
}
3135+
}
3136+
} else {
3137+
// the following is based on Emscripten's stringToUTF8Array
3138+
for (let i = 0, k = str.length; i < k; ++i) {
3139+
let u = str.charCodeAt(i) >>> 0;
3140+
if (u <= 0x7F) {
3141+
binaryen.__i32_store8(idx++, u as u8);
3142+
} else if (u <= 0x7FF) {
3143+
binaryen.__i32_store8(idx++, (0xC0 | (u >>> 6) ) as u8);
3144+
binaryen.__i32_store8(idx++, (0x80 | ( u & 63)) as u8);
3145+
} else if (u >= 0xD800 && u <= 0xDFFF) {
3146+
if (i + 1 < k) {
3147+
u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
3148+
}
3149+
if (u <= 0xFFFF) {
3150+
binaryen.__i32_store8(idx++, (0xE0 | (u >>> 12) ) as u8);
3151+
binaryen.__i32_store8(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
3152+
binaryen.__i32_store8(idx++, (0x80 | ( u & 63)) as u8);
3153+
} else {
3154+
assert(u <= 0x10FFFF, "Invalid Unicode code point during allocString");
3155+
binaryen.__i32_store8(idx++, (0xF0 | (u >>> 18) ) as u8);
3156+
binaryen.__i32_store8(idx++, (0x80 | ((u >>> 12) & 63)) as u8);
3157+
binaryen.__i32_store8(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
3158+
binaryen.__i32_store8(idx++, (0x80 | ( u & 63)) as u8);
3159+
}
3160+
}
31303161
}
31313162
}
3132-
binaryen.__i32_store8(idx, 0);
3163+
binaryen.__i32_store8(idx, 0); // \0
31333164
return ptr;
31343165
}
31353166

31363167
function readBuffer(ptr: usize, len: i32): Uint8Array {
3137-
var ret = new Uint8Array(len);
3138-
for (let i = 0; i < len; ++i) {
3139-
ret[i] = binaryen.__i32_load8_u(ptr + <usize>i);
3168+
if (!ASC_TARGET) {
3169+
return binaryen.HEAPU8.slice(ptr, ptr + len);
3170+
} else {
3171+
var ret = new Uint8Array(len);
3172+
for (let i = 0; i < len; ++i) {
3173+
ret[i] = binaryen.__i32_load8_u(ptr + <usize>i);
3174+
}
3175+
return ret;
31403176
}
3141-
return ret;
31423177
}
31433178

31443179
export function readString(ptr: usize): string | null {

0 commit comments

Comments
 (0)