blob: b2e98396784a7d4ff6b7a9f2ceaac73e71047ecd [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
danno@chromium.orgd3c42102013-08-01 16:58:23 +000044// prototype transitions and multiple property transitons. The details related
45// to property transitions are accessed in the descriptor array of the target
46// map. In the case of a simple transition, the key is also read from the
47// descriptor array of the target map.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000048//
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
danno@chromium.orgd3c42102013-08-01 16:58:23 +000055// [1] Smi(0) or fixed array of prototype transitions
56// [2] First transition
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000057// [length() - kTransitionSize] Last transition
58class TransitionArray: public FixedArray {
59 public:
danno@chromium.org81cac2b2012-07-10 11:28:27 +000060 // Accessors for fetching instance transition at transition number.
ulan@chromium.org750145a2013-03-07 15:14:13 +000061 inline Name* GetKey(int transition_number);
62 inline void SetKey(int transition_number, Name* value);
danno@chromium.org81cac2b2012-07-10 11:28:27 +000063 inline Object** GetKeySlot(int transition_number);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000064 int GetSortedKeyIndex(int transition_number) { return transition_number; }
65
ulan@chromium.org750145a2013-03-07 15:14:13 +000066 Name* GetSortedKey(int transition_number) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000067 return GetKey(transition_number);
68 }
danno@chromium.org81cac2b2012-07-10 11:28:27 +000069
verwaest@chromium.org753aee42012-07-17 16:15:42 +000070 inline Map* GetTarget(int transition_number);
71 inline void SetTarget(int transition_number, Map* target);
danno@chromium.org81cac2b2012-07-10 11:28:27 +000072
danno@chromium.org81cac2b2012-07-10 11:28:27 +000073 inline PropertyDetails GetTargetDetails(int transition_number);
74
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000075 inline bool HasElementsTransition();
danno@chromium.org81cac2b2012-07-10 11:28:27 +000076
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000077 inline Object* back_pointer_storage();
78 inline void set_back_pointer_storage(
79 Object* back_pointer,
80 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
81
danno@chromium.org81cac2b2012-07-10 11:28:27 +000082 inline FixedArray* GetPrototypeTransitions();
83 inline void SetPrototypeTransitions(
84 FixedArray* prototype_transitions,
85 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
86 inline Object** GetPrototypeTransitionsSlot();
87 inline bool HasPrototypeTransitions();
88 inline HeapObject* UncheckedPrototypeTransitions();
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000089
90 // Returns the number of transitions in the array.
91 int number_of_transitions() {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000092 if (IsSimpleTransition()) return 1;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +000093 int len = length();
94 return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kTransitionSize;
95 }
96
97 inline int number_of_entries() { return number_of_transitions(); }
98
99 // Allocate a new transition array with a single entry.
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000100 static MUST_USE_RESULT MaybeObject* NewWith(
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000101 SimpleTransitionFlag flag,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000102 Name* key,
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000103 Map* target,
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000104 Object* back_pointer);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000105
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000106 MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
107
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000108 // Copy the transition array, inserting a new transition.
109 // TODO(verwaest): This should not cause an existing transition to be
110 // overwritten.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000111 MUST_USE_RESULT MaybeObject* CopyInsert(Name* name, Map* target);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000112
113 // Copy a single transition from the origin array.
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000114 inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
115 int origin_transition,
116 int target_transition);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000117
118 // Search a transition for a given property name.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000119 inline int Search(Name* name);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000120
121 // Allocates a TransitionArray.
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +0000122 MUST_USE_RESULT static MaybeObject* Allocate(
123 Isolate* isolate, int number_of_transitions);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000124
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000125 bool IsSimpleTransition() {
126 return length() == kSimpleTransitionSize &&
127 get(kSimpleTransitionTarget)->IsHeapObject() &&
128 // The IntrusivePrototypeTransitionIterator may have set the map of the
129 // prototype transitions array to a smi. In that case, there are
130 // prototype transitions, hence this transition array is a full
131 // transition array.
132 HeapObject::cast(get(kSimpleTransitionTarget))->map()->IsMap() &&
133 get(kSimpleTransitionTarget)->IsMap();
134 }
135
136 bool IsFullTransitionArray() {
137 return length() > kFirstIndex ||
138 (length() == kFirstIndex && !IsSimpleTransition());
139 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000140
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000141 // Casting.
142 static inline TransitionArray* cast(Object* obj);
143
144 // Constant for denoting key was not found.
145 static const int kNotFound = -1;
146
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000147 static const int kBackPointerStorageIndex = 0;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000148
149 // Layout for full transition arrays.
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000150 static const int kPrototypeTransitionsIndex = 1;
151 static const int kFirstIndex = 2;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000152
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000153 // Layout for simple transition arrays.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000154 static const int kSimpleTransitionTarget = 1;
155 static const int kSimpleTransitionSize = 2;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000156 static const int kSimpleTransitionIndex = 0;
157 STATIC_ASSERT(kSimpleTransitionIndex != kNotFound);
158
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000159 static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000160
161 // Layout for the full transition array header.
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000162 static const int kPrototypeTransitionsOffset = kBackPointerStorageOffset +
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000163 kPointerSize;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000164
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000165 // Layout of map transition entries in full transition arrays.
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000166 static const int kTransitionKey = 0;
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000167 static const int kTransitionTarget = 1;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000168 static const int kTransitionSize = 2;
169
170#ifdef OBJECT_PRINT
171 // Print all the transitions.
172 inline void PrintTransitions() {
173 PrintTransitions(stdout);
174 }
175 void PrintTransitions(FILE* out);
176#endif
177
178#ifdef DEBUG
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000179 bool IsSortedNoDuplicates(int valid_entries = -1);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000180 bool IsConsistentWithBackPointers(Map* current_map);
181 bool IsEqualTo(TransitionArray* other);
182#endif
183
184 // The maximum number of transitions we want in a transition array (should
185 // fit in a page).
186 static const int kMaxNumberOfTransitions = 1024 + 512;
187
188 private:
189 // Conversion from transition number to array indices.
190 static int ToKeyIndex(int transition_number) {
191 return kFirstIndex +
192 (transition_number * kTransitionSize) +
193 kTransitionKey;
194 }
195
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000196 static int ToTargetIndex(int transition_number) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000197 return kFirstIndex +
198 (transition_number * kTransitionSize) +
verwaest@chromium.org753aee42012-07-17 16:15:42 +0000199 kTransitionTarget;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000200 }
201
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000202 inline void NoIncrementalWriteBarrierSet(int transition_number,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000203 Name* key,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000204 Map* target);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000205
206 DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
207};
208
209
210} } // namespace v8::internal
211
212#endif // V8_TRANSITIONS_H_