• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 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 namespace v8 {
32 namespace internal {
33 
34 
35 // Abstraction for elements in instance-descriptor arrays.
36 //
37 // Each descriptor has a key, property attributes, property type,
38 // property index (in the actual instance-descriptor array) and
39 // optionally a piece of data.
40 //
41 
42 class Descriptor BASE_EMBEDDED {
43  public:
IndexFromValue(Object * value)44   static int IndexFromValue(Object* value) {
45     return Smi::cast(value)->value();
46   }
47 
KeyToSymbol()48   Object* KeyToSymbol() {
49     if (!StringShape(key_).IsSymbol()) {
50       Object* result = Heap::LookupSymbol(key_);
51       if (result->IsFailure()) return result;
52       key_ = String::cast(result);
53     }
54     return key_;
55   }
56 
GetKey()57   String* GetKey() { return key_; }
GetValue()58   Object* GetValue() { return value_; }
GetDetails()59   PropertyDetails GetDetails() { return details_; }
60 
61 #ifdef DEBUG
62   void Print();
63 #endif
64 
SetEnumerationIndex(int index)65   void SetEnumerationIndex(int index) {
66     ASSERT(PropertyDetails::IsValidIndex(index));
67     details_ = PropertyDetails(details_.attributes(), details_.type(), index);
68   }
69 
70  private:
71   String* key_;
72   Object* value_;
73   PropertyDetails details_;
74 
75  protected:
Descriptor()76   Descriptor() : details_(Smi::FromInt(0)) {}
77 
Init(String * key,Object * value,PropertyDetails details)78   void Init(String* key, Object* value, PropertyDetails details) {
79     key_ = key;
80     value_ = value;
81     details_ = details;
82   }
83 
Descriptor(String * key,Object * value,PropertyDetails details)84   Descriptor(String* key, Object* value, PropertyDetails details)
85       : key_(key),
86         value_(value),
87         details_(details) { }
88 
89   Descriptor(String* key,
90              Object* value,
91              PropertyAttributes attributes,
92              PropertyType type,
93              int index = 0)
key_(key)94       : key_(key),
95         value_(value),
96         details_(attributes, type, index) { }
97 
98   friend class DescriptorArray;
99 };
100 
101 // A pointer from a map to the new map that is created by adding
102 // a named property.  These are key to the speed and functioning of V8.
103 // The two maps should always have the same prototype, since
104 // MapSpace::CreateBackPointers depends on this.
105 class MapTransitionDescriptor: public Descriptor {
106  public:
MapTransitionDescriptor(String * key,Map * map,PropertyAttributes attributes)107   MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
108       : Descriptor(key, map, attributes, MAP_TRANSITION) { }
109 };
110 
111 // Marks a field name in a map so that adding the field is guaranteed
112 // to create a FIELD descriptor in the new map.  Used after adding
113 // a constant function the first time, creating a CONSTANT_FUNCTION
114 // descriptor in the new map.  This avoids creating multiple maps with
115 // the same CONSTANT_FUNCTION field.
116 class ConstTransitionDescriptor: public Descriptor {
117  public:
ConstTransitionDescriptor(String * key)118   explicit ConstTransitionDescriptor(String* key)
119       : Descriptor(key, Smi::FromInt(0), NONE, CONSTANT_TRANSITION) { }
120 };
121 
122 
123 class FieldDescriptor: public Descriptor {
124  public:
125   FieldDescriptor(String* key,
126                   int field_index,
127                   PropertyAttributes attributes,
128                   int index = 0)
Descriptor(key,Smi::FromInt (field_index),attributes,FIELD,index)129       : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
130 };
131 
132 
133 class ConstantFunctionDescriptor: public Descriptor {
134  public:
135   ConstantFunctionDescriptor(String* key,
136                              JSFunction* function,
137                              PropertyAttributes attributes,
138                              int index = 0)
Descriptor(key,function,attributes,CONSTANT_FUNCTION,index)139       : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
140 };
141 
142 
143 class CallbacksDescriptor:  public Descriptor {
144  public:
145   CallbacksDescriptor(String* key,
146                       Object* proxy,
147                       PropertyAttributes attributes,
148                       int index = 0)
Descriptor(key,proxy,attributes,CALLBACKS,index)149       : Descriptor(key, proxy, attributes, CALLBACKS, index) {}
150 };
151 
152 
153 class LookupResult BASE_EMBEDDED {
154  public:
155   // Where did we find the result;
156   enum {
157     NOT_FOUND,
158     DESCRIPTOR_TYPE,
159     DICTIONARY_TYPE,
160     INTERCEPTOR_TYPE,
161     CONSTANT_TYPE
162   } lookup_type_;
163 
LookupResult()164   LookupResult()
165       : lookup_type_(NOT_FOUND),
166         cacheable_(true),
167         details_(NONE, NORMAL) {}
168 
DescriptorResult(JSObject * holder,PropertyDetails details,int number)169   void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
170     lookup_type_ = DESCRIPTOR_TYPE;
171     holder_ = holder;
172     details_ = details;
173     number_ = number;
174   }
175 
ConstantResult(JSObject * holder)176   void ConstantResult(JSObject* holder) {
177     lookup_type_ = CONSTANT_TYPE;
178     holder_ = holder;
179     details_ =
180         PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
181                                                         DONT_DELETE),
182                         CALLBACKS);
183     number_ = -1;
184   }
185 
DictionaryResult(JSObject * holder,int entry)186   void DictionaryResult(JSObject* holder, int entry) {
187     lookup_type_ = DICTIONARY_TYPE;
188     holder_ = holder;
189     details_ = holder->property_dictionary()->DetailsAt(entry);
190     number_ = entry;
191   }
192 
InterceptorResult(JSObject * holder)193   void InterceptorResult(JSObject* holder) {
194     lookup_type_ = INTERCEPTOR_TYPE;
195     holder_ = holder;
196     details_ = PropertyDetails(NONE, INTERCEPTOR);
197   }
198 
NotFound()199   void NotFound() {
200     lookup_type_ = NOT_FOUND;
201   }
202 
holder()203   JSObject* holder() {
204     ASSERT(IsFound());
205     return holder_;
206   }
207 
type()208   PropertyType type() {
209     ASSERT(IsFound());
210     return details_.type();
211   }
212 
GetAttributes()213   PropertyAttributes GetAttributes() {
214     ASSERT(IsFound());
215     return details_.attributes();
216   }
217 
GetPropertyDetails()218   PropertyDetails GetPropertyDetails() {
219     return details_;
220   }
221 
IsReadOnly()222   bool IsReadOnly() { return details_.IsReadOnly(); }
IsDontDelete()223   bool IsDontDelete() { return details_.IsDontDelete(); }
IsDontEnum()224   bool IsDontEnum() { return details_.IsDontEnum(); }
IsDeleted()225   bool IsDeleted() { return details_.IsDeleted(); }
IsFound()226   bool IsFound() { return lookup_type_ != NOT_FOUND; }
227 
228   // Is the result is a property excluding transitions and the null
229   // descriptor?
IsProperty()230   bool IsProperty() {
231     return IsFound() && (type() < FIRST_PHANTOM_PROPERTY_TYPE);
232   }
233 
234   // Is the result a property or a transition?
IsPropertyOrTransition()235   bool IsPropertyOrTransition() {
236     return IsFound() && (type() != NULL_DESCRIPTOR);
237   }
238 
IsCacheable()239   bool IsCacheable() { return cacheable_; }
DisallowCaching()240   void DisallowCaching() { cacheable_ = false; }
241 
GetLazyValue()242   Object* GetLazyValue() {
243     switch (type()) {
244       case FIELD:
245         return holder()->FastPropertyAt(GetFieldIndex());
246       case NORMAL: {
247         Object* value;
248         value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
249         if (holder()->IsGlobalObject()) {
250           value = JSGlobalPropertyCell::cast(value)->value();
251         }
252         return value;
253       }
254       case CONSTANT_FUNCTION:
255         return GetConstantFunction();
256       default:
257         return Smi::FromInt(0);
258     }
259   }
260 
GetTransitionMap()261   Map* GetTransitionMap() {
262     ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
263     ASSERT(type() == MAP_TRANSITION);
264     return Map::cast(GetValue());
265   }
266 
GetFieldIndex()267   int GetFieldIndex() {
268     ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
269     ASSERT(type() == FIELD);
270     return Descriptor::IndexFromValue(GetValue());
271   }
272 
GetDictionaryEntry()273   int GetDictionaryEntry() {
274     ASSERT(lookup_type_ == DICTIONARY_TYPE);
275     return number_;
276   }
277 
GetConstantFunction()278   JSFunction* GetConstantFunction() {
279     ASSERT(type() == CONSTANT_FUNCTION);
280     return JSFunction::cast(GetValue());
281   }
282 
GetCallbackObject()283   Object* GetCallbackObject() {
284     if (lookup_type_ == CONSTANT_TYPE) {
285       // For now we only have the __proto__ as constant type.
286       return Heap::prototype_accessors();
287     }
288     return GetValue();
289   }
290 
291 #ifdef DEBUG
292   void Print();
293 #endif
294 
GetValue()295   Object* GetValue() {
296     if (lookup_type_ == DESCRIPTOR_TYPE) {
297       DescriptorArray* descriptors = holder()->map()->instance_descriptors();
298       return descriptors->GetValue(number_);
299     }
300     // In the dictionary case, the data is held in the value field.
301     ASSERT(lookup_type_ == DICTIONARY_TYPE);
302     return holder()->GetNormalizedProperty(this);
303   }
304 
305  private:
306   JSObject* holder_;
307   int number_;
308   bool cacheable_;
309   PropertyDetails details_;
310 };
311 
312 
313 } }  // namespace v8::internal
314 
315 #endif  // V8_PROPERTY_H_
316