JavascriptArray.h 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  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. #define ARRAY_CROSSOVER_FOR_VALIDATE 0
  7. namespace Js
  8. {
  9. class SegmentBTree
  10. {
  11. // This is an auxiliary data structure to speed finding the correct array segment for sparse arrays.
  12. // Rather than implement remove we only implement SwapSegment which requires the segment to be
  13. // swapped is in the same relative order as the segment it replaces.
  14. // The B-tree algorithm used is adapted from the pseudo-code in
  15. // Introduction to Algorithms by Corman, Leiserson, and Rivest.
  16. protected:
  17. Field(uint32*) keys; // keys[i] == segments[i]->left
  18. Field(SparseArraySegmentBase**) segments; // Length of segmentCount. Allocated with Leaf, no need to annotate inner pointer
  19. Field(SegmentBTree*) children; // Length of segmentCount+1.
  20. Field(uint32) segmentCount; // number of sparseArray segments in the Node
  21. public:
  22. static const uint MinDegree = 20; // Degree is the minimum branching factor. (If non-root, and non-leaf.)
  23. // non-root nodes are between MinDegree and MinDegree*2-1 in size.
  24. // e.g. For MinDegree == 32 -> this is 31 to 62 keys
  25. // and 32 to 63 children (every key is surrounded by before and after children).
  26. //
  27. // Allocations are simply the max possible sizes of nodes
  28. // We may do something more clever in the future.
  29. static const uint32 MinKeys = MinDegree - 1; // Minimum number of keys in any non-root node.
  30. static const uint32 MaxKeys = MinDegree*2 - 1;// Max number of keys in any node
  31. static const uint32 MaxDegree = MinDegree*2; // Max number of children
  32. static uint32 GetLazyCrossOverLimit(); // = MinDegree*3; // This is the crossover point for using the segmentBTee in our Arrays
  33. // Ideally this doesn't belong here.
  34. // Putting it here simply acknowledges that this BTree is not generic.
  35. // The implementation is tightly coupled with it's use in arrays.
  36. // The segment BTree adds memory overhead, we only want to incur it if
  37. // it is needed to prevent O(n) effects from using large sparse arrays
  38. // the BtreeNode is implicit:
  39. // btreenode := (children[0], segments[0], children[1], segments[1], ... segments[segmentCount-1], children[segmentCount])
  40. // Children pointers to the left contain segments strictly less than the segment to the right
  41. // Children points to the right contain segments strictly greater than the segment to the left.
  42. // Segments do not overlap, so the left index in a segment is sufficient to determine ordering.
  43. // keys are replicated in another array so that we do not incur the overhead of touching the memory for segments
  44. // that are uninteresting.
  45. public:
  46. SegmentBTree();
  47. void SwapSegment(uint32 originalKey, SparseArraySegmentBase* oldSeg, SparseArraySegmentBase* newSeg);
  48. template<typename Func>
  49. void Walk(Func& func) const;
  50. protected:
  51. BOOL IsLeaf() const;
  52. BOOL IsFullNode() const;
  53. static void InternalFind(SegmentBTree* node, uint32 itemIndex, SparseArraySegmentBase*& prev, SparseArraySegmentBase*& matchOrNext);
  54. static void SplitChild(Recycler* recycler, SegmentBTree* tree, uint32 count, SegmentBTree* root);
  55. static void InsertNonFullNode(Recycler* recycler, SegmentBTree* tree, SparseArraySegmentBase* newSeg);
  56. };
  57. class SegmentBTreeRoot : public SegmentBTree
  58. {
  59. public:
  60. void Add(Recycler* recycler, SparseArraySegmentBase* newSeg);
  61. void Find(uint itemIndex, SparseArraySegmentBase*& prevOrMatch, SparseArraySegmentBase*& matchOrNext);
  62. Field(SparseArraySegmentBase *) lastUsedSegment;
  63. };
  64. class JavascriptArray : public ArrayObject
  65. {
  66. template <class TPropertyIndex>
  67. friend class ES5ArrayTypeHandlerBase;
  68. public:
  69. static const size_t StackAllocationSize;
  70. private:
  71. static PropertyId const specialPropertyIds[];
  72. protected:
  73. DEFINE_VTABLE_CTOR(JavascriptArray, ArrayObject);
  74. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptArray);
  75. private:
  76. Field(bool) isInitialized;
  77. protected:
  78. Field(SparseArraySegmentBase*) head;
  79. union SegmentUnionType
  80. {
  81. Field(SparseArraySegmentBase*) lastUsedSegment;
  82. Field(SegmentBTreeRoot*) segmentBTreeRoot;
  83. SegmentUnionType() {}
  84. };
  85. Field(SegmentUnionType) segmentUnion;
  86. public:
  87. typedef Var TElement;
  88. static const SparseArraySegmentBase *EmptySegment;
  89. static uint32 const InvalidIndex = 0xFFFFFFFF;
  90. static uint32 const MaxArrayLength = InvalidIndex;
  91. static uint32 const MaxInitialDenseLength=1<<18;
  92. static ushort const MergeSegmentsLengthHeuristics = 128; // If the length is less than MergeSegmentsLengthHeuristics then try to merge the segments
  93. static uint64 const FiftyThirdPowerOfTwoMinusOne = 0x1FFFFFFFFFFFFF; // 2^53-1
  94. static const uint8 AllocationBucketsInfoSize = 3;
  95. // 0th colum in allocationBuckets
  96. static const uint8 AllocationBucketIndex = 0;
  97. // 1st column in allocationBuckets that stores no. of missing elements to initialize for given bucket
  98. static const uint8 MissingElementsCountIndex = 1;
  99. // 2nd column in allocationBuckets that stores allocation size for given bucket
  100. static const uint8 AllocationSizeIndex = 2;
  101. #if defined(_M_X64_OR_ARM64)
  102. static const uint8 AllocationBucketsCount = 3;
  103. #else
  104. static const uint8 AllocationBucketsCount = 2;
  105. #endif
  106. static uint allocationBuckets[AllocationBucketsCount][AllocationBucketsInfoSize];
  107. static const Var MissingItem;
  108. template<typename T> static T GetMissingItem();
  109. SparseArraySegmentBase * GetHead() const { return head; }
  110. SparseArraySegmentBase * GetLastUsedSegment() const;
  111. public:
  112. JavascriptArray(DynamicType * type);
  113. JavascriptArray(uint32 length, uint32 size, DynamicType * type);
  114. JavascriptArray(DynamicType * type, uint32 size);
  115. static Var OP_NewScArray(uint32 argLength, ScriptContext* scriptContext);
  116. static Var OP_NewScArrayWithElements(uint32 argLength, Var *elements, ScriptContext* scriptContext);
  117. static Var OP_NewScArrayWithMissingValues(uint32 argLength, ScriptContext* scriptContext);
  118. static Var OP_NewScIntArray(AuxArray<int32> *ints, ScriptContext* scriptContext);
  119. static Var OP_NewScFltArray(AuxArray<double> *doubles, ScriptContext* scriptContext);
  120. #if ENABLE_PROFILE_INFO
  121. static Var ProfiledNewScArray(uint32 argLength, ScriptContext *scriptContext, ArrayCallSiteInfo *arrayInfo, RecyclerWeakReference<FunctionBody> *weakFuncRef);
  122. static Var ProfiledNewScIntArray(AuxArray<int32> *ints, ScriptContext* scriptContext, ArrayCallSiteInfo *arrayInfo, RecyclerWeakReference<FunctionBody> *weakFuncRef);
  123. static Var ProfiledNewScFltArray(AuxArray<double> *doubles, ScriptContext* scriptContext, ArrayCallSiteInfo *arrayInfo, RecyclerWeakReference<FunctionBody> *weakFuncRef);
  124. static Var ProfiledNewInstanceNoArg(RecyclableObject *function, ScriptContext *scriptContext, ArrayCallSiteInfo *arrayInfo, RecyclerWeakReference<FunctionBody> *weakFuncRef);
  125. #endif
  126. static TypeId OP_SetNativeIntElementC(JavascriptNativeIntArray *arr, uint32 index, Var value, ScriptContext *scriptContext);
  127. static TypeId OP_SetNativeFloatElementC(JavascriptNativeFloatArray *arr, uint32 index, Var value, ScriptContext *scriptContext);
  128. template<typename T> void SetArrayLiteralItem(uint32 index, T value);
  129. void Sort(RecyclableObject* compFn);
  130. template<typename NativeArrayType, typename T> NativeArrayType * ConvertToNativeArrayInPlace(JavascriptArray *varArray);
  131. template <typename T> T GetNativeValue(Var iVal, ScriptContext * scriptContext);
  132. template <> int32 GetNativeValue<int32>(Var iVal, ScriptContext * scriptContext);
  133. template <> double GetNativeValue<double>(Var iVal, ScriptContext * scriptContext);
  134. template<typename T> void ChangeArrayTypeToNativeArray(JavascriptArray * varArray, ScriptContext * scriptContext);
  135. template<> void ChangeArrayTypeToNativeArray<double>(JavascriptArray * varArray, ScriptContext * scriptContext);
  136. template<> void ChangeArrayTypeToNativeArray<int32>(JavascriptArray * varArray, ScriptContext * scriptContext);
  137. template<typename T> inline BOOL DirectGetItemAt(uint32 index, T* outVal);
  138. virtual BOOL DirectGetVarItemAt(uint index, Var* outval, ScriptContext *scriptContext);
  139. virtual BOOL DirectGetItemAtFull(uint index, Var* outVal);
  140. virtual Var DirectGetItem(uint32 index);
  141. Var DirectGetItem(JavascriptString *propName, ScriptContext* scriptContext);
  142. template<typename T> inline void DirectSetItemAt(uint32 itemIndex, T newValue);
  143. template<typename T> inline void DirectSetItemInLastUsedSegmentAt(const uint32 offset, const T newValue);
  144. #if ENABLE_PROFILE_INFO
  145. template<typename T> inline void DirectProfiledSetItemInHeadSegmentAt(const uint32 offset, const T newValue, StElemInfo *const stElemInfo);
  146. #endif
  147. template<typename T> static void CopyValueToSegmentBuferNoCheck(Field(T)* buffer, uint32 length, T value);
  148. template<typename T> void DirectSetItem_Full(uint32 itemIndex, T newValue);
  149. template<typename T> SparseArraySegment<T>* PrepareSegmentForMemOp(uint32 startIndex, uint32 length);
  150. template<typename T> bool DirectSetItemAtRange(uint32 startIndex, uint32 length, T newValue);
  151. template<typename T> bool DirectSetItemAtRangeFull(uint32 startIndex, uint32 length, T newValue);
  152. template<typename T> bool DirectSetItemAtRangeFromArray(uint32 startIndex, uint32 length, JavascriptArray *fromArray, uint32 fromStartIndex);
  153. #if DBG
  154. template <typename T> void VerifyNotNeedMarshal(T value) {};
  155. template <> void VerifyNotNeedMarshal<Var>(Var value) { Assert(value == JavascriptArray::MissingItem || !CrossSite::NeedMarshalVar(value, this->GetScriptContext())); }
  156. #endif
  157. void DirectSetItemIfNotExist(uint32 index, Var newValue);
  158. template<typename T> BOOL DirectDeleteItemAt(uint32 itemIndex);
  159. virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override
  160. {
  161. Var value = nullptr;
  162. return this->DirectGetItemAt(index, &value) ? WritableData : None;
  163. }
  164. static bool Is(Var aValue);
  165. static bool Is(TypeId typeId);
  166. static JavascriptArray* FromVar(Var aValue);
  167. static bool IsVarArray(Var aValue);
  168. static bool IsVarArray(TypeId typeId);
  169. static JavascriptArray* FromAnyArray(Var aValue);
  170. static bool IsDirectAccessArray(Var aValue);
  171. void SetLength(uint32 newLength);
  172. BOOL SetLength(Var newLength);
  173. virtual void ClearElements(SparseArraySegmentBase *seg, uint32 newSegmentLength);
  174. class EntryInfo
  175. {
  176. public:
  177. static FunctionInfo NewInstance;
  178. static FunctionInfo Concat;
  179. static FunctionInfo Every;
  180. static FunctionInfo Filter;
  181. static FunctionInfo ForEach;
  182. static FunctionInfo IndexOf;
  183. static FunctionInfo Includes;
  184. static FunctionInfo Join;
  185. static FunctionInfo LastIndexOf;
  186. static FunctionInfo Map;
  187. static FunctionInfo Pop;
  188. static FunctionInfo Push;
  189. static FunctionInfo Reduce;
  190. static FunctionInfo ReduceRight;
  191. static FunctionInfo Reverse;
  192. static FunctionInfo Shift;
  193. static FunctionInfo Slice;
  194. static FunctionInfo Some;
  195. static FunctionInfo Sort;
  196. static FunctionInfo Splice;
  197. static FunctionInfo ToString;
  198. static FunctionInfo ToLocaleString;
  199. static FunctionInfo Unshift;
  200. static FunctionInfo IsArray;
  201. static FunctionInfo Find;
  202. static FunctionInfo FindIndex;
  203. static FunctionInfo Entries;
  204. static FunctionInfo Keys;
  205. static FunctionInfo Values;
  206. static FunctionInfo CopyWithin;
  207. static FunctionInfo Fill;
  208. static FunctionInfo From;
  209. static FunctionInfo Of;
  210. static FunctionInfo GetterSymbolSpecies;
  211. };
  212. static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  213. static Var NewInstance(RecyclableObject* function, Arguments args);
  214. static Var ProfiledNewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  215. static Var EntryConcat(RecyclableObject* function, CallInfo callInfo, ...);
  216. static Var EntryEvery(RecyclableObject* function, CallInfo callInfo, ...);
  217. static Var EntryFilter(RecyclableObject* function, CallInfo callInfo, ...);
  218. static Var EntryForEach(RecyclableObject* function, CallInfo callInfo, ...);
  219. static Var EntryIndexOf(RecyclableObject* function, CallInfo callInfo, ...);
  220. static Var EntryIncludes(RecyclableObject* function, CallInfo callInfo, ...);
  221. static Var EntryJoin(RecyclableObject* function, CallInfo callInfo, ...);
  222. static Var EntryLastIndexOf(RecyclableObject* function, CallInfo callInfo, ...);
  223. static Var EntryMap(RecyclableObject* function, CallInfo callInfo, ...);
  224. static Var EntryPop(RecyclableObject* function, CallInfo callInfo, ...);
  225. static Var EntryPush(RecyclableObject* function, CallInfo callInfo, ...);
  226. static Var EntryReduce(RecyclableObject* function, CallInfo callInfo, ...);
  227. static Var EntryReduceRight(RecyclableObject* function, CallInfo callInfo, ...);
  228. static Var EntryReverse(RecyclableObject* function, CallInfo callInfo, ...);
  229. static Var EntryShift(RecyclableObject* function, CallInfo callInfo, ...);
  230. static Var EntrySlice(RecyclableObject* function, CallInfo callInfo, ...);
  231. static Var EntrySome(RecyclableObject* function, CallInfo callInfo, ...);
  232. static Var EntrySort(RecyclableObject* function, CallInfo callInfo, ...);
  233. static Var EntrySplice(RecyclableObject* function, CallInfo callInfo, ...);
  234. static Var EntryToString(RecyclableObject* function, CallInfo callInfo, ...);
  235. static Var EntryToLocaleString(RecyclableObject* function, CallInfo callInfo, ...);
  236. static Var EntryUnshift(RecyclableObject* function, CallInfo callInfo, ...);
  237. static Var EntryIsArray(RecyclableObject* function, CallInfo callInfo, ...);
  238. static Var EntryFind(RecyclableObject* function, CallInfo callInfo, ...);
  239. static Var EntryFindIndex(RecyclableObject* function, CallInfo callInfo, ...);
  240. static Var EntryEntries(RecyclableObject* function, CallInfo callInfo, ...);
  241. static Var EntryKeys(RecyclableObject* function, CallInfo callInfo, ...);
  242. static Var EntryValues(RecyclableObject* function, CallInfo callInfo, ...);
  243. static Var EntryCopyWithin(RecyclableObject* function, CallInfo callInfo, ...);
  244. static Var EntryFill(RecyclableObject* function, CallInfo callInfo, ...);
  245. static Var EntryFrom(RecyclableObject* function, CallInfo callInfo, ...);
  246. static Var EntryOf(RecyclableObject* function, CallInfo callInfo, ...);
  247. static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...);
  248. static Var Push(ScriptContext * scriptContext, Var object, Var value);
  249. static Var EntryPushNonJavascriptArray(ScriptContext * scriptContext, Var * args, uint argCount);
  250. static Var EntryPushJavascriptArray(ScriptContext * scriptContext, Var * args, uint argCount);
  251. static Var EntryPushJavascriptArrayNoFastPath(ScriptContext * scriptContext, Var * args, uint argCount);
  252. static Var Pop(ScriptContext * scriptContext, Var object);
  253. static Var EntryPopJavascriptArray(ScriptContext * scriptContext, Var object);
  254. static Var EntryPopNonJavascriptArray(ScriptContext * scriptContext, Var object);
  255. #if DEBUG
  256. static BOOL GetIndex(const char16* propName, uint32 *pIndex);
  257. #endif
  258. uint32 GetNextIndex(uint32 index) const;
  259. template<typename T> uint32 GetNextIndexHelper(uint32 index) const;
  260. #ifdef VALIDATE_ARRAY
  261. virtual void ValidateArray();
  262. void ValidateArrayCommon();
  263. template<typename T> static void ValidateSegment(SparseArraySegment<T>* seg);
  264. static void ValidateVarSegment(SparseArraySegment<Var>* seg);
  265. #endif
  266. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  267. void CheckForceES5Array();
  268. #endif
  269. virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId) override;
  270. virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags) override;
  271. virtual BOOL DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags) override;
  272. virtual BOOL IsEnumerable(PropertyId propertyId) override;
  273. virtual BOOL IsConfigurable(PropertyId propertyId) override;
  274. virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override;
  275. virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override;
  276. virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override;
  277. virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) override;
  278. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  279. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  280. virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
  281. virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  282. virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  283. virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override;
  284. virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
  285. virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  286. virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  287. virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
  288. virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
  289. virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags) override;
  290. virtual BOOL PreventExtensions() override;
  291. virtual BOOL Seal() override;
  292. virtual BOOL Freeze() override;
  293. virtual BOOL GetEnumerator(JavascriptStaticEnumerator * enumerator, EnumeratorFlags flags, ScriptContext* requestContext, ForInCache * forInCache = nullptr) override;
  294. virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  295. virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  296. virtual BOOL GetSpecialPropertyName(uint32 index, JavascriptString ** propertyName, ScriptContext * requestContext) override;
  297. virtual uint GetSpecialPropertyCount() const override;
  298. virtual PropertyId const * GetSpecialPropertyIds() const override;
  299. virtual DescriptorFlags GetSetter(PropertyId propertyId, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
  300. virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
  301. // objectArray support
  302. virtual BOOL SetItemWithAttributes(uint32 index, Var value, PropertyAttributes attributes) override;
  303. virtual BOOL SetItemAttributes(uint32 index, PropertyAttributes attributes) override;
  304. virtual BOOL SetItemAccessors(uint32 index, Var getter, Var setter) override;
  305. virtual BOOL IsObjectArrayFrozen() override;
  306. virtual JavascriptEnumerator * GetIndexEnumerator(EnumeratorFlags flags, ScriptContext* requestContext) override;
  307. // Get non-index enumerator for SCA
  308. BOOL GetNonIndexEnumerator(JavascriptStaticEnumerator * enumerator, ScriptContext* requestContext);
  309. virtual BOOL IsItemEnumerable(uint32 index);
  310. template<typename Func>
  311. void WalkExisting(Func func)
  312. {
  313. Assert(!JavascriptNativeIntArray::Is(this) && !JavascriptNativeFloatArray::Is(this));
  314. ArrayElementEnumerator e(this, 0);
  315. while(e.MoveNext<Var>())
  316. {
  317. func(e.GetIndex(), e.GetItem<Var>());
  318. }
  319. }
  320. static JavascriptArray* CreateArrayFromConstructor(RecyclableObject* constructor, uint32 length, ScriptContext* scriptContext);
  321. static JavascriptArray* CreateArrayFromConstructorNoArg(RecyclableObject* constructor, ScriptContext* scriptContext);
  322. template<typename unitType, typename className>
  323. static className* New(Recycler* recycler, DynamicType* arrayType);
  324. template<typename unitType, typename className, uint inlineSlots>
  325. static className* New(uint32 length, DynamicType* arrayType, Recycler* recycler);
  326. template<typename unitType, typename className, uint inlineSlots>
  327. static className* NewLiteral(uint32 length, DynamicType* arrayType, Recycler* recycler);
  328. #if ENABLE_COPYONACCESS_ARRAY
  329. template<typename unitType, typename className, uint inlineSlots>
  330. static className* NewCopyOnAccessLiteral(DynamicType* arrayType, ArrayCallSiteInfo *arrayInfo, FunctionBody *functionBody, const Js::AuxArray<int32> *ints, Recycler* recycler);
  331. #endif
  332. static bool HasInlineHeadSegment(uint32 length);
  333. template<class T, uint InlinePropertySlots>
  334. static T *New(void *const stackAllocationPointer, const uint32 length, DynamicType *const arrayType);
  335. template<class T, uint InlinePropertySlots>
  336. static T *NewLiteral(void *const stackAllocationPointer, const uint32 length, DynamicType *const arrayType);
  337. static JavascriptArray *EnsureNonNativeArray(JavascriptArray *arr);
  338. #if ENABLE_PROFILE_INFO
  339. virtual JavascriptArray *FillFromArgs(uint length, uint start, Var *args, ArrayCallSiteInfo *info = nullptr, bool dontCreateNewArray = false);
  340. #else
  341. virtual JavascriptArray *FillFromArgs(uint length, uint start, Var *args, bool dontCreateNewArray = false);
  342. #endif
  343. protected:
  344. // Use static New methods to create array.
  345. JavascriptArray(uint32 length, DynamicType * type);
  346. // For BoxStackInstance
  347. JavascriptArray(JavascriptArray * instance, bool boxHead);
  348. template<typename T> inline void LinkSegments(SparseArraySegment<T>* prev, SparseArraySegment<T>* current);
  349. template<typename T> inline SparseArraySegment<T>* ReallocNonLeafSegment(SparseArraySegment<T>* seg, SparseArraySegmentBase* nextSeg, bool forceNonLeaf = false);
  350. void TryAddToSegmentMap(Recycler* recycler, SparseArraySegmentBase* seg);
  351. private:
  352. DynamicObjectFlags GetFlags() const;
  353. DynamicObjectFlags GetFlags_Unchecked() const; // do not use except in extreme circumstances
  354. void SetFlags(const DynamicObjectFlags flags);
  355. void LinkSegmentsCommon(SparseArraySegmentBase* prev, SparseArraySegmentBase* current);
  356. public:
  357. static JavascriptArray *GetArrayForArrayOrObjectWithArray(const Var var);
  358. static JavascriptArray *GetArrayForArrayOrObjectWithArray(const Var var, bool *const isObjectWithArrayRef, TypeId *const arrayTypeIdRef);
  359. static const SparseArraySegmentBase *Jit_GetArrayHeadSegmentForArrayOrObjectWithArray(const Var var);
  360. static uint32 Jit_GetArrayHeadSegmentLength(const SparseArraySegmentBase *const headSegment);
  361. static bool Jit_OperationInvalidatedArrayHeadSegment(const SparseArraySegmentBase *const headSegmentBeforeOperation, const uint32 headSegmentLengthBeforeOperation, const Var varAfterOperation);
  362. static uint32 Jit_GetArrayLength(const Var var);
  363. static bool Jit_OperationInvalidatedArrayLength(const uint32 lengthBeforeOperation, const Var varAfterOperation);
  364. static DynamicObjectFlags Jit_GetArrayFlagsForArrayOrObjectWithArray(const Var var);
  365. static bool Jit_OperationCreatedFirstMissingValue(const DynamicObjectFlags flagsBeforeOperation, const Var varAfterOperation);
  366. public:
  367. bool HasNoMissingValues() const; // if true, the head segment has no missing values
  368. bool HasNoMissingValues_Unchecked() const; // do not use except in extreme circumstances
  369. void SetHasNoMissingValues(const bool hasNoMissingValues = true);
  370. template<typename T>
  371. bool IsMissingItemAt(uint32 index) const;
  372. bool IsMissingItem(uint32 index);
  373. virtual bool IsMissingHeadSegmentItem(const uint32 index) const;
  374. static VTableValue VtableHelper()
  375. {
  376. return VTableValue::VtableJavascriptArray;
  377. }
  378. static LibraryValue InitialTypeHelper()
  379. {
  380. return LibraryValue::ValueJavascriptArrayType;
  381. }
  382. static DynamicType * GetInitialType(ScriptContext * scriptContext);
  383. public:
  384. static uint32 defaultSmallSegmentAlignedSize;
  385. template<typename unitType, typename classname>
  386. inline BOOL TryGrowHeadSegmentAndSetItem(uint32 indexInt, unitType iValue);
  387. static int64 GetIndexFromVar(Js::Var arg, int64 length, ScriptContext* scriptContext);
  388. template <typename T>
  389. static Var MapHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  390. template <typename T>
  391. static Var MapObjectHelper(RecyclableObject* obj, T length, T start, RecyclableObject* newObj, JavascriptArray* newArr,
  392. bool isBuiltinArrayCtor, RecyclableObject* callBackFn, Var thisArg, ScriptContext* scriptContext);
  393. static Var FillHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, int64 length, Arguments& args, ScriptContext* scriptContext);
  394. static Var CopyWithinHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, int64 length, Arguments& args, ScriptContext* scriptContext);
  395. template <typename T>
  396. static BOOL GetParamForIndexOf(T length, Arguments const & args, Var& search, T& fromIndex, ScriptContext * scriptContext);
  397. static BOOL GetParamForLastIndexOf(int64 length, Arguments const & args, Var& search, int64& fromIndex, ScriptContext * scriptContext);
  398. template <bool includesAlgorithm, typename T, typename P = uint32>
  399. static Var TemplatedIndexOfHelper(T* pArr, Var search, P fromIndex, P toIndex, ScriptContext * scriptContext);
  400. template <typename T>
  401. static Var LastIndexOfHelper(T* pArr, Var search, int64 fromIndex, ScriptContext * scriptContext);
  402. template <typename T>
  403. static BOOL TemplatedGetItem(T *pArr, uint32 index, Var * element, ScriptContext * scriptContext, bool checkHasItem = true);
  404. template <typename T>
  405. static BOOL TemplatedGetItem(T *pArr, uint64 index, Var * element, ScriptContext * scriptContext, bool checkHasItem = true);
  406. template <typename T = uint32>
  407. static Var ReverseHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, ScriptContext* scriptContext);
  408. template <typename T = uint32>
  409. static Var SliceHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  410. static Var SliceObjectHelper(RecyclableObject* obj, uint32 sliceStart, uint32 start, JavascriptArray* newArr, RecyclableObject* newObj, uint32 newLen, ScriptContext* scriptContext);
  411. template <typename T = uint32>
  412. static Var EveryHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  413. template <typename T = uint32>
  414. static Var EveryObjectHelper(RecyclableObject* obj, T length, T start, RecyclableObject* callBackFn, Var thisArg, ScriptContext* scriptContext);
  415. template <typename T = uint32>
  416. static Var SomeHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  417. template <typename T = uint32>
  418. static Var SomeObjectHelper(RecyclableObject* obj, T length, T start, RecyclableObject* callBackFn, Var thisArg, ScriptContext* scriptContext);
  419. template <bool findIndex>
  420. static Var FindHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, int64 length, Arguments& args, ScriptContext* scriptContext);
  421. template <bool findIndex>
  422. static Var FindObjectHelper(RecyclableObject* obj, int64 length, int64 start, RecyclableObject* callBackFn, Var thisArg, ScriptContext* scriptContext);
  423. template <typename T = uint32>
  424. static Var ReduceHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  425. template <typename T>
  426. static Var ReduceObjectHelper(RecyclableObject* obj, T length, T start, RecyclableObject* callBackFn, Var accumulator, ScriptContext* scriptContext);
  427. template <typename T>
  428. static Var FilterHelper(JavascriptArray* pArr, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  429. template <typename T>
  430. static Var FilterObjectHelper(RecyclableObject* obj, T length, T start, JavascriptArray* newArr, RecyclableObject* newObj, T newStart,
  431. RecyclableObject* callBackFn, Var thisArg, ScriptContext* scriptContext);
  432. template <typename T = uint32>
  433. static Var ReduceRightHelper(JavascriptArray* pArr, Js::TypedArrayBase* typedArrayBase, RecyclableObject* obj, T length, Arguments& args, ScriptContext* scriptContext);
  434. template <typename T>
  435. static Var ReduceRightObjectHelper(RecyclableObject* obj, T length, T start, RecyclableObject* callBackFn, Var accumulator, ScriptContext* scriptContext);
  436. static Var OfHelper(bool isTypedArrayEntryPoint, Arguments& args, ScriptContext* scriptContext);
  437. template<typename T>
  438. static T GetFromIndex(Var arg, T length, ScriptContext *scriptContext, bool addWithLength = true)
  439. {
  440. T fromIndex = 0;
  441. double value = TaggedInt::Is(arg) ? (double)TaggedInt::ToInt64(arg) : JavascriptConversion::ToInteger(arg, scriptContext);
  442. if (value < 0)
  443. {
  444. fromIndex = addWithLength ? (T)max(0i64, (int64)(value + length)) : 0;
  445. }
  446. else
  447. {
  448. fromIndex = (T)min(value, (double)length);
  449. }
  450. return fromIndex;
  451. }
  452. protected:
  453. template<class T> bool IsMissingHeadSegmentItemImpl(const uint32 index) const;
  454. SegmentBTreeRoot * GetSegmentMap() const;
  455. void SetHeadAndLastUsedSegment(SparseArraySegmentBase * segment);
  456. void SetLastUsedSegment(SparseArraySegmentBase * segment);
  457. bool HasSegmentMap() const;
  458. private:
  459. void SetSegmentMap(SegmentBTreeRoot * segmentMap);
  460. void ClearSegmentMap();
  461. template <typename Fn> SparseArraySegmentBase * ForEachSegment(Fn fn) const;
  462. template <typename Fn> static SparseArraySegmentBase * ForEachSegment(SparseArraySegmentBase * segment, Fn fn);
  463. template<typename T> bool NeedScanForMissingValuesUponSetItem(SparseArraySegment<T> *const segment, const uint32 offset) const;
  464. template<typename T> void ScanForMissingValues(const uint startIndex = 0);
  465. template<typename T> bool ScanForMissingValues(const uint startIndex, const uint endIndex);
  466. template<typename T, uint InlinePropertySlots> static SparseArraySegment<typename T::TElement> *InitArrayAndHeadSegment(T *const array, const uint32 length, const uint32 size, const bool wasZeroAllocated);
  467. template<typename T> static void SliceHelper(JavascriptArray*pArr, JavascriptArray* pNewArr, uint32 start, uint32 newLen);
  468. template<typename T>
  469. static void ShiftHelper(JavascriptArray* pArr, ScriptContext * scriptContext);
  470. template<typename T>
  471. static void UnshiftHelper(JavascriptArray* pArr, uint32 unshiftElements, Js::Var * elements);
  472. template<typename T>
  473. static void GrowArrayHeadHelperForUnshift(JavascriptArray* pArr, uint32 unshiftElements, ScriptContext * scriptContext);
  474. static int64 GetFromLastIndex(Var arg, int64 length, ScriptContext *scriptContext);
  475. static JavascriptString* JoinToString(Var value, ScriptContext* scriptContext);
  476. static JavascriptString* JoinHelper(Var thisArg, JavascriptString* separatorStr, ScriptContext* scriptContext);
  477. template <typename T>
  478. static JavascriptString* JoinArrayHelper(T * arr, JavascriptString* separatorStr, ScriptContext* scriptContext);
  479. static JavascriptString* JoinOtherHelper(RecyclableObject *object, JavascriptString* separatorStr, ScriptContext* scriptContext);
  480. template <bool includesAlgorithm>
  481. static Var IndexOfHelper(Arguments const & args, ScriptContext *scriptContext);
  482. virtual int32 HeadSegmentIndexOfHelper(Var search, uint32 &fromIndex, uint32 toIndex, bool includesAlgorithm, ScriptContext * scriptContext);
  483. template<typename T>
  484. static void CopyHeadIfInlinedHeadSegment(JavascriptArray *array, Recycler *recycler);
  485. template<typename T>
  486. static void ReallocateNonLeafLastSegmentIfLeaf(JavascriptArray * arr, Recycler * recycler);
  487. template<typename T>
  488. static void ArraySpliceHelper(JavascriptArray* pNewArr, JavascriptArray* pArr, uint32 start, uint32 deleteLen,
  489. Var* insertArgs, uint32 insertLen, ScriptContext *scriptContext);
  490. template<typename T>
  491. static void ArraySegmentSpliceHelper(JavascriptArray *pnewArr, SparseArraySegment<T> *seg, SparseArraySegment<T> **prev, uint32 start, uint32 deleteLen,
  492. Var* insertArgs, uint32 insertLen, Recycler *recycler);
  493. template<typename T>
  494. static RecyclableObject* ObjectSpliceHelper(RecyclableObject* pObj, T len, T start, T deleteLen,
  495. Var* insertArgs, uint32 insertLen, ScriptContext *scriptContext, RecyclableObject* pNewObj = nullptr);
  496. static JavascriptString* ToLocaleStringHelper(Var value, ScriptContext* scriptContext);
  497. static Js::JavascriptArray* CreateNewArrayHelper(uint32 len, bool isIntArray, bool isFloatArray, Js::JavascriptArray *baseArray, ScriptContext* scriptContext);
  498. static Var TryArraySplice(JavascriptArray* pArr, uint32 start, uint32 len, uint32 deleteLen,
  499. Var* insertArgs, uint32 insertLen, ScriptContext *scriptContext);
  500. void FillFromPrototypes(uint32 startIndex, uint32 endIndex);
  501. bool IsFillFromPrototypes();
  502. void GetArrayTypeAndConvert(bool* isIntArray, bool* isFloatArray);
  503. template<typename T> void EnsureHeadStartsFromZero(Recycler * recycler);
  504. SparseArraySegmentBase * GetBeginLookupSegment(uint32 index, const bool useSegmentMap = true) const;
  505. SegmentBTreeRoot * BuildSegmentMap();
  506. void InvalidateLastUsedSegment();
  507. inline BOOL IsFullArray() const; // no missing elements till array length
  508. inline BOOL IsSingleSegmentArray() const;
  509. template<typename T> void AllocateHead();
  510. template<typename T> void EnsureHead();
  511. uint32 sort(__inout_ecount(*length) Field(Var) *orig, uint32 *length, ScriptContext *scriptContext);
  512. BOOL GetPropertyBuiltIns(PropertyId propertyId, Var* value);
  513. bool GetSetterBuiltIns(PropertyId propertyId, PropertyValueInfo* info, DescriptorFlags* descriptorFlags);
  514. private:
  515. struct Element
  516. {
  517. Field(Var) Value;
  518. Field(JavascriptString*) StringValue;
  519. };
  520. static int __cdecl CompareElements(void* context, const void* elem1, const void* elem2);
  521. void SortElements(Element* elements, uint32 left, uint32 right);
  522. template <typename Fn>
  523. static void ForEachOwnMissingArrayIndexOfObject(JavascriptArray *baseArr, JavascriptArray *destArray, RecyclableObject* obj, uint32 startIndex, uint32 limitIndex, uint32 destIndex, Fn fn);
  524. // NativeArrays may change it's content type, but not others
  525. template <typename T> static bool MayChangeType() { return false; }
  526. template<typename T, typename P>
  527. static BOOL TryTemplatedGetItem(T *arr, P index, Var *element, ScriptContext *scriptContext, bool checkHasItem = true)
  528. {
  529. return T::Is(arr) ? JavascriptArray::TemplatedGetItem(arr, index, element, scriptContext, checkHasItem) :
  530. JavascriptOperators::GetItem(arr, index, element, scriptContext);
  531. }
  532. template <bool hasSideEffect, typename T, typename Fn>
  533. static void TemplatedForEachItemInRange(T * arr, uint32 startIndex, uint32 limitIndex, Var missingItem, ScriptContext * scriptContext, Fn fn)
  534. {
  535. for (uint32 i = startIndex; i < limitIndex; i++)
  536. {
  537. Var element;
  538. fn(i, TryTemplatedGetItem(arr, i, &element, scriptContext) ? element : missingItem);
  539. if (hasSideEffect && MayChangeType<T>() && !T::Is(arr))
  540. {
  541. // The function has changed, go to another ForEachItemInRange. It is possible that the array might have changed to
  542. // an ES5Array, in such cases we don't need to call the JavascriptArray specific implementation.
  543. if (JavascriptArray::Is(arr))
  544. {
  545. JavascriptArray::FromVar(arr)->template ForEachItemInRange<true>(i + 1, limitIndex, missingItem, scriptContext, fn);
  546. return;
  547. }
  548. else
  549. {
  550. AssertOrFailFastMsg(ES5Array::Is(arr), "The array should have been converted to an ES5Array");
  551. }
  552. }
  553. }
  554. }
  555. template <bool hasSideEffect, typename T, typename P, typename Fn>
  556. static void TemplatedForEachItemInRange(T * arr, P startIndex, P limitIndex, ScriptContext * scriptContext, Fn fn)
  557. {
  558. for (P i = startIndex; i < limitIndex; i++)
  559. {
  560. Var element;
  561. if (TryTemplatedGetItem(arr, i, &element, scriptContext))
  562. {
  563. fn(i, element);
  564. if (hasSideEffect && MayChangeType<T>() && !T::Is(arr))
  565. {
  566. // The function has changed, go to another ForEachItemInRange. It is possible that the array might have changed to
  567. // an ES5Array, in such cases we don't need to call the JavascriptArray specific implementation.
  568. if (JavascriptArray::Is(arr))
  569. {
  570. JavascriptArray::FromVar(arr)->template ForEachItemInRange<true>(i + 1, limitIndex, scriptContext, fn);
  571. return;
  572. }
  573. else
  574. {
  575. AssertOrFailFastMsg(ES5Array::Is(arr), "The array should have been converted to an ES5Array");
  576. }
  577. }
  578. }
  579. }
  580. }
  581. public:
  582. template <bool hasSideEffect, typename Fn>
  583. void ForEachItemInRange(uint64 startIndex, uint64 limitIndex, ScriptContext * scriptContext, Fn fn)
  584. {
  585. Assert(false);
  586. Throw::InternalError();
  587. }
  588. template <bool hasSideEffect, typename Fn>
  589. void ForEachItemInRange(uint32 startIndex, uint32 limitIndex, ScriptContext * scriptContext, Fn fn)
  590. {
  591. switch (this->GetTypeId())
  592. {
  593. case TypeIds_Array:
  594. TemplatedForEachItemInRange<hasSideEffect>(this, startIndex, limitIndex, scriptContext, fn);
  595. break;
  596. case TypeIds_NativeIntArray:
  597. TemplatedForEachItemInRange<hasSideEffect>(JavascriptNativeIntArray::FromVar(this), startIndex, limitIndex, scriptContext, fn);
  598. break;
  599. case TypeIds_NativeFloatArray:
  600. TemplatedForEachItemInRange<hasSideEffect>(JavascriptNativeFloatArray::FromVar(this), startIndex, limitIndex, scriptContext, fn);
  601. break;
  602. default:
  603. Assert(false);
  604. break;
  605. }
  606. }
  607. template <bool hasSideEffect, typename Fn>
  608. void ForEachItemInRange(uint32 startIndex, uint32 limitIndex, Var missingItem, ScriptContext * scriptContext, Fn fn)
  609. {
  610. switch (this->GetTypeId())
  611. {
  612. case TypeIds_Array:
  613. TemplatedForEachItemInRange<hasSideEffect>(this, startIndex, limitIndex, missingItem, scriptContext, fn);
  614. break;
  615. case TypeIds_NativeIntArray:
  616. TemplatedForEachItemInRange<hasSideEffect>(JavascriptNativeIntArray::FromVar(this), startIndex, limitIndex, missingItem, scriptContext, fn);
  617. break;
  618. case TypeIds_NativeFloatArray:
  619. TemplatedForEachItemInRange<hasSideEffect>(JavascriptNativeFloatArray::FromVar(this), startIndex, limitIndex, missingItem, scriptContext, fn);
  620. break;
  621. default:
  622. Assert(false);
  623. break;
  624. }
  625. }
  626. // ArrayElementEnumerator walks an array's segments and enumerates the elements in order.
  627. class ArrayElementEnumerator
  628. {
  629. private:
  630. SparseArraySegmentBase* seg;
  631. uint32 index, endIndex;
  632. const uint32 start, end;
  633. public:
  634. ArrayElementEnumerator(JavascriptArray* arr, uint32 start = 0, uint32 end = MaxArrayLength);
  635. template<typename T> bool MoveNext();
  636. uint32 GetIndex() const;
  637. template<typename T> T GetItem() const;
  638. private:
  639. void Init(JavascriptArray* arr);
  640. };
  641. template <typename T>
  642. class IndexTrace
  643. {
  644. public:
  645. static Var ToNumber(const T& index, ScriptContext* scriptContext);
  646. // index on JavascriptArray
  647. static BOOL GetItem(JavascriptArray* arr, const T& index, Var* outVal);
  648. static BOOL SetItem(JavascriptArray* arr, const T& index, Var newValue);
  649. static void SetItemIfNotExist(JavascriptArray* arr, const T& index, Var newValue);
  650. static BOOL DeleteItem(JavascriptArray* arr, const T& index);
  651. // index on RecyclableObject
  652. static BOOL SetItem(RecyclableObject* obj, const T& index, Var newValue, PropertyOperationFlags flags = PropertyOperation_None);
  653. static BOOL DeleteItem(RecyclableObject* obj, const T& index, PropertyOperationFlags flags = PropertyOperation_None);
  654. };
  655. // BigIndex represents a general index which may grow larger than uint32.
  656. class BigIndex
  657. {
  658. private:
  659. uint32 index;
  660. uint64 bigIndex;
  661. typedef IndexTrace<uint32> small_index;
  662. public:
  663. BigIndex(uint32 initIndex = 0);
  664. BigIndex(uint64 initIndex);
  665. bool IsSmallIndex() const;
  666. bool IsUint32Max() const;
  667. uint32 GetSmallIndex() const;
  668. uint64 GetBigIndex() const;
  669. Var ToNumber(ScriptContext* scriptContext) const;
  670. const BigIndex& operator++();
  671. const BigIndex& operator--();
  672. BigIndex operator+(const BigIndex& delta) const;
  673. BigIndex operator+(uint32 delta) const;
  674. bool operator==(const BigIndex& rhs) const;
  675. bool operator> (const BigIndex& rhs) const;
  676. bool operator< (const BigIndex& rhs) const;
  677. bool operator<=(const BigIndex& rhs) const;
  678. bool operator>=(const BigIndex& rhs) const;
  679. BOOL GetItem(JavascriptArray* arr, Var* outVal) const;
  680. BOOL SetItem(JavascriptArray* arr, Var newValue) const;
  681. void SetItemIfNotExist(JavascriptArray* arr, Var newValue) const;
  682. BOOL DeleteItem(JavascriptArray* arr) const;
  683. BOOL SetItem(RecyclableObject* obj, Var newValue, PropertyOperationFlags flags = PropertyOperation_None) const;
  684. BOOL DeleteItem(RecyclableObject* obj, PropertyOperationFlags flags = PropertyOperation_None) const;
  685. };
  686. void GenericDirectSetItemAt(const BigIndex& index, Var newValue) { index.SetItem(this, newValue); }
  687. void GenericDirectSetItemAt(const uint32 index, Var newValue) { this->DirectSetItemAt(index, newValue); }
  688. void DirectSetItemIfNotExist(const BigIndex& index, Var newValue) { index.SetItemIfNotExist(this, newValue); }
  689. void DirectAppendItem(Var newValue) { BigIndex(this->GetLength()).SetItem(this, newValue); }
  690. void TruncateToProperties(const BigIndex& index, uint32 start);
  691. static void InternalCopyArrayElements(JavascriptArray* dstArray, uint32 dstIndex, JavascriptArray* srcArray, uint32 start, uint32 end);
  692. static void InternalCopyNativeFloatArrayElements(JavascriptArray* dstArray, const uint32 dstIndex, JavascriptNativeFloatArray* srcArray, uint32 start, uint32 end);
  693. static void InternalCopyNativeIntArrayElements(JavascriptArray* dstArray, uint32 dstIndex, JavascriptNativeIntArray* srcArray, uint32 start, uint32 end);
  694. static void InternalFillFromPrototype(JavascriptArray *dstArray, const uint32 dstIndex, JavascriptArray *srcArray, uint32 start, uint32 end, uint32 count);
  695. static void CopyArrayElements(JavascriptArray* dstArray, uint32 dstIndex, JavascriptArray* srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  696. template <typename T>
  697. static void CopyAnyArrayElementsToVar(JavascriptArray* dstArray, T dstIndex, JavascriptArray* srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  698. static bool CopyNativeIntArrayElements(JavascriptNativeIntArray* dstArray, uint32 dstIndex, JavascriptNativeIntArray *srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  699. static bool CopyNativeIntArrayElementsToFloat(JavascriptNativeFloatArray* dstArray, uint32 dstIndex, JavascriptNativeIntArray *srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  700. static void CopyNativeIntArrayElementsToVar(JavascriptArray* dstArray, uint32 dstIndex, JavascriptNativeIntArray *srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  701. static bool CopyNativeFloatArrayElements(JavascriptNativeFloatArray* dstArray, uint32 dstIndex, JavascriptNativeFloatArray *srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  702. static void CopyNativeFloatArrayElementsToVar(JavascriptArray* dstArray, uint32 dstIndex, JavascriptNativeFloatArray *srcArray, uint32 start = 0, uint32 end = MaxArrayLength);
  703. static bool BoxConcatItem(Var aItem, uint idxArg, ScriptContext *scriptContext);
  704. template<typename T>
  705. static void SetConcatItem(Var aItem, uint idxArg, JavascriptArray* pDestArray, RecyclableObject* pDestObj, T idxDest, ScriptContext *scriptContext);
  706. template<typename T>
  707. static void ConcatArgs(RecyclableObject* pDestObj, TypeId* remoteTypeIds, Js::Arguments& args, ScriptContext* scriptContext, uint start, BigIndex startIdxDest, BOOL firstPromotedItemIsSpreadable, BigIndex firstPromotedItemLength, bool spreadableCheckedAndTrue = false);
  708. template<typename T>
  709. static void ConcatArgs(RecyclableObject* pDestObj, TypeId* remoteTypeIds, Js::Arguments& args, ScriptContext* scriptContext, uint start = 0, uint startIdxDest = 0u, BOOL FirstPromotedItemIsSpreadable = false, BigIndex FirstPromotedItemLength = 0u, bool spreadableCheckedAndTrue = false);
  710. static JavascriptArray* ConcatIntArgs(JavascriptNativeIntArray* pDestArray, TypeId* remoteTypeIds, Js::Arguments& args, ScriptContext* scriptContext);
  711. static bool PromoteToBigIndex(BigIndex lhs, BigIndex rhs);
  712. static bool PromoteToBigIndex(BigIndex lhs, uint32 rhs);
  713. static JavascriptArray* ConcatFloatArgs(JavascriptNativeFloatArray* pDestArray, TypeId* remoteTypeIds, Js::Arguments& args, ScriptContext* scriptContext);
  714. private:
  715. template<typename T=uint32>
  716. static RecyclableObject* ArraySpeciesCreate(Var pThisArray, T length, ScriptContext* scriptContext, bool *pIsIntArray = nullptr, bool *pIsFloatArray = nullptr, bool *pIsBuiltinArrayCtor = nullptr);
  717. template <typename T, typename R> static R ConvertToIndex(T idxDest, ScriptContext* scriptContext) { Throw::InternalError(); return 0; }
  718. static BOOL SetArrayLikeObjects(RecyclableObject* pDestObj, uint32 idxDest, Var aItem);
  719. static BOOL SetArrayLikeObjects(RecyclableObject* pDestObj, BigIndex idxDest, Var aItem);
  720. static void ConcatArgsCallingHelper(RecyclableObject* pDestObj, TypeId* remoteTypeIds, Js::Arguments& args, ScriptContext* scriptContext, ::Math::RecordOverflowPolicy &destLengthOverflow);
  721. static void ThrowErrorOnFailure(BOOL succeeded, ScriptContext* scriptContext, uint32 index);
  722. static void ThrowErrorOnFailure(BOOL succeeded, ScriptContext* scriptContext, BigIndex index);
  723. template<typename T>
  724. static void TryGetArrayAndLength(Var arg, ScriptContext *scriptContext, PCWSTR methodName, __out JavascriptArray** array, __out RecyclableObject** obj, __out T * length);
  725. static uint64 OP_GetLength(Var obj, ScriptContext *scriptContext);
  726. public:
  727. template<typename T, typename P = uint32>
  728. static void Unshift(RecyclableObject* obj, const T& toIndex, P start, P end, ScriptContext* scriptContext);
  729. template <typename T>
  730. class ItemTrace
  731. {
  732. public:
  733. static uint32 GetLength(T* obj, ScriptContext* scriptContext);
  734. static BOOL GetItem(T* obj, uint32 index, Var* outVal, ScriptContext* scriptContext);
  735. };
  736. template <typename T>
  737. static JavascriptString* ToLocaleString(T* obj, ScriptContext* scriptContext);
  738. static JavascriptString* GetLocaleSeparator(ScriptContext* scriptContext);
  739. public:
  740. static uint32 GetOffsetOfArrayFlags() { return offsetof(JavascriptArray, arrayFlags); }
  741. static uint32 GetOffsetOfHead() { return offsetof(JavascriptArray, head); }
  742. static uint32 GetOffsetOfLastUsedSegmentOrSegmentMap() { return offsetof(JavascriptArray, segmentUnion.lastUsedSegment); }
  743. static Var SpreadArrayArgs(Var arrayToSpread, const Js::AuxArray<uint32> *spreadIndices, ScriptContext *scriptContext);
  744. static uint32 GetSpreadArgLen(Var spreadArg, ScriptContext *scriptContext);
  745. static JavascriptArray * BoxStackInstance(JavascriptArray * instance);
  746. protected:
  747. template <typename T> void InitBoxedInlineHeadSegment(SparseArraySegment<T> * dst, SparseArraySegment<T> * src);
  748. template <typename T> static T * BoxStackInstance(T * instance);
  749. public:
  750. template<class T, uint InlinePropertySlots> static size_t DetermineAllocationSize(const uint inlineElementSlots, size_t *const allocationPlusSizeRef = nullptr, uint *const alignedInlineElementSlotsRef = nullptr);
  751. template<class ArrayType, uint InlinePropertySlots> static size_t DetermineAllocationSizeForArrayObjects(const uint inlineElementSlots, size_t *const allocationPlusSizeRef = nullptr, uint *const alignedInlineElementSlotsRef = nullptr);
  752. template<class ArrayType> static void EnsureCalculationOfAllocationBuckets();
  753. template<class T, uint InlinePropertySlots> static uint DetermineAvailableInlineElementSlots(const size_t allocationSize, bool *const isSufficientSpaceForInlinePropertySlotsRef);
  754. template<class T, uint ConstInlinePropertySlots, bool UseDynamicInlinePropertySlots> static SparseArraySegment<typename T::TElement> *DetermineInlineHeadSegmentPointer(T *const array);
  755. #if ENABLE_TTD
  756. public:
  757. virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
  758. virtual void ProcessCorePaths() override;
  759. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  760. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  761. #endif
  762. public:
  763. virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
  764. {
  765. return VtableHelper();
  766. }
  767. };
  768. // Ideally we would propagate the throw flag setting of true from the array operations down to the [[Delete]]/[[Put]]/... methods. But that is a big change
  769. // so we are checking for failure on DeleteProperty/DeleteItem/... etc instead. This helper makes that checking a little less intrusive.
  770. class ThrowTypeErrorOnFailureHelper
  771. {
  772. ScriptContext *m_scriptContext;
  773. PCWSTR m_functionName;
  774. public:
  775. ThrowTypeErrorOnFailureHelper(ScriptContext *scriptContext, PCWSTR functionName) : m_scriptContext(scriptContext), m_functionName(functionName) {}
  776. inline void ThrowTypeErrorOnFailure(BOOL operationSucceeded);
  777. inline void ThrowTypeErrorOnFailure();
  778. inline BOOL IsThrowTypeError(BOOL operationSucceeded);
  779. };
  780. class JavascriptNativeArray : public JavascriptArray
  781. {
  782. friend class JavascriptArray;
  783. protected:
  784. DEFINE_VTABLE_CTOR(JavascriptNativeArray, JavascriptArray);
  785. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptNativeArray);
  786. public:
  787. JavascriptNativeArray(DynamicType * type) :
  788. JavascriptArray(type), weakRefToFuncBody(nullptr)
  789. {
  790. }
  791. protected:
  792. JavascriptNativeArray(uint32 length, DynamicType * type) :
  793. JavascriptArray(length, type), weakRefToFuncBody(nullptr) {}
  794. // For BoxStackInstance
  795. JavascriptNativeArray(JavascriptNativeArray * instance);
  796. Field(RecyclerWeakReference<FunctionBody> *) weakRefToFuncBody;
  797. public:
  798. static bool Is(Var aValue);
  799. static bool Is(TypeId typeId);
  800. static JavascriptNativeArray* FromVar(Var aValue);
  801. void SetArrayCallSite(ProfileId index, RecyclerWeakReference<FunctionBody> *weakRef)
  802. {
  803. Assert(weakRef);
  804. Assert(!weakRefToFuncBody);
  805. SetArrayCallSiteIndex(index);
  806. weakRefToFuncBody = weakRef;
  807. }
  808. void ClearArrayCallSiteIndex()
  809. {
  810. weakRefToFuncBody = nullptr;
  811. }
  812. #if ENABLE_PROFILE_INFO
  813. ArrayCallSiteInfo *GetArrayCallSiteInfo();
  814. #endif
  815. static uint32 GetOffsetOfArrayCallSiteIndex() { return offsetof(JavascriptNativeArray, arrayCallSiteIndex); }
  816. static uint32 GetOffsetOfWeakFuncRef() { return offsetof(JavascriptNativeArray, weakRefToFuncBody); }
  817. #if ENABLE_PROFILE_INFO
  818. void SetArrayProfileInfo(RecyclerWeakReference<FunctionBody> *weakRef, ArrayCallSiteInfo *arrayInfo);
  819. void CopyArrayProfileInfo(Js::JavascriptNativeArray* baseArray);
  820. #endif
  821. Var FindMinOrMax(Js::ScriptContext * scriptContext, bool findMax);
  822. template<typename T, bool checkNaNAndNegZero> Var FindMinOrMax(Js::ScriptContext * scriptContext, bool findMax); // NativeInt arrays can't have NaNs or -0
  823. static void PopWithNoDst(Var nativeArray);
  824. };
  825. class JavascriptNativeFloatArray;
  826. class JavascriptNativeIntArray : public JavascriptNativeArray
  827. {
  828. friend class JavascriptArray;
  829. public:
  830. static const size_t StackAllocationSize;
  831. protected:
  832. DEFINE_VTABLE_CTOR(JavascriptNativeIntArray, JavascriptNativeArray);
  833. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptNativeIntArray);
  834. public:
  835. JavascriptNativeIntArray(DynamicType * type);
  836. JavascriptNativeIntArray(uint32 length, uint32 size, DynamicType * type);
  837. JavascriptNativeIntArray(DynamicType * type, uint32 size);
  838. protected:
  839. JavascriptNativeIntArray(uint32 length, DynamicType * type) :
  840. JavascriptNativeArray(length, type) {}
  841. // For BoxStackInstance
  842. JavascriptNativeIntArray(JavascriptNativeIntArray * instance, bool boxHead);
  843. public:
  844. static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  845. static Var NewInstance(RecyclableObject* function, Arguments args);
  846. static bool Is(Var aValue);
  847. static bool Is(TypeId typeId);
  848. static JavascriptNativeIntArray* FromVar(Var aValue);
  849. static bool IsNonCrossSite(Var aValue);
  850. typedef int32 TElement;
  851. static const uint8 AllocationBucketsCount = 3;
  852. static uint allocationBuckets[AllocationBucketsCount][AllocationBucketsInfoSize];
  853. static const int32 MissingItem;
  854. virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
  855. virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  856. virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  857. virtual BOOL DirectGetVarItemAt(uint index, Var* outval, ScriptContext *scriptContext);
  858. virtual BOOL DirectGetItemAtFull(uint index, Var* outVal);
  859. virtual Var DirectGetItem(uint32 index);
  860. virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override;
  861. virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
  862. virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
  863. #ifdef VALIDATE_ARRAY
  864. virtual void ValidateArray() override;
  865. #endif
  866. BOOL SetItem(uint32 index, int32 iValue);
  867. static JavascriptNativeFloatArray * ToNativeFloatArray(JavascriptNativeIntArray *intArray);
  868. static JavascriptArray * ToVarArray(JavascriptNativeIntArray *intArray);
  869. static JavascriptArray * ConvertToVarArray(JavascriptNativeIntArray *intArray);
  870. static Var Push(ScriptContext * scriptContext, Var array, int value);
  871. static int32 Pop(ScriptContext * scriptContext, Var nativeIntArray);
  872. #if ENABLE_PROFILE_INFO
  873. virtual JavascriptArray *FillFromArgs(uint length, uint start, Var *args, ArrayCallSiteInfo *info = nullptr, bool dontCreateNewArray = false) override;
  874. #else
  875. virtual JavascriptArray *FillFromArgs(uint length, uint start, Var *args, bool dontCreateNewArray = false) override;
  876. #endif
  877. virtual void ClearElements(SparseArraySegmentBase *seg, uint32 newSegmentLength) override;
  878. virtual void SetIsPrototype() override;
  879. TypeId TrySetNativeIntArrayItem(Var value, int32 *iValue, double *dValue);
  880. virtual bool IsMissingHeadSegmentItem(const uint32 index) const override;
  881. static VTableValue VtableHelper()
  882. {
  883. return VTableValue::VtableNativeIntArray;
  884. }
  885. static LibraryValue InitialTypeHelper()
  886. {
  887. return LibraryValue::ValueNativeIntArrayType;
  888. }
  889. static DynamicType * GetInitialType(ScriptContext * scriptContext);
  890. static JavascriptNativeIntArray * BoxStackInstance(JavascriptNativeIntArray * instance);
  891. private:
  892. virtual int32 HeadSegmentIndexOfHelper(Var search, uint32 &fromIndex, uint32 toIndex, bool includesAlgorithm, ScriptContext * scriptContext) override;
  893. #if ENABLE_TTD
  894. public:
  895. virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override
  896. {
  897. return;
  898. }
  899. virtual void ProcessCorePaths() override
  900. {
  901. return;
  902. }
  903. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  904. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  905. #endif
  906. public:
  907. virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
  908. {
  909. return VtableHelper();
  910. }
  911. };
  912. #if ENABLE_COPYONACCESS_ARRAY
  913. class JavascriptCopyOnAccessNativeIntArray : public JavascriptNativeIntArray
  914. {
  915. friend class JavascriptArray;
  916. public:
  917. static const size_t StackAllocationSize;
  918. protected:
  919. DEFINE_VTABLE_CTOR(JavascriptCopyOnAccessNativeIntArray, JavascriptNativeIntArray);
  920. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptCopyOnAccessNativeIntArray);
  921. public:
  922. JavascriptCopyOnAccessNativeIntArray(uint32 length, DynamicType * type) :
  923. JavascriptNativeIntArray(length, type) {}
  924. virtual BOOL IsCopyOnAccessArray() { return TRUE; }
  925. static bool Is(Var aValue);
  926. static bool Is(TypeId typeId);
  927. static JavascriptCopyOnAccessNativeIntArray* FromVar(Var aValue);
  928. static DynamicType * GetInitialType(ScriptContext * scriptContext);
  929. void ConvertCopyOnAccessSegment();
  930. uint32 GetNextIndex(uint32 index) const;
  931. BOOL DirectGetItemAt(uint32 index, int* outVal);
  932. static VTableValue VtableHelper()
  933. {
  934. return VTableValue::VtableCopyOnAccessNativeIntArray;
  935. }
  936. #if ENABLE_TTD
  937. public:
  938. virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override
  939. {
  940. return;
  941. }
  942. virtual void ProcessCorePaths() override
  943. {
  944. return;
  945. }
  946. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  947. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  948. #endif
  949. public:
  950. virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
  951. {
  952. return VtableHelper();
  953. }
  954. };
  955. #endif
  956. class JavascriptNativeFloatArray : public JavascriptNativeArray
  957. {
  958. friend class JavascriptArray;
  959. public:
  960. static const size_t StackAllocationSize;
  961. protected:
  962. DEFINE_VTABLE_CTOR(JavascriptNativeFloatArray, JavascriptNativeArray);
  963. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptNativeFloatArray);
  964. public:
  965. JavascriptNativeFloatArray(DynamicType * type);
  966. JavascriptNativeFloatArray(uint32 length, uint32 size, DynamicType * type);
  967. JavascriptNativeFloatArray(DynamicType * type, uint32 size);
  968. private:
  969. JavascriptNativeFloatArray(uint32 length, DynamicType * type) :
  970. JavascriptNativeArray(length, type) {}
  971. // For BoxStackInstance
  972. JavascriptNativeFloatArray(JavascriptNativeFloatArray * instance, bool boxHead);
  973. public:
  974. static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  975. static Var NewInstance(RecyclableObject* function, Arguments args);
  976. static bool Is(Var aValue);
  977. static bool Is(TypeId typeId);
  978. static JavascriptNativeFloatArray* FromVar(Var aValue);
  979. static bool IsNonCrossSite(Var aValue);
  980. typedef double TElement;
  981. static const uint8 AllocationBucketsCount = 3;
  982. static uint allocationBuckets[AllocationBucketsCount][AllocationBucketsInfoSize];
  983. static const double MissingItem;
  984. virtual PropertyQueryFlags HasItemQuery(uint32 index) override;
  985. virtual PropertyQueryFlags GetItemQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  986. virtual PropertyQueryFlags GetItemReferenceQuery(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override;
  987. virtual BOOL DirectGetVarItemAt(uint index, Var* outval, ScriptContext *scriptContext);
  988. virtual BOOL DirectGetItemAtFull(uint index, Var* outVal);
  989. virtual Var DirectGetItem(uint32 index);
  990. virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override
  991. {
  992. double value = 0;
  993. return this->DirectGetItemAt(index, &value) ? WritableData : None;
  994. }
  995. virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
  996. virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
  997. #ifdef VALIDATE_ARRAY
  998. virtual void ValidateArray() override;
  999. #endif
  1000. BOOL SetItem(uint32 index, double dValue);
  1001. static JavascriptArray * ToVarArray(JavascriptNativeFloatArray *fArray);
  1002. static JavascriptArray * ConvertToVarArray(JavascriptNativeFloatArray *fArray);
  1003. #if ENABLE_PROFILE_INFO
  1004. virtual JavascriptArray *FillFromArgs(uint length, uint start, Var *args, ArrayCallSiteInfo *info = nullptr, bool dontCreateNewArray = false) override;
  1005. #else
  1006. virtual JavascriptArray *FillFromArgs(uint length, uint start, Var *args, bool dontCreateNewArray = false) override;
  1007. #endif
  1008. virtual void ClearElements(SparseArraySegmentBase *seg, uint32 newSegmentLength) override;
  1009. virtual void SetIsPrototype() override;
  1010. TypeId TrySetNativeFloatArrayItem(Var value, double *dValue);
  1011. virtual bool IsMissingHeadSegmentItem(const uint32 index) const override;
  1012. static VTableValue VtableHelper()
  1013. {
  1014. return VTableValue::VtableNativeFloatArray;
  1015. }
  1016. static LibraryValue InitialTypeHelper()
  1017. {
  1018. return LibraryValue::ValueNativeFloatArrayType;
  1019. }
  1020. static DynamicType * GetInitialType(ScriptContext * scriptContext);
  1021. static Var Push(ScriptContext * scriptContext, Var * nativeFloatArray, double value);
  1022. static JavascriptNativeFloatArray * BoxStackInstance(JavascriptNativeFloatArray * instance);
  1023. static double Pop(ScriptContext * scriptContext, Var nativeFloatArray);
  1024. private:
  1025. virtual int32 HeadSegmentIndexOfHelper(Var search, uint32 &fromIndex, uint32 toIndex, bool includesAlgorithm, ScriptContext * scriptContext) override;
  1026. #if ENABLE_TTD
  1027. public:
  1028. virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override
  1029. {
  1030. return;
  1031. }
  1032. virtual void ProcessCorePaths() override
  1033. {
  1034. return;
  1035. }
  1036. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  1037. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  1038. #endif
  1039. public:
  1040. virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
  1041. {
  1042. return VtableHelper();
  1043. }
  1044. };
  1045. template <>
  1046. inline bool JavascriptArray::MayChangeType<JavascriptNativeIntArray>() { return true; }
  1047. template <>
  1048. inline bool JavascriptArray::MayChangeType<JavascriptNativeFloatArray>() { return true; }
  1049. template <>
  1050. inline uint32 JavascriptArray::ConvertToIndex<uint32, uint32>(uint32 idxDest, ScriptContext* scriptContext) { return idxDest; }
  1051. } // namespace Js