1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_ELEMENTS_H_
29#define V8_ELEMENTS_H_
30
31#include "objects.h"
32#include "heap.h"
33#include "isolate.h"
34
35namespace v8 {
36namespace internal {
37
38// Abstract base class for handles that can operate on objects with differing
39// ElementsKinds.
40class ElementsAccessor {
41 public:
42  explicit ElementsAccessor(const char* name) : name_(name) { }
43  virtual ~ElementsAccessor() { }
44
45  virtual ElementsKind kind() const = 0;
46  const char* name() const { return name_; }
47
48  // Returns true if a holder contains an element with the specified key
49  // without iterating up the prototype chain.  The caller can optionally pass
50  // in the backing store to use for the check, which must be compatible with
51  // the ElementsKind of the ElementsAccessor. If backing_store is NULL, the
52  // holder->elements() is used as the backing store.
53  virtual bool HasElement(Object* receiver,
54                          JSObject* holder,
55                          uint32_t key,
56                          FixedArrayBase* backing_store = NULL) = 0;
57
58  // Returns the element with the specified key or undefined if there is no such
59  // element. This method doesn't iterate up the prototype chain.  The caller
60  // can optionally pass in the backing store to use for the check, which must
61  // be compatible with the ElementsKind of the ElementsAccessor. If
62  // backing_store is NULL, the holder->elements() is used as the backing store.
63  virtual MaybeObject* Get(Object* receiver,
64                           JSObject* holder,
65                           uint32_t key,
66                           FixedArrayBase* backing_store = NULL) = 0;
67
68  // Modifies the length data property as specified for JSArrays and resizes the
69  // underlying backing store accordingly. The method honors the semantics of
70  // changing array sizes as defined in EcmaScript 5.1 15.4.5.2, i.e. array that
71  // have non-deletable elements can only be shrunk to the size of highest
72  // element that is non-deletable.
73  virtual MaybeObject* SetLength(JSArray* holder,
74                                 Object* new_length) = 0;
75
76  // Modifies both the length and capacity of a JSArray, resizing the underlying
77  // backing store as necessary. This method does NOT honor the semantics of
78  // EcmaScript 5.1 15.4.5.2, arrays can be shrunk beyond non-deletable
79  // elements. This method should only be called for array expansion OR by
80  // runtime JavaScript code that use InternalArrays and don't care about
81  // EcmaScript 5.1 semantics.
82  virtual MaybeObject* SetCapacityAndLength(JSArray* array,
83                                            int capacity,
84                                            int length) = 0;
85
86  // Deletes an element in an object, returning a new elements backing store.
87  virtual MaybeObject* Delete(JSObject* holder,
88                              uint32_t key,
89                              JSReceiver::DeleteMode mode) = 0;
90
91  // If kCopyToEnd is specified as the copy_size to CopyElements, it copies all
92  // of elements from source after source_start to the destination array.
93  static const int kCopyToEnd = -1;
94  // If kCopyToEndAndInitializeToHole is specified as the copy_size to
95  // CopyElements, it copies all of elements from source after source_start to
96  // destination array, padding any remaining uninitialized elements in the
97  // destination array with the hole.
98  static const int kCopyToEndAndInitializeToHole = -2;
99
100  // Copy elements from one backing store to another. Typically, callers specify
101  // the source JSObject or JSArray in source_holder. If the holder's backing
102  // store is available, it can be passed in source and source_holder is
103  // ignored.
104  virtual MaybeObject* CopyElements(JSObject* source_holder,
105                                    uint32_t source_start,
106                                    FixedArrayBase* destination,
107                                    ElementsKind destination_kind,
108                                    uint32_t destination_start,
109                                    int copy_size,
110                                    FixedArrayBase* source = NULL) = 0;
111
112  MaybeObject* CopyElements(JSObject* from_holder,
113                            FixedArrayBase* to,
114                            ElementsKind to_kind,
115                            FixedArrayBase* from = NULL) {
116    return CopyElements(from_holder, 0, to, to_kind, 0,
117                        kCopyToEndAndInitializeToHole, from);
118  }
119
120  virtual MaybeObject* AddElementsToFixedArray(Object* receiver,
121                                               JSObject* holder,
122                                               FixedArray* to,
123                                               FixedArrayBase* from = NULL) = 0;
124
125  // Returns a shared ElementsAccessor for the specified ElementsKind.
126  static ElementsAccessor* ForKind(ElementsKind elements_kind) {
127    ASSERT(elements_kind < kElementsKindCount);
128    return elements_accessors_[elements_kind];
129  }
130
131  static ElementsAccessor* ForArray(FixedArrayBase* array);
132
133  static void InitializeOncePerProcess();
134
135 protected:
136  friend class NonStrictArgumentsElementsAccessor;
137
138  virtual uint32_t GetCapacity(FixedArrayBase* backing_store) = 0;
139
140  // Element handlers distinguish between indexes and keys when they manipulate
141  // elements.  Indexes refer to elements in terms of their location in the
142  // underlying storage's backing store representation, and are between 0 and
143  // GetCapacity.  Keys refer to elements in terms of the value that would be
144  // specified in JavaScript to access the element. In most implementations,
145  // keys are equivalent to indexes, and GetKeyForIndex returns the same value
146  // it is passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps
147  // the index to a key using the KeyAt method on the NumberDictionary.
148  virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
149                                  uint32_t index) = 0;
150
151 private:
152  static ElementsAccessor** elements_accessors_;
153  const char* name_;
154
155  DISALLOW_COPY_AND_ASSIGN(ElementsAccessor);
156};
157
158
159void CopyObjectToObjectElements(FixedArray* from_obj,
160                                ElementsKind from_kind,
161                                uint32_t from_start,
162                                FixedArray* to_obj,
163                                ElementsKind to_kind,
164                                uint32_t to_start,
165                                int copy_size);
166
167
168} }  // namespace v8::internal
169
170#endif  // V8_ELEMENTS_H_
171