Skip to content

Commit c43684d

Browse files
committed
feat: SWAR support all control codes
1 parent 9f154ea commit c43684d

5 files changed

Lines changed: 33 additions & 16 deletions

File tree

assembly/serialize/swar/string.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@ import { BACK_SLASH } from "../../custom/chars";
33
import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
44
import { bytes } from "../../util/bytes";
55

6+
7+
// @ts-ignore: decorator allowed
8+
@lazy const LANE_MASK_HIGH = 0xFF00_FF00_FF00_FF00;
9+
// @ts-ignore: decorator allowed
10+
@lazy const LANE_MASK_LOW = 0x00FF_00FF_00FF_00FF;
11+
// @ts-ignore: decorator allowed
12+
@lazy const UINT64_H8 = 0x8080808080808080;
613
// @ts-ignore: decorator allowed
714
@lazy const QUOTE_MASK = 0x0022_0022_0022_0022;
815
// @ts-ignore: decorator allowed
16+
@lazy const BACKSLASH_MASK = 0x005C_005C_005C_005C;
17+
// @ts-ignore: decorator allowed
18+
@lazy const CONTROL_MASK = 0x0020_0020_0020_0020;
19+
// @ts-ignore: decorator allowed
920
@lazy const U00_MARKER = 13511005048209500;
1021

1122
export function serializeString_SWAR(src: string): void {
@@ -22,9 +33,11 @@ export function serializeString_SWAR(src: string): void {
2233
const block = load<u64>(srcStart);
2334
store<u64>(bs.offset, block);
2435

25-
const quotes = COMP(block, QUOTE_MASK);
26-
let mask = quotes;
27-
36+
let mask = (
37+
v64x4_eq(block, QUOTE_MASK) |
38+
v64x4_eq(block, BACKSLASH_MASK) |
39+
v64x4_ltu(block & LANE_MASK_LOW, CONTROL_MASK)
40+
) & UINT64_H8
2841

2942
while (mask != 0) {
3043
const lane_index = usize(ctz(mask) >> 3);
@@ -81,9 +94,14 @@ export function serializeString_SWAR(src: string): void {
8194
}
8295

8396
// @ts-ignore: decorators allowed
84-
@inline function COMP(x: u64, y: u64): u64 {
85-
const LANE_MASK = 0xFF00_FF00_FF00_FF00;
86-
const xored = (x ^ LANE_MASK) ^ y;
87-
const mask = (((xored >> 1) | 0x8080808080808080) - xored) & 0x8080808080808080;
88-
return (mask << 1) - (mask >> 7) & 0x8080808080808080;
97+
@inline function v64x4_eq(x: u64, y: u64): u64 {
98+
const xored = (x ^ LANE_MASK_HIGH) ^ y;
99+
const mask = (((xored >> 1) | UINT64_H8) - xored) & UINT64_H8;
100+
return (mask << 1) - (mask >> 7);
89101
}
102+
103+
// @ts-ignore: decorators allowed
104+
@inline function v64x4_ltu(a: u64, b: u64): u64 {
105+
// Vigna's algorithm - fastest SWAR unsigned less-than
106+
return (((a | UINT64_H8) - (b & ~UINT64_H8)) | (a ^ b)) ^ (a | ~b);
107+
}

assembly/test.tmp.ts

41 Bytes
Binary file not shown.

assembly/test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import { bs } from "../lib/as-bs";
22
import { serializeString_SIMD } from "./serialize/simd/string";
33
import { serializeString_SWAR } from "./serialize/swar/string";
44

5-
serializeString_SWAR("ab\"d");
6-
// serializeString_SIMD("ab\"defgh");
5+
serializeString_SWAR("a\0b\"\nd");
6+
serializeString_SIMD("a\0b\"\nd");
77
console.log(bs.out<string>());

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
"main": "transform/lib/index.js",
1010
"devDependencies": {
1111
"@assemblyscript/wasi-shim": "^0.1.0",
12-
"@types/node": "^24.2.1",
13-
"assemblyscript": "^0.28.4",
12+
"@types/node": "^25.0.3",
13+
"assemblyscript": "^0.28.9",
1414
"assemblyscript-prettier": "^3.0.1",
15-
"prettier": "^3.6.2",
16-
"tinybench": "^5.0.1",
17-
"typescript": "^5.9.2"
15+
"prettier": "^3.7.4",
16+
"tinybench": "^6.0.0",
17+
"typescript": "^5.9.3"
1818
},
1919
"bugs": {
2020
"url": "https://github.com/JairusSW/json-as/issues"

transform/src/visitor.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ArrayLiteralExpression, AssertionExpression, BinaryExpression, CallExpression, ElementAccessExpression, FloatLiteralExpression, FunctionTypeNode, IdentifierExpression, NamedTypeNode, Node, ObjectLiteralExpression, Source, TypeParameterNode, BlockStatement, BreakStatement, ClassDeclaration, ClassExpression, CommaExpression, ContinueStatement, DecoratorNode, DoStatement, EmptyStatement, EnumDeclaration, EnumValueDeclaration, ExportDefaultStatement, ExportImportStatement, ExportMember, ExportStatement, ExpressionStatement, FieldDeclaration, ForStatement, FunctionDeclaration, FunctionExpression, IfStatement, ImportDeclaration, ImportStatement, IndexSignatureNode, InstanceOfExpression, IntegerLiteralExpression, InterfaceDeclaration, LiteralExpression, MethodDeclaration, NamespaceDeclaration, NewExpression, ParameterNode, ParenthesizedExpression, PropertyAccessExpression, RegexpLiteralExpression, ReturnStatement, StringLiteralExpression, SwitchCase, SwitchStatement, TemplateLiteralExpression, TernaryExpression, ThrowStatement, TryStatement, TypeDeclaration, TypeName, UnaryPostfixExpression, UnaryPrefixExpression, VariableDeclaration, VariableStatement, WhileStatement, NodeKind, TypeNode, Expression, LiteralKind, UnaryExpression, SuperExpression, FalseExpression, TrueExpression, ThisExpression, NullExpression, ConstructorExpression, Statement, VoidStatement, CompiledExpression, CommentNode, Module, OmittedExpression, ForOfStatement, ModuleDeclaration } from "assemblyscript/dist/assemblyscript.js";
2-
import { toString } from "./util.js";
32

43
export class Visitor {
54
public currentSource: Source | null = null;

0 commit comments

Comments
 (0)