aboutsummaryrefslogtreecommitdiff
path: root/src/javascript/jsc/bindings/builtins/js/StreamInternals.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/javascript/jsc/bindings/builtins/js/StreamInternals.js')
-rw-r--r--src/javascript/jsc/bindings/builtins/js/StreamInternals.js114
1 files changed, 108 insertions, 6 deletions
diff --git a/src/javascript/jsc/bindings/builtins/js/StreamInternals.js b/src/javascript/jsc/bindings/builtins/js/StreamInternals.js
index 9c2103293..c2ca3f5b5 100644
--- a/src/javascript/jsc/bindings/builtins/js/StreamInternals.js
+++ b/src/javascript/jsc/bindings/builtins/js/StreamInternals.js
@@ -114,18 +114,119 @@ function validateAndNormalizeQueuingStrategy(size, highWaterMark)
return { size: size, highWaterMark: newHighWaterMark };
}
+@globalPrivate
+function createFIFO() {
+ "use strict";
+ class Denqueue {
+ constructor() {
+ this._head = 0;
+ this._tail = 0;
+ // this._capacity = 0;
+ this._capacityMask = 0x3;
+ this._list = @newArrayWithSize(4);
+ }
+
+ size() {
+ if (this._head === this._tail) return 0;
+ if (this._head < this._tail) return this._tail - this._head;
+ else return this._capacityMask + 1 - (this._head - this._tail);
+ }
+
+ isEmpty() {
+ return this.size() == 0;
+ }
+
+ isNotEmpty() {
+ return this.size() > 0;
+ }
+
+ shift() {
+ var head = this._head;
+ if (head === this._tail) return @undefined;
+ var item = this._list[head];
+ @putByValDirect(this._list, head, @undefined);
+ this._head = (head + 1) & this._capacityMask;
+ if (head < 2 && this._tail > 10000 && this._tail <= this._list.length >>> 2) this._shrinkArray();
+ return item;
+ }
+
+ peek() {
+ if (this._head === this._tail) return @undefined;
+ return this._list[this._head];
+ }
+
+ push(item) {
+ var tail = this._tail;
+ @putByValDirect(this._list, tail, item);
+ this._tail = (tail + 1) & this._capacityMask;
+ if (this._tail === this._head) {
+ this._growArray();
+ }
+ // if (this._capacity && this.size() > this._capacity) {
+ // this.shift();
+ // }
+ }
+
+ toArray(fullCopy) {
+ var list = this._list;
+ var len = @toLength(list.length);
+
+ if (fullCopy || this._head > this._tail) {
+ var _head = @toLength(this._head);
+ var _tail = @toLength(this._tail);
+ var total = @toLength((len - _head) + _tail);
+ var array = @newArrayWithSize(total);
+ var j = 0;
+ for (var i = _head; i < len; i++) @putByValDirect(array, j++, list[i]);
+ for (var i = 0; i < _tail; i++) @putByValDirect(array, j++, list[i]);
+ return array;
+ } else {
+ return @Array.prototype.slice.@call(list, this._head, this._tail);
+ }
+ }
+
+ clear() {
+ this._head = 0;
+ this._tail = 0;
+ this._list.fill(undefined);
+ }
+
+ _growArray() {
+ if (this._head) {
+ // copy existing data, head to end, then beginning to tail.
+ this._list = this.toArray(true);
+ this._head = 0;
+ }
+
+ // head is at 0 and array is now full, safe to extend
+ this._tail = @toLength(this._list.length);
+
+ this._list.length <<= 1;
+ this._capacityMask = (this._capacityMask << 1) | 1;
+ }
+
+ shrinkArray() {
+ this._list.length >>>= 1;
+ this._capacityMask >>>= 1;
+ }
+ }
+
+
+ return new Denqueue();
+}
+
function newQueue()
{
"use strict";
- return { content: [], size: 0 };
+ return { content: @createFIFO(), size: 0 };
}
function dequeueValue(queue)
{
"use strict";
- const record = queue.content.@shift();
+ const record = queue.content.shift();
queue.size -= record.size;
// As described by spec, below case may occur due to rounding errors.
if (queue.size < 0)
@@ -140,7 +241,8 @@ function enqueueValueWithSize(queue, value, size)
size = @toNumber(size);
if (!@isFinite(size) || size < 0)
@throwRangeError("size has an incorrect value");
- @arrayPush(queue.content, { value, size });
+
+ queue.content.push({ value, size });
queue.size += size;
}
@@ -148,9 +250,9 @@ function peekQueueValue(queue)
{
"use strict";
- @assert(queue.content.length > 0);
+ @assert(queue.content.isNotEmpty());
- return queue.content[0].value;
+ return queue.peek().value;
}
function resetQueue(queue)
@@ -159,7 +261,7 @@ function resetQueue(queue)
@assert("content" in queue);
@assert("size" in queue);
- queue.content = [];
+ queue.content.clear();
queue.size = 0;
}