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