| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeLibraryPch.h"
- namespace Js
- {
- const uint32 SparseArraySegmentBase::MaxLength = static_cast<uint32>(INT32_MAX);
- SparseArraySegmentBase::SparseArraySegmentBase(uint32 left, uint32 length, uint32 size) : left(left), length(length), size(size), next(nullptr)
- {
- }
- // "Reduce" size if it exceeds next.left boundary, after operations that shift the following segments.
- void SparseArraySegmentBase::EnsureSizeInBound()
- {
- EnsureSizeInBound(left, length, size, next);
- }
- // Reduce size if it exceeds next.left boundary or MaxArrayLength
- void SparseArraySegmentBase::EnsureSizeInBound(uint32 left, uint32 length, uint32& size, SparseArraySegmentBase* next)
- {
- uint32 nextLeft = next ? next->left : JavascriptArray::MaxArrayLength;
- Assert(nextLeft > left);
- if(size != 0)
- {
- // Avoid writing to 'size' for an empty segment. The empty segment is a constant structure and writing to it (even
- // if it's not being changed) may cause an AV.
- size = min(size, nextLeft - left);
- }
- AssertOrFailFast(length <= size);
- }
- // Test if an element value is null/undefined.
- inline static bool IsMissingOrUndefined(Var value, RecyclableObject *undefined, uint32& countUndefined)
- {
- if (SparseArraySegment<Var>::IsMissingItem(&value))
- {
- return true;
- }
- if (JavascriptOperators::IsUndefinedObject(value, undefined))
- {
- ++countUndefined;
- return true;
- }
- return false;
- }
- bool SparseArraySegmentBase::IsLeafSegment(SparseArraySegmentBase *seg, Recycler *recycler)
- {
- if (!DoNativeArrayLeafSegment())
- {
- return false;
- }
- RecyclerHeapObjectInfo heapObject;
- if (recycler->FindHeapObject(
- seg,
- (Memory::FindHeapObjectFlags)(FindHeapObjectFlags_VerifyFreeBitForAttribute | FindHeapObjectFlags_AllowInterior),
- heapObject))
- {
- return heapObject.IsLeaf();
- }
- return false;
- }
- // Remove null/undefined from this segment. May reorder elements and compact this segment in preparing for sort.
- uint32 SparseArraySegmentBase::RemoveUndefined(ScriptContext* scriptContext)
- {
- SparseArraySegment<Var> *_this = (SparseArraySegment<Var>*)this;
- // Shortcut length==0, otherwise the code below will AV when left==length==0. (WOOB 1114975)
- if (length == 0)
- {
- return 0;
- }
- //remove undefine values
- RecyclableObject *undefined = scriptContext->GetLibrary()->GetUndefined();
- uint32 i = 0;
- uint32 j = length - 1;
- uint32 countUndefined = 0;
- while (i <= j)
- {
- //get the first null/undefined slot from left
- while (i < j && !IsMissingOrUndefined(_this->elements[i], undefined, countUndefined))
- {
- i++;
- }
- bool iIsMissingOrUndefined = (i < j); // Flag to avoid test again if later j comes down to == i
- //get the first slot which is not null/undefined from the right
- while (i < j && IsMissingOrUndefined(_this->elements[j], undefined, countUndefined))
- {
- j--;
- }
- if (i < j)
- {
- //move
- _this->elements[i] = _this->elements[j];
- i++;
- j--;
- }
- else
- {
- Assert(i == j);
- if (iIsMissingOrUndefined || IsMissingOrUndefined(_this->elements[j], undefined, countUndefined))
- {
- j--; // ok if j becomes -1. We'll truncate to length (j + 1).
- }
- break; // done
- }
- }
- if (j != length - 1) // Truncate if j has changed
- {
- uint32 newLen = j + 1;
- Assert(newLen < length);
- Assert(countUndefined <= length - newLen);
- _this->Truncate(left + newLen); // Truncate to new length (also clears moved elements)
- }
- AssertOrFailFast(length <= size);
- return countUndefined;
- }
- }
|