The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / property.h @ 40c0f755

History | View | Annotate | Download (11.2 KB)

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 { namespace internal {
32

    
33

    
34
// Abstraction for elements in instance-descriptor arrays.
35
//
36
// Each descriptor has a key, property attributes, property type,
37
// property index (in the actual instance-descriptor array) and
38
// optionally a piece of data.
39
//
40

    
41
class Descriptor BASE_EMBEDDED {
42
 public:
43
  static int IndexFromValue(Object* value) {
44
    return Smi::cast(value)->value();
45
  }
46

    
47
  Object* KeyToSymbol() {
48
    if (!StringShape(key_).IsSymbol()) {
49
      Object* result = Heap::LookupSymbol(key_);
50
      if (result->IsFailure()) return result;
51
      key_ = String::cast(result);
52
    }
53
    return key_;
54
  }
55

    
56
  String* GetKey() { return key_; }
57
  Object* GetValue() { return value_; }
58
  PropertyDetails GetDetails() { return details_; }
59

    
60
#ifdef DEBUG
61
  void Print();
62
#endif
63

    
64
  void SetEnumerationIndex(int index) {
65
    ASSERT(PropertyDetails::IsValidIndex(index));
66
    details_ = PropertyDetails(details_.attributes(), details_.type(), index);
67
  }
68

    
69
 private:
70
  String* key_;
71
  Object* value_;
72
  PropertyDetails details_;
73

    
74
 protected:
75
  Descriptor() : details_(Smi::FromInt(0)) {}
76

    
77
  void Init(String* key, Object* value, PropertyDetails details) {
78
    key_ = key;
79
    value_ = value;
80
    details_ = details;
81
  }
82

    
83
  Descriptor(String* key, Object* value, PropertyDetails details)
84
      : key_(key),
85
        value_(value),
86
        details_(details) { }
87

    
88
  Descriptor(String* key,
89
             Object* value,
90
             PropertyAttributes attributes,
91
             PropertyType type,
92
             int index = 0)
93
      : key_(key),
94
        value_(value),
95
        details_(attributes, type, index) { }
96

    
97
  friend class DescriptorWriter;
98
  friend class DescriptorReader;
99
  friend class DescriptorArray;
100
};
101

    
102
// A pointer from a map to the new map that is created by adding
103
// a named property.  These are key to the speed and functioning of V8.
104
// The two maps should always have the same prototype, since
105
// MapSpace::CreateBackPointers depends on this.
106
class MapTransitionDescriptor: public Descriptor {
107
 public:
108
  MapTransitionDescriptor(String* key, Map* map, PropertyAttributes attributes)
109
      : Descriptor(key, map, attributes, MAP_TRANSITION) { }
110
};
111

    
112
// Marks a field name in a map so that adding the field is guaranteed
113
// to create a FIELD descriptor in the new map.  Used after adding
114
// a constant function the first time, creating a CONSTANT_FUNCTION
115
// descriptor in the new map.  This avoids creating multiple maps with
116
// the same CONSTANT_FUNCTION field.
117
class ConstTransitionDescriptor: public Descriptor {
118
 public:
119
  explicit ConstTransitionDescriptor(String* key)
120
      : Descriptor(key, Smi::FromInt(0), NONE, CONSTANT_TRANSITION) { }
121
};
122

    
123

    
124
class FieldDescriptor: public Descriptor {
125
 public:
126
  FieldDescriptor(String* key,
127
                  int field_index,
128
                  PropertyAttributes attributes,
129
                  int index = 0)
130
      : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
131
};
132

    
133

    
134
class ConstantFunctionDescriptor: public Descriptor {
135
 public:
136
  ConstantFunctionDescriptor(String* key,
137
                             JSFunction* function,
138
                             PropertyAttributes attributes,
139
                             int index = 0)
140
      : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
141
};
142

    
143

    
144
class CallbacksDescriptor:  public Descriptor {
145
 public:
146
  CallbacksDescriptor(String* key,
147
                      Object* proxy,
148
                      PropertyAttributes attributes,
149
                      int index = 0)
150
      : Descriptor(key, proxy, attributes, CALLBACKS, index) {}
151
};
152

    
153

    
154
class LookupResult BASE_EMBEDDED {
155
 public:
156
  // Where did we find the result;
157
  enum {
158
    NOT_FOUND,
159
    DESCRIPTOR_TYPE,
160
    DICTIONARY_TYPE,
161
    INTERCEPTOR_TYPE,
162
    CONSTANT_TYPE
163
  } lookup_type_;
164

    
165
  LookupResult()
166
      : lookup_type_(NOT_FOUND),
167
        cacheable_(true),
168
        details_(NONE, NORMAL) {}
169

    
170
  void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
171
    lookup_type_ = DESCRIPTOR_TYPE;
172
    holder_ = holder;
173
    details_ = details;
174
    number_ = number;
175
  }
176

    
177
  void ConstantResult(JSObject* holder) {
178
    lookup_type_ = CONSTANT_TYPE;
179
    holder_ = holder;
180
    details_ =
181
        PropertyDetails(static_cast<PropertyAttributes>(DONT_ENUM |
182
                                                        DONT_DELETE),
183
                        CALLBACKS);
184
    number_ = -1;
185
  }
186

    
187
  void DictionaryResult(JSObject* holder, int entry) {
188
    lookup_type_ = DICTIONARY_TYPE;
189
    holder_ = holder;
190
    details_ = holder->property_dictionary()->DetailsAt(entry);
191
    number_ = entry;
192
  }
193

    
194
  void InterceptorResult(JSObject* holder) {
195
    lookup_type_ = INTERCEPTOR_TYPE;
196
    holder_ = holder;
197
    details_ = PropertyDetails(NONE, INTERCEPTOR);
198
  }
199

    
200
  void NotFound() {
201
    lookup_type_ = NOT_FOUND;
202
  }
203

    
204
  JSObject* holder() {
205
    ASSERT(IsValid());
206
    return holder_;
207
  }
208

    
209
  PropertyType type() {
210
    ASSERT(IsValid());
211
    return details_.type();
212
  }
213

    
214
  bool IsTransitionType() {
215
    PropertyType t = type();
216
    if (t == MAP_TRANSITION || t == CONSTANT_TRANSITION) return true;
217
    return false;
218
  }
219

    
220
  PropertyAttributes GetAttributes() {
221
    ASSERT(IsValid());
222
    return details_.attributes();
223
  }
224

    
225
  PropertyDetails GetPropertyDetails() {
226
    return details_;
227
  }
228

    
229
  bool IsReadOnly() { return details_.IsReadOnly(); }
230
  bool IsDontDelete() { return details_.IsDontDelete(); }
231
  bool IsDontEnum() { return details_.IsDontEnum(); }
232

    
233
  bool IsValid() { return  lookup_type_ != NOT_FOUND; }
234
  bool IsNotFound() { return lookup_type_ == NOT_FOUND; }
235

    
236
  // Tells whether the result is a property.
237
  // Excluding transitions and the null descriptor.
238
  bool IsProperty() {
239
    return IsValid() && type() < FIRST_PHANTOM_PROPERTY_TYPE;
240
  }
241

    
242
  bool IsCacheable() { return cacheable_; }
243
  void DisallowCaching() { cacheable_ = false; }
244

    
245
  // Tells whether the value needs to be loaded.
246
  bool IsLoaded() {
247
    if (lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ == DICTIONARY_TYPE) {
248
      Object* value = GetValue();
249
      if (value->IsJSFunction()) {
250
        return JSFunction::cast(value)->IsLoaded();
251
      }
252
    }
253
    return true;
254
  }
255

    
256
  Map* GetTransitionMap() {
257
    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
258
    ASSERT(type() == MAP_TRANSITION);
259
    return Map::cast(GetValue());
260
  }
261

    
262
  int GetFieldIndex() {
263
    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
264
    ASSERT(type() == FIELD);
265
    return Descriptor::IndexFromValue(GetValue());
266
  }
267

    
268
  int GetDictionaryEntry() {
269
    ASSERT(lookup_type_ == DICTIONARY_TYPE);
270
    return number_;
271
  }
272

    
273
  JSFunction* GetConstantFunction() {
274
    ASSERT(type() == CONSTANT_FUNCTION);
275
    return JSFunction::cast(GetValue());
276
  }
277

    
278
  Object* GetCallbackObject() {
279
    if (lookup_type_ == CONSTANT_TYPE) {
280
      // For now we only have the __proto__ as constant type.
281
      return Heap::prototype_accessors();
282
    }
283
    return GetValue();
284
  }
285

    
286
#ifdef DEBUG
287
  void Print();
288
#endif
289

    
290
  Object* GetValue() {
291
    if (lookup_type_ == DESCRIPTOR_TYPE) {
292
      DescriptorArray* descriptors = holder()->map()->instance_descriptors();
293
      return descriptors->GetValue(number_);
294
    }
295
    // In the dictionary case, the data is held in the value field.
296
    ASSERT(lookup_type_ == DICTIONARY_TYPE);
297
    return holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
298
  }
299

    
300
 private:
301
  JSObject* holder_;
302
  int number_;
303
  bool cacheable_;
304
  PropertyDetails details_;
305
};
306

    
307

    
308
// The DescriptorStream is an abstraction for iterating over a map's
309
// instance descriptors.
310
class DescriptorStream BASE_EMBEDDED {
311
 public:
312
  explicit DescriptorStream(DescriptorArray* descriptors, int pos) {
313
    descriptors_ = descriptors;
314
    pos_ = pos;
315
    limit_ = descriptors_->number_of_descriptors();
316
  }
317

    
318
  // Tells whether we have reached the end of the steam.
319
  bool eos() { return pos_ >= limit_; }
320

    
321
  int next_position() { return pos_ + 1; }
322
  void advance() { pos_ = next_position(); }
323

    
324
 protected:
325
  DescriptorArray* descriptors_;
326
  int pos_;   // Current position.
327
  int limit_;  // Limit for position.
328
};
329

    
330

    
331
class DescriptorReader: public DescriptorStream {
332
 public:
333
  explicit DescriptorReader(DescriptorArray* descriptors, int pos = 0)
334
      : DescriptorStream(descriptors, pos) {}
335

    
336
  String* GetKey() { return descriptors_->GetKey(pos_); }
337
  Object* GetValue() { return descriptors_->GetValue(pos_); }
338
  PropertyDetails GetDetails() {
339
    return PropertyDetails(descriptors_->GetDetails(pos_));
340
  }
341

    
342
  int GetFieldIndex() { return Descriptor::IndexFromValue(GetValue()); }
343

    
344
  bool IsDontEnum() { return GetDetails().IsDontEnum(); }
345

    
346
  PropertyType type() { return GetDetails().type(); }
347

    
348
  // Tells whether the type is a transition.
349
  bool IsTransition() {
350
    PropertyType t = type();
351
    ASSERT(t != INTERCEPTOR);
352
    return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
353
  }
354

    
355
  bool IsNullDescriptor() {
356
    return type() == NULL_DESCRIPTOR;
357
  }
358

    
359
  bool IsProperty() {
360
    return type() < FIRST_PHANTOM_PROPERTY_TYPE;
361
  }
362

    
363
  JSFunction* GetConstantFunction() { return JSFunction::cast(GetValue()); }
364

    
365
  AccessorDescriptor* GetCallbacks() {
366
    ASSERT(type() == CALLBACKS);
367
    Proxy* p = Proxy::cast(GetCallbacksObject());
368
    return reinterpret_cast<AccessorDescriptor*>(p->proxy());
369
  }
370

    
371
  Object* GetCallbacksObject() {
372
    ASSERT(type() == CALLBACKS);
373
    return GetValue();
374
  }
375

    
376
  bool Equals(String* name) { return name->Equals(GetKey()); }
377

    
378
  void Get(Descriptor* desc) {
379
    descriptors_->Get(pos_, desc);
380
  }
381
};
382

    
383
class DescriptorWriter: public DescriptorStream {
384
 public:
385
  explicit DescriptorWriter(DescriptorArray* descriptors)
386
      : DescriptorStream(descriptors, 0) {}
387

    
388
  // Append a descriptor to this stream.
389
  void Write(Descriptor* desc);
390
  // Read a descriptor from the reader and append it to this stream.
391
  void WriteFrom(DescriptorReader* reader);
392
};
393

    
394
} }  // namespace v8::internal
395

    
396
#endif  // V8_PROPERTY_H_