• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_PROPERTY_H_
6 #define V8_PROPERTY_H_
7 
8 #include "src/factory.h"
9 #include "src/field-index.h"
10 #include "src/field-index-inl.h"
11 #include "src/isolate.h"
12 #include "src/types.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 class OStream;
18 
19 // Abstraction for elements in instance-descriptor arrays.
20 //
21 // Each descriptor has a key, property attributes, property type,
22 // property index (in the actual instance-descriptor array) and
23 // optionally a piece of data.
24 class Descriptor BASE_EMBEDDED {
25  public:
KeyToUniqueName()26   void KeyToUniqueName() {
27     if (!key_->IsUniqueName()) {
28       key_ = key_->GetIsolate()->factory()->InternalizeString(
29           Handle<String>::cast(key_));
30     }
31   }
32 
GetKey()33   Handle<Name> GetKey() const { return key_; }
GetValue()34   Handle<Object> GetValue() const { return value_; }
GetDetails()35   PropertyDetails GetDetails() const { return details_; }
36 
SetSortedKeyIndex(int index)37   void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); }
38 
39  private:
40   Handle<Name> key_;
41   Handle<Object> value_;
42   PropertyDetails details_;
43 
44  protected:
Descriptor()45   Descriptor() : details_(Smi::FromInt(0)) {}
46 
Init(Handle<Name> key,Handle<Object> value,PropertyDetails details)47   void Init(Handle<Name> key, Handle<Object> value, PropertyDetails details) {
48     key_ = key;
49     value_ = value;
50     details_ = details;
51   }
52 
Descriptor(Handle<Name> key,Handle<Object> value,PropertyDetails details)53   Descriptor(Handle<Name> key, Handle<Object> value, PropertyDetails details)
54       : key_(key),
55         value_(value),
56         details_(details) { }
57 
58   Descriptor(Handle<Name> key,
59              Handle<Object> value,
60              PropertyAttributes attributes,
61              PropertyType type,
62              Representation representation,
63              int field_index = 0)
key_(key)64       : key_(key),
65         value_(value),
66         details_(attributes, type, representation, field_index) { }
67 
68   friend class DescriptorArray;
69   friend class Map;
70 };
71 
72 
73 OStream& operator<<(OStream& os, const Descriptor& d);
74 
75 
76 class FieldDescriptor FINAL : public Descriptor {
77  public:
FieldDescriptor(Handle<Name> key,int field_index,PropertyAttributes attributes,Representation representation)78   FieldDescriptor(Handle<Name> key,
79                   int field_index,
80                   PropertyAttributes attributes,
81                   Representation representation)
82       : Descriptor(key, HeapType::Any(key->GetIsolate()), attributes,
83                    FIELD, representation, field_index) {}
FieldDescriptor(Handle<Name> key,int field_index,Handle<HeapType> field_type,PropertyAttributes attributes,Representation representation)84   FieldDescriptor(Handle<Name> key,
85                   int field_index,
86                   Handle<HeapType> field_type,
87                   PropertyAttributes attributes,
88                   Representation representation)
89       : Descriptor(key, field_type, attributes, FIELD,
90                    representation, field_index) { }
91 };
92 
93 
94 class ConstantDescriptor FINAL : public Descriptor {
95  public:
ConstantDescriptor(Handle<Name> key,Handle<Object> value,PropertyAttributes attributes)96   ConstantDescriptor(Handle<Name> key,
97                      Handle<Object> value,
98                      PropertyAttributes attributes)
99       : Descriptor(key, value, attributes, CONSTANT,
100                    value->OptimalRepresentation()) {}
101 };
102 
103 
104 class CallbacksDescriptor FINAL : public Descriptor {
105  public:
CallbacksDescriptor(Handle<Name> key,Handle<Object> foreign,PropertyAttributes attributes)106   CallbacksDescriptor(Handle<Name> key,
107                       Handle<Object> foreign,
108                       PropertyAttributes attributes)
109       : Descriptor(key, foreign, attributes, CALLBACKS,
110                    Representation::Tagged()) {}
111 };
112 
113 
114 class LookupResult FINAL BASE_EMBEDDED {
115  public:
LookupResult(Isolate * isolate)116   explicit LookupResult(Isolate* isolate)
117       : isolate_(isolate),
118         next_(isolate->top_lookup_result()),
119         lookup_type_(NOT_FOUND),
120         holder_(NULL),
121         transition_(NULL),
122         details_(NONE, NORMAL, Representation::None()) {
123     isolate->set_top_lookup_result(this);
124   }
125 
~LookupResult()126   ~LookupResult() {
127     DCHECK(isolate()->top_lookup_result() == this);
128     isolate()->set_top_lookup_result(next_);
129   }
130 
isolate()131   Isolate* isolate() const { return isolate_; }
132 
DescriptorResult(JSObject * holder,PropertyDetails details,int number)133   void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
134     lookup_type_ = DESCRIPTOR_TYPE;
135     holder_ = holder;
136     transition_ = NULL;
137     details_ = details;
138     number_ = number;
139   }
140 
TransitionResult(JSObject * holder,Map * target)141   void TransitionResult(JSObject* holder, Map* target) {
142     lookup_type_ = TRANSITION_TYPE;
143     number_ = target->LastAdded();
144     details_ = target->instance_descriptors()->GetDetails(number_);
145     holder_ = holder;
146     transition_ = target;
147   }
148 
NotFound()149   void NotFound() {
150     lookup_type_ = NOT_FOUND;
151     details_ = PropertyDetails(NONE, NORMAL, Representation::None());
152     holder_ = NULL;
153     transition_ = NULL;
154   }
155 
representation()156   Representation representation() const {
157     DCHECK(IsFound());
158     return details_.representation();
159   }
160 
161   // Property callbacks does not include transitions to callbacks.
IsPropertyCallbacks()162   bool IsPropertyCallbacks() const {
163     DCHECK(!(details_.type() == CALLBACKS && !IsFound()));
164     return !IsTransition() && details_.type() == CALLBACKS;
165   }
166 
IsReadOnly()167   bool IsReadOnly() const {
168     DCHECK(IsFound());
169     return details_.IsReadOnly();
170   }
171 
IsField()172   bool IsField() const {
173     DCHECK(!(details_.type() == FIELD && !IsFound()));
174     return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == FIELD;
175   }
176 
IsConstant()177   bool IsConstant() const {
178     DCHECK(!(details_.type() == CONSTANT && !IsFound()));
179     return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == CONSTANT;
180   }
181 
IsConfigurable()182   bool IsConfigurable() const { return details_.IsConfigurable(); }
IsFound()183   bool IsFound() const { return lookup_type_ != NOT_FOUND; }
IsTransition()184   bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
185 
186   // Is the result is a property excluding transitions and the null descriptor?
IsProperty()187   bool IsProperty() const {
188     return IsFound() && !IsTransition();
189   }
190 
GetTransitionTarget()191   Map* GetTransitionTarget() const {
192     DCHECK(IsTransition());
193     return transition_;
194   }
195 
IsTransitionToField()196   bool IsTransitionToField() const {
197     return IsTransition() && details_.type() == FIELD;
198   }
199 
GetLocalFieldIndexFromMap(Map * map)200   int GetLocalFieldIndexFromMap(Map* map) const {
201     return GetFieldIndexFromMap(map) - map->inobject_properties();
202   }
203 
GetConstantFromMap(Map * map)204   Object* GetConstantFromMap(Map* map) const {
205     DCHECK(details_.type() == CONSTANT);
206     return GetValueFromMap(map);
207   }
208 
GetValueFromMap(Map * map)209   Object* GetValueFromMap(Map* map) const {
210     DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
211            lookup_type_ == TRANSITION_TYPE);
212     DCHECK(number_ < map->NumberOfOwnDescriptors());
213     return map->instance_descriptors()->GetValue(number_);
214   }
215 
GetFieldIndexFromMap(Map * map)216   int GetFieldIndexFromMap(Map* map) const {
217     DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
218            lookup_type_ == TRANSITION_TYPE);
219     DCHECK(number_ < map->NumberOfOwnDescriptors());
220     return map->instance_descriptors()->GetFieldIndex(number_);
221   }
222 
GetFieldTypeFromMap(Map * map)223   HeapType* GetFieldTypeFromMap(Map* map) const {
224     DCHECK_NE(NOT_FOUND, lookup_type_);
225     DCHECK(number_ < map->NumberOfOwnDescriptors());
226     return map->instance_descriptors()->GetFieldType(number_);
227   }
228 
GetFieldOwnerFromMap(Map * map)229   Map* GetFieldOwnerFromMap(Map* map) const {
230     DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
231            lookup_type_ == TRANSITION_TYPE);
232     DCHECK(number_ < map->NumberOfOwnDescriptors());
233     return map->FindFieldOwner(number_);
234   }
235 
236   void Iterate(ObjectVisitor* visitor);
237 
238  private:
239   Isolate* isolate_;
240   LookupResult* next_;
241 
242   // Where did we find the result;
243   enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_;
244 
245   JSReceiver* holder_;
246   Map* transition_;
247   int number_;
248   PropertyDetails details_;
249 };
250 
251 
252 OStream& operator<<(OStream& os, const LookupResult& r);
253 } }  // namespace v8::internal
254 
255 #endif  // V8_PROPERTY_H_
256