| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 49fb028 commit 615273d
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -791,11 +791,14 @@ data that might not have been allocated for `Buffer`s. | |||
| 791 | 791 | ||
| 792 | 792 | A `TypeError` will be thrown if `size` is not a number. | |
| 793 | 793 | ||
| 794 | - ### Static method: `Buffer.allocUnsafe(size)` | ||
| 794 | + ### Static method: `Buffer.allocUnsafe(size[, alignment])` | ||
| 795 | 795 | ||
| 796 | 796 | <!-- YAML | |
| 797 | 797 | added: v5.10.0 | |
| 798 | 798 | changes: | |
| 799 | + - version: REPLACEME | ||
| 800 | + pr-url: https://github.com/nodejs/node/pull/65003 | ||
| 801 | + description: Added the `alignment` argument. | ||
| 799 | 802 | - version: v20.0.0 | |
| 800 | 803 | pr-url: https://github.com/nodejs/node/pull/45796 | |
| 801 | 804 | description: Throw ERR_INVALID_ARG_TYPE or ERR_OUT_OF_RANGE instead of | |
@@ -810,6 +813,9 @@ changes: | |||
| 810 | 813 | --> | |
| 811 | 814 | ||
| 812 | 815 | * `size` {integer} The desired length of the new `Buffer`. | |
| 816 | + * `alignment` {integer} If given, the memory backing the new `Buffer` will start | ||
| 817 | + at an address that is a multiple of `alignment`. Must be a power of two no | ||
| 818 | + larger than `2 ** 30`. See [Aligned allocations][]. | ||
| 813 | 819 | * Returns: {Buffer} | |
| 814 | 820 | ||
| 815 | 821 | Allocates a new `Buffer` of `size` bytes. If `size` is larger than | |
@@ -865,11 +871,14 @@ pool, while `Buffer.allocUnsafe(size).fill(fill)` _will_ use the internal | |||
| 865 | 871 | difference is subtle but can be important when an application requires the | |
| 866 | 872 | additional performance that [`Buffer.allocUnsafe()`][] provides. | |
| 867 | 873 | ||
| 868 | - ### Static method: `Buffer.allocUnsafeSlow(size)` | ||
| 874 | + ### Static method: `Buffer.allocUnsafeSlow(size[, alignment])` | ||
| 869 | 875 | ||
| 870 | 876 | <!-- YAML | |
| 871 | 877 | added: v5.12.0 | |
| 872 | 878 | changes: | |
| 879 | + - version: REPLACEME | ||
| 880 | + pr-url: https://github.com/nodejs/node/pull/65003 | ||
| 881 | + description: Added the `alignment` argument. | ||
| 873 | 882 | - version: v20.0.0 | |
| 874 | 883 | pr-url: https://github.com/nodejs/node/pull/45796 | |
| 875 | 884 | description: Throw ERR_INVALID_ARG_TYPE or ERR_OUT_OF_RANGE instead of | |
@@ -881,6 +890,9 @@ changes: | |||
| 881 | 890 | --> | |
| 882 | 891 | ||
| 883 | 892 | * `size` {integer} The desired length of the new `Buffer`. | |
| 893 | + * `alignment` {integer} If given, the memory backing the new `Buffer` will start | ||
| 894 | + at an address that is a multiple of `alignment`. Must be a power of two no | ||
| 895 | + larger than `2 ** 30`. See [Aligned allocations][]. | ||
| 884 | 896 | * Returns: {Buffer} | |
| 885 | 897 | ||
| 886 | 898 | Allocates a new `Buffer` of `size` bytes. If `size` is larger than | |
@@ -5608,16 +5620,92 @@ While there are clear performance advantages to using | |||
| 5608 | 5620 | [`Buffer.allocUnsafe()`][], extra care _must_ be taken in order to avoid | |
| 5609 | 5621 | introducing security vulnerabilities into an application. | |
| 5610 | 5622 | ||
| 5623 | + ### Aligned allocations | ||
| 5624 | + | ||
| 5625 | + Some operating system interfaces require the memory they operate on to be | ||
| 5626 | + aligned, and on some hardware alignment is merely faster. The most common | ||
| 5627 | + example of the former is unbuffered ("direct") file I/O, which on Linux requires | ||
| 5628 | + the buffer address, the file offset and the transfer length to all be multiples | ||
| 5629 | + of the logical block size of the underlying device: | ||
| 5630 | + | ||
| 5631 | + ```mjs | ||
| 5632 | + import { open } from 'node:fs/promises'; | ||
| 5633 | + import { constants } from 'node:fs'; | ||
| 5634 | + import { Buffer } from 'node:buffer'; | ||
| 5635 | + | ||
| 5636 | + const blockSize = 4096; | ||
| 5637 | + | ||
| 5638 | + // The buffer address must be block-aligned for O_DIRECT to accept it. | ||
| 5639 | + const buf = Buffer.allocUnsafeSlow(blockSize, blockSize); | ||
| 5640 | + | ||
| 5641 | + const file = await open('/dev/sda', constants.O_RDONLY | constants.O_DIRECT); | ||
| 5642 | + try { | ||
| 5643 | + await file.read(buf, 0, blockSize, 0); | ||
| 5644 | + } finally { | ||
| 5645 | + await file.close(); | ||
| 5646 | + } | ||
| 5647 | + ``` | ||
| 5648 | + | ||
| 5649 | + ```cjs | ||
| 5650 | + const fs = require('node:fs'); | ||
| 5651 | + const { Buffer } = require('node:buffer'); | ||
| 5652 | + | ||
| 5653 | + const blockSize = 4096; | ||
| 5654 | + | ||
| 5655 | + // The buffer address must be block-aligned for O_DIRECT to accept it. | ||
| 5656 | + const buf = Buffer.allocUnsafeSlow(blockSize, blockSize); | ||
| 5657 | + | ||
| 5658 | + const flags = fs.constants.O_RDONLY | fs.constants.O_DIRECT; | ||
| 5659 | + fs.open('/dev/sda', flags, (err, fd) => { | ||
| 5660 | + if (err) throw err; | ||
| 5661 | + fs.read(fd, buf, 0, blockSize, 0, (err) => { | ||
| 5662 | + fs.close(fd, () => {}); | ||
| 5663 | + if (err) throw err; | ||
| 5664 | + }); | ||
| 5665 | + }); | ||
| 5666 | + ``` | ||
| 5667 | + | ||
| 5668 | + Alignment can also be worth requesting purely for performance, even when no | ||
| 5669 | + interface demands it. Aligning a hot `Buffer` to the cache line size (64 bytes on | ||
| 5670 | + most contemporary CPUs) keeps it from straddling one more cache line than it | ||
| 5671 | + needs to, so that a small structure is fetched with one cache miss instead of | ||
| 5672 | + two, and page-aligned (4096 bytes) allocations similarly help interfaces that map | ||
| 5673 | + or pin memory. These are micro-optimizations: measure before reaching for them, | ||
| 5674 | + since the extra bytes are not free. | ||
| 5675 | + | ||
| 5676 | + Because the address of a `Buffer`'s memory cannot be chosen directly, extra bytes | ||
| 5677 | + have to be allocated or skipped to reach an aligned address. | ||
| 5678 | + [`Buffer.allocUnsafeSlow()`][] over-allocates up to `alignment - 1` bytes and | ||
| 5679 | + positions the returned `Buffer` at the first suitably aligned byte within them. | ||
| 5680 | + [`Buffer.allocUnsafe()`][] instead pads its offset into the shared internal pool, | ||
| 5681 | + whose start is always aligned to 64 bytes, and only falls back to an allocation | ||
| 5682 | + of its own when `alignment` is larger than that. Either way, | ||
| 5683 | + [`buf.byteOffset`][] is usually not 0 and [`buf.buffer`][] is larger than `size`, | ||
| 5684 | + so code that reaches past the `Buffer` into its underlying `ArrayBuffer` must | ||
| 5685 | + take the offset into account, as it must for pooled `Buffer`s. | ||
| 5686 | + | ||
| 5687 | + The alignment is a property of the returned `Buffer` and is preserved for its | ||
| 5688 | + whole lifetime, but it is not inherited by other views: [`buf.subarray`][], | ||
| 5689 | + [`buf.slice()`][] and `structuredClone()` may all produce unaligned `Buffer`s. | ||
| 5690 | + | ||
| 5691 | + Alignment also does not survive being captured in a startup snapshot: memory does | ||
| 5692 | + not keep its address across serialization, so a `Buffer` allocated while | ||
| 5693 | + [`--build-snapshot`][] is in effect is not aligned in the deserialized process. | ||
| 5694 | + Allocate inside a [`v8.startupSnapshot.setDeserializeMainFunction()`][] callback, | ||
| 5695 | + or after startup, if the alignment has to hold at run time. | ||
| 5696 | + | ||
| 5611 | 5697 | [ASCII]: https://en.wikipedia.org/wiki/ASCII | |
| 5698 | + [Aligned allocations]: #aligned-allocations | ||
| 5612 | 5699 | [Base64]: https://en.wikipedia.org/wiki/Base64 | |
| 5613 | 5700 | [ISO-8859-1]: https://en.wikipedia.org/wiki/ISO-8859-1 | |
| 5614 | 5701 | [RFC 4648, Section 5]: https://tools.ietf.org/html/rfc4648#section-5 | |
| 5615 | 5702 | [UTF-16]: https://en.wikipedia.org/wiki/UTF-16 | |
| 5616 | 5703 | [UTF-8]: https://en.wikipedia.org/wiki/UTF-8 | |
| 5617 | 5704 | [WHATWG Encoding Standard]: https://encoding.spec.whatwg.org/ | |
| 5705 | + [`--build-snapshot`]: cli.md#--build-snapshot | ||
| 5618 | 5706 | [`Buffer.alloc()`]: #static-method-bufferallocsize-fill-encoding | |
| 5619 | - [`Buffer.allocUnsafe()`]: #static-method-bufferallocunsafesize | ||
| 5620 | - [`Buffer.allocUnsafeSlow()`]: #static-method-bufferallocunsafeslowsize | ||
| 5707 | + [`Buffer.allocUnsafe()`]: #static-method-bufferallocunsafesize-alignment | ||
| 5708 | + [`Buffer.allocUnsafeSlow()`]: #static-method-bufferallocunsafeslowsize-alignment | ||
| 5621 | 5709 | [`Buffer.concat()`]: #static-method-bufferconcatlist-totallength | |
| 5622 | 5710 | [`Buffer.copyBytesFrom()`]: #static-method-buffercopybytesfromview-offset-length | |
| 5623 | 5711 | [`Buffer.from(array)`]: #static-method-bufferfromarray | |
@@ -5639,6 +5727,7 @@ introducing security vulnerabilities into an application. | |||
| 5639 | 5727 | [`TypedArray.prototype.subarray()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray | |
| 5640 | 5728 | [`blob.stream()`]: #blobstream | |
| 5641 | 5729 | [`buf.buffer`]: #bufbuffer | |
| 5730 | + [`buf.byteOffset`]: #bufbyteoffset | ||
| 5642 | 5731 | [`buf.compare()`]: #bufcomparetarget-targetstart-targetend-sourcestart-sourceend | |
| 5643 | 5732 | [`buf.entries()`]: #bufentries | |
| 5644 | 5733 | [`buf.fill()`]: #buffillvalue-offset-end-encoding | |
@@ -5653,6 +5742,7 @@ introducing security vulnerabilities into an application. | |||
| 5653 | 5742 | [`buffer.constants.MAX_STRING_LENGTH`]: #bufferconstantsmax_string_length | |
| 5654 | 5743 | [`buffer.kMaxLength`]: #bufferkmaxlength | |
| 5655 | 5744 | [`util.inspect()`]: util.md#utilinspectobject-options | |
| 5745 | + [`v8.startupSnapshot.setDeserializeMainFunction()`]: v8.md#v8startupsnapshotsetdeserializemainfunctioncallback-data | ||
| 5656 | 5746 | [`v8::Uint8Array::kMaxLength`]: https://v8.github.io/api/head/classv8_1_1Uint8Array.html#a7677e3d0c9c92e4d40bef7212f5980c6 | |
| 5657 | 5747 | [base64url]: https://tools.ietf.org/html/rfc4648#section-5 | |
| 5658 | 5748 | [endianness]: https://en.wikipedia.org/wiki/Endianness | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4624,7 +4624,7 @@ will throw an error in a future version. | |||
| 4624 | 4624 | [`--pending-deprecation`]: cli.md#--pending-deprecation | |
| 4625 | 4625 | [`--throw-deprecation`]: cli.md#--throw-deprecation | |
| 4626 | 4626 | [`--unhandled-rejections`]: cli.md#--unhandled-rejectionsmode | |
| 4627 | - [`Buffer.allocUnsafeSlow(size)`]: buffer.md#static-method-bufferallocunsafeslowsize | ||
| 4627 | + [`Buffer.allocUnsafeSlow(size)`]: buffer.md#static-method-bufferallocunsafeslowsize-alignment | ||
| 4628 | 4628 | [`Buffer.from(array)`]: buffer.md#static-method-bufferfromarray | |
| 4629 | 4629 | [`Buffer.from(buffer)`]: buffer.md#static-method-bufferfrombuffer | |
| 4630 | 4630 | [`Buffer.isBuffer()`]: buffer.md#static-method-bufferisbufferobj | |
@@ -4770,7 +4770,7 @@ will throw an error in a future version. | |||
| 4770 | 4770 | [`writable.writableLength`]: stream.md#writablewritablelength | |
| 4771 | 4771 | [`zlib.bytesWritten`]: zlib.md#zlibbyteswritten | |
| 4772 | 4772 | [alloc]: buffer.md#static-method-bufferallocsize-fill-encoding | |
| 4773 | - [alloc_unsafe_size]: buffer.md#static-method-bufferallocunsafesize | ||
| 4773 | + [alloc_unsafe_size]: buffer.md#static-method-bufferallocunsafesize-alignment | ||
| 4774 | 4774 | [caveats of asynchronous customization hooks]: module.md#caveats-of-asynchronous-customization-hooks | |
| 4775 | 4775 | [from_arraybuffer]: buffer.md#static-method-bufferfromarraybuffer-byteoffset-length | |
| 4776 | 4776 | [from_string_encoding]: buffer.md#static-method-bufferfromstring-encoding | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2234,7 +2234,7 @@ thread spawned will spawn another until the application crashes. | |||
| 2234 | 2234 | [`--max-old-space-size`]: cli.md#--max-old-space-sizesize-in-mib | |
| 2235 | 2235 | [`--max-semi-space-size`]: cli.md#--max-semi-space-sizesize-in-mib | |
| 2236 | 2236 | [`AsyncResource`]: async_hooks.md#class-asyncresource | |
| 2237 | - [`Buffer.allocUnsafe()`]: buffer.md#static-method-bufferallocunsafesize | ||
| 2237 | + [`Buffer.allocUnsafe()`]: buffer.md#static-method-bufferallocunsafesize-alignment | ||
| 2238 | 2238 | [`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: errors.md#err_missing_message_port_in_transfer_list | |
| 2239 | 2239 | [`ERR_WORKER_MESSAGING_ERRORED`]: errors.md#err_worker_messaging_errored | |
| 2240 | 2240 | [`ERR_WORKER_MESSAGING_FAILED`]: errors.md#err_worker_messaging_failed | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -140,6 +140,7 @@ const { | |||
| 140 | 140 | markAsUntransferable, | |
| 141 | 141 | addBufferPrototypeMethods, | |
| 142 | 142 | createUnsafeBuffer, | |
| 143 | + createUnsafeAlignedBuffer, | ||
| 143 | 144 | asciiWrite, | |
| 144 | 145 | latin1Write, | |
| 145 | 146 | utf8Write, | |
@@ -171,13 +172,27 @@ const constants = ObjectDefineProperties({}, { | |||
| 171 | 172 | }, | |
| 172 | 173 | }); | |
| 173 | 174 | ||
| 175 | + // The largest alignment accepted by `Buffer.allocUnsafeSlow()`. Any plausible | ||
| 176 | + // I/O alignment requirement (logical block size, memory page size, huge page | ||
| 177 | + // size) is well below this. | ||
| 178 | + const kMaxAlignment = 2 ** 30; | ||
| 179 | + | ||
| 180 | + // Slices handed out of the pool are 8 byte aligned relative to the start of the | ||
| 181 | + // pool, so aligning the pool itself to a cache line keeps them from straddling | ||
| 182 | + // one more cache line than their size requires. | ||
| 183 | + const kPoolAlignment = 64; | ||
| 184 | + | ||
| 174 | 185 | Buffer.poolSize = 64 * 1024; | |
| 175 | - let poolSize, poolOffset, allocPool, allocBuffer; | ||
| 186 | + // `poolOffset` is relative to `poolBase`, which is where the pool starts inside | ||
| 187 | + // `allocPool`. The pool is over-allocated to be able to align it, so `poolBase` | ||
| 188 | + // is not necessarily 0. | ||
| 189 | + let poolSize, poolOffset, poolBase, allocPool, allocBuffer; | ||
| 176 | 190 | ||
| 177 | 191 | function createPool() { | |
| 178 | 192 | poolSize = Buffer.poolSize; | |
| 179 | - allocBuffer = createUnsafeBuffer(poolSize); | ||
| 193 | + allocBuffer = createUnsafeAlignedBuffer(poolSize, kPoolAlignment); | ||
| 180 | 194 | allocPool = allocBuffer.buffer; | |
| 195 | + poolBase = TypedArrayPrototypeGetByteOffset(allocBuffer); | ||
| 181 | 196 | markAsUntransferable(allocPool); | |
| 182 | 197 | poolOffset = 0; | |
| 183 | 198 | } | |
@@ -444,40 +459,92 @@ Buffer.alloc = function alloc(size, fill, encoding) { | |||
| 444 | 459 | /** | |
| 445 | 460 | * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer | |
| 446 | 461 | * instance. If `--zero-fill-buffers` is set, will zero-fill the buffer. | |
| 462 | + * | ||
| 463 | + * If `alignment` is given, the memory backing the returned buffer starts at an | ||
| 464 | + * address that is a multiple of `alignment`. See `Buffer.allocUnsafeSlow()`. | ||
| 465 | + * @param {number} size | ||
| 466 | + * @param {number} [alignment] A power of two, at most 2 ** 30 | ||
| 447 | 467 | * @returns {FastBuffer} | |
| 448 | 468 | */ | |
| 449 | - Buffer.allocUnsafe = function allocUnsafe(size) { | ||
| 469 | + Buffer.allocUnsafe = function allocUnsafe(size, alignment) { | ||
| 450 | 470 | validateNumber(size, 'size', 0, kMaxLength); | |
| 451 | - return allocate(size); | ||
| 471 | + if (alignment === undefined) { | ||
| 472 | + return allocate(size); | ||
| 473 | + } | ||
| 474 | + validateAlignment(size, alignment); | ||
| 475 | + return allocateAligned(size, alignment); | ||
| 452 | 476 | }; | |
| 453 | 477 | ||
| 454 | 478 | /** | |
| 455 | 479 | * By default creates a non-zero-filled Buffer instance that is not allocated | |
| 456 | 480 | * off the pre-initialized pool. If `--zero-fill-buffers` is set, will zero-fill | |
| 457 | 481 | * the buffer. | |
| 482 | + * | ||
| 483 | + * If `alignment` is given, the memory backing the returned buffer starts at an | ||
| 484 | + * address that is a multiple of `alignment`, which is required by e.g. reads | ||
| 485 | + * and writes on file descriptors opened with `O_DIRECT`. Note that up to | ||
| 486 | + * `alignment - 1` extra bytes are allocated to satisfy the request, and that | ||
| 487 | + * the returned buffer's `byteOffset` is therefore usually non-zero. | ||
| 458 | 488 | * @param {number} size | |
| 459 | - * @returns {FastBuffer|undefined} | ||
| 489 | + * @param {number} [alignment] A power of two, at most 2 ** 30 | ||
| 490 | + * @returns {FastBuffer} | ||
| 460 | 491 | */ | |
| 461 | - Buffer.allocUnsafeSlow = function allocUnsafeSlow(size) { | ||
| 492 | + Buffer.allocUnsafeSlow = function allocUnsafeSlow(size, alignment) { | ||
| 462 | 493 | validateNumber(size, 'size', 0, kMaxLength); | |
| 463 | - return createUnsafeBuffer(size); | ||
| 494 | + if (alignment === undefined) { | ||
| 495 | + return createUnsafeBuffer(size); | ||
| 496 | + } | ||
| 497 | + validateAlignment(size, alignment); | ||
| 498 | + return createUnsafeAlignedBuffer(size, alignment); | ||
| 464 | 499 | }; | |
| 465 | 500 | ||
| 501 | + function validateAlignment(size, alignment) { | ||
| 502 | + validateInteger(alignment, 'alignment', 1, kMaxAlignment); | ||
| 503 | + if ((alignment & (alignment - 1)) !== 0) { | ||
| 504 | + throw new ERR_INVALID_ARG_VALUE( | ||
| 505 | + 'alignment', alignment, 'must be a power of two'); | ||
| 506 | + } | ||
| 507 | + // Satisfying the alignment costs up to `alignment - 1` extra bytes. | ||
| 508 | + if (size > kMaxLength - (alignment - 1)) { | ||
| 509 | + throw new ERR_OUT_OF_RANGE( | ||
| 510 | + 'size', `<= ${kMaxLength - (alignment - 1)}`, size); | ||
| 511 | + } | ||
| 512 | + } | ||
| 513 | + | ||
| 466 | 514 | function allocate(size) { | |
| 467 | 515 | if (size <= 0) { | |
| 468 | 516 | return new FastBuffer(); | |
| 469 | 517 | } | |
| 470 | 518 | if (size < (Buffer.poolSize >>> 1)) { | |
| 471 | 519 | if (size > (poolSize - poolOffset)) | |
| 472 | 520 | createPool(); | |
| 473 | - const b = new FastBuffer(allocPool, poolOffset, size); | ||
| 521 | + const b = new FastBuffer(allocPool, poolBase + poolOffset, size); | ||
| 474 | 522 | poolOffset += size; | |
| 475 | 523 | alignPool(); | |
| 476 | 524 | return b; | |
| 477 | 525 | } | |
| 478 | 526 | return createUnsafeBuffer(size); | |
| 479 | 527 | } | |
| 480 | 528 | ||
| 529 | + function allocateAligned(size, alignment) { | ||
| 530 | + if (size <= 0) { | ||
| 531 | + return new FastBuffer(); | ||
| 532 | + } | ||
| 533 | + // The pool starts at a `kPoolAlignment` aligned address, so any alignment up | ||
| 534 | + // to that can be satisfied by padding the offset into the pool. Stricter | ||
| 535 | + // alignments need an allocation of their own. | ||
| 536 | + if (alignment > kPoolAlignment || size >= (Buffer.poolSize >>> 1)) { | ||
| 537 | + return createUnsafeAlignedBuffer(size, alignment); | ||
| 538 | + } | ||
| 539 | + poolOffset = (poolOffset + alignment - 1) & ~(alignment - 1); | ||
| 540 | + if (size > (poolSize - poolOffset)) | ||
| 541 | + createPool(); | ||
| 542 | + const b = new FastBuffer(allocPool, poolBase + poolOffset, size); | ||
| 543 | + poolOffset += size; | ||
| 544 | + alignPool(); | ||
| 545 | + return b; | ||
| 546 | + } | ||
| 547 | + | ||
| 481 | 548 | function fromStringFast(string, ops) { | |
| 482 | 549 | const maxLength = Buffer.poolSize >>> 1; | |
| 483 | 550 | ||
@@ -498,7 +565,7 @@ function fromStringFast(string, ops) { | |||
| 498 | 565 | createPool(); | |
| 499 | 566 | ||
| 500 | 567 | const actual = ops.write(allocBuffer, string, poolOffset, length); | |
| 501 | - const b = new FastBuffer(allocPool, poolOffset, actual); | ||
| 568 | + const b = new FastBuffer(allocPool, poolBase + poolOffset, actual); | ||
| 502 | 569 | ||
| 503 | 570 | poolOffset += actual; | |
| 504 | 571 | alignPool(); | |
@@ -560,7 +627,7 @@ function fromArrayLike(obj) { | |||
| 560 | 627 | if (length < (Buffer.poolSize >>> 1)) { | |
| 561 | 628 | if (length > (poolSize - poolOffset)) | |
| 562 | 629 | createPool(); | |
| 563 | - const b = new FastBuffer(allocPool, poolOffset, length); | ||
| 630 | + const b = new FastBuffer(allocPool, poolBase + poolOffset, length); | ||
| 564 | 631 | TypedArrayPrototypeSet(b, obj, 0); | |
| 565 | 632 | poolOffset += length; | |
| 566 | 633 | alignPool(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,6 +33,7 @@ const { | |||
| 33 | 33 | hexWrite, | |
| 34 | 34 | ucs2Write, | |
| 35 | 35 | utf8WriteStatic, | |
| 36 | + arrayBufferAlignedOffset, | ||
| 36 | 37 | createUnsafeArrayBuffer, | |
| 37 | 38 | setDetachKey, | |
| 38 | 39 | } = internalBinding('buffer'); | |
@@ -1104,12 +1105,28 @@ function createUnsafeBuffer(size) { | |||
| 1104 | 1105 | return new FastBuffer(createUnsafeArrayBuffer(size)); | |
| 1105 | 1106 | } | |
| 1106 | 1107 | ||
| 1108 | + // Returns an uninitialized buffer of `size` bytes whose first byte is located at | ||
| 1109 | + // a memory address that is a multiple of `alignment`. `alignment` must be a | ||
| 1110 | + // power of two, and `size + alignment - 1` must not exceed the maximum buffer | ||
| 1111 | + // length. Since the address of a backing store cannot be chosen, `alignment - 1` | ||
| 1112 | + // extra bytes are allocated and skipped, which leaves the returned buffer with a | ||
| 1113 | + // non-zero `byteOffset` into a larger ArrayBuffer. | ||
| 1114 | + function createUnsafeAlignedBuffer(size, alignment) { | ||
| 1115 | + if (size === 0) { | ||
| 1116 | + return new FastBuffer(); | ||
| 1117 | + } | ||
| 1118 | + | ||
| 1119 | + const ab = createUnsafeArrayBuffer(size + alignment - 1); | ||
| 1120 | + return new FastBuffer(ab, arrayBufferAlignedOffset(ab, alignment), size); | ||
| 1121 | + } | ||
| 1122 | + | ||
| 1107 | 1123 | module.exports = { | |
| 1108 | 1124 | FastBuffer, | |
| 1109 | 1125 | addBufferPrototypeMethods, | |
| 1110 | 1126 | markAsUntransferable, | |
| 1111 | 1127 | isMarkedAsUntransferable, | |
| 1112 | 1128 | createUnsafeBuffer, | |
| 1129 | + createUnsafeAlignedBuffer, | ||
| 1113 | 1130 | readUInt16BE, | |
| 1114 | 1131 | readUInt32BE, | |
| 1115 | 1132 | asciiWrite, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments