SparseArraySegment.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Js
  7. {
  8. class SparseArraySegmentBase
  9. {
  10. public:
  11. static const uint32 MaxLength;
  12. Field(uint32) left; // TODO: (leish)(swb) this can easily be recycler false positive on x86, or on x64 if combine with length field
  13. // find a way to either tag this or find a better solution
  14. Field(uint32) length; //we use length instead of right so that we can denote a segment is empty
  15. Field(uint32) size;
  16. Field(SparseArraySegmentBase*) next;
  17. static const uint32 CHUNK_SIZE = 16;
  18. static const uint32 HEAD_CHUNK_SIZE = 16;
  19. static const uint32 INLINE_CHUNK_SIZE = 64; // Max number of elements in a segment that is initialized inline within the array.
  20. static const uint32 SMALL_CHUNK_SIZE = 4;
  21. static const uint32 BigLeft = 1 << 20;
  22. SparseArraySegmentBase(uint32 left, uint32 length, uint32 size);
  23. bool HasIndex(uint32 index) { return (left <= index) && index < (left + length); };
  24. uint32 RemoveUndefined(ScriptContext* scriptContext); //returns count of undefined removed
  25. void EnsureSizeInBound();
  26. void CheckLengthvsSize() { AssertOrFailFast(this->length <= this->size); }
  27. static uint32 GetOffsetOfLeft() { return offsetof(SparseArraySegmentBase, left); }
  28. static uint32 GetOffsetOfLength() { return offsetof(SparseArraySegmentBase, length); }
  29. static uint32 GetOffsetOfSize() { return offsetof(SparseArraySegmentBase, size); }
  30. static uint32 GetOffsetOfNext() { return offsetof(SparseArraySegmentBase, next); }
  31. static bool DoNativeArrayLeafSegment() { return !PHASE_OFF1(Js::NativeArrayLeafSegmentPhase); }
  32. static bool IsLeafSegment(SparseArraySegmentBase *seg, Recycler *recycler);
  33. protected:
  34. static void EnsureSizeInBound(uint32 left, uint32 length, uint32& size, SparseArraySegmentBase* next);
  35. };
  36. template<typename T>
  37. class SparseArraySegment : public SparseArraySegmentBase
  38. {
  39. public:
  40. SparseArraySegment(uint32 left, uint32 length, uint32 size) :
  41. SparseArraySegmentBase(left, length, size) {}
  42. Field(T) elements[]; // actual elements will follow this determined by size
  43. void FillSegmentBuffer(uint start, uint size);
  44. T GetElement(uint32 index);
  45. void SetElement(Recycler *recycler, uint32 index, T value); // sets elements within the segment
  46. void RemoveElement(Recycler *recycler, uint32 index); // NOTE: RemoveElement calls memmove, for perf reasons use SetElement(index, null)
  47. SparseArraySegment<T> *GrowBy(Recycler *recycler, uint32 n);
  48. SparseArraySegment<T>* GrowByMin(Recycler *recycler, uint32 minValue);
  49. SparseArraySegment<T>* GrowByMinMax(Recycler *recycler, uint32 minValue, uint32 maxValue);
  50. SparseArraySegment<T>* GrowFrontByMax(Recycler *recycler, uint32 n);
  51. void ReverseSegment(Recycler *recycler);
  52. void Truncate(uint32 index);
  53. //following will change the current segment allocation
  54. SparseArraySegment<T> *SetElementGrow(Recycler *recycler, SparseArraySegmentBase* prev, uint32 index, T value);
  55. static SparseArraySegment<T> *AllocateLiteralHeadSegment(Recycler *const recycler, const uint32 length);
  56. static SparseArraySegment<T> * AllocateSegment(Recycler* recycler, uint32 left, uint32 length, SparseArraySegmentBase *nextSeg);
  57. static SparseArraySegment<T> * AllocateSegment(Recycler* recycler, uint32 left, uint32 length, uint32 size, SparseArraySegmentBase *nextSeg);
  58. static SparseArraySegment<T> * AllocateSegment(Recycler* recycler, SparseArraySegmentBase* prev, uint32 index);
  59. template<bool isLeaf>
  60. static SparseArraySegment<T> * AllocateSegmentImpl(Recycler* recycler, uint32 left, uint32 length, SparseArraySegmentBase *nextSeg);
  61. template<bool isLeaf>
  62. static SparseArraySegment<T> * AllocateSegmentImpl(Recycler* recycler, uint32 left, uint32 length, uint32 size, SparseArraySegmentBase *nextSeg);
  63. template<bool isLeaf>
  64. static SparseArraySegment<T> * AllocateSegmentImpl(Recycler* recycler, SparseArraySegmentBase* prev, uint32 index);
  65. template<bool isLeaf>
  66. static SparseArraySegment<T> *AllocateLiteralHeadSegmentImpl(Recycler *const recycler, const uint32 length);
  67. static void ClearElements(__out_ecount(len) Field(T)* elements, uint32 len);
  68. static SparseArraySegment<T>* CopySegment(Recycler *recycler, SparseArraySegment<T>* dst, uint32 dstIndex, SparseArraySegment<T>* src, uint32 srcIndex, uint32 inputLen);
  69. static T GetMissingItem();
  70. static Var GetMissingItemVar();
  71. static bool IsMissingItem(const T* value);
  72. template <class S>
  73. static bool IsMissingItem(const WriteBarrierPtr<S>* value)
  74. {
  75. return IsMissingItem(AddressOf(value[0]));
  76. }
  77. static uint32 GetAlignedSize(uint32 size);
  78. static inline SparseArraySegment* From(SparseArraySegmentBase* seg)
  79. {
  80. return static_cast<SparseArraySegment*>(seg);
  81. }
  82. static inline Field(SparseArraySegment*)* AddressFrom(Field(SparseArraySegmentBase*) *addr)
  83. {
  84. return reinterpret_cast<Field(SparseArraySegment*)*>(addr);
  85. }
  86. private:
  87. template<bool isLeaf>
  88. static SparseArraySegment<T>* Allocate(Recycler* recycler, uint32 left, uint32 length, uint32 size, uint32 fillStart = 0);
  89. template<bool isLeaf>
  90. SparseArraySegment<T> *GrowByImpl(Recycler *recycler, uint32 n);
  91. template<bool isLeaf>
  92. SparseArraySegment<T>* GrowFrontByMaxImpl(Recycler *recycler, uint32 n);
  93. uint32 GetGrowByFactor();
  94. };
  95. template<typename T>
  96. T SparseArraySegment<T>::GetMissingItem()
  97. {
  98. return (T)JavascriptArray::MissingItem;
  99. }
  100. template<>
  101. inline int32 SparseArraySegment<int32>::GetMissingItem()
  102. {
  103. return IntMissingItemPattern;
  104. }
  105. template<>
  106. inline double SparseArraySegment<double>::GetMissingItem()
  107. {
  108. return *(double*)&FloatMissingItemPattern;
  109. }
  110. template<typename T>
  111. Var SparseArraySegment<T>::GetMissingItemVar()
  112. {
  113. return JavascriptArray::MissingItem;
  114. }
  115. template<> Var SparseArraySegment<int32>::GetMissingItemVar();
  116. template<> Var SparseArraySegment<double>::GetMissingItemVar();
  117. template<>
  118. inline bool SparseArraySegment<double>::IsMissingItem(const double* value)
  119. {
  120. return *(uint64*)value == FloatMissingItemPattern;
  121. }
  122. template<typename T>
  123. bool SparseArraySegment<T>::IsMissingItem(const T* value)
  124. {
  125. return *value == SparseArraySegment<T>::GetMissingItem();
  126. }
  127. } // namespace Js