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_FIELD_INDEX_H_
      6 #define V8_FIELD_INDEX_H_
      7 
      8 #include "src/utils.h"
      9 #include "src/property-details.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 class Map;
     15 
     16 // Wrapper class to hold a field index, usually but not necessarily generated
     17 // from a property index. When available, the wrapper class captures additional
     18 // information to allow the field index to be translated back into the property
     19 // index it was originally generated from.
     20 class FieldIndex V8_FINAL {
     21  public:
     22   static FieldIndex ForPropertyIndex(Map* map,
     23                                      int index,
     24                                      bool is_double = false);
     25   static FieldIndex ForInObjectOffset(int offset, Map* map = NULL);
     26   static FieldIndex ForLookupResult(const LookupResult* result);
     27   static FieldIndex ForDescriptor(Map* map, int descriptor_index);
     28   static FieldIndex ForLoadByFieldIndex(Map* map, int index);
     29   static FieldIndex ForKeyedLookupCacheIndex(Map* map, int index);
     30 
     31   bool is_inobject() const {
     32     return IsInObjectBits::decode(bit_field_);
     33   }
     34 
     35   bool is_double() const {
     36     return IsDoubleBits::decode(bit_field_);
     37   }
     38 
     39   int offset() const {
     40     return index() * kPointerSize;
     41   }
     42 
     43   int index() const {
     44     return IndexBits::decode(bit_field_);
     45   }
     46 
     47   int outobject_array_index() const {
     48     ASSERT(!is_inobject());
     49     return index() - first_inobject_property_offset() / kPointerSize;
     50   }
     51 
     52   int property_index() const {
     53     ASSERT(!IsHiddenField::decode(bit_field_));
     54     int result = index() - first_inobject_property_offset() / kPointerSize;
     55     if (!is_inobject()) {
     56       result += InObjectPropertyBits::decode(bit_field_);
     57     }
     58     return result;
     59   }
     60 
     61   int GetLoadByFieldIndex() const {
     62     // For efficiency, the LoadByFieldIndex instruction takes an index that is
     63     // optimized for quick access. If the property is inline, the index is
     64     // positive. If it's out-of-line, the encoded index is -raw_index - 1 to
     65     // disambiguate the zero out-of-line index from the zero inobject case.
     66     // The index itself is shifted up by one bit, the lower-most bit
     67     // signifying if the field is a mutable double box (1) or not (0).
     68     int result = index() - first_inobject_property_offset() / kPointerSize;
     69     if (!is_inobject()) {
     70       result = -result - 1;
     71     }
     72     result <<= 1;
     73     return is_double() ? (result | 1) : result;
     74   }
     75 
     76   int GetKeyedLookupCacheIndex() const;
     77 
     78   int GetLoadFieldStubKey() const {
     79     return bit_field_ &
     80         (IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask);
     81   }
     82 
     83  private:
     84   FieldIndex(bool is_inobject, int local_index, bool is_double,
     85              int inobject_properties, int first_inobject_property_offset,
     86              bool is_hidden = false) {
     87     ASSERT((first_inobject_property_offset & (kPointerSize - 1)) == 0);
     88     bit_field_ = IsInObjectBits::encode(is_inobject) |
     89       IsDoubleBits::encode(is_double) |
     90       FirstInobjectPropertyOffsetBits::encode(first_inobject_property_offset) |
     91       IsHiddenField::encode(is_hidden) |
     92       IndexBits::encode(local_index) |
     93       InObjectPropertyBits::encode(inobject_properties);
     94   }
     95 
     96   int first_inobject_property_offset() const {
     97     ASSERT(!IsHiddenField::decode(bit_field_));
     98     return FirstInobjectPropertyOffsetBits::decode(bit_field_);
     99   }
    100 
    101   static const int kIndexBitsSize = kDescriptorIndexBitCount + 1;
    102 
    103   class IndexBits: public BitField<int, 0, kIndexBitsSize> {};
    104   class IsInObjectBits: public BitField<bool, IndexBits::kNext, 1> {};
    105   class IsDoubleBits: public BitField<bool, IsInObjectBits::kNext, 1> {};
    106   class InObjectPropertyBits: public BitField<int, IsDoubleBits::kNext,
    107                                               kDescriptorIndexBitCount> {};
    108   class FirstInobjectPropertyOffsetBits:
    109       public BitField<int, InObjectPropertyBits::kNext, 7> {};
    110   class IsHiddenField:
    111       public BitField<bool, FirstInobjectPropertyOffsetBits::kNext, 1> {};
    112   STATIC_ASSERT(IsHiddenField::kNext <= 32);
    113 
    114   int bit_field_;
    115 };
    116 
    117 } }  // namespace v8::internal
    118 
    119 #endif
    120