blob: ddecc92198cdd3f502222428e36234fccaac189a [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
32
kasperl@chromium.org71affb52009-05-26 05:44:31 +000033namespace v8 {
34namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
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
44class Descriptor BASE_EMBEDDED {
45 public:
46 static int IndexFromValue(Object* value) {
47 return Smi::cast(value)->value();
48 }
49
lrn@chromium.org303ada72010-10-27 09:33:13 +000050 MUST_USE_RESULT MaybeObject* KeyToSymbol() {
ager@chromium.org870a0b62008-11-04 11:43:05 +000051 if (!StringShape(key_).IsSymbol()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +000052 Object* result;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000053 { MaybeObject* maybe_result = HEAP->LookupSymbol(key_);
lrn@chromium.org303ada72010-10-27 09:33:13 +000054 if (!maybe_result->ToObject(&result)) return maybe_result;
55 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056 key_ = String::cast(result);
57 }
58 return key_;
59 }
60
61 String* GetKey() { return key_; }
62 Object* GetValue() { return value_; }
63 PropertyDetails GetDetails() { return details_; }
64
whesse@chromium.org023421e2010-12-21 12:19:12 +000065#ifdef OBJECT_PRINT
66 void Print(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067#endif
68
69 void SetEnumerationIndex(int index) {
70 ASSERT(PropertyDetails::IsValidIndex(index));
71 details_ = PropertyDetails(details_.attributes(), details_.type(), index);
72 }
73
74 private:
75 String* key_;
76 Object* value_;
77 PropertyDetails details_;
78
79 protected:
80 Descriptor() : details_(Smi::FromInt(0)) {}
81
82 void Init(String* key, Object* value, PropertyDetails details) {
83 key_ = key;
84 value_ = value;
85 details_ = details;
86 }
87
88 Descriptor(String* key, Object* value, PropertyDetails details)
89 : key_(key),
90 value_(value),
91 details_(details) { }
92
93 Descriptor(String* key,
94 Object* value,
95 PropertyAttributes attributes,
96 PropertyType type,
97 int index = 0)
98 : key_(key),
99 value_(value),
100 details_(attributes, type, index) { }
101
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102 friend class DescriptorArray;
103};
104
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000105// A pointer from a map to the new map that is created by adding
106// a named property. These are key to the speed and functioning of V8.
107// The two maps should always have the same prototype, since
108// MapSpace::CreateBackPointers depends on this.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109class MapTransitionDescriptor: public Descriptor {
110 public:
111 MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
112 : Descriptor(key, map, attributes, MAP_TRANSITION) { }
113};
114
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000115class ExternalArrayTransitionDescriptor: public Descriptor {
116 public:
117 ExternalArrayTransitionDescriptor(String* key,
118 Map* map,
119 ExternalArrayType array_type)
120 : Descriptor(key, map, PropertyDetails(NONE,
121 EXTERNAL_ARRAY_TRANSITION,
122 array_type)) { }
123};
124
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000125// Marks a field name in a map so that adding the field is guaranteed
126// to create a FIELD descriptor in the new map. Used after adding
127// a constant function the first time, creating a CONSTANT_FUNCTION
128// descriptor in the new map. This avoids creating multiple maps with
129// the same CONSTANT_FUNCTION field.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130class ConstTransitionDescriptor: public Descriptor {
131 public:
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000132 explicit ConstTransitionDescriptor(String* key, Map* map)
133 : Descriptor(key, map, NONE, CONSTANT_TRANSITION) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000134};
135
136
137class FieldDescriptor: public Descriptor {
138 public:
139 FieldDescriptor(String* key,
140 int field_index,
141 PropertyAttributes attributes,
142 int index = 0)
143 : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
144};
145
146
147class ConstantFunctionDescriptor: public Descriptor {
148 public:
149 ConstantFunctionDescriptor(String* key,
150 JSFunction* function,
151 PropertyAttributes attributes,
152 int index = 0)
153 : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
154};
155
156
157class CallbacksDescriptor: public Descriptor {
158 public:
159 CallbacksDescriptor(String* key,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000160 Object* foreign,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161 PropertyAttributes attributes,
162 int index = 0)
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000163 : Descriptor(key, foreign, attributes, CALLBACKS, index) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000164};
165
166
167class LookupResult BASE_EMBEDDED {
168 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169 LookupResult()
170 : lookup_type_(NOT_FOUND),
171 cacheable_(true),
172 details_(NONE, NORMAL) {}
173
174 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
175 lookup_type_ = DESCRIPTOR_TYPE;
176 holder_ = holder;
177 details_ = details;
178 number_ = number;
179 }
180
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000181 void DescriptorResult(JSObject* holder, Smi* details, int number) {
182 lookup_type_ = DESCRIPTOR_TYPE;
183 holder_ = holder;
184 details_ = PropertyDetails(details);
185 number_ = number;
186 }
187
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 void ConstantResult(JSObject* holder) {
189 lookup_type_ = CONSTANT_TYPE;
190 holder_ = holder;
191 details_ =
192 PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
193 DONT_DELETE),
194 CALLBACKS);
195 number_ = -1;
196 }
197
198 void DictionaryResult(JSObject* holder, int entry) {
199 lookup_type_ = DICTIONARY_TYPE;
200 holder_ = holder;
201 details_ = holder->property_dictionary()->DetailsAt(entry);
202 number_ = entry;
203 }
204
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000205 void HandlerResult() {
206 lookup_type_ = HANDLER_TYPE;
207 holder_ = NULL;
208 details_ = PropertyDetails(NONE, HANDLER);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000209 cacheable_ = false;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000210 }
211
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 JSObject* holder() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000223 ASSERT(IsFound());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224 return holder_;
225 }
226
227 PropertyType type() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000228 ASSERT(IsFound());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 return details_.type();
230 }
231
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000232 PropertyAttributes GetAttributes() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000233 ASSERT(IsFound());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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(); }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000244 bool IsDeleted() { return details_.IsDeleted(); }
ager@chromium.org5c838252010-02-19 08:53:10 +0000245 bool IsFound() { return lookup_type_ != NOT_FOUND; }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000246 bool IsHandler() { return lookup_type_ == HANDLER_TYPE; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247
ager@chromium.org5c838252010-02-19 08:53:10 +0000248 // Is the result is a property excluding transitions and the null
249 // descriptor?
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250 bool IsProperty() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000251 return IsFound() && (type() < FIRST_PHANTOM_PROPERTY_TYPE);
252 }
253
254 // Is the result a property or a transition?
255 bool IsPropertyOrTransition() {
256 return IsFound() && (type() != NULL_DESCRIPTOR);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257 }
258
259 bool IsCacheable() { return cacheable_; }
260 void DisallowCaching() { cacheable_ = false; }
261
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000262 Object* GetLazyValue() {
263 switch (type()) {
264 case FIELD:
265 return holder()->FastPropertyAt(GetFieldIndex());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000266 case NORMAL: {
267 Object* value;
268 value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
269 if (holder()->IsGlobalObject()) {
270 value = JSGlobalPropertyCell::cast(value)->value();
271 }
272 return value;
273 }
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000274 case CONSTANT_FUNCTION:
275 return GetConstantFunction();
276 default:
277 return Smi::FromInt(0);
278 }
279 }
280
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281 Map* GetTransitionMap() {
282 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000283 ASSERT(type() == MAP_TRANSITION || type() == CONSTANT_TRANSITION ||
284 type() == EXTERNAL_ARRAY_TRANSITION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000285 return Map::cast(GetValue());
286 }
287
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000288 Map* GetTransitionMapFromMap(Map* map) {
289 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
290 ASSERT(type() == MAP_TRANSITION);
291 return Map::cast(map->instance_descriptors()->GetValue(number_));
292 }
293
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000294 int GetFieldIndex() {
295 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
296 ASSERT(type() == FIELD);
297 return Descriptor::IndexFromValue(GetValue());
298 }
299
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000300 int GetLocalFieldIndexFromMap(Map* map) {
301 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
302 ASSERT(type() == FIELD);
303 return Descriptor::IndexFromValue(
304 map->instance_descriptors()->GetValue(number_)) -
305 map->inobject_properties();
306 }
307
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 int GetDictionaryEntry() {
309 ASSERT(lookup_type_ == DICTIONARY_TYPE);
310 return number_;
311 }
312
313 JSFunction* GetConstantFunction() {
314 ASSERT(type() == CONSTANT_FUNCTION);
315 return JSFunction::cast(GetValue());
316 }
317
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000318 JSFunction* GetConstantFunctionFromMap(Map* map) {
319 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
320 ASSERT(type() == CONSTANT_FUNCTION);
321 return JSFunction::cast(map->instance_descriptors()->GetValue(number_));
322 }
323
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000324 Object* GetCallbackObject() {
325 if (lookup_type_ == CONSTANT_TYPE) {
326 // For now we only have the __proto__ as constant type.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000327 return HEAP->prototype_accessors();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 }
329 return GetValue();
330 }
331
whesse@chromium.org023421e2010-12-21 12:19:12 +0000332#ifdef OBJECT_PRINT
333 void Print(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000334#endif
335
336 Object* GetValue() {
337 if (lookup_type_ == DESCRIPTOR_TYPE) {
338 DescriptorArray* descriptors = holder()->map()->instance_descriptors();
339 return descriptors->GetValue(number_);
340 }
341 // In the dictionary case, the data is held in the value field.
342 ASSERT(lookup_type_ == DICTIONARY_TYPE);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000343 return holder()->GetNormalizedProperty(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 }
345
346 private:
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000347 // Where did we find the result;
348 enum {
349 NOT_FOUND,
350 DESCRIPTOR_TYPE,
351 DICTIONARY_TYPE,
352 HANDLER_TYPE,
353 INTERCEPTOR_TYPE,
354 CONSTANT_TYPE
355 } lookup_type_;
356
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357 JSObject* holder_;
358 int number_;
359 bool cacheable_;
360 PropertyDetails details_;
361};
362
363
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000364} } // namespace v8::internal
365
366#endif // V8_PROPERTY_H_