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