Skip to content

Commit

Permalink
(more) branchless serializing
Browse files Browse the repository at this point in the history
  • Loading branch information
JairusSW committed Nov 25, 2024
1 parent 64f5797 commit bec20c0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 42 deletions.
81 changes: 41 additions & 40 deletions assembly/serialize/simd/string.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";

const ESCAPE_TABLE = memory.data<u16>([
48, 48, 48, 49, 48, 50, 48, 51, // 0-3
48, 52, 48, 53, 48, 54, 48, 55, // 4-7
48, 56, 92, 116, 92, 110, 48, 98, // 8-11
92, 102, 92, 114, 48, 101, 48, 102, // 12-15
49, 48, 49, 49, 49, 50, 49, 51, // 16-19
49, 52, 49, 53, 49, 54, 49, 55, // 20-23
49, 56, 49, 57, 49, 97, 49, 98, // 24-27
49, 99, 49, 100, 49, 101, 49, 102, // 28-31
48, 48, 48, 49, 48, 50, 48, 51, // 0-3
48, 52, 48, 53, 48, 54, 48, 55, // 4-7
48, 56, 92, 116, 92, 110, 48, 98, // 8-11
92, 102, 92, 114, 48, 101, 48, 102, // 12-15
49, 48, 49, 49, 49, 50, 49, 51, // 16-19
49, 52, 49, 53, 49, 54, 49, 55, // 20-23
49, 56, 49, 57, 49, 97, 49, 98, // 24-27
49, 99, 49, 100, 49, 101, 49, 102, // 28-31
0, 0, 0, 0, 92, 34, 0, 0, // 32-35
0, 0, 0, 0, 0, 0, 0, 0, // 36-39
0, 0, 0, 0, 0, 0, 0, 0, // 40-43
0, 0, 0, 0, 0, 0, 0, 0, // 44-47
0, 0, 0, 0, 0, 0, 0, 0, // 48-51
0, 0, 0, 0, 0, 0, 0, 0, // 52-55
0, 0, 0, 0, 0, 0, 0, 0, // 56-59
0, 0, 0, 0, 0, 0, 0, 0, // 60-63
0, 0, 0, 0, 0, 0, 0, 0, // 64-67
0, 0, 0, 0, 0, 0, 0, 0, // 68-71
0, 0, 0, 0, 0, 0, 0, 0, // 72-75
0, 0, 0, 0, 0, 0, 0, 0, // 76-79
0, 0, 0, 0, 0, 0, 0, 0, // 80-83
0, 0, 0, 0, 0, 0, 0, 0, // 86-89
0, 0, 0, 0, 92, 92, 0, 0, // 90-93
0, 0, 0, 0, 0, 0, 0, 0, // 94-97
0, 0, 0, 0, 0, 0, 0, 0, // 98-101
]);

const SPLAT_34 = i16x8.splat(34); /* " */
Expand Down Expand Up @@ -41,41 +58,25 @@ const SPLAT_32 = i16x8.splat(32); /* [ESC] */
const escape_indices = i16x8.lt_u(block, SPLAT_32);
const sieve = v128.or(char_indices, escape_indices);

if (v128.any_true(sieve)) {
let char_mask = i16x8.bitmask(char_indices);
let escape_mask = i16x8.bitmask(escape_indices);
v128.store(dst_ptr, block);

v128.store(dst_ptr, block);
if (v128.any_true(sieve)) {
let sieve_mask = i16x8.bitmask(sieve);
do {
const lane_index = ctz(sieve_mask) << 1;
const dst_offset = dst_ptr + lane_index;
const src_offset = src_ptr + lane_index;
const table_index = load<u16>(src_offset) << 2;
const escaped = load<u32>(ESCAPE_TABLE + table_index);
store<u32>(dst_offset, escaped);
v128.store(dst_offset, v128.load(src_offset, 2), 4);
sieve_mask &= sieve_mask - 1;
dst_ptr += 2;
} while (sieve_mask != 0);

if (char_mask != 0) {
do {
const lane_index = ctz(char_mask) << 1;
const dst_offset = dst_ptr + lane_index;
store<u16>(dst_offset, 92); /* \ */
v128.store(dst_offset, v128.load(src_ptr + lane_index), 2);
char_mask &= char_mask - 1;
dst_ptr += 2;
} while (char_mask != 0);
// dst_ptr += offset;
}
if (escape_mask != 0) {
do {
const lane_index = ctz(escape_mask) << 1;
const dst_offset = dst_ptr + lane_index;
const src_offset = src_ptr + lane_index;
const table_index = load<u16>(src_offset) << 2;
store<u32>(dst_offset, load<u32>(ESCAPE_TABLE + table_index));
v128.store(dst_offset, v128.load(src_offset, 2), 4);
escape_mask &= escape_mask - 1;
dst_ptr += 4;
} while (escape_mask != 0);
}
} else {
v128.store(dst_ptr, block);
src_ptr += 16;
dst_ptr += 16;
}

src_ptr += 16;
dst_ptr += 16;
}

do {
Expand Down
7 changes: 5 additions & 2 deletions assembly/test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { JSON } from "."
import { serializeString_SIMD } from "./serialize/simd/string";

const a = memory.data<u16>([
92, 117, 48, 48
])
@json
class Vec3 {
public x: i32 = 0;
Expand Down Expand Up @@ -29,8 +31,9 @@ class Vec3 {
// // ^ this is not okay
// }
const out = new ArrayBuffer(128);
const len = serializeString_SIMD("h\\e\tllo wor\"ld", changetype<usize>(out));
const len = serializeString_SIMD("h\ne\tllo wor\"ld", changetype<usize>(out));
const serialized = String.UTF16.decodeUnsafe(changetype<usize>(out), out.byteLength);
console.log("Serialized: " + serialized);
console.log(load<u64>(a).toString())
// const deserialized = JSON.parseSafe<Vec3>(`{"x":1,"y":true,"z":3}`);
// console.log("Deserialized: " + JSON.stringify(deserialized));

0 comments on commit bec20c0

Please sign in to comment.