v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
property.h
Go to the documentation of this file.
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_PROPERTY_H_
29 #define V8_PROPERTY_H_
30 
31 #include "allocation.h"
32 #include "transitions.h"
33 
34 namespace v8 {
35 namespace internal {
36 
37 
38 // Abstraction for elements in instance-descriptor arrays.
39 //
40 // Each descriptor has a key, property attributes, property type,
41 // property index (in the actual instance-descriptor array) and
42 // optionally a piece of data.
43 //
44 
45 class Descriptor BASE_EMBEDDED {
46  public:
48  if (!key_->IsUniqueName()) {
49  MaybeObject* maybe_result =
50  key_->GetIsolate()->heap()->InternalizeString(String::cast(key_));
51  if (!maybe_result->To(&key_)) return maybe_result;
52  }
53  return key_;
54  }
55 
56  Name* GetKey() { return key_; }
57  Object* GetValue() { return value_; }
58  PropertyDetails GetDetails() { return details_; }
59 
60 #ifdef OBJECT_PRINT
61  void Print(FILE* out);
62 #endif
63 
64  void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); }
65 
66  private:
67  Name* key_;
68  Object* value_;
69  PropertyDetails details_;
70 
71  protected:
72  Descriptor() : details_(Smi::FromInt(0)) {}
73 
74  void Init(Name* key, Object* value, PropertyDetails details) {
75  key_ = key;
76  value_ = value;
77  details_ = details;
78  }
79 
80  Descriptor(Name* key, Object* value, PropertyDetails details)
81  : key_(key),
82  value_(value),
83  details_(details) { }
84 
86  Object* value,
87  PropertyAttributes attributes,
88  PropertyType type,
89  Representation representation,
90  int field_index = 0)
91  : key_(key),
92  value_(value),
93  details_(attributes, type, representation, field_index) { }
94 
95  friend class DescriptorArray;
96 };
97 
98 
99 class FieldDescriptor: public Descriptor {
100  public:
102  int field_index,
103  PropertyAttributes attributes,
104  Representation representation)
105  : Descriptor(key, Smi::FromInt(0), attributes,
106  FIELD, representation, field_index) {}
107 };
108 
109 
110 class ConstantDescriptor: public Descriptor {
111  public:
113  Object* value,
114  PropertyAttributes attributes)
115  : Descriptor(key, value, attributes, CONSTANT,
116  value->OptimalRepresentation()) {}
117 };
118 
119 
120 class CallbacksDescriptor: public Descriptor {
121  public:
123  Object* foreign,
124  PropertyAttributes attributes)
125  : Descriptor(key, foreign, attributes, CALLBACKS,
126  Representation::Tagged()) {}
127 };
128 
129 
130 // Holds a property index value distinguishing if it is a field index or an
131 // index inside the object header.
133  public:
134  static PropertyIndex NewFieldIndex(int index) {
135  return PropertyIndex(index, false);
136  }
137  static PropertyIndex NewHeaderIndex(int index) {
138  return PropertyIndex(index, true);
139  }
140 
141  bool is_field_index() { return (index_ & kHeaderIndexBit) == 0; }
142  bool is_header_index() { return (index_ & kHeaderIndexBit) != 0; }
143 
144  int field_index() {
146  return value();
147  }
148  int header_index() {
150  return value();
151  }
152 
154  if (is_header_index()) return true;
155  return field_index() < holder->map()->inobject_properties();
156  }
157 
159  if (is_header_index()) return header_index();
160  int index = field_index() - holder->map()->inobject_properties();
161  if (index >= 0) return index;
162  return index + holder->map()->instance_size() / kPointerSize;
163  }
164 
165  private:
166  static const int kHeaderIndexBit = 1 << 31;
167  static const int kIndexMask = ~kHeaderIndexBit;
168 
169  int value() { return index_ & kIndexMask; }
170 
171  PropertyIndex(int index, bool is_header_based)
172  : index_(index | (is_header_based ? kHeaderIndexBit : 0)) {
173  ASSERT(index <= kIndexMask);
174  }
175 
176  int index_;
177 };
178 
179 
180 class LookupResult BASE_EMBEDDED {
181  public:
182  explicit LookupResult(Isolate* isolate)
183  : isolate_(isolate),
184  next_(isolate->top_lookup_result()),
185  lookup_type_(NOT_FOUND),
186  holder_(NULL),
187  transition_(NULL),
188  cacheable_(true),
189  details_(NONE, NONEXISTENT, Representation::None()) {
190  isolate->set_top_lookup_result(this);
191  }
192 
194  ASSERT(isolate()->top_lookup_result() == this);
195  isolate()->set_top_lookup_result(next_);
196  }
197 
198  Isolate* isolate() const { return isolate_; }
199 
200  void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
201  lookup_type_ = DESCRIPTOR_TYPE;
202  holder_ = holder;
203  transition_ = NULL;
204  details_ = details;
205  number_ = number;
206  }
207 
209  if (IsNormal()) return true;
210  ASSERT(!IsTransition());
211  return value->FitsRepresentation(details_.representation());
212  }
213 
214  void TransitionResult(JSObject* holder, Map* target) {
215  lookup_type_ = TRANSITION_TYPE;
216  details_ = PropertyDetails(NONE, TRANSITION, Representation::None());
217  holder_ = holder;
218  transition_ = target;
219  number_ = 0xAAAA;
220  }
221 
222  void DictionaryResult(JSObject* holder, int entry) {
223  lookup_type_ = DICTIONARY_TYPE;
224  holder_ = holder;
225  transition_ = NULL;
226  details_ = holder->property_dictionary()->DetailsAt(entry);
227  number_ = entry;
228  }
229 
230  void HandlerResult(JSProxy* proxy) {
231  lookup_type_ = HANDLER_TYPE;
232  holder_ = proxy;
233  transition_ = NULL;
234  details_ = PropertyDetails(NONE, HANDLER, Representation::Tagged());
235  cacheable_ = false;
236  }
237 
238  void InterceptorResult(JSObject* holder) {
239  lookup_type_ = INTERCEPTOR_TYPE;
240  holder_ = holder;
241  transition_ = NULL;
242  details_ = PropertyDetails(NONE, INTERCEPTOR, Representation::Tagged());
243  }
244 
245  void NotFound() {
246  lookup_type_ = NOT_FOUND;
247  details_ = PropertyDetails(NONE, NONEXISTENT, Representation::None());
248  holder_ = NULL;
249  transition_ = NULL;
250  }
251 
252  JSObject* holder() const {
253  ASSERT(IsFound());
254  return JSObject::cast(holder_);
255  }
256 
257  JSProxy* proxy() const {
258  ASSERT(IsHandler());
259  return JSProxy::cast(holder_);
260  }
261 
262  PropertyType type() const {
263  ASSERT(IsFound());
264  return details_.type();
265  }
266 
268  ASSERT(IsFound());
269  ASSERT(!IsTransition());
270  ASSERT(details_.type() != NONEXISTENT);
271  return details_.representation();
272  }
273 
275  ASSERT(!IsTransition());
276  ASSERT(IsFound());
277  ASSERT(details_.type() != NONEXISTENT);
278  return details_.attributes();
279  }
280 
281  PropertyDetails GetPropertyDetails() const {
282  ASSERT(!IsTransition());
283  return details_;
284  }
285 
286  bool IsFastPropertyType() const {
287  ASSERT(IsFound());
288  return IsTransition() || type() != NORMAL;
289  }
290 
291  // Property callbacks does not include transitions to callbacks.
292  bool IsPropertyCallbacks() const {
293  ASSERT(!(details_.type() == CALLBACKS && !IsFound()));
294  return details_.type() == CALLBACKS;
295  }
296 
297  bool IsReadOnly() const {
298  ASSERT(IsFound());
299  ASSERT(!IsTransition());
300  ASSERT(details_.type() != NONEXISTENT);
301  return details_.IsReadOnly();
302  }
303 
304  bool IsField() const {
305  ASSERT(!(details_.type() == FIELD && !IsFound()));
306  return details_.type() == FIELD;
307  }
308 
309  bool IsNormal() const {
310  ASSERT(!(details_.type() == NORMAL && !IsFound()));
311  return details_.type() == NORMAL;
312  }
313 
314  bool IsConstant() const {
315  ASSERT(!(details_.type() == CONSTANT && !IsFound()));
316  return details_.type() == CONSTANT;
317  }
318 
319  bool IsConstantFunction() const {
320  return IsConstant() && GetValue()->IsJSFunction();
321  }
322 
323  bool IsDontDelete() const { return details_.IsDontDelete(); }
324  bool IsDontEnum() const { return details_.IsDontEnum(); }
325  bool IsFound() const { return lookup_type_ != NOT_FOUND; }
326  bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
327  bool IsHandler() const { return lookup_type_ == HANDLER_TYPE; }
328  bool IsInterceptor() const { return lookup_type_ == INTERCEPTOR_TYPE; }
329 
330  // Is the result is a property excluding transitions and the null descriptor?
331  bool IsProperty() const {
332  return IsFound() && !IsTransition();
333  }
334 
335  bool IsDataProperty() const {
336  switch (type()) {
337  case FIELD:
338  case NORMAL:
339  case CONSTANT:
340  return true;
341  case CALLBACKS: {
342  Object* callback = GetCallbackObject();
343  return callback->IsAccessorInfo() || callback->IsForeign();
344  }
345  case HANDLER:
346  case INTERCEPTOR:
347  case TRANSITION:
348  case NONEXISTENT:
349  return false;
350  }
351  UNREACHABLE();
352  return false;
353  }
354 
355  bool IsCacheable() const { return cacheable_; }
356  void DisallowCaching() { cacheable_ = false; }
357 
358  Object* GetLazyValue() const {
359  switch (type()) {
360  case FIELD:
361  return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
362  case NORMAL: {
363  Object* value;
364  value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
365  if (holder()->IsGlobalObject()) {
366  value = PropertyCell::cast(value)->value();
367  }
368  return value;
369  }
370  case CONSTANT:
371  return GetConstant();
372  case CALLBACKS:
373  case HANDLER:
374  case INTERCEPTOR:
375  case TRANSITION:
376  case NONEXISTENT:
377  return isolate()->heap()->the_hole_value();
378  }
379  UNREACHABLE();
380  return NULL;
381  }
382 
384  return transition_;
385  }
386 
387  PropertyDetails GetTransitionDetails() const {
388  ASSERT(IsTransition());
389  return transition_->GetLastDescriptorDetails();
390  }
391 
392  bool IsTransitionToField() const {
393  return IsTransition() && GetTransitionDetails().type() == FIELD;
394  }
395 
396  bool IsTransitionToConstant() const {
397  return IsTransition() && GetTransitionDetails().type() == CONSTANT;
398  }
399 
400  int GetDescriptorIndex() const {
401  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
402  return number_;
403  }
404 
406  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
407  return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map()));
408  }
409 
411  return GetFieldIndexFromMap(map) - map->inobject_properties();
412  }
413 
414  int GetDictionaryEntry() const {
415  ASSERT(lookup_type_ == DICTIONARY_TYPE);
416  return number_;
417  }
418 
420  ASSERT(type() == CONSTANT);
421  return JSFunction::cast(GetValue());
422  }
423 
425  ASSERT(type() == CONSTANT);
426  return GetValueFromMap(map);
427  }
428 
430  return JSFunction::cast(GetConstantFromMap(map));
431  }
432 
433  Object* GetConstant() const {
434  ASSERT(type() == CONSTANT);
435  return GetValue();
436  }
437 
439  ASSERT(type() == CALLBACKS && !IsTransition());
440  return GetValue();
441  }
442 
443 #ifdef OBJECT_PRINT
444  void Print(FILE* out);
445 #endif
446 
447  Object* GetValue() const {
448  if (lookup_type_ == DESCRIPTOR_TYPE) {
449  return GetValueFromMap(holder()->map());
450  }
451  // In the dictionary case, the data is held in the value field.
452  ASSERT(lookup_type_ == DICTIONARY_TYPE);
453  return holder()->GetNormalizedProperty(this);
454  }
455 
457  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
458  ASSERT(number_ < map->NumberOfOwnDescriptors());
459  return map->instance_descriptors()->GetValue(number_);
460  }
461 
463  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
464  ASSERT(number_ < map->NumberOfOwnDescriptors());
465  return map->instance_descriptors()->GetFieldIndex(number_);
466  }
467 
468  void Iterate(ObjectVisitor* visitor);
469 
470  private:
471  Isolate* isolate_;
472  LookupResult* next_;
473 
474  // Where did we find the result;
475  enum {
476  NOT_FOUND,
477  DESCRIPTOR_TYPE,
478  TRANSITION_TYPE,
479  DICTIONARY_TYPE,
480  HANDLER_TYPE,
481  INTERCEPTOR_TYPE
482  } lookup_type_;
483 
484  JSReceiver* holder_;
485  Map* transition_;
486  int number_;
487  bool cacheable_;
488  PropertyDetails details_;
489 };
490 
491 
492 } } // namespace v8::internal
493 
494 #endif // V8_PROPERTY_H_
void DescriptorResult(JSObject *holder, PropertyDetails details, int number)
Definition: property.h:200
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
Descriptor(Name *key, Object *value, PropertyDetails details)
Definition: property.h:80
PropertyDetails GetTransitionDetails() const
Definition: property.h:387
Object * GetLazyValue() const
Definition: property.h:358
Object * GetConstant() const
Definition: property.h:433
PropertyDetails GetPropertyDetails() const
Definition: property.h:281
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
Representation representation() const
Definition: property.h:267
static String * cast(Object *obj)
Object * GetValueFromMap(Map *map) const
Definition: property.h:456
int GetDescriptorIndex() const
Definition: property.h:400
JSProxy * proxy() const
Definition: property.h:257
PropertyType type() const
Definition: property.h:262
MUST_USE_RESULT MaybeObject * KeyToUniqueName()
Definition: property.h:47
static PropertyIndex NewFieldIndex(int index)
Definition: property.h:134
bool is_inobject(Handle< JSObject > holder)
Definition: property.h:153
bool IsReadOnly() const
Definition: property.h:297
#define ASSERT(condition)
Definition: checks.h:329
int translate(Handle< JSObject > holder)
Definition: property.h:158
bool IsDontEnum() const
Definition: property.h:324
Object * GetValue() const
Definition: property.h:447
CallbacksDescriptor(Name *key, Object *foreign, PropertyAttributes attributes)
Definition: property.h:122
bool IsDataProperty() const
Definition: property.h:335
PropertyAttributes
bool IsPropertyCallbacks() const
Definition: property.h:292
#define UNREACHABLE()
Definition: checks.h:52
void SetSortedKeyIndex(int index)
Definition: property.h:64
LookupResult(Isolate *isolate)
Definition: property.h:182
#define MUST_USE_RESULT
Definition: globals.h:381
const int kPointerSize
Definition: globals.h:268
JSFunction * GetConstantFunctionFromMap(Map *map) const
Definition: property.h:429
bool IsConstant() const
Definition: property.h:314
static PropertyCell * cast(Object *obj)
#define BASE_EMBEDDED
Definition: allocation.h:68
bool CanHoldValue(Handle< Object > value)
Definition: property.h:208
bool IsFastPropertyType() const
Definition: property.h:286
Definition: v8.h:2107
Isolate * isolate() const
Definition: property.h:198
bool IsInterceptor() const
Definition: property.h:328
int GetDictionaryEntry() const
Definition: property.h:414
NameDictionary * property_dictionary()
Definition: objects-inl.h:6142
JSFunction * GetConstantFunction() const
Definition: property.h:419
int GetLocalFieldIndexFromMap(Map *map) const
Definition: property.h:410
static PropertyIndex NewHeaderIndex(int index)
Definition: property.h:137
int GetFieldIndexFromMap(Map *map) const
Definition: property.h:462
void HandlerResult(JSProxy *proxy)
Definition: property.h:230
PropertyIndex GetFieldIndex() const
Definition: property.h:405
void Init(Name *key, Object *value, PropertyDetails details)
Definition: property.h:74
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3940
bool IsNormal() const
Definition: property.h:309
bool IsProperty() const
Definition: property.h:331
bool IsCacheable() const
Definition: property.h:355
FieldDescriptor(Name *key, int field_index, PropertyAttributes attributes, Representation representation)
Definition: property.h:101
JSObject * holder() const
Definition: property.h:252
bool IsTransitionToConstant() const
Definition: property.h:396
static JSProxy * cast(Object *obj)
void Print(const v8::FunctionCallbackInfo< v8::Value > &args)
void InterceptorResult(JSObject *holder)
Definition: property.h:238
Object * GetCallbackObject() const
Definition: property.h:438
bool IsHandler() const
Definition: property.h:327
void DictionaryResult(JSObject *holder, int entry)
Definition: property.h:222
PropertyAttributes GetAttributes() const
Definition: property.h:274
static Representation None()
Map * GetTransitionTarget() const
Definition: property.h:383
static Representation Tagged()
Descriptor(Name *key, Object *value, PropertyAttributes attributes, PropertyType type, Representation representation, int field_index=0)
Definition: property.h:85
bool IsDontDelete() const
Definition: property.h:323
bool IsConstantFunction() const
Definition: property.h:319
static JSObject * cast(Object *obj)
bool IsTransition() const
Definition: property.h:326
bool IsTransitionToField() const
Definition: property.h:392
Object * GetConstantFromMap(Map *map) const
Definition: property.h:424
PropertyDetails GetDetails()
Definition: property.h:58
void TransitionResult(JSObject *holder, Map *target)
Definition: property.h:214
ConstantDescriptor(Name *key, Object *value, PropertyAttributes attributes)
Definition: property.h:112
static JSFunction * cast(Object *obj)