diff options
Diffstat (limited to 'deps/v8/src/builtins/array.tq')
-rw-r--r-- | deps/v8/src/builtins/array.tq | 321 |
1 files changed, 37 insertions, 284 deletions
diff --git a/deps/v8/src/builtins/array.tq b/deps/v8/src/builtins/array.tq index 590947dd44..df4387878d 100644 --- a/deps/v8/src/builtins/array.tq +++ b/deps/v8/src/builtins/array.tq @@ -14,303 +14,56 @@ module array { type FastDoubleElements; type DictionaryElements; - macro GetLengthProperty(context: Context, o: Object): Number { - if (BranchIfFastJSArray(o, context)) { - let a: JSArray = unsafe_cast<JSArray>(o); - return a.length_fast; - } else - deferred { - return ToLength_Inline(context, GetProperty(context, o, 'length')); - } - } - - macro FastArraySplice( - context: Context, args: constexpr Arguments, o: Object, - originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi, - actualDeleteCountNumber: Number): Object - labels Bailout { - let originalLength: Smi = cast<Smi>(originalLengthNumber) otherwise Bailout; - let actualStart: Smi = cast<Smi>(actualStartNumber) otherwise Bailout; - let actualDeleteCount: Smi = - cast<Smi>(actualDeleteCountNumber) otherwise Bailout; - let lengthDelta: Smi = insertCount - actualDeleteCount; - let newLength: Smi = originalLength + lengthDelta; - - let a: JSArray = cast<JSArray>(o) otherwise Bailout; - - let map: Map = a.map; - if (!IsPrototypeInitialArrayPrototype(context, map)) goto Bailout; - if (IsNoElementsProtectorCellInvalid()) goto Bailout; - if (IsArraySpeciesProtectorCellInvalid()) goto Bailout; - - // Fast path only works on fast elements kind and with writable length. - let elementsKind: ElementsKind = EnsureArrayPushable(map) otherwise Bailout; - if (!IsFastElementsKind(elementsKind)) goto Bailout; - - // For now, only support non-double fast elements - if (!IsFastSmiOrTaggedElementsKind(elementsKind)) goto Bailout; - - if (IsFastSmiElementsKind(elementsKind)) { - for (let e: Object of args [2: ]) { - if (TaggedIsNotSmi(e)) goto Bailout; - } - } - - // Make sure that the length hasn't been changed by side-effect. - let length: Smi = cast<Smi>(a.length) otherwise Bailout; - if (originalLength != length) goto Bailout; - - let deletedResult: JSArray = - ExtractFastJSArray(context, a, actualStart, actualDeleteCount); - - if (newLength == 0) { - a.elements = kEmptyFixedArray; - a.length = 0; - return deletedResult; - } - - let elements: FixedArray = cast<FixedArray>(a.elements) otherwise Bailout; - let elementsMap: Map = elements.map; - - // If the source is a COW array or the spliced array is larger then the - // source array, then allocate a new FixedArray to hold the result. - let newElements: FixedArray = elements; - if ((elementsMap == kCOWMap) || (lengthDelta > 0)) { - newElements = ExtractFixedArray( - elements, 0, actualStart, newLength, kAllFixedArrays); - newElements.map = elementsMap; - a.elements = newElements; - } + macro EnsureWriteableFastElements(array: JSArray) { + assert(IsFastElementsKind(array.map.elements_kind)); - // Double check that the array is still in fast elements mode - assert(IsFastSmiElementsKind(a.map.elements_kind)); + const elements: FixedArrayBase = array.elements; + if (elements.map != kCOWMap) return; - // Copy over inserted elements. - let k: Smi = actualStart; - if (insertCount > 0) { - for (let e: Object of args [2: ]) { - newElements[k++] = e; - } - } - - // Copy over elements after deleted elements. - let count: Smi = length - actualStart - actualDeleteCount; - while (count > 0) { - let e: Object = elements[k - lengthDelta]; - newElements[k++] = e; - count--; - } - - // Fill rest of spliced FixedArray with the hole, but only if the - // destination FixedArray is the original array's, since otherwise the array - // is pre-filled with holes. - if (elements == newElements) { - let limit: Smi = elements.length; - while (k < limit) { - newElements[k++] = Hole; - } - } - - // Update the array's length after all the FixedArray shuffling is done. - a.length = newLength; + // There are no COW *_DOUBLE_ELEMENTS arrays, so we are allowed to always + // extract FixedArrays and don't have to worry about FixedDoubleArrays. + assert(IsFastSmiOrTaggedElementsKind(array.map.elements_kind)); - return deletedResult; + const length: Smi = array.length_fast; + array.elements = + ExtractFixedArray(elements, 0, length, length, kFixedArrays); + assert(array.elements.map != kCOWMap); } - // https://tc39.github.io/ecma262/#sec-array.prototype.splice - javascript builtin ArraySpliceTorque( - context: Context, receiver: Object, ...arguments): Object { - // 1. Let O be ? ToObject(this value). - let o: JSReceiver = ToObject(context, receiver); - - // 2. Let len be ? ToLength(? Get(O, "length")). - let len: Number = GetLengthProperty(context, o); - - // 3. Let relativeStart be ? ToInteger(start). - let start: Object = arguments[0]; - let relativeStart: Number = ToInteger_Inline(context, start); - - // 4. If relativeStart < 0, let actualStart be max((len + relativeStart), - // 0); - // else let actualStart be min(relativeStart, len). - let actualStart: Number = relativeStart < 0 ? - max((len + relativeStart), 0) : - min(relativeStart, len); - - let insertCount: Smi; - let actualDeleteCount: Number; - // 5. If the Number of actual arguments is 0, then - if (arguments.length == 0) { - // a. Let insertCount be 0. - insertCount = 0; - // b. Let actualDeleteCount be 0. - actualDeleteCount = 0; - // 6. Else if the Number of actual arguments is 1, then - } else if (arguments.length == 1) { - // a. Let insertCount be 0. - insertCount = 0; - // b. Let actualDeleteCount be len - actualStart. - actualDeleteCount = len - actualStart; - // 7. Else, - } else { - // a. Let insertCount be the Number of actual arguments minus 2. - insertCount = convert<Smi>(arguments.length) - 2; - // b. Let dc be ? ToInteger(deleteCount). - let deleteCount: Object = arguments[1]; - let dc: Number = ToInteger_Inline(context, deleteCount); - // c. Let actualDeleteCount be min(max(dc, 0), len - actualStart). - actualDeleteCount = min(max(dc, 0), len - actualStart); - } - - // 8. If len + insertCount - actualDeleteCount > 2^53-1, throw a - // Bailout exception. - if (len + insertCount - actualDeleteCount > kMaxSafeInteger) { - ThrowRangeError(context, kInvalidArrayLength); - } - + macro IsJSArray(o: Object): bool { try { - return FastArraySplice( - context, arguments, o, len, actualStart, insertCount, - actualDeleteCount) otherwise Bailout; + const array: JSArray = Cast<JSArray>(o) otherwise NotArray; + return true; } - label Bailout {} - // If the fast case fails, just continue with the slow, correct, - // spec-compliant case. - - // 9. Let A be ? ArraySpeciesCreate(O, actualDeleteCount). - let a: Object = ArraySpeciesCreate(context, o, actualDeleteCount); - - // 10. Let k be 0. - let k: Number = 0; - - // 11. Repeat, while k < actualDeleteCount - while (k < actualDeleteCount) { - // a. Let from be ! ToString(actualStart + k). - let from: String = ToString_Inline(context, actualStart + k); - - // b. Let fromPresent be ? HasProperty(O, from). - let fromPresent: Oddball = HasProperty(context, o, from); - - // c. If fromPresent is true, then - if (fromPresent == True) { - // i. Let fromValue be ? Get(O, from). - let fromValue: Object = GetProperty(context, o, from); - - // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue). - CreateDataProperty(context, a, ToString_Inline(context, k), fromValue); - } - - // d. Increment k by 1. - k = k + 1; + label NotArray { + return false; } + } - // 12. Perform ? Set(A, "length", actualDeleteCount, true). - SetProperty(context, a, 'length', actualDeleteCount); - - // 13. Let items be a List whose elements are, in left-to-right order, - // the portion of the actual argument list starting with the third - // argument. The list is empty if fewer than three arguments were - // passed. - // 14. Let itemCount be the Number of elements in items. - let itemCount: Number = insertCount; - - // 15. If itemCount < actualDeleteCount, then - if (itemCount < actualDeleteCount) { - // a. Let k be actualStart. - let k: Number = actualStart; - - // b. Repeat, while k < (len - actualDeleteCount) - while (k < (len - actualDeleteCount)) { - // i. Let from be ! ToString(k + actualDeleteCount). - let from: String = ToString_Inline(context, k + actualDeleteCount); - // ii. Let to be ! ToString(k + itemCount). - let to: String = ToString_Inline(context, k + itemCount); - - // iii. Let fromPresent be ? HasProperty(O, from). - let fromPresent: Oddball = HasProperty(context, o, from); - - // iv. If fromPresent is true, then - if (fromPresent == True) { - // 1. Let fromValue be ? Get(O, from). - let fromValue: Object = GetProperty(context, o, from); - - // 2. Perform ? Set(O, to, fromValue, true). - SetProperty(context, o, to, fromValue); - - // v. Else fromPresent is false, - } else { - // 1. Perform ? DeletePropertyOrThrow(O, to). - DeleteProperty(context, o, to, kStrict); - } - // vi. Increase k by 1. - k = k + 1; - } - - // c. Let k be len. - k = len; - // d. Repeat, while k > (len - actualDeleteCount + itemCount) - while (k > (len - actualDeleteCount + itemCount)) { - // i. Perform ? DeletePropertyOrThrow(O, ! ToString(k - 1)). - DeleteProperty(context, o, ToString_Inline(context, k - 1), kStrict); - - // ii. Decrease k by 1. - k = k - 1; - } - // 16. Else if itemCount > actualDeleteCount, then - } else if (itemCount > actualDeleteCount) { - // a. Let k be (len - actualDeleteCount). - let k: Number = len - actualDeleteCount; - - // b. Repeat, while k > actualStart - while (k > actualStart) { - // i. Let from be ! ToString(k + actualDeleteCount - 1). - let from: String = ToString_Inline(context, k + actualDeleteCount - 1); - - // ii. Let to be ! ToString(k + itemCount - 1). - let to: String = ToString_Inline(context, k + itemCount - 1); - - // iii. Let fromPresent be ? HasProperty(O, from). - let fromPresent: Oddball = HasProperty(context, o, from); - - // iv. If fromPresent is true, then - if (fromPresent == True) { - // 1. Let fromValue be ? Get(O, from). - let fromValue: Object = GetProperty(context, o, from); + macro StoreArrayHole(elements: FixedDoubleArray, k: Smi): void { + StoreFixedDoubleArrayHoleSmi(elements, k); + } - // 2. Perform ? Set(O, to, fromValue, true). - SetProperty(context, o, to, fromValue); + macro StoreArrayHole(elements: FixedArray, k: Smi): void { + elements[k] = Hole; + } - // v. Else fromPresent is false, - } else { - // 1. Perform ? DeletePropertyOrThrow(O, to). - DeleteProperty(context, o, to, kStrict); - } + macro CopyArrayElement( + elements: FixedArray, newElements: FixedArray, from: Smi, to: Smi): void { + const e: Object = elements[from]; + newElements[to] = e; + } - // vi. Decrease k by 1. - k = k - 1; - } + macro CopyArrayElement( + elements: FixedDoubleArray, newElements: FixedDoubleArray, from: Smi, + to: Smi): void { + try { + const floatValue: float64 = LoadDoubleWithHoleCheck(elements, from) + otherwise FoundHole; + newElements[to] = floatValue; } - - // 17. Let k be actualStart. - k = actualStart; - - // 18. Repeat, while items is not empty - // a. Remove the first element from items and let E be the value of that - // element. - if (arguments.length > 2) { - for (let e: Object of arguments [2: ]) { - // b. Perform ? Set(O, ! ToString(k), E, true). - SetProperty(context, o, ToString_Inline(context, k), e); - - // c. Increase k by 1. - k = k + 1; - } + label FoundHole { + StoreArrayHole(newElements, to); } - - // 19. Perform ? Set(O, "length", len - actualDeleteCount + itemCount, - // true). - SetProperty(context, o, 'length', len - actualDeleteCount + itemCount); - - return a; } } |