13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Redistribution and use in source and binary forms, with or without 369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// modification, are permitted provided that the following conditions are 469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// met: 569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// 669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// * Redistributions of source code must retain the above copyright 769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// notice, this list of conditions and the following disclaimer. 869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// * Redistributions in binary form must reproduce the above 969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// copyright notice, this list of conditions and the following 1069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// disclaimer in the documentation and/or other materials provided 1169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// with the distribution. 1269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// * Neither the name of Google Inc. nor the names of its 1369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// contributors may be used to endorse or promote products derived 1469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// from this software without specific prior written permission. 1569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// 1669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 2869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#ifndef V8_ELEMENTS_H_ 2969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define V8_ELEMENTS_H_ 3069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 3169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "objects.h" 323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "heap.h" 333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "isolate.h" 3469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 3569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochnamespace v8 { 3669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochnamespace internal { 3769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 3869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Abstract base class for handles that can operate on objects with differing 3969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// ElementsKinds. 4069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ElementsAccessor { 4169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public: 423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch explicit ElementsAccessor(const char* name) : name_(name) { } 4369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch virtual ~ElementsAccessor() { } 4485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual ElementsKind kind() const = 0; 463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const char* name() const { return name_; } 473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returns true if a holder contains an element with the specified key 493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // without iterating up the prototype chain. The caller can optionally pass 503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the backing store to use for the check, which must be compatible with 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the ElementsKind of the ElementsAccessor. If backing_store is NULL, the 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // holder->elements() is used as the backing store. 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual bool HasElement(Object* receiver, 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject* holder, 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t key, 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* backing_store = NULL) = 0; 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returns the element with the specified key or undefined if there is no such 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // element. This method doesn't iterate up the prototype chain. The caller 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // can optionally pass in the backing store to use for the check, which must 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // be compatible with the ElementsKind of the ElementsAccessor. If 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // backing_store is NULL, the holder->elements() is used as the backing store. 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual MaybeObject* Get(Object* receiver, 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject* holder, 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t key, 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* backing_store = NULL) = 0; 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Modifies the length data property as specified for JSArrays and resizes the 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // underlying backing store accordingly. The method honors the semantics of 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // changing array sizes as defined in EcmaScript 5.1 15.4.5.2, i.e. array that 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // have non-deletable elements can only be shrunk to the size of highest 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // element that is non-deletable. 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual MaybeObject* SetLength(JSArray* holder, 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Object* new_length) = 0; 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Modifies both the length and capacity of a JSArray, resizing the underlying 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // backing store as necessary. This method does NOT honor the semantics of 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // EcmaScript 5.1 15.4.5.2, arrays can be shrunk beyond non-deletable 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements. This method should only be called for array expansion OR by 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // runtime JavaScript code that use InternalArrays and don't care about 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // EcmaScript 5.1 semantics. 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual MaybeObject* SetCapacityAndLength(JSArray* array, 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int capacity, 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length) = 0; 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Deletes an element in an object, returning a new elements backing store. 8769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch virtual MaybeObject* Delete(JSObject* holder, 8869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch uint32_t key, 8969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch JSReceiver::DeleteMode mode) = 0; 9069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If kCopyToEnd is specified as the copy_size to CopyElements, it copies all 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of elements from source after source_start to the destination array. 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kCopyToEnd = -1; 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If kCopyToEndAndInitializeToHole is specified as the copy_size to 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CopyElements, it copies all of elements from source after source_start to 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // destination array, padding any remaining uninitialized elements in the 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // destination array with the hole. 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kCopyToEndAndInitializeToHole = -2; 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy elements from one backing store to another. Typically, callers specify 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the source JSObject or JSArray in source_holder. If the holder's backing 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // store is available, it can be passed in source and source_holder is 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ignored. 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual MaybeObject* CopyElements(JSObject* source_holder, 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t source_start, 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* destination, 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind destination_kind, 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t destination_start, 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int copy_size, 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* source = NULL) = 0; 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MaybeObject* CopyElements(JSObject* from_holder, 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* to, 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind to_kind, 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* from = NULL) { 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return CopyElements(from_holder, 0, to, to_kind, 0, 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kCopyToEndAndInitializeToHole, from); 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual MaybeObject* AddElementsToFixedArray(Object* receiver, 12185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch JSObject* holder, 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray* to, 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase* from = NULL) = 0; 12469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 12569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Returns a shared ElementsAccessor for the specified ElementsKind. 126589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static ElementsAccessor* ForKind(ElementsKind elements_kind) { 127589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(elements_kind < kElementsKindCount); 12869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return elements_accessors_[elements_kind]; 12969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 13069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 13169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static ElementsAccessor* ForArray(FixedArrayBase* array); 13269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 13369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static void InitializeOncePerProcess(); 13469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 13569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected: 13669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch friend class NonStrictArgumentsElementsAccessor; 13769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 13869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch virtual uint32_t GetCapacity(FixedArrayBase* backing_store) = 0; 13969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Element handlers distinguish between indexes and keys when they manipulate 14169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // elements. Indexes refer to elements in terms of their location in the 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // underlying storage's backing store representation, and are between 0 and 14369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // GetCapacity. Keys refer to elements in terms of the value that would be 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // specified in JavaScript to access the element. In most implementations, 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // keys are equivalent to indexes, and GetKeyForIndex returns the same value 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it is passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the index to a key using the KeyAt method on the NumberDictionary. 14869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, 14969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch uint32_t index) = 0; 15069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 15169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private: 15269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static ElementsAccessor** elements_accessors_; 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const char* name_; 15469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 15569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DISALLOW_COPY_AND_ASSIGN(ElementsAccessor); 15669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}; 15769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CopyObjectToObjectElements(FixedArray* from_obj, 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind from_kind, 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t from_start, 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray* to_obj, 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind to_kind, 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t to_start, 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int copy_size); 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} } // namespace v8::internal 16969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 17069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#endif // V8_ELEMENTS_H_ 171