blob: c39fe41e75ddd99bc6b9a1cf52aebc34599f2b9f [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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000031namespace v8 {
32namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033
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
lrn@chromium.org303ada72010-10-27 09:33:13 +000048 MUST_USE_RESULT MaybeObject* KeyToSymbol() {
ager@chromium.org870a0b62008-11-04 11:43:05 +000049 if (!StringShape(key_).IsSymbol()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +000050 Object* result;
51 { MaybeObject* maybe_result = Heap::LookupSymbol(key_);
52 if (!maybe_result->ToObject(&result)) return maybe_result;
53 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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
whesse@chromium.org023421e2010-12-21 12:19:12 +000063#ifdef OBJECT_PRINT
64 void Print(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000100 friend class DescriptorArray;
101};
102
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000103// 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.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107class MapTransitionDescriptor: public Descriptor {
108 public:
109 MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
110 : Descriptor(key, map, attributes, MAP_TRANSITION) { }
111};
112
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000113// Marks a field name in a map so that adding the field is guaranteed
114// to create a FIELD descriptor in the new map. Used after adding
115// a constant function the first time, creating a CONSTANT_FUNCTION
116// descriptor in the new map. This avoids creating multiple maps with
117// the same CONSTANT_FUNCTION field.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118class ConstTransitionDescriptor: public Descriptor {
119 public:
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000120 explicit ConstTransitionDescriptor(String* key, Map* map)
121 : Descriptor(key, map, NONE, CONSTANT_TRANSITION) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122};
123
124
125class FieldDescriptor: public Descriptor {
126 public:
127 FieldDescriptor(String* key,
128 int field_index,
129 PropertyAttributes attributes,
130 int index = 0)
131 : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
132};
133
134
135class ConstantFunctionDescriptor: public Descriptor {
136 public:
137 ConstantFunctionDescriptor(String* key,
138 JSFunction* function,
139 PropertyAttributes attributes,
140 int index = 0)
141 : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
142};
143
144
145class CallbacksDescriptor: public Descriptor {
146 public:
147 CallbacksDescriptor(String* key,
148 Object* proxy,
149 PropertyAttributes attributes,
150 int index = 0)
151 : Descriptor(key, proxy, attributes, CALLBACKS, index) {}
152};
153
154
155class LookupResult BASE_EMBEDDED {
156 public:
157 // Where did we find the result;
158 enum {
159 NOT_FOUND,
160 DESCRIPTOR_TYPE,
161 DICTIONARY_TYPE,
162 INTERCEPTOR_TYPE,
163 CONSTANT_TYPE
164 } lookup_type_;
165
166 LookupResult()
167 : lookup_type_(NOT_FOUND),
168 cacheable_(true),
169 details_(NONE, NORMAL) {}
170
171 void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
172 lookup_type_ = DESCRIPTOR_TYPE;
173 holder_ = holder;
174 details_ = details;
175 number_ = number;
176 }
177
178 void ConstantResult(JSObject* holder) {
179 lookup_type_ = CONSTANT_TYPE;
180 holder_ = holder;
181 details_ =
182 PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
183 DONT_DELETE),
184 CALLBACKS);
185 number_ = -1;
186 }
187
188 void DictionaryResult(JSObject* holder, int entry) {
189 lookup_type_ = DICTIONARY_TYPE;
190 holder_ = holder;
191 details_ = holder->property_dictionary()->DetailsAt(entry);
192 number_ = entry;
193 }
194
195 void InterceptorResult(JSObject* holder) {
196 lookup_type_ = INTERCEPTOR_TYPE;
197 holder_ = holder;
198 details_ = PropertyDetails(NONE, INTERCEPTOR);
199 }
200
201 void NotFound() {
202 lookup_type_ = NOT_FOUND;
203 }
204
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205 JSObject* holder() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000206 ASSERT(IsFound());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207 return holder_;
208 }
209
210 PropertyType type() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000211 ASSERT(IsFound());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 return details_.type();
213 }
214
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000215 PropertyAttributes GetAttributes() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000216 ASSERT(IsFound());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217 return details_.attributes();
218 }
219
220 PropertyDetails GetPropertyDetails() {
221 return details_;
222 }
223
224 bool IsReadOnly() { return details_.IsReadOnly(); }
225 bool IsDontDelete() { return details_.IsDontDelete(); }
226 bool IsDontEnum() { return details_.IsDontEnum(); }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000227 bool IsDeleted() { return details_.IsDeleted(); }
ager@chromium.org5c838252010-02-19 08:53:10 +0000228 bool IsFound() { return lookup_type_ != NOT_FOUND; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229
ager@chromium.org5c838252010-02-19 08:53:10 +0000230 // Is the result is a property excluding transitions and the null
231 // descriptor?
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000232 bool IsProperty() {
ager@chromium.org5c838252010-02-19 08:53:10 +0000233 return IsFound() && (type() < FIRST_PHANTOM_PROPERTY_TYPE);
234 }
235
236 // Is the result a property or a transition?
237 bool IsPropertyOrTransition() {
238 return IsFound() && (type() != NULL_DESCRIPTOR);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239 }
240
241 bool IsCacheable() { return cacheable_; }
242 void DisallowCaching() { cacheable_ = false; }
243
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000244 Object* GetLazyValue() {
245 switch (type()) {
246 case FIELD:
247 return holder()->FastPropertyAt(GetFieldIndex());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000248 case NORMAL: {
249 Object* value;
250 value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
251 if (holder()->IsGlobalObject()) {
252 value = JSGlobalPropertyCell::cast(value)->value();
253 }
254 return value;
255 }
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000256 case CONSTANT_FUNCTION:
257 return GetConstantFunction();
258 default:
259 return Smi::FromInt(0);
260 }
261 }
262
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263 Map* GetTransitionMap() {
264 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000265 ASSERT(type() == MAP_TRANSITION || type() == CONSTANT_TRANSITION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000266 return Map::cast(GetValue());
267 }
268
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269 Map* GetTransitionMapFromMap(Map* map) {
270 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
271 ASSERT(type() == MAP_TRANSITION);
272 return Map::cast(map->instance_descriptors()->GetValue(number_));
273 }
274
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275 int GetFieldIndex() {
276 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
277 ASSERT(type() == FIELD);
278 return Descriptor::IndexFromValue(GetValue());
279 }
280
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000281 int GetLocalFieldIndexFromMap(Map* map) {
282 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
283 ASSERT(type() == FIELD);
284 return Descriptor::IndexFromValue(
285 map->instance_descriptors()->GetValue(number_)) -
286 map->inobject_properties();
287 }
288
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289 int GetDictionaryEntry() {
290 ASSERT(lookup_type_ == DICTIONARY_TYPE);
291 return number_;
292 }
293
294 JSFunction* GetConstantFunction() {
295 ASSERT(type() == CONSTANT_FUNCTION);
296 return JSFunction::cast(GetValue());
297 }
298
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000299 JSFunction* GetConstantFunctionFromMap(Map* map) {
300 ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
301 ASSERT(type() == CONSTANT_FUNCTION);
302 return JSFunction::cast(map->instance_descriptors()->GetValue(number_));
303 }
304
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 Object* GetCallbackObject() {
306 if (lookup_type_ == CONSTANT_TYPE) {
307 // For now we only have the __proto__ as constant type.
308 return Heap::prototype_accessors();
309 }
310 return GetValue();
311 }
312
whesse@chromium.org023421e2010-12-21 12:19:12 +0000313#ifdef OBJECT_PRINT
314 void Print(FILE* out);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315#endif
316
317 Object* GetValue() {
318 if (lookup_type_ == DESCRIPTOR_TYPE) {
319 DescriptorArray* descriptors = holder()->map()->instance_descriptors();
320 return descriptors->GetValue(number_);
321 }
322 // In the dictionary case, the data is held in the value field.
323 ASSERT(lookup_type_ == DICTIONARY_TYPE);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000324 return holder()->GetNormalizedProperty(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000325 }
326
327 private:
328 JSObject* holder_;
329 int number_;
330 bool cacheable_;
331 PropertyDetails details_;
332};
333
334
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000335} } // namespace v8::internal
336
337#endif // V8_PROPERTY_H_