Start adding support for elements to the LookupIterator
authorverwaest <verwaest@chromium.org>
Thu, 21 May 2015 12:19:39 +0000 (05:19 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 21 May 2015 12:19:23 +0000 (12:19 +0000)
BUG=

Review URL: https://codereview.chromium.org/1144883002

Cr-Commit-Position: refs/heads/master@{#28546}

src/elements.cc
src/elements.h
src/lookup-inl.h
src/lookup.cc
src/lookup.h

index 0237a97..a2068dc 100644 (file)
@@ -616,7 +616,7 @@ class ElementsAccessorBase : public ElementsAccessor {
       Handle<JSObject> obj,
       uint32_t key,
       Handle<FixedArrayBase> backing_store) {
-    if (key < ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) {
+    if (key < ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) {
       return BackingStore::get(Handle<BackingStore>::cast(backing_store), key);
     } else {
       return backing_store->GetIsolate()->factory()->the_hole_value();
@@ -634,7 +634,8 @@ class ElementsAccessorBase : public ElementsAccessor {
         Handle<JSObject> obj,
         uint32_t key,
         Handle<FixedArrayBase> backing_store) {
-    if (key >= ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) {
+    if (key >=
+        ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) {
       return ABSENT;
     }
     return
@@ -749,7 +750,7 @@ class ElementsAccessorBase : public ElementsAccessor {
 
     // Optimize if 'other' is empty.
     // We cannot optimize if 'this' is empty, as other may have holes.
-    uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(receiver, from);
+    uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from);
     if (len1 == 0) return to;
 
     Isolate* isolate = from->GetIsolate();
@@ -757,7 +758,7 @@ class ElementsAccessorBase : public ElementsAccessor {
     // Compute how many elements are not in other.
     uint32_t extra = 0;
     for (uint32_t y = 0; y < len1; y++) {
-      uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y);
+      uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y);
       if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) {
         Handle<Object> value;
         ASSIGN_RETURN_ON_EXCEPTION(
@@ -793,8 +794,7 @@ class ElementsAccessorBase : public ElementsAccessor {
     // Fill in the extra values.
     uint32_t index = 0;
     for (uint32_t y = 0; y < len1; y++) {
-      uint32_t key =
-          ElementsAccessorSubclass::GetKeyForIndexImpl(from, y);
+      uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y);
       if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) {
         Handle<Object> value;
         ASSIGN_RETURN_ON_EXCEPTION(
@@ -815,26 +815,45 @@ class ElementsAccessorBase : public ElementsAccessor {
   }
 
  protected:
-  static uint32_t GetCapacityImpl(Handle<JSObject> holder,
-                                  Handle<FixedArrayBase> backing_store) {
+  static uint32_t GetCapacityImpl(JSObject* holder,
+                                  FixedArrayBase* backing_store) {
     return backing_store->length();
   }
 
-  uint32_t GetCapacity(Handle<JSObject> holder,
-                       Handle<FixedArrayBase> backing_store) final {
+  uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final {
     return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store);
   }
 
-  static uint32_t GetKeyForIndexImpl(Handle<FixedArrayBase> backing_store,
+  static uint32_t GetKeyForIndexImpl(FixedArrayBase* backing_store,
                                      uint32_t index) {
     return index;
   }
 
-  virtual uint32_t GetKeyForIndex(Handle<FixedArrayBase> backing_store,
+  virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
                                   uint32_t index) final {
     return ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index);
   }
 
+  static uint32_t GetIndexForKeyImpl(FixedArrayBase* backing_store,
+                                     uint32_t key) {
+    return key;
+  }
+
+  virtual uint32_t GetIndexForKey(FixedArrayBase* backing_store,
+                                  uint32_t key) final {
+    return ElementsAccessorSubclass::GetIndexForKeyImpl(backing_store, key);
+  }
+
+  static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
+                                        uint32_t index) {
+    return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
+  }
+
+  virtual PropertyDetails GetDetails(FixedArrayBase* backing_store,
+                                     uint32_t index) final {
+    return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index);
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
 };
@@ -1260,7 +1279,7 @@ class TypedElementsAccessor
       Handle<JSObject> obj,
       uint32_t key,
       Handle<FixedArrayBase> backing_store) {
-    if (key < AccessorClass::GetCapacityImpl(obj, backing_store)) {
+    if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) {
       return BackingStore::get(Handle<BackingStore>::cast(backing_store), key);
     } else {
       return backing_store->GetIsolate()->factory()->undefined_value();
@@ -1271,8 +1290,8 @@ class TypedElementsAccessor
       Handle<JSObject> obj,
       uint32_t key,
       Handle<FixedArrayBase> backing_store) {
-    return key < AccessorClass::GetCapacityImpl(obj, backing_store) ? NONE
-                                                                    : ABSENT;
+    return key < AccessorClass::GetCapacityImpl(*obj, *backing_store) ? NONE
+                                                                      : ABSENT;
   }
 
   MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl(
@@ -1292,13 +1311,13 @@ class TypedElementsAccessor
 
   static bool HasElementImpl(Handle<JSObject> holder, uint32_t key,
                              Handle<FixedArrayBase> backing_store) {
-    uint32_t capacity = AccessorClass::GetCapacityImpl(holder, backing_store);
+    uint32_t capacity = AccessorClass::GetCapacityImpl(*holder, *backing_store);
     return key < capacity;
   }
 
-  static uint32_t GetCapacityImpl(Handle<JSObject> holder,
-                                  Handle<FixedArrayBase> backing_store) {
-    Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(holder);
+  static uint32_t GetCapacityImpl(JSObject* holder,
+                                  FixedArrayBase* backing_store) {
+    JSArrayBufferView* view = JSArrayBufferView::cast(holder);
     if (view->WasNeutered()) return 0;
     return backing_store->length();
   }
@@ -1500,14 +1519,27 @@ class DictionaryElementsAccessor
     return backing_store->FindEntry(key) != SeededNumberDictionary::kNotFound;
   }
 
-  static uint32_t GetKeyForIndexImpl(Handle<FixedArrayBase> store,
-                                     uint32_t index) {
+  static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) {
     DisallowHeapAllocation no_gc;
-    Handle<SeededNumberDictionary> dict =
-        Handle<SeededNumberDictionary>::cast(store);
+    SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
     Object* key = dict->KeyAt(index);
     return Smi::cast(key)->value();
   }
+
+  static uint32_t GetIndexForKeyImpl(FixedArrayBase* store, uint32_t key) {
+    DisallowHeapAllocation no_gc;
+    SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
+    int entry = dict->FindEntry(key);
+    if (entry == SeededNumberDictionary::kNotFound) {
+      return kMaxUInt32;
+    }
+    return static_cast<uint32_t>(entry);
+  }
+
+  static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
+                                        uint32_t index) {
+    return SeededNumberDictionary::cast(backing_store)->DetailsAt(index);
+  }
 };
 
 
@@ -1637,20 +1669,28 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
     UNREACHABLE();
   }
 
-  static uint32_t GetCapacityImpl(Handle<JSObject> holder,
-                                  Handle<FixedArrayBase> backing_store) {
-    Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(backing_store);
-    Handle<FixedArrayBase> arguments(
-        FixedArrayBase::cast(parameter_map->get(1)));
+  static uint32_t GetCapacityImpl(JSObject* holder,
+                                  FixedArrayBase* backing_store) {
+    FixedArray* parameter_map = FixedArray::cast(backing_store);
+    FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
     return Max(static_cast<uint32_t>(parameter_map->length() - 2),
                ForArray(arguments)->GetCapacity(holder, arguments));
   }
 
-  static uint32_t GetKeyForIndexImpl(Handle<FixedArrayBase> dict,
-                                     uint32_t index) {
+  static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, uint32_t index) {
     return index;
   }
 
+  static uint32_t GetIndexForKeyImpl(FixedArrayBase* dict, uint32_t key) {
+    return key;
+  }
+
+  static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
+                                        uint32_t index) {
+    return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
+  }
+
+
  private:
   static Handle<Object> GetParameterMapArg(Handle<JSObject> holder,
                                            Handle<FixedArray> parameter_map,
@@ -1666,8 +1706,13 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
 };
 
 
+ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
+  return elements_accessors_[ElementsKindForArray(array)];
+}
+
+
 ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) {
-  return elements_accessors_[ElementsKindForArray(*array)];
+  return ForArray(*array);
 }
 
 
index 8704fff..f4d15fc 100644 (file)
@@ -175,9 +175,12 @@ class ElementsAccessor {
 
  protected:
   friend class SloppyArgumentsElementsAccessor;
+  friend class LookupIterator;
 
-  virtual uint32_t GetCapacity(Handle<JSObject> holder,
-                               Handle<FixedArrayBase> backing_store) = 0;
+  static ElementsAccessor* ForArray(FixedArrayBase* array);
+
+  virtual uint32_t GetCapacity(JSObject* holder,
+                               FixedArrayBase* backing_store) = 0;
 
   // Element handlers distinguish between indexes and keys when they manipulate
   // elements.  Indexes refer to elements in terms of their location in the
@@ -187,8 +190,12 @@ class ElementsAccessor {
   // keys are equivalent to indexes, and GetKeyForIndex returns the same value
   // it is passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps
   // the index to a key using the KeyAt method on the NumberDictionary.
-  virtual uint32_t GetKeyForIndex(Handle<FixedArrayBase> backing_store,
+  virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
                                   uint32_t index) = 0;
+  virtual uint32_t GetIndexForKey(FixedArrayBase* backing_store,
+                                  uint32_t key) = 0;
+  virtual PropertyDetails GetDetails(FixedArrayBase* backing_store,
+                                     uint32_t index) = 0;
 
  private:
   static ElementsAccessor** elements_accessors_;
index a801e34..50f0d3e 100644 (file)
@@ -42,25 +42,33 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
     case NOT_FOUND:
       if (map->IsJSProxyMap()) return JSPROXY;
       if (map->is_access_check_needed() &&
-          !isolate_->IsInternallyUsedPropertyName(name_)) {
+          (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) {
         return ACCESS_CHECK;
       }
     // Fall through.
     case ACCESS_CHECK:
-      if (exotic_index_state_ != ExoticIndexState::kNoIndex &&
+      if (exotic_index_state_ != ExoticIndexState::kNotExotic &&
           IsIntegerIndexedExotic(holder)) {
         return INTEGER_INDEXED_EXOTIC;
       }
-      if (check_interceptor() && map->has_named_interceptor() &&
+      if (check_interceptor() && HasInterceptor(map) &&
           !SkipInterceptor(JSObject::cast(holder))) {
         return INTERCEPTOR;
       }
     // Fall through.
     case INTERCEPTOR:
-      if (map->is_dictionary_map()) {
+      if (IsElement()) {
+        JSObject* js_object = JSObject::cast(holder);
+        ElementsAccessor* accessor = js_object->GetElementsAccessor();
+        FixedArrayBase* backing_store = js_object->elements();
+        number_ = accessor->GetIndexForKey(backing_store, index_);
+        if (number_ == kMaxUInt32) return NOT_FOUND;
+        property_details_ = accessor->GetDetails(backing_store, number_);
+      } else if (map->is_dictionary_map()) {
         NameDictionary* dict = JSObject::cast(holder)->property_dictionary();
-        number_ = dict->FindEntry(name_);
-        if (number_ == NameDictionary::kNotFound) return NOT_FOUND;
+        int number = dict->FindEntry(name_);
+        if (number == NameDictionary::kNotFound) return NOT_FOUND;
+        number_ = static_cast<uint32_t>(number);
         if (holder->IsGlobalObject()) {
           DCHECK(dict->ValueAt(number_)->IsPropertyCell());
           PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
@@ -69,8 +77,9 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
         property_details_ = dict->DetailsAt(number_);
       } else {
         DescriptorArray* descriptors = map->instance_descriptors();
-        number_ = descriptors->SearchWithCache(*name_, map);
-        if (number_ == DescriptorArray::kNotFound) return NOT_FOUND;
+        int number = descriptors->SearchWithCache(*name_, map);
+        if (number == DescriptorArray::kNotFound) return NOT_FOUND;
+        number_ = static_cast<uint32_t>(number);
         property_details_ = descriptors->GetDetails(number_);
       }
       has_property_ = true;
@@ -97,7 +106,7 @@ LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder(
     Map* const map, JSReceiver* const holder) {
   switch (state_) {
     case NOT_FOUND:
-      if (check_interceptor() && map->has_named_interceptor() &&
+      if (check_interceptor() && HasInterceptor(map) &&
           !SkipInterceptor(JSObject::cast(holder))) {
         return INTERCEPTOR;
       }
index 85745ce..8eb5571 100644 (file)
@@ -145,7 +145,7 @@ void LookupIterator::PrepareTransitionToDataProperty(
   DCHECK(state_ != LookupIterator::ACCESSOR ||
          (GetAccessors()->IsAccessorInfo() &&
           AccessorInfo::cast(*GetAccessors())->is_special_data_property()));
-  DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, state_);
+  DCHECK_NE(INTEGER_INDEXED_EXOTIC, state_);
   DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype());
   // Can only be called when the receiver is a JSObject. JSProxy has to be
   // handled via a trap. Adding properties to primitive values is not
@@ -355,10 +355,10 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
 
 
 bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) {
-  DCHECK(exotic_index_state_ != ExoticIndexState::kNoIndex);
+  DCHECK(ExoticIndexState::kNotExotic != exotic_index_state_);
   // Currently typed arrays are the only such objects.
   if (!holder->IsJSTypedArray()) return false;
-  if (exotic_index_state_ == ExoticIndexState::kIndex) return true;
+  if (exotic_index_state_ == ExoticIndexState::kExotic) return true;
   DCHECK(exotic_index_state_ == ExoticIndexState::kUninitialized);
   bool result = false;
   // Compute and cache result.
@@ -369,7 +369,7 @@ bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) {
     }
   }
   exotic_index_state_ =
-      result ? ExoticIndexState::kIndex : ExoticIndexState::kNoIndex;
+      result ? ExoticIndexState::kExotic : ExoticIndexState::kNotExotic;
   return result;
 }
 
@@ -380,6 +380,12 @@ void LookupIterator::InternalizeName() {
 }
 
 
+bool LookupIterator::HasInterceptor(Map* map) const {
+  if (IsElement()) return map->has_indexed_interceptor();
+  return map->has_named_interceptor();
+}
+
+
 bool LookupIterator::SkipInterceptor(JSObject* holder) {
   auto info = holder->GetNamedInterceptor();
   // TODO(dcarney): check for symbol/can_intercept_symbols here as well.
index a574980..48dce3a 100644 (file)
@@ -52,6 +52,8 @@ class LookupIterator final BASE_EMBEDDED {
         property_details_(PropertyDetails::Empty()),
         isolate_(name->GetIsolate()),
         name_(name),
+        // kMaxUInt32 isn't a valid index.
+        index_(kMaxUInt32),
         receiver_(receiver),
         holder_(GetRoot(receiver_, isolate_)),
         holder_map_(holder_->map(), isolate_),
@@ -70,6 +72,8 @@ class LookupIterator final BASE_EMBEDDED {
         property_details_(PropertyDetails::Empty()),
         isolate_(name->GetIsolate()),
         name_(name),
+        // kMaxUInt32 isn't a valid index.
+        index_(kMaxUInt32),
         receiver_(receiver),
         holder_(holder),
         holder_map_(holder_->map(), isolate_),
@@ -78,9 +82,54 @@ class LookupIterator final BASE_EMBEDDED {
     Next();
   }
 
+  LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
+                 Configuration configuration = PROTOTYPE_CHAIN)
+      : configuration_(configuration),
+        state_(NOT_FOUND),
+        exotic_index_state_(ExoticIndexState::kNotExotic),
+        interceptor_state_(InterceptorState::kUninitialized),
+        property_details_(PropertyDetails::Empty()),
+        isolate_(isolate),
+        name_(),
+        index_(index),
+        receiver_(receiver),
+        holder_(GetRoot(receiver_, isolate_)),
+        holder_map_(holder_->map(), isolate_),
+        initial_holder_(holder_),
+        number_(DescriptorArray::kNotFound) {
+    // kMaxUInt32 isn't a valid index.
+    DCHECK_NE(kMaxUInt32, index_);
+    Next();
+  }
+
+  LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
+                 Handle<JSReceiver> holder,
+                 Configuration configuration = PROTOTYPE_CHAIN)
+      : configuration_(configuration),
+        state_(NOT_FOUND),
+        exotic_index_state_(ExoticIndexState::kNotExotic),
+        interceptor_state_(InterceptorState::kUninitialized),
+        property_details_(PropertyDetails::Empty()),
+        isolate_(isolate),
+        name_(),
+        index_(index),
+        receiver_(receiver),
+        holder_(holder),
+        holder_map_(holder_->map(), isolate_),
+        initial_holder_(holder_),
+        number_(DescriptorArray::kNotFound) {
+    // kMaxUInt32 isn't a valid index.
+    DCHECK_NE(kMaxUInt32, index_);
+    Next();
+  }
+
   Isolate* isolate() const { return isolate_; }
   State state() const { return state_; }
+
   Handle<Name> name() const { return name_; }
+  uint32_t index() const { return index_; }
+
+  bool IsElement() const { return index_ != kMaxUInt32; }
 
   bool IsFound() const { return state_ != NOT_FOUND; }
   void Next();
@@ -161,6 +210,7 @@ class LookupIterator final BASE_EMBEDDED {
   Handle<Object> FetchValue() const;
   void ReloadPropertyInformation();
   bool SkipInterceptor(JSObject* holder);
+  bool HasInterceptor(Map* map) const;
 
   bool IsBootstrapping() const;
 
@@ -192,7 +242,7 @@ class LookupIterator final BASE_EMBEDDED {
     }
   }
 
-  enum class ExoticIndexState { kUninitialized, kNoIndex, kIndex };
+  enum class ExoticIndexState { kUninitialized, kNotExotic, kExotic };
   bool IsIntegerIndexedExotic(JSReceiver* holder);
 
   // If configuration_ becomes mutable, update
@@ -205,12 +255,13 @@ class LookupIterator final BASE_EMBEDDED {
   PropertyDetails property_details_;
   Isolate* const isolate_;
   Handle<Name> name_;
+  uint32_t index_;
   Handle<Object> transition_;
   const Handle<Object> receiver_;
   Handle<JSReceiver> holder_;
   Handle<Map> holder_map_;
   const Handle<JSReceiver> initial_holder_;
-  int number_;
+  uint32_t number_;
 };