blob: 0a660261c58735e2fe8511e2ff8903caf919bdd5 [file] [log] [blame]
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001// 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_TRANSITIONS_H_
29#define V8_TRANSITIONS_H_
30
31#include "elements-kind.h"
32#include "heap.h"
33#include "isolate.h"
34#include "objects.h"
35#include "v8checks.h"
36
37namespace v8 {
38namespace internal {
39
40
41// TransitionArrays are fixed arrays used to hold map transitions for property,
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000042// constant, and element changes. They can either be simple transition arrays
43// that store a single property transition, or a full transition array that has
44// space for elements transitions, prototype transitions and multiple property
45// transitons. The details related to property transitions are accessed in the
46// descriptor array of the target map. In the case of a simple transition, the
47// key is also read from the descriptor array of the target map.
48//
49// The simple format of the these objects is:
50// [0] Undefined or back pointer map
51// [1] Single transition
52//
53// The full format is:
54// [0] Undefined or back pointer map
55// [1] Smi(0) or elements transition map
56// [2] Smi(0) or fixed array of prototype transitions
57// [3] First transition
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000058// [length() - kTransitionSize] Last transition
59class TransitionArray: public FixedArray {
60 public:
danno@chromium.org81cac2b2012-07-10 11:28:27 +000061 // Accessors for fetching instance transition at transition number.
62 inline String* GetKey(int transition_number);
63 inline void SetKey(int transition_number, String* value);
64 inline Object** GetKeySlot(int transition_number);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000065 int GetSortedKeyIndex(int transition_number) { return transition_number; }
66
67 String* GetSortedKey(int transition_number) {
68 return GetKey(transition_number);
69 }
danno@chromium.org81cac2b2012-07-10 11:28:27 +000070
verwaest@chromium.org753aee42012-07-17 16:15:42 +000071 inline Map* GetTarget(int transition_number);
72 inline void SetTarget(int transition_number, Map* target);
danno@chromium.org81cac2b2012-07-10 11:28:27 +000073
danno@chromium.org81cac2b2012-07-10 11:28:27 +000074 inline PropertyDetails GetTargetDetails(int transition_number);
75
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000076 inline Map* elements_transition();
77 inline void set_elements_transition(
verwaest@chromium.org753aee42012-07-17 16:15:42 +000078 Map* target,
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000079 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000080 inline bool HasElementsTransition();
danno@chromium.org81cac2b2012-07-10 11:28:27 +000081 inline void ClearElementsTransition();
82
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000083 inline Object* back_pointer_storage();
84 inline void set_back_pointer_storage(
85 Object* back_pointer,
86 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
87
danno@chromium.org81cac2b2012-07-10 11:28:27 +000088 inline FixedArray* GetPrototypeTransitions();
89 inline void SetPrototypeTransitions(
90 FixedArray* prototype_transitions,
91 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
92 inline Object** GetPrototypeTransitionsSlot();
93 inline bool HasPrototypeTransitions();
94 inline HeapObject* UncheckedPrototypeTransitions();
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000095
96 // Returns the number of transitions in the array.
97 int number_of_transitions() {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000098 if (IsSimpleTransition()) return 1;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000099 int len = length();
100 return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kTransitionSize;
101 }
102
103 inline int number_of_entries() { return number_of_transitions(); }
104
105 // Allocate a new transition array with a single entry.
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000106 static MUST_USE_RESULT MaybeObject* NewWith(
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000107 SimpleTransitionFlag flag,
108 String* key,
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000109 Map* target,
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000110 Object* back_pointer);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000111
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000112 MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
113
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000114 // Copy the transition array, inserting a new transition.
115 // TODO(verwaest): This should not cause an existing transition to be
116 // overwritten.
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000117 MUST_USE_RESULT MaybeObject* CopyInsert(String* name, Map* target);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000118
119 // Copy a single transition from the origin array.
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000120 inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
121 int origin_transition,
122 int target_transition);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000123
124 // Search a transition for a given property name.
125 inline int Search(String* name);
126
127 // Allocates a TransitionArray.
jkummerow@chromium.orgc1956672012-10-11 15:57:38 +0000128 MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000129
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000130 bool IsSimpleTransition() { return length() == kSimpleTransitionSize; }
131 bool IsFullTransitionArray() { return length() >= kFirstIndex; }
132
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000133 // Casting.
134 static inline TransitionArray* cast(Object* obj);
135
136 // Constant for denoting key was not found.
137 static const int kNotFound = -1;
138
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000139 static const int kBackPointerStorageIndex = 0;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000140
141 // Layout for full transition arrays.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000142 static const int kElementsTransitionIndex = 1;
143 static const int kPrototypeTransitionsIndex = 2;
144 static const int kFirstIndex = 3;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000145
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000146 // Layout for simple transition arrays.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000147 static const int kSimpleTransitionTarget = 1;
148 static const int kSimpleTransitionSize = 2;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000149 static const int kSimpleTransitionIndex = 0;
150 STATIC_ASSERT(kSimpleTransitionIndex != kNotFound);
151
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000152 static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000153
154 // Layout for the full transition array header.
verwaest@chromium.orgde64f722012-08-16 15:44:54 +0000155 static const int kElementsTransitionOffset = kBackPointerStorageOffset +
156 kPointerSize;
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000157 static const int kPrototypeTransitionsOffset = kElementsTransitionOffset +
158 kPointerSize;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000159
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000160 // Layout of map transition entries in full transition arrays.
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000161 static const int kTransitionKey = 0;
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000162 static const int kTransitionTarget = 1;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000163 static const int kTransitionSize = 2;
164
165#ifdef OBJECT_PRINT
166 // Print all the transitions.
167 inline void PrintTransitions() {
168 PrintTransitions(stdout);
169 }
170 void PrintTransitions(FILE* out);
171#endif
172
173#ifdef DEBUG
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000174 bool IsSortedNoDuplicates(int valid_entries = -1);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000175 bool IsConsistentWithBackPointers(Map* current_map);
176 bool IsEqualTo(TransitionArray* other);
177#endif
178
179 // The maximum number of transitions we want in a transition array (should
180 // fit in a page).
181 static const int kMaxNumberOfTransitions = 1024 + 512;
182
183 private:
184 // Conversion from transition number to array indices.
185 static int ToKeyIndex(int transition_number) {
186 return kFirstIndex +
187 (transition_number * kTransitionSize) +
188 kTransitionKey;
189 }
190
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000191 static int ToTargetIndex(int transition_number) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000192 return kFirstIndex +
193 (transition_number * kTransitionSize) +
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000194 kTransitionTarget;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000195 }
196
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000197 inline void NoIncrementalWriteBarrierSet(int transition_number,
198 String* key,
199 Map* target);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000200
201 DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
202};
203
204
205} } // namespace v8::internal
206
207#endif // V8_TRANSITIONS_H_