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
14namespace v8 {
15namespace internal {
16
17class 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.
24class Descriptor BASE_EMBEDDED {
25 public:
26  void KeyToUniqueName() {
27    if (!key_->IsUniqueName()) {
28      key_ = key_->GetIsolate()->factory()->InternalizeString(
29          Handle<String>::cast(key_));
30    }
31  }
32
33  Handle<Name> GetKey() const { return key_; }
34  Handle<Object> GetValue() const { return value_; }
35  PropertyDetails GetDetails() const { return details_; }
36
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:
45  Descriptor() : details_(Smi::FromInt(0)) {}
46
47  void Init(Handle<Name> key, Handle<Object> value, PropertyDetails details) {
48    key_ = key;
49    value_ = value;
50    details_ = details;
51  }
52
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)
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
73OStream& operator<<(OStream& os, const Descriptor& d);
74
75
76class FieldDescriptor FINAL : public Descriptor {
77 public:
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) {}
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
94class ConstantDescriptor FINAL : public Descriptor {
95 public:
96  ConstantDescriptor(Handle<Name> key,
97                     Handle<Object> value,
98                     PropertyAttributes attributes)
99      : Descriptor(key, value, attributes, CONSTANT,
100                   value->OptimalRepresentation()) {}
101};
102
103
104class CallbacksDescriptor FINAL : public Descriptor {
105 public:
106  CallbacksDescriptor(Handle<Name> key,
107                      Handle<Object> foreign,
108                      PropertyAttributes attributes)
109      : Descriptor(key, foreign, attributes, CALLBACKS,
110                   Representation::Tagged()) {}
111};
112
113
114class LookupResult FINAL BASE_EMBEDDED {
115 public:
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
126  ~LookupResult() {
127    DCHECK(isolate()->top_lookup_result() == this);
128    isolate()->set_top_lookup_result(next_);
129  }
130
131  Isolate* isolate() const { return isolate_; }
132
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
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
149  void NotFound() {
150    lookup_type_ = NOT_FOUND;
151    details_ = PropertyDetails(NONE, NORMAL, Representation::None());
152    holder_ = NULL;
153    transition_ = NULL;
154  }
155
156  Representation representation() const {
157    DCHECK(IsFound());
158    return details_.representation();
159  }
160
161  // Property callbacks does not include transitions to callbacks.
162  bool IsPropertyCallbacks() const {
163    DCHECK(!(details_.type() == CALLBACKS && !IsFound()));
164    return !IsTransition() && details_.type() == CALLBACKS;
165  }
166
167  bool IsReadOnly() const {
168    DCHECK(IsFound());
169    return details_.IsReadOnly();
170  }
171
172  bool IsField() const {
173    DCHECK(!(details_.type() == FIELD && !IsFound()));
174    return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == FIELD;
175  }
176
177  bool IsConstant() const {
178    DCHECK(!(details_.type() == CONSTANT && !IsFound()));
179    return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == CONSTANT;
180  }
181
182  bool IsConfigurable() const { return details_.IsConfigurable(); }
183  bool IsFound() const { return lookup_type_ != NOT_FOUND; }
184  bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
185
186  // Is the result is a property excluding transitions and the null descriptor?
187  bool IsProperty() const {
188    return IsFound() && !IsTransition();
189  }
190
191  Map* GetTransitionTarget() const {
192    DCHECK(IsTransition());
193    return transition_;
194  }
195
196  bool IsTransitionToField() const {
197    return IsTransition() && details_.type() == FIELD;
198  }
199
200  int GetLocalFieldIndexFromMap(Map* map) const {
201    return GetFieldIndexFromMap(map) - map->inobject_properties();
202  }
203
204  Object* GetConstantFromMap(Map* map) const {
205    DCHECK(details_.type() == CONSTANT);
206    return GetValueFromMap(map);
207  }
208
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
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
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
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
252OStream& operator<<(OStream& os, const LookupResult& r);
253} }  // namespace v8::internal
254
255#endif  // V8_PROPERTY_H_
256