SparseArraySegment.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. uint32 left;
  13. uint32 length; //we use length instead of right so that we can denote a segment is empty
  14. uint32 size;
  15. SparseArraySegmentBase* next;
  16. static const uint32 CHUNK_SIZE = 16;
  17. static const uint32 HEAD_CHUNK_SIZE = 16;
  18. static const uint32 INLINE_CHUNK_SIZE = 64; // Max number of elements in a segment that is initialized inline within the array.
  19. static const uint32 SMALL_CHUNK_SIZE = 4;
  20. static const uint32 BigLeft = 1 << 20;
  21. SparseArraySegmentBase(uint32 left, uint32 length, uint32 size);
  22. bool HasIndex(uint32 index) { return (left <= index) && index < (left + length); };
  23. uint32 RemoveUndefined(ScriptContext* scriptContext); //returns count of undefined removed
  24. void EnsureSizeInBound();
  25. static uint32 GetOffsetOfLeft() { return offsetof(SparseArraySegmentBase, left); }
  26. static uint32 GetOffsetOfLength() { return offsetof(SparseArraySegmentBase, length); }
  27. static uint32 GetOffsetOfSize() { return offsetof(SparseArraySegmentBase, size); }
  28. static uint32 GetOffsetOfNext() { return offsetof(SparseArraySegmentBase, next); }
  29. static bool DoNativeArrayLeafSegment() { return !PHASE_OFF1(Js::NativeArrayLeafSegmentPhase); }
  30. static bool IsLeafSegment(SparseArraySegmentBase *seg, Recycler *recycler);
  31. protected:
  32. static void EnsureSizeInBound(uint32 left, uint32 length, uint32& size, SparseArraySegmentBase* next);
  33. };
  34. template<typename T>
  35. class SparseArraySegment : public SparseArraySegmentBase
  36. {
  37. public:
  38. SparseArraySegment(uint32 left, uint32 length, uint32 size) :
  39. SparseArraySegmentBase(left, length, size) {}
  40. T elements[]; // actual elements will follow this determined by size
  41. inline void FillSegmentBuffer(uint start, uint size);
  42. inline T GetElement(uint32 index);
  43. inline void SetElement(Recycler *recycler, uint32 index, T value); // sets elements within the segment
  44. inline void RemoveElement(Recycler *recycler, uint32 index); // NOTE: RemoveElement calls memmove, for perf reasons use SetElement(index, null)
  45. inline SparseArraySegment<T> *GrowBy(Recycler *recycler, uint32 n);
  46. inline SparseArraySegment<T>* GrowByMin(Recycler *recycler, uint32 minValue);
  47. inline SparseArraySegment<T>* GrowByMinMax(Recycler *recycler, uint32 minValue, uint32 maxValue);
  48. inline SparseArraySegment<T>* GrowFrontByMax(Recycler *recycler, uint32 n);
  49. inline void ReverseSegment(Recycler *recycler);
  50. void Truncate(uint32 index);
  51. //following will change the current segment allocation
  52. inline SparseArraySegment<T> *SetElementGrow(Recycler *recycler, SparseArraySegmentBase* prev, uint32 index, T value);
  53. static SparseArraySegment<T> *AllocateLiteralHeadSegment(Recycler *const recycler, const uint32 length);
  54. static inline SparseArraySegment<T> * AllocateSegment(Recycler* recycler, uint32 left, uint32 length, SparseArraySegmentBase *nextSeg);
  55. static inline SparseArraySegment<T> * AllocateSegment(Recycler* recycler, uint32 left, uint32 length, uint32 size, SparseArraySegmentBase *nextSeg);
  56. static inline SparseArraySegment<T> * AllocateSegment(Recycler* recycler, SparseArraySegmentBase* prev, uint32 index);
  57. template<bool isLeaf>
  58. static inline SparseArraySegment<T> * AllocateSegmentImpl(Recycler* recycler, uint32 left, uint32 length, SparseArraySegmentBase *nextSeg);
  59. template<bool isLeaf>
  60. static inline SparseArraySegment<T> * AllocateSegmentImpl(Recycler* recycler, uint32 left, uint32 length, uint32 size, SparseArraySegmentBase *nextSeg);
  61. template<bool isLeaf>
  62. static inline SparseArraySegment<T> * AllocateSegmentImpl(Recycler* recycler, SparseArraySegmentBase* prev, uint32 index);
  63. template<bool isLeaf>
  64. static SparseArraySegment<T> *AllocateLiteralHeadSegmentImpl(Recycler *const recycler, const uint32 length);
  65. static void ClearElements(__out_ecount(len) T* elements, uint32 len);
  66. static inline SparseArraySegment<T>* CopySegment(Recycler *recycler, SparseArraySegment<T>* dst, uint32 dstIndex, SparseArraySegment<T>* src, uint32 srcIndex, uint32 inputLen);
  67. static inline T GetMissingItem();
  68. static inline bool IsMissingItem(const T* value);
  69. static inline uint32 GetAlignedSize(uint32 size);
  70. private:
  71. template<bool isLeaf>
  72. static inline SparseArraySegment<T>* Allocate(Recycler* recycler, uint32 left, uint32 length, uint32 size, uint32 fillStart = 0);
  73. template<bool isLeaf>
  74. inline SparseArraySegment<T> *GrowByImpl(Recycler *recycler, uint32 n);
  75. template<bool isLeaf>
  76. inline SparseArraySegment<T>* GrowFrontByMaxImpl(Recycler *recycler, uint32 n);
  77. inline uint32 GetGrowByFactor();
  78. };
  79. template<typename T>
  80. T SparseArraySegment<T>::GetMissingItem()
  81. {
  82. return (T)JavascriptArray::MissingItem;
  83. }
  84. template<>
  85. int32 SparseArraySegment<int32>::GetMissingItem()
  86. {
  87. return 0x80000002;
  88. }
  89. template<>
  90. double SparseArraySegment<double>::GetMissingItem()
  91. {
  92. uint64 u = 0x8000000280000002;
  93. return *(double*)&u;
  94. }
  95. template<>
  96. bool SparseArraySegment<double>::IsMissingItem(const double* value)
  97. {
  98. return *(uint64*)value == 0x8000000280000002ull;
  99. }
  100. template<typename T>
  101. bool SparseArraySegment<T>::IsMissingItem(const T* value)
  102. {
  103. return *value == SparseArraySegment<T>::GetMissingItem();
  104. }
  105. } // namespace Js