v8  3.11.10(node0.8.26)
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 
33 namespace v8 {
34 namespace internal {
35 
36 
37 // Abstraction for elements in instance-descriptor arrays.
38 //
39 // Each descriptor has a key, property attributes, property type,
40 // property index (in the actual instance-descriptor array) and
41 // optionally a piece of data.
42 //
43 
44 class Descriptor BASE_EMBEDDED {
45  public:
46  static int IndexFromValue(Object* value) {
47  return Smi::cast(value)->value();
48  }
49 
50  MUST_USE_RESULT MaybeObject* KeyToSymbol() {
51  if (!StringShape(key_).IsSymbol()) {
52  MaybeObject* maybe_result = HEAP->LookupSymbol(key_);
53  if (!maybe_result->To(&key_)) return maybe_result;
54  }
55  return key_;
56  }
57 
58  String* GetKey() { return key_; }
59  Object* GetValue() { return value_; }
60  PropertyDetails GetDetails() { return details_; }
61 
62 #ifdef OBJECT_PRINT
63  void Print(FILE* out);
64 #endif
65 
66  void SetEnumerationIndex(int index) {
67  ASSERT(PropertyDetails::IsValidIndex(index));
68  details_ = PropertyDetails(details_.attributes(), details_.type(), index);
69  }
70 
71  bool ContainsTransition();
72 
73  private:
74  String* key_;
75  Object* value_;
76  PropertyDetails details_;
77 
78  protected:
79  Descriptor() : details_(Smi::FromInt(0)) {}
80 
81  void Init(String* key, Object* value, PropertyDetails details) {
82  key_ = key;
83  value_ = value;
84  details_ = details;
85  }
86 
87  Descriptor(String* key, Object* value, PropertyDetails details)
88  : key_(key),
89  value_(value),
90  details_(details) { }
91 
93  Object* value,
94  PropertyAttributes attributes,
96  int index = 0)
97  : key_(key),
98  value_(value),
99  details_(attributes, type, index) { }
100 
101  friend class DescriptorArray;
102 };
103 
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:
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 
126 class FieldDescriptor: public Descriptor {
127  public:
129  int field_index,
130  PropertyAttributes attributes,
131  int index = 0)
132  : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
133 };
134 
135 
136 class ConstantFunctionDescriptor: public Descriptor {
137  public:
139  JSFunction* function,
140  PropertyAttributes attributes,
141  int index = 0)
142  : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
143 };
144 
145 
146 class CallbacksDescriptor: public Descriptor {
147  public:
149  Object* foreign,
150  PropertyAttributes attributes,
151  int index = 0)
152  : Descriptor(key, foreign, attributes, CALLBACKS, index) {}
153 };
154 
155 
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  case NULL_DESCRIPTOR:
177  return false;
178  }
179  UNREACHABLE(); // keep the compiler happy
180  return false;
181 }
182 
183 
184 class LookupResult BASE_EMBEDDED {
185  public:
186  explicit LookupResult(Isolate* isolate)
187  : isolate_(isolate),
188  next_(isolate->top_lookup_result()),
189  lookup_type_(NOT_FOUND),
190  holder_(NULL),
191  cacheable_(true),
192  details_(NONE, NORMAL) {
193  isolate->SetTopLookupResult(this);
194  }
195 
197  ASSERT(isolate_->top_lookup_result() == this);
198  isolate_->SetTopLookupResult(next_);
199  }
200 
201  void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
202  lookup_type_ = DESCRIPTOR_TYPE;
203  holder_ = holder;
204  details_ = details;
205  number_ = number;
206  }
207 
208  void ConstantResult(JSObject* holder) {
209  lookup_type_ = CONSTANT_TYPE;
210  holder_ = holder;
211  details_ =
212  PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
213  DONT_DELETE),
214  CALLBACKS);
215  number_ = -1;
216  }
217 
218  void DictionaryResult(JSObject* holder, int entry) {
219  lookup_type_ = DICTIONARY_TYPE;
220  holder_ = holder;
221  details_ = holder->property_dictionary()->DetailsAt(entry);
222  number_ = entry;
223  }
224 
225  void HandlerResult(JSProxy* proxy) {
226  lookup_type_ = HANDLER_TYPE;
227  holder_ = proxy;
228  details_ = PropertyDetails(NONE, HANDLER);
229  cacheable_ = false;
230  }
231 
232  void InterceptorResult(JSObject* holder) {
233  lookup_type_ = INTERCEPTOR_TYPE;
234  holder_ = holder;
235  details_ = PropertyDetails(NONE, INTERCEPTOR);
236  }
237 
238  void NotFound() {
239  lookup_type_ = NOT_FOUND;
240  holder_ = NULL;
241  }
242 
244  ASSERT(IsFound());
245  return JSObject::cast(holder_);
246  }
247 
249  ASSERT(IsFound());
250  return JSProxy::cast(holder_);
251  }
252 
254  ASSERT(IsFound());
255  return details_.type();
256  }
257 
259  ASSERT(IsFound());
260  return details_.attributes();
261  }
262 
263  PropertyDetails GetPropertyDetails() {
264  return details_;
265  }
266 
267  bool IsReadOnly() { return details_.IsReadOnly(); }
268  bool IsDontDelete() { return details_.IsDontDelete(); }
269  bool IsDontEnum() { return details_.IsDontEnum(); }
270  bool IsDeleted() { return details_.IsDeleted(); }
271  bool IsFound() { return lookup_type_ != NOT_FOUND; }
272  bool IsHandler() { return lookup_type_ == HANDLER_TYPE; }
273 
274  // Is the result is a property excluding transitions and the null descriptor?
275  bool IsProperty() {
276  return IsFound() && IsPropertyDescriptor(this);
277  }
278 
279  bool IsCacheable() { return cacheable_; }
280  void DisallowCaching() { cacheable_ = false; }
281 
283  switch (type()) {
284  case FIELD:
285  return holder()->FastPropertyAt(GetFieldIndex());
286  case NORMAL: {
287  Object* value;
288  value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
289  if (holder()->IsGlobalObject()) {
290  value = JSGlobalPropertyCell::cast(value)->value();
291  }
292  return value;
293  }
294  case CONSTANT_FUNCTION:
295  return GetConstantFunction();
296  default:
297  return Smi::FromInt(0);
298  }
299  }
300 
301 
303  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
304  ASSERT(type() == MAP_TRANSITION ||
306  return Map::cast(GetValue());
307  }
308 
310  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
311  ASSERT(type() == MAP_TRANSITION);
312  return Map::cast(map->instance_descriptors()->GetValue(number_));
313  }
314 
316  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
317  ASSERT(type() == FIELD);
318  return Descriptor::IndexFromValue(GetValue());
319  }
320 
322  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
323  ASSERT(type() == FIELD);
324  return Descriptor::IndexFromValue(
325  map->instance_descriptors()->GetValue(number_)) -
326  map->inobject_properties();
327  }
328 
330  ASSERT(lookup_type_ == DICTIONARY_TYPE);
331  return number_;
332  }
333 
336  return JSFunction::cast(GetValue());
337  }
338 
340  ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
342  return JSFunction::cast(map->instance_descriptors()->GetValue(number_));
343  }
344 
346  if (lookup_type_ == CONSTANT_TYPE) {
347  // For now we only have the __proto__ as constant type.
348  return HEAP->prototype_accessors();
349  }
350  return GetValue();
351  }
352 
353 #ifdef OBJECT_PRINT
354  void Print(FILE* out);
355 #endif
356 
358  if (lookup_type_ == DESCRIPTOR_TYPE) {
359  DescriptorArray* descriptors = holder()->map()->instance_descriptors();
360  return descriptors->GetValue(number_);
361  }
362  // In the dictionary case, the data is held in the value field.
363  ASSERT(lookup_type_ == DICTIONARY_TYPE);
364  return holder()->GetNormalizedProperty(this);
365  }
366 
367  void Iterate(ObjectVisitor* visitor);
368 
369  private:
370  Isolate* isolate_;
371  LookupResult* next_;
372 
373  // Where did we find the result;
374  enum {
375  NOT_FOUND,
376  DESCRIPTOR_TYPE,
377  DICTIONARY_TYPE,
378  HANDLER_TYPE,
379  INTERCEPTOR_TYPE,
380  CONSTANT_TYPE
381  } lookup_type_;
382 
383  JSReceiver* holder_;
384  int number_;
385  bool cacheable_;
386  PropertyDetails details_;
387 };
388 
389 
390 } } // namespace v8::internal
391 
392 #endif // V8_PROPERTY_H_
void DescriptorResult(JSObject *holder, PropertyDetails details, int number)
Definition: property.h:201
void ConstantResult(JSObject *holder)
Definition: property.h:208
int GetLocalFieldIndexFromMap(Map *map)
Definition: property.h:321
MUST_USE_RESULT MaybeObject * KeyToSymbol()
Definition: property.h:50
Descriptor(String *key, Object *value, PropertyAttributes attributes, PropertyType type, int index=0)
Definition: property.h:92
static Smi * FromInt(int value)
Definition: objects-inl.h:973
static AccessorPair * cast(Object *obj)
static Map * cast(Object *obj)
ConstTransitionDescriptor(String *key, Map *map)
Definition: property.h:121
#define ASSERT(condition)
Definition: checks.h:270
v8::Handle< v8::Value > Print(const v8::Arguments &args)
void SetEnumerationIndex(int index)
Definition: property.h:66
Object * GetCallbackObject()
Definition: property.h:345
ConstantFunctionDescriptor(String *key, JSFunction *function, PropertyAttributes attributes, int index=0)
Definition: property.h:138
PropertyDetails GetPropertyDetails()
Definition: property.h:263
PropertyAttributes
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:1984
static Smi * cast(Object *object)
bool IsPropertyDescriptor(T *desc)
Definition: property.h:157
MapTransitionDescriptor(String *key, Map *map, PropertyAttributes attributes)
Definition: property.h:110
#define UNREACHABLE()
Definition: checks.h:50
static int IndexFromValue(Object *value)
Definition: property.h:46
LookupResult(Isolate *isolate)
Definition: property.h:186
PropertyAttributes GetAttributes()
Definition: property.h:258
#define MUST_USE_RESULT
Definition: globals.h:360
FieldDescriptor(String *key, int field_index, PropertyAttributes attributes, int index=0)
Definition: property.h:128
Descriptor(String *key, Object *value, PropertyDetails details)
Definition: property.h:87
JSFunction * GetConstantFunctionFromMap(Map *map)
Definition: property.h:339
#define BASE_EMBEDDED
Definition: allocation.h:68
void SetTopLookupResult(LookupResult *top)
Definition: isolate.h:1023
#define T(name, string, precedence)
Definition: token.cc:48
void HandlerResult(JSProxy *proxy)
Definition: property.h:225
static JSGlobalPropertyCell * cast(Object *obj)
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3049
#define HEAP
Definition: isolate.h:1408
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
static JSProxy * cast(Object *obj)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping true
Definition: flags.cc:157
void InterceptorResult(JSObject *holder)
Definition: property.h:232
void DictionaryResult(JSObject *holder, int entry)
Definition: property.h:218
Map * GetTransitionMapFromMap(Map *map)
Definition: property.h:309
CallbacksDescriptor(String *key, Object *foreign, PropertyAttributes attributes, int index=0)
Definition: property.h:148
JSFunction * GetConstantFunction()
Definition: property.h:334
void Init(String *key, Object *value, PropertyDetails details)
Definition: property.h:81
StringDictionary * property_dictionary()
Definition: objects-inl.h:4626
static JSObject * cast(Object *obj)
FlagType type() const
Definition: flags.cc:1358
PropertyDetails GetDetails()
Definition: property.h:60
static JSFunction * cast(Object *obj)