Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit f3e7432

Browse files
feat: bs2 wasm optimizations
1 parent f0108ce commit f3e7432

File tree

5 files changed

+5829
-85
lines changed

5 files changed

+5829
-85
lines changed

asconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"targets": {
66
"release": {
77
"outFile": "./src/js/vendor/bz2.wasm",
8+
"textFile": "./assembly/bz2.wat",
89
"sourceMap": false,
910
"optimizeLevel": 3,
1011
"shrinkLevel": 0,

assembly/bz2.ts

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,24 @@
11
// https://gist.github.com/ultraviolet-jordan/2ded15754aee4fa82caacb0c7c77d866
22

3+
@final
34
class BZip2State {
4-
// generated from 1 << i, except for 32
5-
// prettier-ignore
6-
static readonly MASKS: StaticArray<i32> = [
7-
0x00000000, 0x00000001, 0x00000003, 0x00000007,
8-
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
9-
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
10-
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
11-
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
12-
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
13-
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
14-
0x0fffffff, 0x1fffffff, 0x3fffffff, -0x80000000
15-
];
16-
17-
static readonly MTFA_SIZE: i16 = 4096;
18-
static readonly MTFL_SIZE: i8 = 16;
19-
static readonly BZ_MAX_ALPHA_SIZE: i16 = 258;
20-
static readonly BZ_MAX_CODE_LEN: i8 = 23;
5+
@inline static readonly MTFA_SIZE: i16 = 4096;
6+
@inline static readonly MTFL_SIZE: i8 = 16;
7+
@inline static readonly BZ_MAX_ALPHA_SIZE: i16 = 258;
8+
@inline static readonly BZ_MAX_CODE_LEN: i8 = 23;
219
// static readonly anInt732: i32 = 1; // TODO
22-
static readonly BZ_N_GROUPS: i8 = 6;
23-
static readonly BZ_G_SIZE: i8 = 50;
24-
static readonly BZ_MAX_SELECTORS: i16 = 18002; // (2 + (900000 / BZip2State.BZ_G_SIZE));
10+
@inline static readonly BZ_N_GROUPS: i8 = 6;
11+
@inline static readonly BZ_G_SIZE: i8 = 50;
12+
@inline static readonly BZ_MAX_SELECTORS: i16 = 18002; // (2 + (900000 / BZip2State.BZ_G_SIZE));
2513
// static readonly anInt735: i32 = 4; // TODO
2614

27-
static readonly BZ_RUNA: i8 = 0;
28-
static readonly BZ_RUNB: i8 = 1;
15+
@inline static readonly BZ_RUNA: i8 = 0;
16+
@inline static readonly BZ_RUNB: i8 = 1;
2917

3018
static tt: StaticArray<i32> = new StaticArray<i32>(100_000);
3119

32-
stream: Int8Array = new Int8Array(0);
33-
decompressed: Int8Array = new Int8Array(0);
20+
stream: StaticArray<i8> = new StaticArray(0);
21+
decompressed: StaticArray<i8> = new StaticArray(0);
3422
next_in: i32 = 0;
3523
avail_in: i32 = 0;
3624
total_in_lo32: i32 = 0;
@@ -70,14 +58,12 @@ class BZip2State {
7058
readonly minLens: StaticArray<i32> = new StaticArray<i32>(BZip2State.BZ_N_GROUPS);
7159
}
7260

73-
export function newBzip2State(): BZip2State {
74-
return new BZip2State();
75-
}
61+
const state: BZip2State = new BZip2State();
7662

77-
export function read(length: i32, stream: Int8Array, avail_in: i32, next_in: i32, state: BZip2State): Int8Array {
63+
export function read(length: i32, stream: StaticArray<i8>, avail_in: i32, next_in: i32): StaticArray<i8> {
7864
state.stream = stream;
7965
state.next_in = next_in;
80-
state.decompressed = new Int8Array(length);
66+
state.decompressed = new StaticArray(length);
8167
state.next_out = 0;
8268
state.avail_in = avail_in;
8369
state.avail_out = length;
@@ -88,12 +74,12 @@ export function read(length: i32, stream: Int8Array, avail_in: i32, next_in: i32
8874
state.total_out_lo32 = 0;
8975
state.total_out_hi32 = 0;
9076
state.currBlockNo = 0;
91-
decompress(state);
77+
decompress();
9278
// return length - state.avail_out;
9379
return state.decompressed;
9480
}
9581

96-
function decompress(state: BZip2State): void {
82+
function decompress(): void {
9783
let gMinlen: i32 = 0;
9884
let gLimit: StaticArray<i32> = [];
9985
let gBase: StaticArray<i32> = [];
@@ -106,43 +92,43 @@ function decompress(state: BZip2State): void {
10692

10793
let reading: bool = true;
10894
while (reading) {
109-
let uc: u8 = getByte(state);
95+
let uc: u8 = getByte();
11096
if (uc === 0x17) {
11197
// 23
11298
return;
11399
}
114100

115101
// uc checks originally broke the loop and returned an error in libbzip2
116-
uc = getByte(state);
117-
uc = getByte(state);
118-
uc = getByte(state);
119-
uc = getByte(state);
120-
uc = getByte(state);
102+
uc = getByte();
103+
uc = getByte();
104+
uc = getByte();
105+
uc = getByte();
106+
uc = getByte();
121107

122108
state.currBlockNo++;
123109

124-
uc = getByte(state);
125-
uc = getByte(state);
126-
uc = getByte(state);
127-
uc = getByte(state);
110+
uc = getByte();
111+
uc = getByte();
112+
uc = getByte();
113+
uc = getByte();
128114

129-
uc = getBit(state);
115+
uc = getBit();
130116
state.blockRandomized = uc !== 0;
131117
if (state.blockRandomized) {
132118
// console.log('PANIC! RANDOMISED BLOCK!');
133119
}
134120

135121
state.origPtr = 0;
136-
uc = getByte(state);
122+
uc = getByte();
137123
state.origPtr = (state.origPtr << 8) | (uc & 0xff);
138-
uc = getByte(state);
124+
uc = getByte();
139125
state.origPtr = (state.origPtr << 8) | (uc & 0xff);
140-
uc = getByte(state);
126+
uc = getByte();
141127
state.origPtr = (state.origPtr << 8) | (uc & 0xff);
142128

143129
// Receive the mapping table
144130
for (let i: i32 = 0; i < 16; i++) {
145-
uc = getBit(state);
131+
uc = getBit();
146132
unchecked((state.inUse16[i] = uc === 1));
147133
}
148134

@@ -153,23 +139,23 @@ function decompress(state: BZip2State): void {
153139
for (let i: i32 = 0; i < 16; i++) {
154140
if (unchecked(state.inUse16[i])) {
155141
for (let j: i32 = 0; j < 16; j++) {
156-
uc = getBit(state);
142+
uc = getBit();
157143
if (uc === 1) {
158144
unchecked((state.inUse[i * 16 + j] = true));
159145
}
160146
}
161147
}
162148
}
163-
makeMaps(state);
149+
makeMaps();
164150
const alphaSize: i32 = state.nInUse + 2;
165151

166-
const nGroups: i32 = getBits(3, state);
167-
const nSelectors: i32 = getBits(15, state);
152+
const nGroups: i32 = getBits(3);
153+
const nSelectors: i32 = getBits(15);
168154
for (let i: i32 = 0; i < nSelectors; i++) {
169155
let j: i32 = 0;
170156
// eslint-disable-next-line no-constant-condition
171157
while (true) {
172-
uc = getBit(state);
158+
uc = getBit();
173159
if (uc === 0) {
174160
break;
175161
}
@@ -198,17 +184,17 @@ function decompress(state: BZip2State): void {
198184

199185
// Now the coding tables
200186
for (let t: i32 = 0; t < nGroups; t++) {
201-
let curr: i32 = getBits(5, state);
187+
let curr: i32 = getBits(5);
202188

203189
for (let i: i32 = 0; i < alphaSize; i++) {
204190
// eslint-disable-next-line no-constant-condition
205191
while (true) {
206-
uc = getBit(state);
192+
uc = getBit();
207193
if (uc === 0) {
208194
break;
209195
}
210196

211-
uc = getBit(state);
197+
uc = getBit();
212198
if (uc === 0) {
213199
curr++;
214200
} else {
@@ -279,9 +265,9 @@ function decompress(state: BZip2State): void {
279265
let zn: i32 = gMinlen;
280266
let zvec: i32;
281267
let zj: u8;
282-
for (zvec = getBits(gMinlen, state); zvec > unchecked(gLimit[zn]); zvec = (zvec << 1) | zj) {
268+
for (zvec = getBits(gMinlen); zvec > unchecked(gLimit[zn]); zvec = (zvec << 1) | zj) {
283269
zn++;
284-
zj = getBit(state);
270+
zj = getBit();
285271
}
286272

287273
let nextSym: i32 = unchecked(gPerm[zvec - unchecked(gBase[zn])]);
@@ -310,9 +296,9 @@ function decompress(state: BZip2State): void {
310296

311297
gPos--;
312298
zn = gMinlen;
313-
for (zvec = getBits(gMinlen, state); zvec > unchecked(gLimit[zn]); zvec = (zvec << 1) | zj) {
299+
for (zvec = getBits(gMinlen); zvec > unchecked(gLimit[zn]); zvec = (zvec << 1) | zj) {
314300
zn++;
315-
zj = getBit(state);
301+
zj = getBit();
316302
}
317303

318304
nextSym = unchecked(gPerm[zvec - unchecked(gBase[zn])]);
@@ -407,9 +393,9 @@ function decompress(state: BZip2State): void {
407393

408394
gPos--;
409395
zn = gMinlen;
410-
for (zvec = getBits(gMinlen, state); zvec > unchecked(gLimit[zn]); zvec = (zvec << 1) | zj) {
396+
for (zvec = getBits(gMinlen); zvec > unchecked(gLimit[zn]); zvec = (zvec << 1) | zj) {
411397
zn++;
412-
zj = getBit(state);
398+
zj = getBit();
413399
}
414400
nextSym = unchecked(gPerm[zvec - unchecked(gBase[zn])]);
415401
}
@@ -448,12 +434,13 @@ function decompress(state: BZip2State): void {
448434
state.c_nblock_used++;
449435

450436
state.save_nblock = nblock;
451-
finish(state);
437+
finish();
452438
reading = state.c_nblock_used === state.save_nblock + 1 && state.state_out_len === 0;
453439
}
454440
}
455441

456-
function getBits(n: i32, state: BZip2State): i32 {
442+
// macro: GET_BITS
443+
function getBits(n: i32): i32 {
457444
while (state.bsLive < n) {
458445
state.bsBuff = (state.bsBuff << 8) | (unchecked(state.stream[state.next_in]) & 0xff);
459446
state.bsLive += 8;
@@ -465,20 +452,23 @@ function getBits(n: i32, state: BZip2State): i32 {
465452
}
466453
}
467454

468-
const value: i32 = (state.bsBuff >> (state.bsLive - n)) & unchecked(BZip2State.MASKS[n]);
455+
const value: i32 = state.bsBuff >> state.bsLive - n & (1 << n) - 1;
469456
state.bsLive -= n;
470457
return value;
471458
}
472459

473-
function getBit(state: BZip2State): u8 {
474-
return <u8>getBits(1, state);
460+
// macro: GET_BIT
461+
function getBit(): u8 {
462+
return <u8>getBits(1);
475463
}
476464

477-
function getByte(state: BZip2State): u8 {
478-
return <u8>getBits(8, state);
465+
// macro: GET_UCHAR
466+
function getByte(): u8 {
467+
return <u8>getBits(8);
479468
}
480469

481-
function makeMaps(state: BZip2State): void {
470+
// makeMaps_d
471+
function makeMaps(): void {
482472
state.nInUse = 0;
483473

484474
for (let i: i32 = 0; i < 256; i++) {
@@ -489,6 +479,7 @@ function makeMaps(state: BZip2State): void {
489479
}
490480
}
491481

482+
// BZ2_hbCreateDecodeTables
492483
function createDecodeTables(limit: StaticArray<i32>, base: StaticArray<i32>, perm: StaticArray<i32>, length: StaticArray<u8>, minLen: i32, maxLen: i32, alphaSize: i32): void {
493484
let pp: i32 = 0;
494485

@@ -530,14 +521,14 @@ function createDecodeTables(limit: StaticArray<i32>, base: StaticArray<i32>, per
530521
}
531522

532523
// unRLE_obuf_to_output_FAST
533-
function finish(state: BZip2State): void {
524+
function finish(): void {
534525
let c_state_out_ch: u8 = <u8>state.state_out_ch;
535526
let c_state_out_len: i32 = state.state_out_len;
536527
let c_nblock_used: i32 = state.c_nblock_used;
537528
let c_k0: i32 = state.k0;
538529
const c_tt: StaticArray<i32> = BZip2State.tt;
539530
let c_tPos: i32 = state.tPos;
540-
const cs_decompressed: Int8Array = state.decompressed;
531+
const cs_decompressed: StaticArray<i8> = state.decompressed;
541532
let cs_next_out: i32 = state.next_out;
542533
let cs_avail_out: i32 = state.avail_out;
543534
const avail_out_INIT: i32 = cs_avail_out;

0 commit comments

Comments
 (0)