blob: ee95ca217a28b42b7916b3d36dceef2a2843a41c [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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
31namespace v8 {
32namespace 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
42class Descriptor BASE_EMBEDDED {
43 public:
44 static int IndexFromValue(Object* value) {
45 return Smi::cast(value)->value();
46 }
47
John Reck59135872010-11-02 12:39:01 -070048 MUST_USE_RESULT MaybeObject* KeyToSymbol() {
Steve Blocka7e24c12009-10-30 11:49:00 +000049 if (!StringShape(key_).IsSymbol()) {
John Reck59135872010-11-02 12:39:01 -070050 Object* result;
Steve Block44f0eee2011-05-26 01:26:41 +010051 { MaybeObject* maybe_result = HEAP->LookupSymbol(key_);
John Reck59135872010-11-02 12:39:01 -070052 if (!maybe_result->ToObject(&result)) return maybe_result;
53 }
Steve Blocka7e24c12009-10-30 11:49:00 +000054 key_ = String::cast(result);
55 }
56 return key_;
57 }
58
59 String* GetKey() { return key_; }
60 Object* GetValue() { return value_; }
61 PropertyDetails GetDetails() { return details_; }
62
Ben Murdochb0fe1622011-05-05 13:52:32 +010063#ifdef OBJECT_PRINT
64 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +000065#endif
66
67 void SetEnumerationIndex(int index) {
68 ASSERT(PropertyDetails::IsValidIndex(index));
69 details_ = PropertyDetails(details_.attributes(), details_.type(), index);
70 }
71
72 private:
73 String* key_;
74 Object* value_;
75 PropertyDetails details_;
76
77 protected:
78 Descriptor() : details_(Smi::FromInt(0)) {}
79
80 void Init(String* key, Object* value, PropertyDetails details) {
81 key_ = key;
82 value_ = value;
83 details_ = details;
84 }
85
86 Descriptor(String* key, Object* value, PropertyDetails details)
87 : key_(key),
88 value_(value),
89 details_(details) { }
90
91 Descriptor(String* key,
92 Object* value,
93 PropertyAttributes attributes,
94 PropertyType type,
95 int index = 0)
96 : key_(key),
97 value_(value),
98 details_(attributes, type, index) { }
99
100 friend class DescriptorArray;
101};
102
103// A pointer from a map to the new map that is created by adding
104// a named property. These are key to the speed and functioning of V8.
105// The two maps should always have the same prototype, since
106// MapSpace::CreateBackPointers depends on this.
107class MapTransitionDescriptor: public Descriptor {
108 public:
109 MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
110 : Descriptor(key, map, attributes, MAP_TRANSITION) { }
111};
112
Steve Block44f0eee2011-05-26 01:26:41 +0100113class ExternalArrayTransitionDescriptor: public Descriptor {
114 public:
115 ExternalArrayTransitionDescriptor(String* key,
116 Map* map,
117 ExternalArrayType array_type)
118 : Descriptor(key, map, PropertyDetails(NONE,
119 EXTERNAL_ARRAY_TRANSITION,
120 array_type)) { }
121};
122
Steve Blocka7e24c12009-10-30 11:49:00 +0000123// Marks a field name in a map so that adding the field is guaranteed
124// to create a FIELD descriptor in the new map. Used after adding
125// a constant function the first time, creating a CONSTANT_FUNCTION
126// descriptor in the new map. This avoids creating multiple maps with
127// the same CONSTANT_FUNCTION field.
128class ConstTransitionDescriptor: public Descriptor {
129 public:
Iain Merrick75681382010-08-19 15:07:18 +0100130 explicit ConstTransitionDescriptor(String* key, Map* map)
131 : Descriptor(key, map, NONE, CONSTANT_TRANSITION) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000132};
133
134
135class FieldDescriptor: public Descriptor {
136 public:
137 FieldDescriptor(String* key,
138 int field_index,
139 PropertyAttributes attributes,
140 int index = 0)
141 : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
142};
143
144
145class ConstantFunctionDescriptor: public Descriptor {
146 public:
147 ConstantFunctionDescriptor(String* key,
148 JSFunction* function,
149 PropertyAttributes attributes,
150 int index = 0)
151 : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
152};
153
154
155class CallbacksDescriptor: public Descriptor {
156 public:
157 CallbacksDescriptor(String* key,
158 Object* proxy,
159 PropertyAttributes attributes,
160 int index = 0)
161 : Descriptor(key, proxy, attributes, CALLBACKS, index) {}
162};
163
164
165class LookupResult BASE_EMBEDDED {
166 public:
167 // Where did we find the result;
168 enum {
169 NOT_FOUND,
170 DESCRIPTOR_TYPE,
171 DICTIONARY_TYPE,
172 INTERCEPTOR_TYPE,
173 CONSTANT_TYPE
174 } lookup_type_;
175
176 LookupResult()
177 : lookup_type_(NOT_FOUND),
178 cacheable_(true),
179 details_(NONE, NORMAL) {}
180
181 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
182 lookup_type_ = DESCRIPTOR_TYPE;
183 holder_ = holder;
184 details_ = details;
185 number_ = number;
186 }
187
Ben Murdoch8b112d22011-06-08 16:22:53 +0100188 void DescriptorResult(JSObject* holder, Smi* details, int number) {
189 lookup_type_ = DESCRIPTOR_TYPE;
190 holder_ = holder;
191 details_ = PropertyDetails(details);
192 number_ = number;
193 }
194
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 void ConstantResult(JSObject* holder) {
196 lookup_type_ = CONSTANT_TYPE;
197 holder_ = holder;
198 details_ =
199 PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
200 DONT_DELETE),
201 CALLBACKS);
202 number_ = -1;
203 }
204
205 void DictionaryResult(JSObject* holder, int entry) {
206 lookup_type_ = DICTIONARY_TYPE;
207 holder_ = holder;
208 details_ = holder->property_dictionary()->DetailsAt(entry);
209 number_ = entry;
210 }
211
212 void InterceptorResult(JSObject* holder) {
213 lookup_type_ = INTERCEPTOR_TYPE;
214 holder_ = holder;
215 details_ = PropertyDetails(NONE, INTERCEPTOR);
216 }
217
218 void NotFound() {
219 lookup_type_ = NOT_FOUND;
220 }
221
222 JSObject* holder() {
Andrei Popescu402d9372010-02-26 13:31:12 +0000223 ASSERT(IsFound());
Steve Blocka7e24c12009-10-30 11:49:00 +0000224 return holder_;
225 }
226
227 PropertyType type() {
Andrei Popescu402d9372010-02-26 13:31:12 +0000228 ASSERT(IsFound());
Steve Blocka7e24c12009-10-30 11:49:00 +0000229 return details_.type();
230 }
231
Steve Blocka7e24c12009-10-30 11:49:00 +0000232 PropertyAttributes GetAttributes() {
Andrei Popescu402d9372010-02-26 13:31:12 +0000233 ASSERT(IsFound());
Steve Blocka7e24c12009-10-30 11:49:00 +0000234 return details_.attributes();
235 }
236
237 PropertyDetails GetPropertyDetails() {
238 return details_;
239 }
240
241 bool IsReadOnly() { return details_.IsReadOnly(); }
242 bool IsDontDelete() { return details_.IsDontDelete(); }
243 bool IsDontEnum() { return details_.IsDontEnum(); }
244 bool IsDeleted() { return details_.IsDeleted(); }
Andrei Popescu402d9372010-02-26 13:31:12 +0000245 bool IsFound() { return lookup_type_ != NOT_FOUND; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000246
Andrei Popescu402d9372010-02-26 13:31:12 +0000247 // Is the result is a property excluding transitions and the null
248 // descriptor?
Steve Blocka7e24c12009-10-30 11:49:00 +0000249 bool IsProperty() {
Andrei Popescu402d9372010-02-26 13:31:12 +0000250 return IsFound() && (type() < FIRST_PHANTOM_PROPERTY_TYPE);
251 }
252
253 // Is the result a property or a transition?
254 bool IsPropertyOrTransition() {
255 return IsFound() && (type() != NULL_DESCRIPTOR);
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 }
257
258 bool IsCacheable() { return cacheable_; }
259 void DisallowCaching() { cacheable_ = false; }
260
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 Object* GetLazyValue() {
262 switch (type()) {
263 case FIELD:
264 return holder()->FastPropertyAt(GetFieldIndex());
265 case NORMAL: {
266 Object* value;
267 value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
268 if (holder()->IsGlobalObject()) {
269 value = JSGlobalPropertyCell::cast(value)->value();
270 }
271 return value;
272 }
273 case CONSTANT_FUNCTION:
274 return GetConstantFunction();
275 default:
276 return Smi::FromInt(0);
277 }
278 }
279
280 Map* GetTransitionMap() {
281 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
Steve Block44f0eee2011-05-26 01:26:41 +0100282 ASSERT(type() == MAP_TRANSITION || type() == CONSTANT_TRANSITION ||
283 type() == EXTERNAL_ARRAY_TRANSITION);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 return Map::cast(GetValue());
285 }
286
Ben Murdochb0fe1622011-05-05 13:52:32 +0100287 Map* GetTransitionMapFromMap(Map* map) {
288 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
289 ASSERT(type() == MAP_TRANSITION);
290 return Map::cast(map->instance_descriptors()->GetValue(number_));
291 }
292
Steve Blocka7e24c12009-10-30 11:49:00 +0000293 int GetFieldIndex() {
294 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
295 ASSERT(type() == FIELD);
296 return Descriptor::IndexFromValue(GetValue());
297 }
298
Ben Murdochb0fe1622011-05-05 13:52:32 +0100299 int GetLocalFieldIndexFromMap(Map* map) {
300 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
301 ASSERT(type() == FIELD);
302 return Descriptor::IndexFromValue(
303 map->instance_descriptors()->GetValue(number_)) -
304 map->inobject_properties();
305 }
306
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 int GetDictionaryEntry() {
308 ASSERT(lookup_type_ == DICTIONARY_TYPE);
309 return number_;
310 }
311
312 JSFunction* GetConstantFunction() {
313 ASSERT(type() == CONSTANT_FUNCTION);
314 return JSFunction::cast(GetValue());
315 }
316
Ben Murdochb0fe1622011-05-05 13:52:32 +0100317 JSFunction* GetConstantFunctionFromMap(Map* map) {
318 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
319 ASSERT(type() == CONSTANT_FUNCTION);
320 return JSFunction::cast(map->instance_descriptors()->GetValue(number_));
321 }
322
Steve Blocka7e24c12009-10-30 11:49:00 +0000323 Object* GetCallbackObject() {
324 if (lookup_type_ == CONSTANT_TYPE) {
325 // For now we only have the __proto__ as constant type.
Steve Block44f0eee2011-05-26 01:26:41 +0100326 return HEAP->prototype_accessors();
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 }
328 return GetValue();
329 }
330
Ben Murdochb0fe1622011-05-05 13:52:32 +0100331#ifdef OBJECT_PRINT
332 void Print(FILE* out);
Steve Blocka7e24c12009-10-30 11:49:00 +0000333#endif
334
335 Object* GetValue() {
336 if (lookup_type_ == DESCRIPTOR_TYPE) {
337 DescriptorArray* descriptors = holder()->map()->instance_descriptors();
338 return descriptors->GetValue(number_);
339 }
340 // In the dictionary case, the data is held in the value field.
341 ASSERT(lookup_type_ == DICTIONARY_TYPE);
342 return holder()->GetNormalizedProperty(this);
343 }
344
345 private:
346 JSObject* holder_;
347 int number_;
348 bool cacheable_;
349 PropertyDetails details_;
350};
351
352
353} } // namespace v8::internal
354
355#endif // V8_PROPERTY_H_