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