(ptr: number)
| 385 | } |
| 386 | |
| 387 | private readString(ptr: number): string { |
| 388 | if (this.stringCache.has(ptr)) { |
| 389 | return this.stringCache.get(ptr)!; |
| 390 | } |
| 391 | |
| 392 | const len = this.u32[ptr >> 2]!; |
| 393 | const offset = ptr + 4; |
| 394 | |
| 395 | // Optimization: SWAR (SIMD Within A Register) for short strings. |
| 396 | // TextDecoder has high overhead for short strings (< ~64 chars). |
| 397 | // Manual decoding is faster, provided we can process 4 bytes at a time. |
| 398 | if (len < 64) { |
| 399 | let res = ""; |
| 400 | let i = 0; |
| 401 | |
| 402 | // We can safely read u32 from 'offset' because 'ptr' is 8-byte aligned, |
| 403 | // making 'offset' (ptr + 4) always 4-byte aligned. |
| 404 | const u32Index = offset >> 2; |
| 405 | const loopLimit = len - 3; // Ensure we have a full 4-byte chunk |
| 406 | |
| 407 | for (; i < loopLimit; i += 4) { |
| 408 | const chunk = this.u32[u32Index + (i >> 2)]!; |
| 409 | |
| 410 | // Magic Mask: 0x80808080 |
| 411 | // Checks bit 7 of all 4 bytes simultaneously. |
| 412 | // If ANY bit is set, it's UTF-8 (multibyte), so we bail to TextDecoder. |
| 413 | if ((chunk & 0x80808080) !== 0) { |
| 414 | i = -1; // Flag as failed |
| 415 | break; |
| 416 | } |
| 417 | |
| 418 | // Fast Decode: We verified all 4 bytes are ASCII. |
| 419 | // Unpack Little-Endian u32 into characters. |
| 420 | res += String.fromCharCode( |
| 421 | chunk & 0xff, |
| 422 | (chunk >> 8) & 0xff, |
| 423 | (chunk >> 16) & 0xff, |
| 424 | chunk >>> 24, |
| 425 | ); |
| 426 | } |
| 427 | |
| 428 | // Handle trailing bytes (0 to 3 bytes remainder) or check failure |
| 429 | if (i !== -1) { |
| 430 | for (; i < len; i++) { |
| 431 | const code = this.u8[offset + i]!; |
| 432 | if (code & 0x80) { |
| 433 | i = -1; |
| 434 | break; |
| 435 | } |
| 436 | res += String.fromCharCode(code); |
| 437 | } |
| 438 | } |
| 439 | |
| 440 | // If i != -1, we successfully decoded everything as ASCII |
| 441 | if (i !== -1) { |
| 442 | this.stringCache.set(ptr, res); |
| 443 | return res; |
| 444 | } |
no outgoing calls
no test coverage detected