SparseArraySegment.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 bool IsMissingItem(const T* value);
  71. template <class S>
  72. static bool IsMissingItem(const WriteBarrierPtr<S>* value)
  73. {
  74. return IsMissingItem(AddressOf(value[0]));
  75. }
  76. static uint32 GetAlignedSize(uint32 size);
  77. static inline SparseArraySegment* From(SparseArraySegmentBase* seg)
  78. {
  79. return static_cast<SparseArraySegment*>(seg);
  80. }
  81. static inline Field(SparseArraySegment*)* AddressFrom(Field(SparseArraySegmentBase*) *addr)
  82. {
  83. return reinterpret_cast<Field(SparseArraySegment*)*>(addr);
  84. }
  85. private:
  86. template<bool isLeaf>
  87. static SparseArraySegment<T>* Allocate(Recycler* recycler, uint32 left, uint32 length, uint32 size, uint32 fillStart = 0);
  88. template<bool isLeaf>
  89. SparseArraySegment<T> *GrowByImpl(Recycler *recycler, uint32 n);
  90. template<bool isLeaf>
  91. SparseArraySegment<T>* GrowFrontByMaxImpl(Recycler *recycler, uint32 n);
  92. uint32 GetGrowByFactor();
  93. };
  94. template<typename T>
  95. T SparseArraySegment<T>::GetMissingItem()
  96. {
  97. return (T)JavascriptArray::MissingItem;
  98. }
  99. template<>
  100. inline int32 SparseArraySegment<int32>::GetMissingItem()
  101. {
  102. return 0x80000002;
  103. }
  104. template<>
  105. inline double SparseArraySegment<double>::GetMissingItem()
  106. {
  107. uint64 u = 0x8000000280000002;
  108. return *(double*)&u;
  109. }
  110. template<>
  111. inline bool SparseArraySegment<double>::IsMissingItem(const double* value)
  112. {
  113. return *(uint64*)value == 0x8000000280000002ull;
  114. }
  115. template<typename T>
  116. bool SparseArraySegment<T>::IsMissingItem(const T* value)
  117. {
  118. return *value == SparseArraySegment<T>::GetMissingItem();
  119. }
  120. } // namespace Js