Home | History | Annotate | Download | only in src
      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:
     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 
     73 OStream& operator<<(OStream& os, const Descriptor& d);
     74 
     75 
     76 class 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 
     94 class 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 
    104 class 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 
    114 class 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 
    252 OStream& operator<<(OStream& os, const LookupResult& r);
    253 } }  // namespace v8::internal
    254 
    255 #endif  // V8_PROPERTY_H_
    256