Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(455)

Side by Side Diff: src/property.h

Issue 10697015: Separating transitions from descriptors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Using WhitenessWitness in TransitionArray code. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.cc ('k') | src/property.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifndef V8_PROPERTY_H_ 28 #ifndef V8_PROPERTY_H_
29 #define V8_PROPERTY_H_ 29 #define V8_PROPERTY_H_
30 30
31 #include "allocation.h" 31 #include "allocation.h"
32 #include "transitions.h"
32 33
33 namespace v8 { 34 namespace v8 {
34 namespace internal { 35 namespace internal {
35 36
36 37
37 // Abstraction for elements in instance-descriptor arrays. 38 // Abstraction for elements in instance-descriptor arrays.
38 // 39 //
39 // Each descriptor has a key, property attributes, property type, 40 // Each descriptor has a key, property attributes, property type,
40 // property index (in the actual instance-descriptor array) and 41 // property index (in the actual instance-descriptor array) and
41 // optionally a piece of data. 42 // optionally a piece of data.
(...skipping 19 matching lines...) Expand all
61 62
62 #ifdef OBJECT_PRINT 63 #ifdef OBJECT_PRINT
63 void Print(FILE* out); 64 void Print(FILE* out);
64 #endif 65 #endif
65 66
66 void SetEnumerationIndex(int index) { 67 void SetEnumerationIndex(int index) {
67 ASSERT(PropertyDetails::IsValidIndex(index)); 68 ASSERT(PropertyDetails::IsValidIndex(index));
68 details_ = PropertyDetails(details_.attributes(), details_.type(), index); 69 details_ = PropertyDetails(details_.attributes(), details_.type(), index);
69 } 70 }
70 71
71 bool ContainsTransition();
72
73 private: 72 private:
74 String* key_; 73 String* key_;
75 Object* value_; 74 Object* value_;
76 PropertyDetails details_; 75 PropertyDetails details_;
77 76
78 protected: 77 protected:
79 Descriptor() : details_(Smi::FromInt(0)) {} 78 Descriptor() : details_(Smi::FromInt(0)) {}
80 79
81 void Init(String* key, Object* value, PropertyDetails details) { 80 void Init(String* key, Object* value, PropertyDetails details) {
82 key_ = key; 81 key_ = key;
(...skipping 11 matching lines...) Expand all
94 PropertyAttributes attributes, 93 PropertyAttributes attributes,
95 PropertyType type, 94 PropertyType type,
96 int index = 0) 95 int index = 0)
97 : key_(key), 96 : key_(key),
98 value_(value), 97 value_(value),
99 details_(attributes, type, index) { } 98 details_(attributes, type, index) { }
100 99
101 friend class DescriptorArray; 100 friend class DescriptorArray;
102 }; 101 };
103 102
104 // A pointer from a map to the new map that is created by adding
105 // a named property. These are key to the speed and functioning of V8.
106 // The two maps should always have the same prototype, since
107 // MapSpace::CreateBackPointers depends on this.
108 class MapTransitionDescriptor: public Descriptor {
109 public:
110 MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
111 : Descriptor(key, map, attributes, MAP_TRANSITION) { }
112 };
113
114 // Marks a field name in a map so that adding the field is guaranteed
115 // to create a FIELD descriptor in the new map. Used after adding
116 // a constant function the first time, creating a CONSTANT_FUNCTION
117 // descriptor in the new map. This avoids creating multiple maps with
118 // the same CONSTANT_FUNCTION field.
119 class ConstTransitionDescriptor: public Descriptor {
120 public:
121 explicit ConstTransitionDescriptor(String* key, Map* map)
122 : Descriptor(key, map, NONE, CONSTANT_TRANSITION) { }
123 };
124
125 103
126 class FieldDescriptor: public Descriptor { 104 class FieldDescriptor: public Descriptor {
127 public: 105 public:
128 FieldDescriptor(String* key, 106 FieldDescriptor(String* key,
129 int field_index, 107 int field_index,
130 PropertyAttributes attributes, 108 PropertyAttributes attributes,
131 int index = 0) 109 int index = 0)
132 : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {} 110 : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
133 }; 111 };
134 112
(...skipping 11 matching lines...) Expand all
146 class CallbacksDescriptor: public Descriptor { 124 class CallbacksDescriptor: public Descriptor {
147 public: 125 public:
148 CallbacksDescriptor(String* key, 126 CallbacksDescriptor(String* key,
149 Object* foreign, 127 Object* foreign,
150 PropertyAttributes attributes, 128 PropertyAttributes attributes,
151 int index = 0) 129 int index = 0)
152 : Descriptor(key, foreign, attributes, CALLBACKS, index) {} 130 : Descriptor(key, foreign, attributes, CALLBACKS, index) {}
153 }; 131 };
154 132
155 133
156 template <class T>
157 bool IsPropertyDescriptor(T* desc) {
158 switch (desc->type()) {
159 case NORMAL:
160 case FIELD:
161 case CONSTANT_FUNCTION:
162 case HANDLER:
163 case INTERCEPTOR:
164 return true;
165 case CALLBACKS: {
166 Object* callback_object = desc->GetCallbackObject();
167 // Non-JavaScript (i.e. native) accessors are always a property, otherwise
168 // either the getter or the setter must be an accessor. Put another way:
169 // If we only see map transitions and holes in a pair, this is not a
170 // property.
171 return (!callback_object->IsAccessorPair() ||
172 AccessorPair::cast(callback_object)->ContainsAccessor());
173 }
174 case MAP_TRANSITION:
175 case CONSTANT_TRANSITION:
176 return false;
177 case NONEXISTENT:
178 UNREACHABLE();
179 break;
180 }
181 UNREACHABLE(); // keep the compiler happy
182 return false;
183 }
184
185
186 class LookupResult BASE_EMBEDDED { 134 class LookupResult BASE_EMBEDDED {
187 public: 135 public:
188 explicit LookupResult(Isolate* isolate) 136 explicit LookupResult(Isolate* isolate)
189 : isolate_(isolate), 137 : isolate_(isolate),
190 next_(isolate->top_lookup_result()), 138 next_(isolate->top_lookup_result()),
191 lookup_type_(NOT_FOUND), 139 lookup_type_(NOT_FOUND),
192 holder_(NULL), 140 holder_(NULL),
193 cacheable_(true), 141 cacheable_(true),
194 details_(NONE, NONEXISTENT) { 142 details_(NONE, NONEXISTENT) {
195 isolate->SetTopLookupResult(this); 143 isolate->SetTopLookupResult(this);
196 } 144 }
197 145
198 ~LookupResult() { 146 ~LookupResult() {
199 ASSERT(isolate_->top_lookup_result() == this); 147 ASSERT(isolate_->top_lookup_result() == this);
200 isolate_->SetTopLookupResult(next_); 148 isolate_->SetTopLookupResult(next_);
201 } 149 }
202 150
203 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) { 151 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
204 lookup_type_ = DESCRIPTOR_TYPE; 152 lookup_type_ = DESCRIPTOR_TYPE;
205 holder_ = holder; 153 holder_ = holder;
206 details_ = details; 154 details_ = details;
207 number_ = number; 155 number_ = number;
208 } 156 }
209 157
158 void TransitionResult(JSObject* holder, int number) {
159 lookup_type_ = TRANSITION_TYPE;
160 details_ = PropertyDetails(NONE, TRANSITION);
161 holder_ = holder;
162 number_ = number;
163 }
164
210 void ConstantResult(JSObject* holder) { 165 void ConstantResult(JSObject* holder) {
211 lookup_type_ = CONSTANT_TYPE; 166 lookup_type_ = CONSTANT_TYPE;
212 holder_ = holder; 167 holder_ = holder;
213 details_ = 168 details_ =
214 PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM | 169 PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
215 DONT_DELETE), 170 DONT_DELETE),
216 CALLBACKS); 171 CALLBACKS);
217 number_ = -1; 172 number_ = -1;
218 } 173 }
219 174
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 ASSERT(IsFound()); 207 ASSERT(IsFound());
253 return JSProxy::cast(holder_); 208 return JSProxy::cast(holder_);
254 } 209 }
255 210
256 PropertyType type() { 211 PropertyType type() {
257 ASSERT(IsFound()); 212 ASSERT(IsFound());
258 return details_.type(); 213 return details_.type();
259 } 214 }
260 215
261 PropertyAttributes GetAttributes() { 216 PropertyAttributes GetAttributes() {
217 ASSERT(!IsTransition());
262 ASSERT(IsFound()); 218 ASSERT(IsFound());
219 ASSERT(details_.type() != NONEXISTENT);
263 return details_.attributes(); 220 return details_.attributes();
264 } 221 }
265 222
266 PropertyDetails GetPropertyDetails() { 223 PropertyDetails GetPropertyDetails() {
224 ASSERT(!IsTransition());
267 return details_; 225 return details_;
268 } 226 }
269 227
270 bool IsFastPropertyType() { 228 bool IsFastPropertyType() {
271 ASSERT(IsFound()); 229 ASSERT(IsFound());
272 return type() != NORMAL; 230 return IsTransition() || type() != NORMAL;
231 }
232
233 // Property callbacks does not include transitions to callbacks.
234 bool IsPropertyCallbacks() {
235 ASSERT(!(details_.type() == CALLBACKS && !IsFound()));
236 return details_.type() == CALLBACKS;
237 }
238
239 // Is callbacks contains both property callbacks and transitions to callbacks.
240 bool IsCallbacks() {
241 return IsPropertyCallbacks() ||
242 (IsTransition() && GetTransitionValue()->IsAccessorPair());
273 } 243 }
274 244
275 bool IsReadOnly() { 245 bool IsReadOnly() {
276 ASSERT(IsFound()); 246 ASSERT(IsFound());
247 ASSERT(!IsTransition());
248 ASSERT(details_.type() != NONEXISTENT);
277 return details_.IsReadOnly(); 249 return details_.IsReadOnly();
278 } 250 }
279 251
280 bool IsCallbacks() {
281 ASSERT(!(details_.type() == CALLBACKS && !IsFound()));
282 return details_.type() == CALLBACKS;
283 }
284
285 bool IsField() { 252 bool IsField() {
286 ASSERT(!(details_.type() == FIELD && !IsFound())); 253 ASSERT(!(details_.type() == FIELD && !IsFound()));
287 return details_.type() == FIELD; 254 return details_.type() == FIELD;
288 } 255 }
289 256
290 bool IsNormal() { 257 bool IsNormal() {
291 ASSERT(!(details_.type() == NORMAL && !IsFound())); 258 ASSERT(!(details_.type() == NORMAL && !IsFound()));
292 return details_.type() == NORMAL; 259 return details_.type() == NORMAL;
293 } 260 }
294 261
295 bool IsConstantFunction() { 262 bool IsConstantFunction() {
296 ASSERT(!(details_.type() == CONSTANT_FUNCTION && !IsFound())); 263 ASSERT(!(details_.type() == CONSTANT_FUNCTION && !IsFound()));
297 return details_.type() == CONSTANT_FUNCTION; 264 return details_.type() == CONSTANT_FUNCTION;
298 } 265 }
299 266
300 bool IsMapTransition() {
301 ASSERT(!(details_.type() == MAP_TRANSITION && !IsFound()));
302 return details_.type() == MAP_TRANSITION;
303 }
304
305 bool IsDontDelete() { return details_.IsDontDelete(); } 267 bool IsDontDelete() { return details_.IsDontDelete(); }
306 bool IsDontEnum() { return details_.IsDontEnum(); } 268 bool IsDontEnum() { return details_.IsDontEnum(); }
307 bool IsDeleted() { return details_.IsDeleted(); } 269 bool IsDeleted() { return details_.IsDeleted(); }
308 bool IsFound() { return lookup_type_ != NOT_FOUND; } 270 bool IsFound() { return lookup_type_ != NOT_FOUND; }
271 bool IsTransition() { return lookup_type_ == TRANSITION_TYPE; }
309 bool IsHandler() { return lookup_type_ == HANDLER_TYPE; } 272 bool IsHandler() { return lookup_type_ == HANDLER_TYPE; }
310 bool IsInterceptor() { return lookup_type_ == INTERCEPTOR_TYPE; } 273 bool IsInterceptor() { return lookup_type_ == INTERCEPTOR_TYPE; }
311 274
312 // Is the result is a property excluding transitions and the null descriptor? 275 // Is the result is a property excluding transitions and the null descriptor?
313 bool IsProperty() { 276 bool IsProperty() {
314 return IsFound() && IsPropertyDescriptor(this); 277 return IsFound() && !IsTransition();
315 } 278 }
316 279
317 bool IsCacheable() { return cacheable_; } 280 bool IsCacheable() { return cacheable_; }
318 void DisallowCaching() { cacheable_ = false; } 281 void DisallowCaching() { cacheable_ = false; }
319 282
320 Object* GetLazyValue() { 283 Object* GetLazyValue() {
321 switch (type()) { 284 switch (type()) {
322 case FIELD: 285 case FIELD:
323 return holder()->FastPropertyAt(GetFieldIndex()); 286 return holder()->FastPropertyAt(GetFieldIndex());
324 case NORMAL: { 287 case NORMAL: {
325 Object* value; 288 Object* value;
326 value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry()); 289 value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
327 if (holder()->IsGlobalObject()) { 290 if (holder()->IsGlobalObject()) {
328 value = JSGlobalPropertyCell::cast(value)->value(); 291 value = JSGlobalPropertyCell::cast(value)->value();
329 } 292 }
330 return value; 293 return value;
331 } 294 }
332 case CONSTANT_FUNCTION: 295 case CONSTANT_FUNCTION:
333 return GetConstantFunction(); 296 return GetConstantFunction();
334 default: 297 default:
335 return Smi::FromInt(0); 298 return Smi::FromInt(0);
336 } 299 }
337 } 300 }
338 301
302 Object* GetTransitionValue() {
303 ASSERT(IsTransition());
304 TransitionArray* transitions = holder()->map()->transitions();
305 Object* value = transitions->GetValue(number_);
306 return value;
307 }
308
309 PropertyDetails GetTransitionDetails(Map* map) {
310 ASSERT(IsTransition());
311 TransitionArray* transitions = map->transitions();
312 return transitions->GetTargetDetails(number_);
313 }
314
315 PropertyDetails GetTransitionDetails() {
316 return GetTransitionDetails(holder()->map());
317 }
318
319 bool IsTransitionToField(Map* map) {
320 return IsTransition() && GetTransitionDetails(map).type() == FIELD;
321 }
322
339 Map* GetTransitionMap() { 323 Map* GetTransitionMap() {
340 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); 324 ASSERT(IsTransition());
341 ASSERT(type() == MAP_TRANSITION ||
342 type() == CONSTANT_TRANSITION);
343 return Map::cast(GetValue()); 325 return Map::cast(GetValue());
344 } 326 }
345 327
346 Map* GetTransitionMapFromMap(Map* map) { 328 Map* GetTransitionMapFromMap(Map* map) {
347 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); 329 ASSERT(IsTransition());
348 ASSERT(type() == MAP_TRANSITION); 330 return Map::cast(map->transitions()->GetValue(number_));
349 return Map::cast(map->instance_descriptors()->GetValue(number_));
350 } 331 }
351 332
352 int GetFieldIndex() { 333 int GetFieldIndex() {
353 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); 334 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
354 ASSERT(IsField()); 335 ASSERT(IsField());
355 return Descriptor::IndexFromValue(GetValue()); 336 return Descriptor::IndexFromValue(GetValue());
356 } 337 }
357 338
358 int GetLocalFieldIndexFromMap(Map* map) { 339 int GetLocalFieldIndexFromMap(Map* map) {
359 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); 340 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
(...skipping 13 matching lines...) Expand all
373 return JSFunction::cast(GetValue()); 354 return JSFunction::cast(GetValue());
374 } 355 }
375 356
376 JSFunction* GetConstantFunctionFromMap(Map* map) { 357 JSFunction* GetConstantFunctionFromMap(Map* map) {
377 ASSERT(lookup_type_ == DESCRIPTOR_TYPE); 358 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
378 ASSERT(type() == CONSTANT_FUNCTION); 359 ASSERT(type() == CONSTANT_FUNCTION);
379 return JSFunction::cast(map->instance_descriptors()->GetValue(number_)); 360 return JSFunction::cast(map->instance_descriptors()->GetValue(number_));
380 } 361 }
381 362
382 Object* GetCallbackObject() { 363 Object* GetCallbackObject() {
383 if (lookup_type_ == CONSTANT_TYPE) { 364 switch (lookup_type_) {
384 // For now we only have the __proto__ as constant type. 365 case CONSTANT_TYPE:
385 return HEAP->prototype_accessors(); 366 return HEAP->prototype_accessors();
367 case TRANSITION_TYPE:
368 return GetTransitionValue();
369 default:
370 return GetValue();
386 } 371 }
387 return GetValue();
388 } 372 }
389 373
390 #ifdef OBJECT_PRINT 374 #ifdef OBJECT_PRINT
391 void Print(FILE* out); 375 void Print(FILE* out);
392 #endif 376 #endif
393 377
394 Object* GetValue() { 378 Object* GetValue() {
395 if (lookup_type_ == DESCRIPTOR_TYPE) { 379 if (lookup_type_ == DESCRIPTOR_TYPE) {
396 DescriptorArray* descriptors = holder()->map()->instance_descriptors(); 380 DescriptorArray* descriptors = holder()->map()->instance_descriptors();
397 return descriptors->GetValue(number_); 381 return descriptors->GetValue(number_);
398 } 382 }
399 // In the dictionary case, the data is held in the value field. 383 // In the dictionary case, the data is held in the value field.
400 ASSERT(lookup_type_ == DICTIONARY_TYPE); 384 ASSERT(lookup_type_ == DICTIONARY_TYPE);
401 return holder()->GetNormalizedProperty(this); 385 return holder()->GetNormalizedProperty(this);
402 } 386 }
403 387
404 void Iterate(ObjectVisitor* visitor); 388 void Iterate(ObjectVisitor* visitor);
405 389
406 private: 390 private:
407 Isolate* isolate_; 391 Isolate* isolate_;
408 LookupResult* next_; 392 LookupResult* next_;
409 393
410 // Where did we find the result; 394 // Where did we find the result;
411 enum { 395 enum {
412 NOT_FOUND, 396 NOT_FOUND,
413 DESCRIPTOR_TYPE, 397 DESCRIPTOR_TYPE,
398 TRANSITION_TYPE,
414 DICTIONARY_TYPE, 399 DICTIONARY_TYPE,
415 HANDLER_TYPE, 400 HANDLER_TYPE,
416 INTERCEPTOR_TYPE, 401 INTERCEPTOR_TYPE,
417 CONSTANT_TYPE 402 CONSTANT_TYPE
418 } lookup_type_; 403 } lookup_type_;
419 404
420 JSReceiver* holder_; 405 JSReceiver* holder_;
421 int number_; 406 int number_;
422 bool cacheable_; 407 bool cacheable_;
423 PropertyDetails details_; 408 PropertyDetails details_;
424 }; 409 };
425 410
426 411
427 } } // namespace v8::internal 412 } } // namespace v8::internal
428 413
429 #endif // V8_PROPERTY_H_ 414 #endif // V8_PROPERTY_H_
OLDNEW
« no previous file with comments | « src/profile-generator.cc ('k') | src/property.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698