Use the LookupIterator for SetElement and friends
authorverwaest <verwaest@chromium.org>
Thu, 11 Jun 2015 15:07:00 +0000 (08:07 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 11 Jun 2015 15:07:16 +0000 (15:07 +0000)
BUG=v8:4137
LOG=n

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

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

26 files changed:
src/api.cc
src/api.h
src/array.js
src/ast.cc
src/elements.cc
src/elements.h
src/harmony-array.js
src/ic/ic.cc
src/json-parser.h
src/liveedit.cc
src/liveedit.h
src/lookup.cc
src/lookup.h
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime.js
src/runtime/runtime-array.cc
src/runtime/runtime-classes.cc
src/runtime/runtime-debug.cc
src/runtime/runtime-literals.cc
src/runtime/runtime-object.cc
src/runtime/runtime.h
test/cctest/test-api.cc
test/cctest/test-heap.cc
test/cctest/test-migrations.cc

index 7c29a344f1faa45140d865afe047c905fb742590..b8812800081d1b36ea84b5871c2a80a8d870bb93 100644 (file)
@@ -3485,8 +3485,8 @@ Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, uint32_t index,
   PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Set()", bool);
   auto self = Utils::OpenHandle(this);
   auto value_obj = Utils::OpenHandle(*value);
-  has_pending_exception = i::JSObject::SetElement(
-      self, index, value_obj, NONE, i::SLOPPY).is_null();
+  has_pending_exception =
+      i::JSReceiver::SetElement(self, index, value_obj, i::SLOPPY).is_null();
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
   return Just(true);
 }
@@ -3533,18 +3533,7 @@ Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
     it.Next();
   }
 
-  if (it.state() == i::LookupIterator::DATA ||
-      it.state() == i::LookupIterator::ACCESSOR) {
-    if (!it.IsConfigurable()) return Just(false);
-
-    if (it.state() == i::LookupIterator::ACCESSOR) {
-      has_pending_exception = i::JSObject::SetOwnPropertyIgnoreAttributes(
-                                  self, key_obj, value_obj, NONE,
-                                  i::JSObject::DONT_FORCE_FIELD).is_null();
-      RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-      return Just(true);
-    }
-  }
+  if (it.IsFound() && !it.IsConfigurable()) return Just(false);
 
   has_pending_exception = i::Runtime::DefineObjectProperty(
                               self, key_obj, value_obj, NONE).is_null();
index 6d7aaeab4adec09d6404310a530c842be86c82fe..b20ef5cf66f3cb401875ea40c1a3fca8b3e8045e 100644 (file)
--- a/src/api.h
+++ b/src/api.h
@@ -95,6 +95,7 @@ void NeanderObject::set(int offset, v8::internal::Object* value) {
 
 template <typename T> inline T ToCData(v8::internal::Object* obj) {
   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
+  if (obj == v8::internal::Smi::FromInt(0)) return nullptr;
   return reinterpret_cast<T>(
       reinterpret_cast<intptr_t>(
           v8::internal::Foreign::cast(obj)->foreign_address()));
@@ -105,6 +106,7 @@ template <typename T>
 inline v8::internal::Handle<v8::internal::Object> FromCData(
     v8::internal::Isolate* isolate, T obj) {
   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
+  if (obj == nullptr) return handle(v8::internal::Smi::FromInt(0), isolate);
   return isolate->factory()->NewForeign(
       reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
 }
index 467fd99d68a4868b49ebb63f5ccf4acacf7fb6e5..309871f6f95a7811537d1be6132e6afe7fea1be3 100644 (file)
@@ -243,7 +243,7 @@ function SparseSlice(array, start_i, del_count, len, deleted_elements) {
     for (var i = start_i; i < limit; ++i) {
       var current = array[i];
       if (!IS_UNDEFINED(current) || i in array) {
-        %AddElement(deleted_elements, i - start_i, current, NONE);
+        %AddElement(deleted_elements, i - start_i, current);
       }
     }
   } else {
@@ -254,7 +254,7 @@ function SparseSlice(array, start_i, del_count, len, deleted_elements) {
         if (key >= start_i) {
           var current = array[key];
           if (!IS_UNDEFINED(current) || key in array) {
-            %AddElement(deleted_elements, key - start_i, current, NONE);
+            %AddElement(deleted_elements, key - start_i, current);
           }
         }
       }
@@ -336,7 +336,7 @@ function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
       var current = array[index];
       // The spec requires [[DefineOwnProperty]] here, %AddElement is close
       // enough (in that it ignores the prototype).
-      %AddElement(deleted_elements, i, current, NONE);
+      %AddElement(deleted_elements, i, current);
     }
   }
 }
index 06846ffb8f5c431c938beb5ced8bb0f2ad55d0b2..c9e4c0f21974a8983024e4bc0b4f1415cccc87e1 100644 (file)
@@ -541,17 +541,19 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
       }
     }
     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
+
     if (boilerplate_value->IsTheHole()) {
       is_holey = true;
-    } else if (boilerplate_value->IsUninitialized()) {
+      continue;
+    }
+
+    if (boilerplate_value->IsUninitialized()) {
+      boilerplate_value = handle(Smi::FromInt(0), isolate);
       is_simple = false;
-      JSObject::SetOwnElement(array, array_index,
-                              handle(Smi::FromInt(0), isolate),
-                              SLOPPY).Assert();
-    } else {
-      JSObject::SetOwnElement(array, array_index, boilerplate_value, SLOPPY)
-          .Assert();
     }
+
+    JSObject::AddDataElement(array, array_index, boilerplate_value, NONE)
+        .Assert();
   }
 
   if (array_index != values()->length()) {
index cf55a202b4689f6b57598abfd0ebef6fc6d2450f..2734823852896d9379bcd870f10c32cb263de373 100644 (file)
@@ -618,6 +618,21 @@ class ElementsAccessorBase : public ElementsAccessor {
     }
   }
 
+  virtual Handle<Object> Set(Handle<JSObject> holder, uint32_t key,
+                             Handle<FixedArrayBase> backing_store,
+                             Handle<Object> value) final {
+    return ElementsAccessorSubclass::SetImpl(holder, key, backing_store, value);
+  }
+
+  static Handle<Object> SetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> backing_store,
+                                Handle<Object> value) {
+    CHECK(key <
+          ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store));
+    return BackingStore::SetValue(
+        obj, Handle<BackingStore>::cast(backing_store), key, value);
+  }
+
   virtual PropertyAttributes GetAttributes(
       JSObject* holder, uint32_t key, FixedArrayBase* backing_store) final {
     return ElementsAccessorSubclass::GetAttributesImpl(holder, key,
@@ -1280,8 +1295,14 @@ class TypedElementsAccessor
 
   static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
                                               FixedArrayBase* backing_store) {
-    return key < AccessorClass::GetCapacityImpl(obj, backing_store) ? NONE
-                                                                    : ABSENT;
+    return key < AccessorClass::GetCapacityImpl(obj, backing_store)
+               ? DONT_DELETE
+               : ABSENT;
+  }
+
+  static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
+                                        uint32_t index) {
+    return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell);
   }
 
   MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl(
@@ -1453,6 +1474,17 @@ class DictionaryElementsAccessor
     return isolate->factory()->the_hole_value();
   }
 
+  static Handle<Object> SetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> store,
+                                Handle<Object> value) {
+    Handle<SeededNumberDictionary> backing_store =
+        Handle<SeededNumberDictionary>::cast(store);
+    int entry = backing_store->FindEntry(key);
+    DCHECK_NE(SeededNumberDictionary::kNotFound, entry);
+    backing_store->ValueAtPut(entry, *value);
+    return value;
+  }
+
   static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
                                               FixedArrayBase* backing_store) {
     SeededNumberDictionary* dictionary =
@@ -1559,6 +1591,23 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
     }
   }
 
+  static Handle<Object> SetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> store,
+                                Handle<Object> value) {
+    Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
+    Object* probe = GetParameterMapArg(*parameter_map, key);
+    if (!probe->IsTheHole()) {
+      Context* context = Context::cast(parameter_map->get(0));
+      int context_index = Smi::cast(probe)->value();
+      DCHECK(!context->get(context_index)->IsTheHole());
+      context->set(context_index, *value);
+      return value;
+    }
+    Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+    return ElementsAccessor::ForArray(arguments)
+        ->Set(obj, key, arguments, value);
+  }
+
   static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
                                               FixedArrayBase* backing_store) {
     FixedArray* parameter_map = FixedArray::cast(backing_store);
index 49faeab0dbd04012b87de6d22067e5cb72040b10..60ff130d2998ce59089567e218ee2716de6cae9b 100644 (file)
@@ -43,6 +43,11 @@ class ElementsAccessor {
     return HasElement(holder, key, handle(holder->elements()));
   }
 
+  inline Handle<Object> Set(Handle<JSObject> holder, uint32_t key,
+                            Handle<Object> value) {
+    return Set(holder, key, handle(holder->elements()), value);
+  }
+
   // Returns the element with the specified key or undefined if there is no such
   // element. This method doesn't iterate up the prototype chain.  The caller
   // can optionally pass in the backing store to use for the check, which must
@@ -187,6 +192,10 @@ class ElementsAccessor {
                                      uint32_t index) = 0;
   virtual bool HasIndex(FixedArrayBase* backing_store, uint32_t key) = 0;
 
+  virtual Handle<Object> Set(Handle<JSObject> holder, uint32_t key,
+                             Handle<FixedArrayBase> backing_store,
+                             Handle<Object> value) = 0;
+
  private:
   static ElementsAccessor** elements_accessors_;
   const char* name_;
index 51e2d01b50147ded30436174685b23aca3484ac9..f9ce2f194f9ac0976cc7fe1ec289abbfc7154899 100644 (file)
@@ -238,7 +238,8 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
       } else {
         mappedValue = nextValue;
       }
-      %AddElement(result, k++, mappedValue, NONE);
+      // TODO(verwaest): This should redefine rather than adding.
+      %AddElement(result, k++, mappedValue);
     }
   } else {
     var len = $toLength(items.length);
@@ -251,7 +252,8 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
       } else {
         mappedValue = nextValue;
       }
-      %AddElement(result, k, mappedValue, NONE);
+      // TODO(verwaest): This should redefine rather than adding.
+      %AddElement(result, k, mappedValue);
     }
 
     result.length = k;
@@ -266,7 +268,8 @@ function ArrayOf() {
   // TODO: Implement IsConstructor (ES6 section 7.2.5)
   var array = %IsConstructor(constructor) ? new constructor(length) : [];
   for (var i = 0; i < length; i++) {
-    %AddElement(array, i, %_Arguments(i), NONE);
+    // TODO(verwaest): This should redefine rather than adding.
+    %AddElement(array, i, %_Arguments(i));
   }
   array.length = length;
   return array;
index e8be95ba34a5e9d17a89d2ab76b692b2ebc16f91..c0d8e005abedeb32ce95b1d70c396e590e24a719 100644 (file)
@@ -1480,8 +1480,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
     Handle<Object> result;
     ASSIGN_RETURN_ON_EXCEPTION(
         isolate(), result,
-        JSObject::SetElement(receiver, index, value, NONE, language_mode()),
-        Object);
+        JSObject::SetElement(receiver, index, value, language_mode()), Object);
     return value;
   }
 
index cecac9bfdb128bb1a8ba374aae7f95633e281c71..9234e85aa20d171fcad6a1f27a5317457debee1b 100644 (file)
@@ -325,7 +325,8 @@ ParseElementResult JsonParser<seq_one_byte>::ParseElement(
       AdvanceSkipWhitespace();
       Handle<Object> value = ParseJsonValue();
       if (!value.is_null()) {
-        JSObject::SetOwnElement(json_object, index, value, SLOPPY).Assert();
+        JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
+            .Assert();
         return kElementFound;
       } else {
         return kNullHandle;
index fa291fefbdeaa49febef68e14caac639badf87dd..982ac109be1867758a3b19e30a6e543f261615d7 100644 (file)
@@ -28,7 +28,7 @@ void SetElementSloppy(Handle<JSObject> object,
   // Ignore return value from SetElement. It can only be a failure if there
   // are element setters causing exceptions and the debugger context has none
   // of these.
-  JSObject::SetElement(object, index, value, NONE, SLOPPY).Assert();
+  JSObject::SetElement(object, index, value, SLOPPY).Assert();
 }
 
 
index 65fe1a61c7ee7cd552dc6da3d9aeb7a953febfd6..495fcce64dea22f00bc68acf0cfff563e9c5a385 100644 (file)
@@ -249,7 +249,7 @@ class JSArrayBasedStruct {
 
  protected:
   void SetField(int field_position, Handle<Object> value) {
-    JSObject::SetElement(array_, field_position, value, NONE, SLOPPY).Assert();
+    JSObject::SetElement(array_, field_position, value, SLOPPY).Assert();
   }
 
   void SetSmiValueField(int field_position, int value) {
index aa66d152e39a9cae781a9978f6fa2facecac6825..1bb491a9dee2aa528f1a85de8a9756f99c8143bf 100644 (file)
@@ -109,10 +109,59 @@ void LookupIterator::ReloadPropertyInformation() {
 void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
   DCHECK(state_ == DATA || state_ == ACCESSOR);
   DCHECK(HolderIsReceiverOrHiddenPrototype());
-  if (holder_map_->is_dictionary_map()) return;
-  holder_map_ =
-      Map::PrepareForDataProperty(holder_map_, descriptor_number(), value);
-  JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_);
+
+  Handle<JSObject> holder = GetHolder<JSObject>();
+
+  if (IsElement()) {
+    ElementsKind old_kind = holder_map_->elements_kind();
+    holder_map_ = Map::PrepareForDataElement(holder_map_, value);
+    ElementsKind new_kind = holder_map_->elements_kind();
+    if (new_kind != old_kind) {
+      // TODO(verwaest): Handle element migration in MigrateToMap.
+      JSObject::UpdateAllocationSite(holder, new_kind);
+      if (IsFastDoubleElementsKind(old_kind) !=
+          IsFastDoubleElementsKind(new_kind)) {
+        Handle<FixedArrayBase> old_elements(holder->elements());
+        int capacity = old_elements->length();
+        Handle<FixedArrayBase> new_elements;
+        if (IsFastDoubleElementsKind(new_kind)) {
+          new_elements = factory()->NewFixedDoubleArray(capacity);
+        } else {
+          new_elements = factory()->NewFixedArray(capacity);
+        }
+
+        ElementsAccessor* accessor = ElementsAccessor::ForKind(new_kind);
+        accessor->CopyElements(holder, new_elements, old_kind);
+
+        JSObject::ValidateElements(holder);
+        JSObject::SetMapAndElements(holder, holder_map_, new_elements);
+
+        if (FLAG_trace_elements_transitions) {
+          JSObject::PrintElementsTransition(
+              stdout, holder, old_kind, old_elements, new_kind, new_elements);
+        }
+        // SetMapAndElements above migrated the object. No reloading of property
+        // infomation is necessary for elements.
+        return;
+      } else if (FLAG_trace_elements_transitions) {
+        Handle<FixedArrayBase> elements(holder->elements());
+        JSObject::PrintElementsTransition(stdout, holder, old_kind, elements,
+                                          new_kind, elements);
+      }
+    }
+
+    // Copy the backing store if it is copy-on-write.
+    if (IsFastSmiOrObjectElementsKind(new_kind)) {
+      JSObject::EnsureWritableFastElements(holder);
+    }
+
+  } else {
+    if (holder_map_->is_dictionary_map()) return;
+    holder_map_ =
+        Map::PrepareForDataProperty(holder_map_, descriptor_number(), value);
+  }
+
+  JSObject::MigrateToMap(holder, holder_map_);
   ReloadPropertyInformation();
 }
 
@@ -122,7 +171,25 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
   DCHECK(state_ == DATA || state_ == ACCESSOR);
   DCHECK(HolderIsReceiverOrHiddenPrototype());
   Handle<JSObject> holder = GetHolder<JSObject>();
-  if (holder_map_->is_dictionary_map()) {
+  if (IsElement()) {
+    // TODO(verwaest): Clean up.
+    if (attributes == NONE && !holder->HasDictionaryElements() &&
+        !holder->HasDictionaryArgumentsElements()) {
+      ElementsAccessor* accessor = holder->GetElementsAccessor();
+      accessor->Set(holder, index(), value);
+    } else {
+      DCHECK(holder->HasFastElements() || holder->HasDictionaryElements() ||
+             holder->HasSloppyArgumentsElements());
+      Handle<SeededNumberDictionary> d = JSObject::NormalizeElements(holder);
+      // TODO(verwaest): Move this into NormalizeElements.
+      d->set_requires_slow_elements();
+      if (holder->HasDictionaryElements()) {
+        JSObject::SetDictionaryElement(holder, index(), value, attributes);
+      } else {
+        JSObject::SetSloppyArgumentsElement(holder, index(), value, attributes);
+      }
+    }
+  } else if (holder_map_->is_dictionary_map()) {
     PropertyDetails details(attributes, v8::internal::DATA, 0,
                             PropertyCellType::kMutable);
     JSObject::SetNormalizedProperty(holder, name(), value, details);
@@ -352,11 +419,13 @@ Handle<Object> LookupIterator::GetDataValue() const {
 }
 
 
-void LookupIterator::WriteDataValue(Handle<Object> value) {
+Handle<Object> LookupIterator::WriteDataValue(Handle<Object> value) {
   DCHECK_EQ(DATA, state_);
-  DCHECK(!IsElement());
   Handle<JSObject> holder = GetHolder<JSObject>();
-  if (holder->IsGlobalObject()) {
+  if (IsElement()) {
+    ElementsAccessor* accessor = holder->GetElementsAccessor();
+    return accessor->Set(holder, index_, value);
+  } else if (holder->IsGlobalObject()) {
     Handle<GlobalDictionary> property_dictionary =
         handle(holder->global_dictionary());
     PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value,
@@ -370,6 +439,7 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
   } else {
     DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type());
   }
+  return value;
 }
 
 
index 29b7d77b270d26447f8190d651ba1c1704462834..be8394afec4e7242fd294695f6b31f347dac8628 100644 (file)
@@ -212,9 +212,9 @@ class LookupIterator final BASE_EMBEDDED {
   Handle<Object> GetAccessors() const;
   Handle<InterceptorInfo> GetInterceptor() const;
   Handle<Object> GetDataValue() const;
-  // Usually returns the value that was passed in, but may perform
-  // non-observable modifications on it, such as internalize strings.
-  void WriteDataValue(Handle<Object> value);
+  // Usually returns the value that was passed in. In case of typed array
+  // accesses it returns the converted value.
+  Handle<Object> WriteDataValue(Handle<Object> value);
   void InternalizeName();
 
  private:
index 39646cd4b5e47cc2419c9fbb0a556c209dcc1440..27528d644253793d8418fc019ec183557cd52c31 100644 (file)
@@ -1197,17 +1197,6 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
 }
 
 
-MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
-                                                   Handle<JSReceiver> receiver,
-                                                   uint32_t index,
-                                                   Handle<Object> value,
-                                                   LanguageMode language_mode) {
-  Isolate* isolate = proxy->GetIsolate();
-  Handle<String> name = isolate->factory()->Uint32ToString(index);
-  return SetPropertyWithHandler(proxy, receiver, name, value, language_mode);
-}
-
-
 #define FIELD_ADDR(p, offset) \
   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
 
@@ -2216,14 +2205,6 @@ bool JSObject::HasFastProperties() {
 }
 
 
-MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
-                                            uint32_t index,
-                                            Handle<Object> value,
-                                            LanguageMode language_mode) {
-  return JSObject::SetOwnElement(object, index, value, NONE, language_mode);
-}
-
-
 bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
   if (unused_property_fields() != 0) return false;
   if (is_prototype_map()) return false;
@@ -6776,15 +6757,6 @@ bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
 }
 
 
-// static
-void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
-  auto foreign = info->GetIsolate()->factory()->NewForeign(
-      reinterpret_cast<v8::internal::Address>(
-          reinterpret_cast<intptr_t>(nullptr)));
-  info->set_setter(*foreign);
-}
-
-
 template<typename Derived, typename Shape, typename Key>
 void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
                                                Handle<Object> key,
index fa98881bb5e9eba0cd11a3f4a23dff9079a2fa71..91abf11a01beb2e9cd683b8ccaa97f30a9d6f55d 100644 (file)
@@ -307,12 +307,16 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
   Handle<Object> structure = it->GetAccessors();
   Handle<Object> receiver = it->GetReceiver();
 
+  // We should never get here to initialize a const with the hole value since a
+  // const declaration would conflict with the getter.
   DCHECK(!structure->IsForeign());
-  // api style callbacks.
+
+  // API style callbacks.
   if (structure->IsAccessorInfo()) {
     Handle<JSObject> holder = it->GetHolder<JSObject>();
     Handle<Name> name = it->GetName();
-    Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
+    Handle<ExecutableAccessorInfo> info =
+        Handle<ExecutableAccessorInfo>::cast(structure);
     if (!info->IsCompatibleReceiver(*receiver)) {
       THROW_NEW_ERROR(isolate,
                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
@@ -320,14 +324,12 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
                       Object);
     }
 
-    Handle<ExecutableAccessorInfo> data =
-        Handle<ExecutableAccessorInfo>::cast(structure);
     v8::AccessorNameGetterCallback call_fun =
-        v8::ToCData<v8::AccessorNameGetterCallback>(data->getter());
-    if (call_fun == NULL) return isolate->factory()->undefined_value();
+        v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
+    if (call_fun == nullptr) return isolate->factory()->undefined_value();
 
     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
-    PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
+    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
     v8::Handle<v8::Value> result =
         args.Call(call_fun, v8::Utils::ToLocal(name));
     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
@@ -340,9 +342,8 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
     return handle(*return_value, isolate);
   }
 
-  // __defineGetter__ callback
-  Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
-                        isolate);
+  // Regular accessor.
+  Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
   if (getter->IsSpecFunction()) {
     // TODO(rossberg): nicer would be to cast to some JSCallable here...
     return Object::GetPropertyWithDefinedGetter(
@@ -364,55 +365,53 @@ bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
 
 
 MaybeHandle<Object> Object::SetPropertyWithAccessor(
-    Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
-    Handle<JSObject> holder, Handle<Object> structure,
-    LanguageMode language_mode) {
-  Isolate* isolate = name->GetIsolate();
+    LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
+  Isolate* isolate = it->isolate();
+  Handle<Object> structure = it->GetAccessors();
+  Handle<Object> receiver = it->GetReceiver();
 
-  // We should never get here to initialize a const with the hole
-  // value since a const declaration would conflict with the setter.
+  // We should never get here to initialize a const with the hole value since a
+  // const declaration would conflict with the setter.
   DCHECK(!structure->IsForeign());
+
+  // API style callbacks.
   if (structure->IsExecutableAccessorInfo()) {
-    // Don't call executable accessor setters with non-JSObject receivers.
-    if (!receiver->IsJSObject()) return value;
-    // api style callbacks
-    ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
+    Handle<JSObject> holder = it->GetHolder<JSObject>();
+    Handle<Name> name = it->GetName();
+    Handle<ExecutableAccessorInfo> info =
+        Handle<ExecutableAccessorInfo>::cast(structure);
     if (!info->IsCompatibleReceiver(*receiver)) {
       THROW_NEW_ERROR(isolate,
                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
                                    name, receiver),
                       Object);
     }
-    Object* call_obj = info->setter();
+
     v8::AccessorNameSetterCallback call_fun =
-        v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
-    if (call_fun == NULL) return value;
+        v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
+    if (call_fun == nullptr) return value;
+
     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
-    args.Call(call_fun,
-              v8::Utils::ToLocal(name),
-              v8::Utils::ToLocal(value));
+    args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
     return value;
   }
 
-  if (structure->IsAccessorPair()) {
-    Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
-    if (setter->IsSpecFunction()) {
-      // TODO(rossberg): nicer would be to cast to some JSCallable here...
-      return SetPropertyWithDefinedSetter(
-          receiver, Handle<JSReceiver>::cast(setter), value);
-    } else {
-      if (is_sloppy(language_mode)) return value;
-      THROW_NEW_ERROR(
-          isolate,
-          NewTypeError(MessageTemplate::kNoSetterInCallback, name, holder),
-          Object);
-    }
+  // Regular accessor.
+  Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
+  if (setter->IsSpecFunction()) {
+    // TODO(rossberg): nicer would be to cast to some JSCallable here...
+    return SetPropertyWithDefinedSetter(
+        receiver, Handle<JSReceiver>::cast(setter), value);
   }
 
-  UNREACHABLE();
-  return MaybeHandle<Object>();
+  if (is_sloppy(language_mode)) return value;
+
+  THROW_NEW_ERROR(isolate,
+                  NewTypeError(MessageTemplate::kNoSetterInCallback,
+                               it->GetName(), it->GetHolder<JSObject>()),
+                  Object);
 }
 
 
@@ -540,9 +539,7 @@ MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
   Handle<JSObject> checked = it->GetHolder<JSObject>();
   if (FindAllCanWriteHolder(it)) {
-    return SetPropertyWithAccessor(it->GetReceiver(), it->GetName(), value,
-                                   it->GetHolder<JSObject>(),
-                                   it->GetAccessors(), language_mode);
+    return SetPropertyWithAccessor(it, value, language_mode);
   }
 
   it->isolate()->ReportFailedAccessCheck(checked);
@@ -597,82 +594,6 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
 }
 
 
-MaybeHandle<Object> Object::SetElementWithReceiver(
-    Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
-    uint32_t index, Handle<Object> value, LanguageMode language_mode) {
-  // Iterate up the prototype chain until an element is found or the null
-  // prototype is encountered.
-  bool done = false;
-  for (PrototypeIterator iter(isolate, object,
-                              object->IsJSProxy() || object->IsJSObject()
-                                  ? PrototypeIterator::START_AT_RECEIVER
-                                  : PrototypeIterator::START_AT_PROTOTYPE);
-       !iter.IsAtEnd() && !done; iter.Advance()) {
-    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
-      // TODO(dslomov): implement.
-      isolate->ThrowIllegalOperation();
-      return MaybeHandle<Object>();
-    }
-
-    Handle<JSObject> js_object =
-        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
-
-    // Check access rights if needed.
-    if (js_object->IsAccessCheckNeeded()) {
-      if (!isolate->MayAccess(js_object)) {
-        isolate->ReportFailedAccessCheck(js_object);
-        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-        return isolate->factory()->undefined_value();
-      }
-    }
-
-    if (js_object->HasIndexedInterceptor()) {
-      LookupIterator it(isolate, receiver, index, js_object,
-                        LookupIterator::OWN);
-      Maybe<PropertyAttributes> from_interceptor =
-          JSObject::GetPropertyAttributes(&it);
-      if (!from_interceptor.IsJust()) return MaybeHandle<Object>();
-      if ((from_interceptor.FromJust() & READ_ONLY) != 0) {
-        return WriteToReadOnlyElement(isolate, receiver, index, value,
-                                      language_mode);
-      }
-      done = from_interceptor.FromJust() != ABSENT;
-    }
-
-    if (!done &&
-        js_object->elements() != isolate->heap()->empty_fixed_array()) {
-      ElementsAccessor* accessor = js_object->GetElementsAccessor();
-      PropertyAttributes attrs = accessor->GetAttributes(js_object, index);
-      if ((attrs & READ_ONLY) != 0) {
-        return WriteToReadOnlyElement(isolate, receiver, index, value,
-                                      language_mode);
-      }
-      Handle<AccessorPair> pair;
-      if (accessor->GetAccessorPair(js_object, index).ToHandle(&pair)) {
-        return JSObject::SetElementWithCallback(receiver, pair, index, value,
-                                                js_object, language_mode);
-      } else {
-        done = attrs != ABSENT;
-      }
-    }
-  }
-
-  if (!receiver->IsJSObject()) {
-    return WriteToReadOnlyElement(isolate, receiver, index, value,
-                                  language_mode);
-  }
-  Handle<JSObject> target = Handle<JSObject>::cast(receiver);
-  ElementsAccessor* accessor = target->GetElementsAccessor();
-  PropertyAttributes attrs = accessor->GetAttributes(target, index);
-  if (attrs == ABSENT) {
-    return JSObject::SetElement(target, index, value, NONE, language_mode,
-                                false);
-  }
-  return JSObject::SetElement(target, index, value, attrs, language_mode, false,
-                              DEFINE_PROPERTY);
-}
-
-
 Map* Object::GetRootMap(Isolate* isolate) {
   DisallowHeapAllocation no_alloc;
   if (IsSmi()) {
@@ -3037,27 +2958,50 @@ Handle<Map> Map::Update(Handle<Map> map) {
 
 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
                                                          Handle<Object> value) {
-  Handle<Name> name = it->name();
+  Isolate* isolate = it->isolate();
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc(isolate);
+
+  DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
+  if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
+
   Handle<JSObject> holder = it->GetHolder<JSObject>();
-  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
-  if (interceptor->setter()->IsUndefined() ||
-      (name->IsSymbol() && !interceptor->can_intercept_symbols())) {
-    return MaybeHandle<Object>();
+  v8::Handle<v8::Value> result;
+  PropertyCallbackArguments args(isolate, interceptor->data(),
+                                 *it->GetReceiver(), *holder);
+
+  if (it->IsElement()) {
+    uint32_t index = it->index();
+    v8::IndexedPropertySetterCallback setter =
+        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
+    LOG(isolate,
+        ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index));
+    result = args.Call(setter, index, v8::Utils::ToLocal(value));
+  } else {
+    Handle<Name> name = it->name();
+
+    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
+      return MaybeHandle<Object>();
+    }
+
+    v8::GenericNamedPropertySetterCallback setter =
+        v8::ToCData<v8::GenericNamedPropertySetterCallback>(
+            interceptor->setter());
+    LOG(it->isolate(),
+        ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
+    result =
+        args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
   }
 
-  LOG(it->isolate(),
-      ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
-  PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
-                                 *holder);
-  v8::GenericNamedPropertySetterCallback setter =
-      v8::ToCData<v8::GenericNamedPropertySetterCallback>(
-          interceptor->setter());
-  v8::Handle<v8::Value> result =
-      args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
-  if (!result.IsEmpty()) return value;
-
-  return MaybeHandle<Object>();
+  if (result.IsEmpty()) return MaybeHandle<Object>();
+#ifdef DEBUG
+  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
+  result_internal->VerifyApiCallResultType();
+#endif
+  return value;
 }
 
 
@@ -3088,10 +3032,9 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
         UNREACHABLE();
 
       case LookupIterator::ACCESS_CHECK:
-        // TODO(verwaest): Remove the distinction. This is mostly bogus since we
-        // don't know whether we'll want to fetch attributes or call a setter
-        // until we find the property.
         if (it->HasAccess()) break;
+        // Check whether it makes sense to reuse the lookup iterator. Here it
+        // might still call into setters up the prototype chain.
         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
                                                           language_mode);
 
@@ -3130,7 +3073,7 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
         break;
 
       case LookupIterator::ACCESSOR: {
-        if (it->property_details().IsReadOnly()) {
+        if (it->IsReadOnly()) {
           return WriteToReadOnlyProperty(it, value, language_mode);
         }
         Handle<Object> accessors = it->GetAccessors();
@@ -3140,16 +3083,14 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
           done = true;
           break;
         }
-        return SetPropertyWithAccessor(it->GetReceiver(), it->GetName(), value,
-                                       it->GetHolder<JSObject>(), accessors,
-                                       language_mode);
+        return SetPropertyWithAccessor(it, value, language_mode);
       }
       case LookupIterator::INTEGER_INDEXED_EXOTIC:
         done = true;
         break;
 
       case LookupIterator::DATA:
-        if (it->property_details().IsReadOnly()) {
+        if (it->IsReadOnly()) {
           return WriteToReadOnlyProperty(it, value, language_mode);
         }
         if (it->HolderIsReceiverOrHiddenPrototype()) {
@@ -3202,66 +3143,72 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
   if (found) return result;
 
   if (!it->GetReceiver()->IsJSReceiver()) {
-    return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(),
-                                   value, language_mode);
+    return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
+                                   it->GetName(), value, language_mode);
   }
 
-  LookupIterator own_lookup(it->GetReceiver(), it->name(), LookupIterator::OWN);
+  LookupIterator::Configuration c = LookupIterator::OWN;
+  LookupIterator own_lookup =
+      it->IsElement()
+          ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c)
+          : LookupIterator(it->GetReceiver(), it->name(), c);
 
-  switch (own_lookup.state()) {
-    case LookupIterator::NOT_FOUND:
-      return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
-                                       store_mode);
+  for (; own_lookup.IsFound(); own_lookup.Next()) {
+    switch (own_lookup.state()) {
+      case LookupIterator::ACCESS_CHECK:
+        if (!it->isolate()->MayAccess(own_lookup.GetHolder<JSObject>())) {
+          return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
+                                                            language_mode);
+        }
+        break;
 
-    case LookupIterator::INTEGER_INDEXED_EXOTIC:
-      return result;
+      case LookupIterator::INTEGER_INDEXED_EXOTIC:
+        return result;
 
-    case LookupIterator::DATA: {
-      PropertyDetails details = own_lookup.property_details();
-      if (details.IsConfigurable() || !details.IsReadOnly()) {
-        return JSObject::SetOwnPropertyIgnoreAttributes(
-            Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
-            details.attributes());
+      case LookupIterator::DATA: {
+        PropertyDetails details = own_lookup.property_details();
+        if (details.IsConfigurable() || !details.IsReadOnly()) {
+          return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
+                                                     details.attributes());
+        }
+        return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
       }
-      return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
-    }
 
-    case LookupIterator::ACCESSOR: {
-      PropertyDetails details = own_lookup.property_details();
-      if (details.IsConfigurable()) {
-        return JSObject::SetOwnPropertyIgnoreAttributes(
-            Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
-            details.attributes());
-      }
+      case LookupIterator::ACCESSOR: {
+        PropertyDetails details = own_lookup.property_details();
+        if (details.IsConfigurable()) {
+          return JSObject::ReconfigureAsDataProperty(&own_lookup, value,
+                                                     details.attributes());
+        }
 
-      return RedefineNonconfigurableProperty(it->isolate(), it->name(), value,
-                                             language_mode);
-    }
+        return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
+                                               value, language_mode);
+      }
 
-    case LookupIterator::TRANSITION:
-      UNREACHABLE();
-      break;
+      case LookupIterator::INTERCEPTOR:
+      case LookupIterator::JSPROXY: {
+        bool found = false;
+        MaybeHandle<Object> result = SetPropertyInternal(
+            &own_lookup, value, language_mode, store_mode, &found);
+        if (found) return result;
+        break;
+      }
 
-    case LookupIterator::INTERCEPTOR:
-    case LookupIterator::JSPROXY:
-    case LookupIterator::ACCESS_CHECK: {
-      bool found = false;
-      MaybeHandle<Object> result = SetPropertyInternal(
-          &own_lookup, value, language_mode, store_mode, &found);
-      if (found) return result;
-      return SetDataProperty(&own_lookup, value);
+      case LookupIterator::NOT_FOUND:
+      case LookupIterator::TRANSITION:
+        UNREACHABLE();
     }
   }
 
-  UNREACHABLE();
-  return MaybeHandle<Object>();
+  return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
+                                   store_mode);
 }
 
 
 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
-  return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(),
-                                 value, language_mode);
+  return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
+                                 it->GetName(), value, language_mode);
 }
 
 
@@ -3310,21 +3257,32 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
   // Fetch before transforming the object since the encoding may become
   // incompatible with what's cached in |it|.
   bool is_observed = receiver->map()->is_observed() &&
-                     !it->isolate()->IsInternallyUsedPropertyName(it->name());
+                     (it->IsElement() ||
+                      !it->isolate()->IsInternallyUsedPropertyName(it->name()));
   MaybeHandle<Object> maybe_old;
   if (is_observed) maybe_old = it->GetDataValue();
 
+  // Convert the incoming value to a number for storing into typed arrays.
+  if (it->IsElement() && (receiver->HasExternalArrayElements() ||
+                          receiver->HasFixedTypedArrayElements())) {
+    if (!value->IsNumber() && !value->IsUndefined()) {
+      ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), value,
+                                 Execution::ToNumber(it->isolate(), value),
+                                 Object);
+    }
+  }
+
   // Possibly migrate to the most up-to-date map that will be able to store
   // |value| under it->name().
   it->PrepareForDataProperty(value);
 
   // Write the property value.
-  it->WriteDataValue(value);
+  value = it->WriteDataValue(value);
 
   // Send the change record if there are observers.
   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
-                                           receiver, "update", it->name(),
+                                           receiver, "update", it->GetName(),
                                            maybe_old.ToHandleChecked()),
                         Object);
   }
@@ -3333,6 +3291,47 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
 }
 
 
+MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
+    Handle<JSArray> object) {
+  Isolate* isolate = object->GetIsolate();
+  HandleScope scope(isolate);
+  Handle<Object> args[] = {object};
+
+  return Execution::Call(
+      isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
+      isolate->factory()->undefined_value(), arraysize(args), args);
+}
+
+
+MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
+    Handle<JSArray> object) {
+  Isolate* isolate = object->GetIsolate();
+  HandleScope scope(isolate);
+  Handle<Object> args[] = {object};
+
+  return Execution::Call(
+      isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
+      isolate->factory()->undefined_value(), arraysize(args), args);
+}
+
+
+MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
+    Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
+    uint32_t add_count) {
+  Isolate* isolate = object->GetIsolate();
+  HandleScope scope(isolate);
+  Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
+  Handle<Object> add_count_object =
+      isolate->factory()->NewNumberFromUint(add_count);
+
+  Handle<Object> args[] = {object, index_object, deleted, add_count_object};
+
+  return Execution::Call(
+      isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
+      isolate->factory()->undefined_value(), arraysize(args), args);
+}
+
+
 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
                                             Handle<Object> value,
                                             PropertyAttributes attributes,
@@ -3352,84 +3351,66 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
   // instead. If the prototype is Null, the proxy is detached.
   if (receiver->IsJSGlobalProxy()) return value;
 
-  // Possibly migrate to the most up-to-date map that will be able to store
-  // |value| under it->name() with |attributes|.
-  it->PrepareTransitionToDataProperty(value, attributes, store_mode);
-  if (it->state() != LookupIterator::TRANSITION) {
-    if (is_sloppy(language_mode)) return value;
-    THROW_NEW_ERROR(
-        it->isolate(),
-        NewTypeError(MessageTemplate::kObjectNotExtensible, it->name()),
-        Object);
-  }
-  it->ApplyTransitionToDataProperty();
-
-  // TODO(verwaest): Encapsulate dictionary handling better.
-  if (receiver->map()->is_dictionary_map()) {
-    // TODO(verwaest): Probably should ensure this is done beforehand.
-    it->InternalizeName();
-    // TODO(dcarney): just populate TransitionPropertyCell here?
-    JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
-  } else {
-    // Write the property value.
-    it->WriteDataValue(value);
-  }
+  Isolate* isolate = it->isolate();
 
-  // Send the change record if there are observers.
-  if (receiver->map()->is_observed() &&
-      !it->isolate()->IsInternallyUsedPropertyName(it->name())) {
-    RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
-                                           receiver, "add", it->name(),
-                                           it->factory()->the_hole_value()),
-                        Object);
+  if (!receiver->map()->is_extensible() &&
+      (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
+    if (is_sloppy(language_mode)) return value;
+    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible,
+                                          it->GetName()),
+                    Object);
   }
 
-  return value;
-}
-
+  if (it->IsElement()) {
+    if (receiver->IsJSArray()) {
+      Handle<JSArray> array = Handle<JSArray>::cast(receiver);
+      if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
+        if (is_sloppy(language_mode)) return value;
+        return JSArray::ReadOnlyLengthError(array);
+      }
 
-MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
-    Handle<JSObject> object, uint32_t index, Handle<Object> value, bool* found,
-    LanguageMode language_mode) {
-  Isolate* isolate = object->GetIsolate();
-  for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
-       iter.Advance()) {
-    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
-      return JSProxy::SetPropertyViaPrototypesWithHandler(
-          Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
-          isolate->factory()->Uint32ToString(index),  // name
-          value, language_mode, found);
-    }
-    Handle<JSObject> js_proto =
-        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
+      if (FLAG_trace_external_array_abuse &&
+          (array->HasExternalArrayElements() ||
+           array->HasFixedTypedArrayElements())) {
+        CheckArrayAbuse(array, "typed elements write", it->index(), true);
+      }
 
-    if (js_proto->IsAccessCheckNeeded()) {
-      if (!isolate->MayAccess(js_proto)) {
-        *found = true;
-        isolate->ReportFailedAccessCheck(js_proto);
-        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-        return MaybeHandle<Object>();
+      if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() &&
+          !array->HasFixedTypedArrayElements()) {
+        CheckArrayAbuse(array, "elements write", it->index(), false);
       }
     }
 
-    if (!js_proto->HasDictionaryElements()) {
-      continue;
+    return JSObject::AddDataElement(receiver, it->index(), value, attributes);
+  } else {
+    // Migrate to the most up-to-date map that will be able to store |value|
+    // under it->name() with |attributes|.
+    it->PrepareTransitionToDataProperty(value, attributes, store_mode);
+    DCHECK_EQ(LookupIterator::TRANSITION, it->state());
+    it->ApplyTransitionToDataProperty();
+
+    // TODO(verwaest): Encapsulate dictionary handling better.
+    if (receiver->map()->is_dictionary_map()) {
+      // TODO(verwaest): Probably should ensure this is done beforehand.
+      it->InternalizeName();
+      // TODO(dcarney): just populate TransitionPropertyCell here?
+      JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
+    } else {
+      // Write the property value.
+      it->WriteDataValue(value);
     }
 
-    Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
-    int entry = dictionary->FindEntry(index);
-    if (entry != SeededNumberDictionary::kNotFound) {
-      PropertyDetails details = dictionary->DetailsAt(entry);
-      if (details.type() == ACCESSOR_CONSTANT) {
-        *found = true;
-        Handle<Object> structure(dictionary->ValueAt(entry), isolate);
-        return SetElementWithCallback(object, structure, index, value, js_proto,
-                                      language_mode);
-      }
+    // Send the change record if there are observers.
+    if (receiver->map()->is_observed() &&
+        !isolate->IsInternallyUsedPropertyName(it->name())) {
+      RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
+                                       receiver, "add", it->name(),
+                                       it->factory()->the_hole_value()),
+                          Object);
     }
   }
-  *found = false;
-  return isolate->factory()->the_hole_value();
+
+  return value;
 }
 
 
@@ -4144,129 +4125,174 @@ void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
 }
 
 
-// Reconfigures a property to a data property with attributes, even if it is not
-// reconfigurable.
-MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
-    Handle<JSObject> object,
-    Handle<Name> name,
-    Handle<Object> value,
-    PropertyAttributes attributes,
-    ExecutableAccessorInfoHandling handling) {
-  DCHECK(!value->IsTheHole());
-  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
-  bool is_observed = object->map()->is_observed() &&
-                     !it.isolate()->IsInternallyUsedPropertyName(name);
-  for (; it.IsFound(); it.Next()) {
-    switch (it.state()) {
-      case LookupIterator::INTEGER_INDEXED_EXOTIC:
-        return value;
+// static
+void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
+  info->set_setter(*v8::FromCData(info->GetIsolate(), nullptr));
+}
 
-      case LookupIterator::INTERCEPTOR:
-      case LookupIterator::JSPROXY:
-      case LookupIterator::NOT_FOUND:
-      case LookupIterator::TRANSITION:
-        UNREACHABLE();
 
-      case LookupIterator::ACCESS_CHECK:
-        if (!it.isolate()->MayAccess(object)) {
-          return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
-        }
-        break;
+MaybeHandle<Object> JSObject::ReconfigureAsDataProperty(
+    LookupIterator* it, Handle<Object> value, PropertyAttributes attributes) {
+  Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
+  bool is_observed = object->map()->is_observed() &&
+                     (it->IsElement() ||
+                      !it->isolate()->IsInternallyUsedPropertyName(it->name()));
 
-      case LookupIterator::ACCESSOR: {
-        PropertyDetails details = it.property_details();
-        // Ensure the context isn't changed after calling into accessors.
-        AssertNoContextChange ncc(it.isolate());
+  switch (it->state()) {
+    case LookupIterator::INTERCEPTOR:
+    case LookupIterator::JSPROXY:
+    case LookupIterator::NOT_FOUND:
+    case LookupIterator::TRANSITION:
+    case LookupIterator::ACCESS_CHECK:
+      UNREACHABLE();
 
-        Handle<Object> accessors = it.GetAccessors();
+    case LookupIterator::INTEGER_INDEXED_EXOTIC:
+      return value;
 
-        // Special handling for ExecutableAccessorInfo, which behaves like a
-        // data property.
-        if (handling == DONT_FORCE_FIELD &&
-            accessors->IsExecutableAccessorInfo()) {
-          Handle<Object> result;
-          ASSIGN_RETURN_ON_EXCEPTION(
-              it.isolate(), result,
-              JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(),
-                                                value, it.GetHolder<JSObject>(),
-                                                accessors, STRICT),
-              Object);
-          DCHECK(result->SameValue(*value));
+    case LookupIterator::ACCESSOR: {
+      PropertyDetails details = it->property_details();
+      // Ensure the context isn't changed after calling into accessors.
+      AssertNoContextChange ncc(it->isolate());
 
-          if (details.attributes() == attributes) {
-            return value;
-          }
+      Handle<Object> accessors = it->GetAccessors();
 
-          // Reconfigure the accessor if attributes mismatch.
-          Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
-              it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
-          new_data->set_property_attributes(attributes);
-          // By clearing the setter we don't have to introduce a lookup to
-          // the setter, simply make it unavailable to reflect the
-          // attributes.
-          if (attributes & READ_ONLY) {
-            ExecutableAccessorInfo::ClearSetter(new_data);
-          }
-          SetPropertyCallback(object, name, new_data, attributes);
-          if (is_observed) {
-            RETURN_ON_EXCEPTION(
-                it.isolate(),
-                EnqueueChangeRecord(object, "reconfigure", name,
-                                    it.isolate()->factory()->the_hole_value()),
-                Object);
-          }
-          return value;
+      // Special handling for ExecutableAccessorInfo, which behaves like a
+      // data property.
+      if (accessors->IsExecutableAccessorInfo()) {
+        Handle<Object> result;
+        ASSIGN_RETURN_ON_EXCEPTION(
+            it->isolate(), result,
+            JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
+        DCHECK(result->SameValue(*value));
+
+        if (details.attributes() == attributes) return value;
+
+        // Reconfigure the accessor if attributes mismatch.
+        Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
+            it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
+        new_data->set_property_attributes(attributes);
+        // By clearing the setter we don't have to introduce a lookup to
+        // the setter, simply make it unavailable to reflect the
+        // attributes.
+        if (attributes & READ_ONLY) {
+          ExecutableAccessorInfo::ClearSetter(new_data);
         }
 
-        it.ReconfigureDataProperty(value, attributes);
-        it.WriteDataValue(value);
-
+        if (it->IsElement()) {
+          SetElementCallback(object, it->index(), new_data, attributes);
+        } else {
+          SetPropertyCallback(object, it->name(), new_data, attributes);
+        }
         if (is_observed) {
           RETURN_ON_EXCEPTION(
-              it.isolate(),
-              EnqueueChangeRecord(object, "reconfigure", name,
-                                  it.isolate()->factory()->the_hole_value()),
+              it->isolate(),
+              EnqueueChangeRecord(object, "reconfigure", it->GetName(),
+                                  it->factory()->the_hole_value()),
               Object);
         }
-
         return value;
       }
 
-      case LookupIterator::DATA: {
-        PropertyDetails details = it.property_details();
-        Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
-        // Regular property update if the attributes match.
-        if (details.attributes() == attributes) {
-          return SetDataProperty(&it, value);
-        }
-        // Reconfigure the data property if the attributes mismatch.
-        if (is_observed) old_value = it.GetDataValue();
+      it->ReconfigureDataProperty(value, attributes);
+      it->WriteDataValue(value);
 
-        it.ReconfigureDataProperty(value, attributes);
-        it.WriteDataValue(value);
+      if (is_observed) {
+        RETURN_ON_EXCEPTION(
+            it->isolate(),
+            EnqueueChangeRecord(object, "reconfigure", it->GetName(),
+                                it->factory()->the_hole_value()),
+            Object);
+      }
 
-        if (is_observed) {
-          if (old_value->SameValue(*value)) {
-            old_value = it.isolate()->factory()->the_hole_value();
-          }
-          RETURN_ON_EXCEPTION(
-              it.isolate(),
-              EnqueueChangeRecord(object, "reconfigure", name, old_value),
-              Object);
-        }
+      return value;
+    }
 
-        return value;
+    case LookupIterator::DATA: {
+      PropertyDetails details = it->property_details();
+      Handle<Object> old_value = it->factory()->the_hole_value();
+      // Regular property update if the attributes match.
+      if (details.attributes() == attributes) {
+        return SetDataProperty(it, value);
       }
-    }
-  }
 
-  return AddDataProperty(&it, value, attributes, STRICT,
-                         CERTAINLY_NOT_STORE_FROM_KEYED);
-}
+      // Special case: properties of typed arrays cannot be reconfigured to
+      // non-writable nor to non-enumerable.
+      if (it->IsElement() && (object->HasExternalArrayElements() ||
+                              object->HasFixedTypedArrayElements())) {
+        return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
+                                               value, STRICT);
+      }
 
+      // Reconfigure the data property if the attributes mismatch.
+      if (is_observed) old_value = it->GetDataValue();
 
-Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
-    LookupIterator* it) {
+      it->ReconfigureDataProperty(value, attributes);
+      it->WriteDataValue(value);
+
+      if (is_observed) {
+        if (old_value->SameValue(*value)) {
+          old_value = it->factory()->the_hole_value();
+        }
+        RETURN_ON_EXCEPTION(it->isolate(),
+                            EnqueueChangeRecord(object, "reconfigure",
+                                                it->GetName(), old_value),
+                            Object);
+      }
+    }
+  }
+
+  return value;
+}
+
+
+// Reconfigures a property to a data property with attributes, even if it is not
+// reconfigurable.
+MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
+    Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
+    PropertyAttributes attributes) {
+  DCHECK(!value->IsTheHole());
+  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
+  if (it.state() == LookupIterator::ACCESS_CHECK) {
+    if (!it.isolate()->MayAccess(object)) {
+      return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
+    }
+    it.Next();
+  }
+
+  if (it.IsFound()) {
+    return ReconfigureAsDataProperty(&it, value, attributes);
+  }
+
+  return AddDataProperty(&it, value, attributes, STRICT,
+                         CERTAINLY_NOT_STORE_FROM_KEYED);
+}
+
+
+MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
+    Handle<JSObject> object, uint32_t index, Handle<Object> value,
+    PropertyAttributes attributes) {
+  DCHECK(!object->HasExternalArrayElements());
+  Isolate* isolate = object->GetIsolate();
+  LookupIterator it(isolate, object, index,
+                    LookupIterator::OWN_SKIP_INTERCEPTOR);
+  if (it.state() == LookupIterator::ACCESS_CHECK) {
+    if (!isolate->MayAccess(object)) {
+      return SetPropertyWithFailedAccessCheck(&it, value, STRICT);
+    }
+    it.Next();
+  }
+
+  if (it.IsFound()) {
+    return ReconfigureAsDataProperty(&it, value, attributes);
+  }
+
+  return AddDataProperty(&it, value, attributes, STRICT,
+                         MAY_BE_STORE_FROM_KEYED);
+}
+
+
+Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
+    LookupIterator* it) {
   Isolate* isolate = it->isolate();
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
@@ -7154,6 +7180,43 @@ bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
 }
 
 
+// static
+Handle<Map> Map::PrepareForDataElement(Handle<Map> map, Handle<Object> value) {
+  ElementsKind kind = map->elements_kind();
+  bool holey = IsHoleyElementsKind(kind);
+
+  switch (kind) {
+    case FAST_SMI_ELEMENTS:
+    case FAST_HOLEY_SMI_ELEMENTS:
+      if (value->IsSmi()) return map;
+      kind = value->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS;
+      break;
+
+    case FAST_DOUBLE_ELEMENTS:
+    case FAST_HOLEY_DOUBLE_ELEMENTS:
+      if (value->IsNumber()) return map;
+      kind = FAST_ELEMENTS;
+      break;
+
+    case FAST_ELEMENTS:
+    case FAST_HOLEY_ELEMENTS:
+    case DICTIONARY_ELEMENTS:
+    case SLOPPY_ARGUMENTS_ELEMENTS:
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+  case EXTERNAL_##TYPE##_ELEMENTS:                      \
+  case TYPE##_ELEMENTS:
+
+      TYPED_ARRAYS(TYPED_ARRAY_CASE)
+#undef TYPED_ARRAY_CASE
+      return map;
+  }
+
+  if (holey) kind = GetHoleyElementsKind(kind);
+  return Map::AsElementsKind(map, kind);
+}
+
+
+// static
 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
                                         Handle<Object> value) {
   // Dictionaries can store any property value.
@@ -11896,48 +11959,6 @@ static bool GetOldValue(Isolate* isolate,
   return true;
 }
 
-MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
-    Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
-    uint32_t add_count) {
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
-  Handle<Object> add_count_object =
-      isolate->factory()->NewNumberFromUint(add_count);
-
-  Handle<Object> args[] =
-      { object, index_object, deleted, add_count_object };
-
-  return Execution::Call(
-      isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
-      isolate->factory()->undefined_value(), arraysize(args), args);
-}
-
-
-MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
-    Handle<JSArray> object) {
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<Object> args[] = { object };
-
-  return Execution::Call(
-      isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
-      isolate->factory()->undefined_value(), arraysize(args), args);
-}
-
-
-MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
-    Handle<JSArray> object) {
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<Object> args[] = { object };
-
-  return Execution::Call(
-      isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
-      isolate->factory()->undefined_value(), arraysize(args), args);
-}
-
-
 MaybeHandle<Object> JSArray::SetElementsLength(
     Handle<JSArray> array,
     Handle<Object> new_length_handle) {
@@ -12022,16 +12043,13 @@ MaybeHandle<Object> JSArray::SetElementsLength(
       // Skip deletions where the property was an accessor, leaving holes
       // in the array of old values.
       if (old_values[i]->IsTheHole()) continue;
-      JSObject::SetOwnElement(deleted, indices[i] - index, old_values[i],
-                              SLOPPY).Assert();
+      JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
+          .Assert();
     }
 
-    RETURN_ON_EXCEPTION(
-        isolate,
-        SetProperty(deleted, isolate->factory()->length_string(),
-                    isolate->factory()->NewNumberFromUint(delete_count),
-                    STRICT),
-        Object);
+    SetProperty(deleted, isolate->factory()->length_string(),
+                isolate->factory()->NewNumberFromUint(delete_count),
+                STRICT).Assert();
   }
 
   RETURN_ON_EXCEPTION(
@@ -12456,84 +12474,6 @@ MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
 }
 
 
-MaybeHandle<Object> JSObject::SetElementWithInterceptor(
-    Handle<JSObject> object, uint32_t index, Handle<Object> value,
-    PropertyAttributes attributes, LanguageMode language_mode,
-    bool check_prototype, SetPropertyMode set_mode) {
-  Isolate* isolate = object->GetIsolate();
-
-  // Make sure that the top context does not change when doing
-  // callbacks or interceptor calls.
-  AssertNoContextChange ncc(isolate);
-
-  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
-  if (!interceptor->setter()->IsUndefined()) {
-    v8::IndexedPropertySetterCallback setter =
-        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
-    LOG(isolate,
-        ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
-    PropertyCallbackArguments args(isolate, interceptor->data(), *object,
-                                   *object);
-    v8::Handle<v8::Value> result =
-        args.Call(setter, index, v8::Utils::ToLocal(value));
-    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-    if (!result.IsEmpty()) return value;
-  }
-
-  return SetElementWithoutInterceptor(object, index, value, attributes,
-                                      language_mode, check_prototype, set_mode);
-}
-
-
-MaybeHandle<Object> JSObject::SetElementWithCallback(
-    Handle<Object> object, Handle<Object> structure, uint32_t index,
-    Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) {
-  Isolate* isolate = holder->GetIsolate();
-
-  // We should never get here to initialize a const with the hole
-  // value since a const declaration would conflict with the setter.
-  DCHECK(!value->IsTheHole());
-  DCHECK(!structure->IsForeign());
-  if (structure->IsExecutableAccessorInfo()) {
-    // api style callbacks
-    Handle<ExecutableAccessorInfo> data =
-        Handle<ExecutableAccessorInfo>::cast(structure);
-    Object* call_obj = data->setter();
-    v8::AccessorNameSetterCallback call_fun =
-        v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
-    if (call_fun == NULL) return value;
-    Handle<String> key(isolate->factory()->Uint32ToString(index));
-    LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
-    PropertyCallbackArguments
-        args(isolate, data->data(), *object, *holder);
-    args.Call(call_fun,
-              v8::Utils::ToLocal(key),
-              v8::Utils::ToLocal(value));
-    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-    return value;
-  }
-
-  if (structure->IsAccessorPair()) {
-    Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
-    if (setter->IsSpecFunction()) {
-      // TODO(rossberg): nicer would be to cast to some JSCallable here...
-      return SetPropertyWithDefinedSetter(
-          object, Handle<JSReceiver>::cast(setter), value);
-    } else {
-      if (is_sloppy(language_mode)) return value;
-      Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
-      THROW_NEW_ERROR(
-          isolate,
-          NewTypeError(MessageTemplate::kNoSetterInCallback, key, holder),
-          Object);
-    }
-  }
-
-  UNREACHABLE();
-  return MaybeHandle<Object>();
-}
-
-
 bool JSObject::HasFastArgumentsElements() {
   Heap* heap = GetHeap();
   if (!elements()->IsFixedArray()) return false;
@@ -12558,14 +12498,8 @@ bool JSObject::HasDictionaryArgumentsElements() {
 }
 
 
-// Adding n elements in fast case is O(n*n).
-// Note: revisit design to have dual undefined values to capture absent
-// elements.
-MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
-                                             uint32_t index,
-                                             Handle<Object> value,
-                                             LanguageMode language_mode,
-                                             bool check_prototype) {
+void JSObject::SetFastElement(Handle<JSObject> object, uint32_t index,
+                              Handle<Object> value) {
   DCHECK(object->HasFastSmiOrObjectElements() ||
          object->HasFastArgumentsElements());
 
@@ -12577,22 +12511,13 @@ MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
   isolate->UpdateArrayProtectorOnSetElement(object);
 
   Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
-  if (backing_store->map() ==
-      isolate->heap()->sloppy_arguments_elements_map()) {
+  if (object->HasSloppyArgumentsElements()) {
     backing_store = handle(FixedArray::cast(backing_store->get(1)));
   } else {
     backing_store = EnsureWritableFastElements(object);
   }
   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
 
-  if (check_prototype &&
-      (index >= capacity || backing_store->get(index)->IsTheHole())) {
-    bool found;
-    MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
-        object, index, value, &found, language_mode);
-    if (found) return result;
-  }
-
   uint32_t new_capacity = capacity;
   // Check if the length property of this object needs to be updated.
   uint32_t array_length = 0;
@@ -12633,8 +12558,8 @@ MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
     }
     if (convert_to_slow) {
       NormalizeElements(object);
-      return SetDictionaryElement(object, index, value, NONE, language_mode,
-                                  check_prototype);
+      SetDictionaryElement(object, index, value, NONE);
+      return;
     }
   }
   // Convert to fast double elements if appropriate.
@@ -12649,7 +12574,7 @@ MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
     SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
     FixedDoubleArray::cast(object->elements())->set(index, value->Number());
     JSObject::ValidateElements(object);
-    return value;
+    return;
   }
   // Change elements kind from Smi-only to generic FAST if necessary.
   if (object->HasFastSmiElements() && !value->IsSmi()) {
@@ -12673,7 +12598,7 @@ MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
                                          smi_mode);
     new_elements->set(index, *value);
     JSObject::ValidateElements(object);
-    return value;
+    return;
   }
 
   // Finally, set the new element and length.
@@ -12682,22 +12607,63 @@ MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
   if (must_update_array_length) {
     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
   }
-  return value;
 }
 
 
-MaybeHandle<Object> JSObject::SetDictionaryElement(
-    Handle<JSObject> object, uint32_t index, Handle<Object> value,
-    PropertyAttributes attributes, LanguageMode language_mode,
-    bool check_prototype, SetPropertyMode set_mode) {
-  DCHECK(object->HasDictionaryElements() ||
-         object->HasDictionaryArgumentsElements());
+void JSObject::SetSloppyArgumentsElement(Handle<JSObject> object,
+                                         uint32_t index, Handle<Object> value,
+                                         PropertyAttributes attributes) {
+  // TODO(verwaest): Handle with the elements accessor.
+  Isolate* isolate = object->GetIsolate();
+
+  DCHECK(object->HasSloppyArgumentsElements());
+
+  Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
+  uint32_t length = parameter_map->length();
+  Handle<Object> probe =
+      index < length - 2
+          ? Handle<Object>(parameter_map->get(index + 2), isolate)
+          : Handle<Object>();
+  if (!probe.is_null() && !probe->IsTheHole()) {
+    Handle<Context> context(Context::cast(parameter_map->get(0)));
+    int context_index = Handle<Smi>::cast(probe)->value();
+    DCHECK(!context->get(context_index)->IsTheHole());
+    context->set(context_index, *value);
+
+    if (attributes == NONE) return;
+
+    // Redefining attributes of an aliased element destroys fast aliasing.
+    parameter_map->set_the_hole(index + 2);
+    // For elements that are still writable we re-establish slow aliasing.
+    if ((attributes & READ_ONLY) == 0) {
+      value = Handle<Object>::cast(
+          isolate->factory()->NewAliasedArgumentsEntry(context_index));
+    }
+  }
+
+  Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+  if (arguments->IsDictionary()) {
+    SetDictionaryElement(object, index, value, attributes);
+  } else {
+    SetFastElement(object, index, value);
+  }
+}
+
+
+void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index,
+                                    Handle<Object> value,
+                                    PropertyAttributes attributes) {
+  // TODO(verwaest): Handle with the elements accessor.
   Isolate* isolate = object->GetIsolate();
 
   // Insert element in the dictionary.
   Handle<FixedArray> elements(FixedArray::cast(object->elements()));
   bool is_arguments =
       (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
+
+  DCHECK(object->HasDictionaryElements() ||
+         object->HasDictionaryArgumentsElements());
+
   Handle<SeededNumberDictionary> dictionary(is_arguments
     ? SeededNumberDictionary::cast(elements->get(1))
     : SeededNumberDictionary::cast(*elements));
@@ -12706,71 +12672,28 @@ MaybeHandle<Object> JSObject::SetDictionaryElement(
   if (entry != SeededNumberDictionary::kNotFound) {
     Handle<Object> element(dictionary->ValueAt(entry), isolate);
     PropertyDetails details = dictionary->DetailsAt(entry);
-    if (details.type() == ACCESSOR_CONSTANT && set_mode == SET_PROPERTY) {
-      return SetElementWithCallback(object, element, index, value, object,
-                                    language_mode);
-    } else if (set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
-               details.kind() == kAccessor) {
-      return RedefineNonconfigurableProperty(
-          isolate, isolate->factory()->NewNumberFromUint(index),
-          isolate->factory()->undefined_value(), language_mode);
-
-    } else if ((set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
-                details.IsReadOnly()) ||
-               (set_mode == SET_PROPERTY && details.IsReadOnly() &&
-                !element->IsTheHole())) {
-      // If a value has not been initialized we allow writing to it even if it
-      // is read-only (a declared const that has not been initialized).
-      return WriteToReadOnlyProperty(
-          isolate, object, isolate->factory()->NewNumberFromUint(index),
-          isolate->factory()->undefined_value(), language_mode);
-    } else {
-      DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
-             element->IsTheHole());
-      dictionary->UpdateMaxNumberKey(index);
-      if (set_mode == DEFINE_PROPERTY) {
-        details = PropertyDetails(attributes, DATA, details.dictionary_index(),
-                                  PropertyCellType::kNoCell);
-        dictionary->DetailsAtPut(entry, details);
-      }
-
-      // Elements of the arguments object in slow mode might be slow aliases.
-      if (is_arguments && element->IsAliasedArgumentsEntry()) {
-        Handle<AliasedArgumentsEntry> entry =
-            Handle<AliasedArgumentsEntry>::cast(element);
-        Handle<Context> context(Context::cast(elements->get(0)));
-        int context_index = entry->aliased_context_slot();
-        DCHECK(!context->get(context_index)->IsTheHole());
-        context->set(context_index, *value);
-        // For elements that are still writable we keep slow aliasing.
-        if (!details.IsReadOnly()) value = element;
-      }
-      dictionary->ValueAtPut(entry, *value);
+    DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
+           element->IsTheHole());
+    dictionary->UpdateMaxNumberKey(index);
+
+    details = PropertyDetails(attributes, DATA, details.dictionary_index(),
+                              PropertyCellType::kNoCell);
+    dictionary->DetailsAtPut(entry, details);
+
+    // Elements of the arguments object in slow mode might be slow aliases.
+    if (is_arguments && element->IsAliasedArgumentsEntry()) {
+      Handle<AliasedArgumentsEntry> entry =
+          Handle<AliasedArgumentsEntry>::cast(element);
+      Handle<Context> context(Context::cast(elements->get(0)));
+      int context_index = entry->aliased_context_slot();
+      DCHECK(!context->get(context_index)->IsTheHole());
+      context->set(context_index, *value);
+      // For elements that are still writable we keep slow aliasing.
+      if (!details.IsReadOnly()) value = element;
     }
+    dictionary->ValueAtPut(entry, *value);
   } else {
-    // Index not already used. Look for an accessor in the prototype chain.
-    // Can cause GC!
-    if (check_prototype) {
-      bool found;
-      MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
-          object, index, value, &found, language_mode);
-      if (found) return result;
-    }
-
-    // When we set the is_extensible flag to false we always force the
-    // element into dictionary mode (and force them to stay there).
-    if (!object->map()->is_extensible()) {
-      if (is_sloppy(language_mode)) {
-        return isolate->factory()->undefined_value();
-      } else {
-        Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
-        Handle<String> name = isolate->factory()->NumberToString(number);
-        THROW_NEW_ERROR(
-            isolate, NewTypeError(MessageTemplate::kObjectNotExtensible, name),
-            Object);
-      }
-    }
-
+    DCHECK(object->map()->is_extensible());
     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
     Handle<SeededNumberDictionary> new_dictionary =
         SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
@@ -12821,58 +12744,34 @@ MaybeHandle<Object> JSObject::SetDictionaryElement(
     }
 #endif
   }
-  return value;
 }
 
-MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
-                                                   uint32_t index,
-                                                   Handle<Object> value,
-                                                   LanguageMode language_mode,
-                                                   bool check_prototype) {
+void JSObject::SetFastDoubleElement(Handle<JSObject> object, uint32_t index,
+                                    Handle<Object> value) {
   DCHECK(object->HasFastDoubleElements());
 
   Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
+  uint32_t length = elms_length;
 
-  // If storing to an element that isn't in the array, pass the store request
-  // up the prototype chain before storing in the receiver's elements.
-  if (check_prototype &&
-      (index >= elms_length ||
-       Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
-    bool found;
-    MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
-        object, index, value, &found, language_mode);
-    if (found) return result;
-  }
-
-  // If the value object is not a heap number, switch to fast elements and try
-  // again.
-  bool value_is_smi = value->IsSmi();
   bool introduces_holes = true;
-  uint32_t length = elms_length;
   if (object->IsJSArray()) {
+    // In case of JSArray, the length does not equal the capacity.
     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length));
     introduces_holes = index > length;
   } else {
     introduces_holes = index >= elms_length;
   }
 
+  // If the value object is not a heap number, switch to fast elements and try
+  // again.
   if (!value->IsNumber()) {
     SetFastElementsCapacityAndLength(object, elms_length, length,
                                      kDontAllowSmiElements);
-    Handle<Object> result;
-    ASSIGN_RETURN_ON_EXCEPTION(
-        object->GetIsolate(), result,
-        SetFastElement(object, index, value, language_mode, check_prototype),
-        Object);
-    JSObject::ValidateElements(object);
-    return result;
+    SetFastElement(object, index, value);
+    return;
   }
 
-  double double_value = value_is_smi
-      ? static_cast<double>(Handle<Smi>::cast(value)->value())
-      : Handle<HeapNumber>::cast(value)->value();
-
   // If the array is growing, and it's not growth by a single element at the
   // end, make sure that the ElementsKind is HOLEY.
   ElementsKind elements_kind = object->GetElementsKind();
@@ -12884,7 +12783,7 @@ MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
   // Check whether there is extra space in the fixed array.
   if (index < elms_length) {
     Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
-    elms->set(index, double_value);
+    elms->set(index, value->Number());
     if (object->IsJSArray()) {
       // Update the length of the array if needed.
       uint32_t array_length = 0;
@@ -12894,7 +12793,7 @@ MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
       }
     }
-    return value;
+    return;
   }
 
   // Allow gap in fast case.
@@ -12904,9 +12803,9 @@ MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
     if (!object->ShouldConvertToSlowElements(new_capacity)) {
       DCHECK(static_cast<uint32_t>(new_capacity) > index);
       SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
-      FixedDoubleArray::cast(object->elements())->set(index, double_value);
+      FixedDoubleArray::cast(object->elements())->set(index, value->Number());
       JSObject::ValidateElements(object);
-      return value;
+      return;
     }
   }
 
@@ -12918,277 +12817,111 @@ MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
 
   NormalizeElements(object);
   DCHECK(object->HasDictionaryElements());
-  return SetElement(object, index, value, NONE, language_mode, check_prototype);
+  SetDictionaryElement(object, index, value, NONE);
 }
 
 
+// static
 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
                                            uint32_t index, Handle<Object> value,
-                                           PropertyAttributes attributes,
                                            LanguageMode language_mode) {
-  if (object->IsJSProxy()) {
-    return JSProxy::SetElementWithHandler(Handle<JSProxy>::cast(object), object,
-                                          index, value, language_mode);
-  }
-  return JSObject::SetElement(Handle<JSObject>::cast(object), index, value,
-                              attributes, language_mode);
-}
-
-
-MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
-                                            uint32_t index,
-                                            Handle<Object> value,
-                                            PropertyAttributes attributes,
-                                            LanguageMode language_mode) {
-  DCHECK(!object->HasExternalArrayElements());
-  return JSObject::SetElement(object, index, value, attributes, language_mode,
-                              false);
-}
-
-
-MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
-                                         uint32_t index, Handle<Object> value,
-                                         PropertyAttributes attributes,
-                                         LanguageMode language_mode,
-                                         bool check_prototype,
-                                         SetPropertyMode set_mode) {
   Isolate* isolate = object->GetIsolate();
+  LookupIterator it(isolate, object, index);
+  return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
+}
 
-  if (object->HasExternalArrayElements() ||
-      object->HasFixedTypedArrayElements()) {
-    if (!value->IsNumber() && !value->IsUndefined()) {
-      ASSIGN_RETURN_ON_EXCEPTION(
-          isolate, value,
-          Execution::ToNumber(isolate, value), Object);
-    }
-  }
-
-  // Check access rights if needed.
-  if (object->IsAccessCheckNeeded()) {
-    if (!isolate->MayAccess(object)) {
-      isolate->ReportFailedAccessCheck(object);
-      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-      return value;
-    }
-  }
-
-  if (object->IsJSGlobalProxy()) {
-    PrototypeIterator iter(isolate, object);
-    if (iter.IsAtEnd()) return value;
-    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
-    return SetElement(
-        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
-        value, attributes, language_mode, check_prototype, set_mode);
-  }
-
-  // Don't allow element properties to be redefined for external arrays.
-  if ((object->HasExternalArrayElements() ||
-          object->HasFixedTypedArrayElements()) &&
-      set_mode == DEFINE_PROPERTY) {
-    THROW_NEW_ERROR(
-        isolate, NewTypeError(MessageTemplate::kRedefineExternalArray), Object);
-  }
-
-  // Normalize the elements to enable attributes on the property.
-  if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
-    Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
-    // Make sure that we never go back to fast case.
-    dictionary->set_requires_slow_elements();
-  }
 
-  if (!object->map()->is_observed()) {
-    return object->HasIndexedInterceptor()
-               ? SetElementWithInterceptor(object, index, value, attributes,
-                                           language_mode, check_prototype,
-                                           set_mode)
-               : SetElementWithoutInterceptor(object, index, value, attributes,
-                                              language_mode, check_prototype,
-                                              set_mode);
-  }
+// static
+MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> receiver,
+                                             uint32_t index,
+                                             Handle<Object> value,
+                                             PropertyAttributes attributes) {
+  DCHECK(receiver->map()->is_extensible());
 
-  Maybe<PropertyAttributes> maybe =
-      JSReceiver::GetOwnElementAttributes(object, index);
-  if (!maybe.IsJust()) return MaybeHandle<Object>();
-  PropertyAttributes old_attributes = maybe.FromJust();
+  Isolate* isolate = receiver->GetIsolate();
 
-  Handle<Object> old_value = isolate->factory()->the_hole_value();
+  // TODO(verwaest): Use ElementAccessor.
   Handle<Object> old_length_handle;
-  Handle<Object> new_length_handle;
-
-  if (old_attributes != ABSENT) {
-    if (GetOwnElementAccessorPair(object, index).is_null()) {
-      old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
-    }
-  } else if (object->IsJSArray()) {
-    // Store old array length in case adding an element grows the array.
-    old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
-                               isolate);
+  if (receiver->IsJSArray() && receiver->map()->is_observed()) {
+    old_length_handle = handle(JSArray::cast(*receiver)->length(), isolate);
   }
 
-  // Check for lookup interceptor
-  Handle<Object> result;
-  ASSIGN_RETURN_ON_EXCEPTION(
-      isolate, result,
-      object->HasIndexedInterceptor()
-          ? SetElementWithInterceptor(object, index, value, attributes,
-                                      language_mode, check_prototype, set_mode)
-          : SetElementWithoutInterceptor(object, index, value, attributes,
-                                         language_mode, check_prototype,
-                                         set_mode),
-      Object);
-
-  Handle<String> name = isolate->factory()->Uint32ToString(index);
-  maybe = GetOwnElementAttributes(object, index);
-  if (!maybe.IsJust()) return MaybeHandle<Object>();
-  PropertyAttributes new_attributes = maybe.FromJust();
-
-  if (old_attributes == ABSENT) {
-    if (object->IsJSArray() &&
-        !old_length_handle->SameValue(
-            Handle<JSArray>::cast(object)->length())) {
-      new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
-                                 isolate);
-      uint32_t old_length = 0;
-      uint32_t new_length = 0;
-      CHECK(old_length_handle->ToArrayLength(&old_length));
-      CHECK(new_length_handle->ToArrayLength(&new_length));
-
-      RETURN_ON_EXCEPTION(
-          isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object);
-      RETURN_ON_EXCEPTION(
-          isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
-      RETURN_ON_EXCEPTION(
-          isolate, EnqueueChangeRecord(object, "update",
-                                       isolate->factory()->length_string(),
-                                       old_length_handle),
-          Object);
-      RETURN_ON_EXCEPTION(
-          isolate, EndPerformSplice(Handle<JSArray>::cast(object)), Object);
-      Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
-      RETURN_ON_EXCEPTION(
-          isolate,
-          EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length,
-                              deleted, new_length - old_length),
-          Object);
-    } else {
-      RETURN_ON_EXCEPTION(
-          isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
-    }
-  } else if (old_value->IsTheHole()) {
-    RETURN_ON_EXCEPTION(
-        isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
-        Object);
-  } else {
-    Handle<Object> new_value =
-        Object::GetElement(isolate, object, index).ToHandleChecked();
-    bool value_changed = !old_value->SameValue(*new_value);
-    if (old_attributes != new_attributes) {
-      if (!value_changed) old_value = isolate->factory()->the_hole_value();
-      RETURN_ON_EXCEPTION(
-          isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
-          Object);
-    } else if (value_changed) {
-      RETURN_ON_EXCEPTION(
-          isolate, EnqueueChangeRecord(object, "update", name, old_value),
-          Object);
-    }
+  if (attributes != NONE) {
+    Handle<SeededNumberDictionary> d = JSObject::NormalizeElements(receiver);
+    // TODO(verwaest): Move this into NormalizeElements.
+    d->set_requires_slow_elements();
   }
 
-  return result;
-}
-
+  Handle<Object> result = value;
 
-MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
-    Handle<JSObject> object, uint32_t index, Handle<Object> value,
-    PropertyAttributes attributes, LanguageMode language_mode,
-    bool check_prototype, SetPropertyMode set_mode) {
-  DCHECK(object->HasDictionaryElements() ||
-         object->HasDictionaryArgumentsElements() ||
-         (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
-  Isolate* isolate = object->GetIsolate();
-  if (FLAG_trace_external_array_abuse &&
-      IsExternalArrayElementsKind(object->GetElementsKind())) {
-    CheckArrayAbuse(object, "external elements write", index);
-  }
-  if (FLAG_trace_js_array_abuse &&
-      !IsExternalArrayElementsKind(object->GetElementsKind())) {
-    if (object->IsJSArray()) {
-      CheckArrayAbuse(object, "elements write", index, true);
-    }
-  }
-  if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
-      Handle<JSArray>::cast(object), index)) {
-    if (is_sloppy(language_mode)) {
-      return value;
-    } else {
-      return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
-    }
-  }
-  switch (object->GetElementsKind()) {
+  switch (receiver->GetElementsKind()) {
     case FAST_SMI_ELEMENTS:
     case FAST_ELEMENTS:
     case FAST_HOLEY_SMI_ELEMENTS:
     case FAST_HOLEY_ELEMENTS:
-      return SetFastElement(object, index, value, language_mode,
-                            check_prototype);
+      SetFastElement(receiver, index, value);
+      break;
     case FAST_DOUBLE_ELEMENTS:
     case FAST_HOLEY_DOUBLE_ELEMENTS:
-      return SetFastDoubleElement(object, index, value, language_mode,
-                                  check_prototype);
+      SetFastDoubleElement(receiver, index, value);
+      break;
 
-#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                  \
-  case EXTERNAL_##TYPE##_ELEMENTS: {                                     \
-    Handle<External##Type##Array> array(                                 \
-        External##Type##Array::cast(object->elements()));                \
-    return External##Type##Array::SetValue(object, array, index, value); \
-  }                                                                      \
-  case TYPE##_ELEMENTS: {                                                \
-    Handle<Fixed##Type##Array> array(                                    \
-        Fixed##Type##Array::cast(object->elements()));                   \
-    return Fixed##Type##Array::SetValue(object, array, index, value);    \
-  }
+    case DICTIONARY_ELEMENTS:
+      SetDictionaryElement(receiver, index, value, attributes);
+      break;
+    case SLOPPY_ARGUMENTS_ELEMENTS:
+      SetSloppyArgumentsElement(receiver, index, value, attributes);
+      break;
 
-    TYPED_ARRAYS(TYPED_ARRAY_CASE)
+// Elements cannot be added to typed arrays.
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+  case EXTERNAL_##TYPE##_ELEMENTS:                      \
+  case TYPE##_ELEMENTS:
+
+      TYPED_ARRAYS(TYPED_ARRAY_CASE)
 
 #undef TYPED_ARRAY_CASE
+      UNREACHABLE();
+      break;
+  }
 
-    case DICTIONARY_ELEMENTS:
-      return SetDictionaryElement(object, index, value, attributes,
-                                  language_mode, check_prototype, set_mode);
-    case SLOPPY_ARGUMENTS_ELEMENTS: {
-      Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
-      uint32_t length = parameter_map->length();
-      Handle<Object> probe = index < length - 2 ?
-          Handle<Object>(parameter_map->get(index + 2), isolate) :
-          Handle<Object>();
-      if (!probe.is_null() && !probe->IsTheHole()) {
-        Handle<Context> context(Context::cast(parameter_map->get(0)));
-        int context_index = Handle<Smi>::cast(probe)->value();
-        DCHECK(!context->get(context_index)->IsTheHole());
-        context->set(context_index, *value);
-        // Redefining attributes of an aliased element destroys fast aliasing.
-        if (set_mode == SET_PROPERTY || attributes == NONE) return value;
-        parameter_map->set_the_hole(index + 2);
-        // For elements that are still writable we re-establish slow aliasing.
-        if ((attributes & READ_ONLY) == 0) {
-          value = Handle<Object>::cast(
-              isolate->factory()->NewAliasedArgumentsEntry(context_index));
-        }
-      }
-      Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
-      if (arguments->IsDictionary()) {
-        return SetDictionaryElement(object, index, value, attributes,
-                                    language_mode, check_prototype, set_mode);
-      } else {
-        return SetFastElement(object, index, value, language_mode,
-                              check_prototype);
-      }
-    }
+  if (!old_length_handle.is_null() &&
+      !old_length_handle->SameValue(
+          Handle<JSArray>::cast(receiver)->length())) {
+    // |old_length_handle| is kept null above unless the receiver is observed.
+    DCHECK(receiver->map()->is_observed());
+    Handle<JSArray> array = Handle<JSArray>::cast(receiver);
+    Handle<String> name = isolate->factory()->Uint32ToString(index);
+    Handle<Object> new_length_handle(array->length(), isolate);
+    uint32_t old_length = 0;
+    uint32_t new_length = 0;
+    CHECK(old_length_handle->ToArrayLength(&old_length));
+    CHECK(new_length_handle->ToArrayLength(&new_length));
+
+    RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
+    RETURN_ON_EXCEPTION(
+        isolate, JSObject::EnqueueChangeRecord(
+                     array, "add", name, isolate->factory()->the_hole_value()),
+        Object);
+    RETURN_ON_EXCEPTION(
+        isolate, JSObject::EnqueueChangeRecord(
+                     array, "update", isolate->factory()->length_string(),
+                     old_length_handle),
+        Object);
+    RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
+    Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
+    RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted,
+                                                     new_length - old_length),
+                        Object);
+  } else if (receiver->map()->is_observed()) {
+    Handle<String> name = isolate->factory()->Uint32ToString(index);
+    RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
+                                     receiver, "add", name,
+                                     isolate->factory()->the_hole_value()),
+                        Object);
   }
-  // All possible cases have been handled above. Add a return to avoid the
-  // complaints from the compiler.
-  UNREACHABLE();
-  return isolate->factory()->null_value();
+
+  return result;
 }
 
 
@@ -14979,6 +14712,23 @@ size_t JSTypedArray::element_size() {
 }
 
 
+Handle<Object> FixedArray::SetValue(Handle<JSObject> holder,
+                                    Handle<FixedArray> array, uint32_t index,
+                                    Handle<Object> value) {
+  array->set(index, *value);
+  return value;
+}
+
+
+Handle<Object> FixedDoubleArray::SetValue(Handle<JSObject> holder,
+                                          Handle<FixedDoubleArray> array,
+                                          uint32_t index,
+                                          Handle<Object> value) {
+  array->set(index, value->Number());
+  return value;
+}
+
+
 Handle<Object> ExternalUint8ClampedArray::SetValue(
     Handle<JSObject> holder, Handle<ExternalUint8ClampedArray> array,
     uint32_t index, Handle<Object> value) {
index 582038cca64ea6cd8e8ae83ced0b43ec80968d0a..bd9e4abe71354c1936cb5bac273dfa645fc2a0cb 100644 (file)
@@ -1199,9 +1199,7 @@ class Object {
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor(
       LookupIterator* it);
   MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor(
-      Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
-      Handle<JSObject> holder, Handle<Object> structure,
-      LanguageMode language_mode);
+      LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
 
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
       Handle<Object> receiver,
@@ -1216,10 +1214,6 @@ class Object {
       Handle<Object> object,
       uint32_t index);
 
-  MUST_USE_RESULT static MaybeHandle<Object> SetElementWithReceiver(
-      Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
-      uint32_t index, Handle<Object> value, LanguageMode language_mode);
-
   static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
       Isolate* isolate, Handle<Object> receiver);
 
@@ -1649,16 +1643,6 @@ enum EnsureElementsMode {
 };
 
 
-// Indicates whether a property should be set or (re)defined.  Setting of a
-// property causes attributes to remain unchanged, writability to be checked
-// and callbacks to be called.  Defining of a property causes attributes to
-// be updated and callbacks to be overridden.
-enum SetPropertyMode {
-  SET_PROPERTY,
-  DEFINE_PROPERTY
-};
-
-
 // Indicator for one component of an AccessorPair.
 enum AccessorComponent {
   ACCESSOR_GETTER,
@@ -1674,7 +1658,7 @@ class JSReceiver: public HeapObject {
 
   MUST_USE_RESULT static MaybeHandle<Object> SetElement(
       Handle<JSReceiver> object, uint32_t index, Handle<Object> value,
-      PropertyAttributes attributes, LanguageMode language_mode);
+      LanguageMode language_mode);
 
   // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
   MUST_USE_RESULT static inline Maybe<bool> HasProperty(
@@ -1857,21 +1841,24 @@ class JSObject: public JSReceiver {
   MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor(
       LookupIterator* it, Handle<Object> value);
 
-  // SetLocalPropertyIgnoreAttributes converts callbacks to fields. We need to
-  // grant an exemption to ExecutableAccessor callbacks in some cases.
-  enum ExecutableAccessorInfoHandling {
-    DEFAULT_HANDLING,
-    DONT_FORCE_FIELD
-  };
-
   MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes(
       Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
-      PropertyAttributes attributes,
-      ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING);
+      PropertyAttributes attributes);
+
+  MUST_USE_RESULT static MaybeHandle<Object> SetOwnElementIgnoreAttributes(
+      Handle<JSObject> object, uint32_t index, Handle<Object> value,
+      PropertyAttributes attributes);
+
+  MUST_USE_RESULT static MaybeHandle<Object> ReconfigureAsDataProperty(
+      LookupIterator* it, Handle<Object> value, PropertyAttributes attributes);
 
   static void AddProperty(Handle<JSObject> object, Handle<Name> name,
                           Handle<Object> value, PropertyAttributes attributes);
 
+  MUST_USE_RESULT static MaybeHandle<Object> AddDataElement(
+      Handle<JSObject> receiver, uint32_t index, Handle<Object> value,
+      PropertyAttributes attributes);
+
   // Extend the receiver with a single fast property appeared first in the
   // passed map. This also extends the property backing store if necessary.
   static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map);
@@ -1889,6 +1876,17 @@ class JSObject: public JSReceiver {
   static void SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
                                     Handle<Object> value,
                                     PropertyDetails details);
+  static void SetDictionaryElement(Handle<JSObject> object, uint32_t index,
+                                   Handle<Object> value,
+                                   PropertyAttributes attributes);
+  static void SetSloppyArgumentsElement(Handle<JSObject> object, uint32_t index,
+                                        Handle<Object> value,
+                                        PropertyAttributes attributes);
+
+  static void SetFastElement(Handle<JSObject> object, uint32_t index,
+                             Handle<Object> value);
+  static void SetFastDoubleElement(Handle<JSObject> object, uint32_t index,
+                                   Handle<Object> value);
 
   static void OptimizeAsPrototype(Handle<JSObject> object,
                                   PrototypeOptimizationMode mode);
@@ -2011,23 +2009,8 @@ class JSObject: public JSReceiver {
   MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair(
       Handle<JSObject> object, uint32_t index);
 
-  MUST_USE_RESULT static MaybeHandle<Object> SetFastElement(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      LanguageMode language_mode, bool check_prototype);
-
-  MUST_USE_RESULT static inline MaybeHandle<Object> SetOwnElement(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      LanguageMode language_mode);
-
-  MUST_USE_RESULT static MaybeHandle<Object> SetOwnElement(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      PropertyAttributes attributes, LanguageMode language_mode);
-
-  // Empty handle is returned if the element cannot be set to the given value.
-  MUST_USE_RESULT static MaybeHandle<Object> SetElement(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      PropertyAttributes attributes, LanguageMode language_mode,
-      bool check_prototype = true, SetPropertyMode set_mode = SET_PROPERTY);
+  static void UpdateAllocationSite(Handle<JSObject> object,
+                                   ElementsKind to_kind);
 
   enum SetFastElementsCapacitySmiMode {
     kAllowSmiElements,
@@ -2319,37 +2302,10 @@ class JSObject: public JSReceiver {
                                 Handle<Map> new_map,
                                 int expected_additional_properties);
 
-  static void UpdateAllocationSite(Handle<JSObject> object,
-                                   ElementsKind to_kind);
-
   // Used from Object::GetProperty().
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck(
       LookupIterator* it);
 
-  MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback(
-      Handle<Object> object, Handle<Object> structure, uint32_t index,
-      Handle<Object> value, Handle<JSObject> holder,
-      LanguageMode language_mode);
-  MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      PropertyAttributes attributes, LanguageMode language_mode,
-      bool check_prototype, SetPropertyMode set_mode);
-  MUST_USE_RESULT static MaybeHandle<Object> SetElementWithoutInterceptor(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      PropertyAttributes attributes, LanguageMode language_mode,
-      bool check_prototype, SetPropertyMode set_mode);
-  MUST_USE_RESULT
-  static MaybeHandle<Object> SetElementWithCallbackSetterInPrototypes(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      bool* found, LanguageMode language_mode);
-  MUST_USE_RESULT static MaybeHandle<Object> SetDictionaryElement(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      PropertyAttributes attributes, LanguageMode language_mode,
-      bool check_prototype, SetPropertyMode set_mode = SET_PROPERTY);
-  MUST_USE_RESULT static MaybeHandle<Object> SetFastDoubleElement(
-      Handle<JSObject> object, uint32_t index, Handle<Object> value,
-      LanguageMode language_mode, bool check_prototype = true);
-
   MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck(
       LookupIterator* it, Handle<Object> value, LanguageMode language_mode);
 
@@ -2453,6 +2409,9 @@ class FixedArray: public FixedArrayBase {
  public:
   // Setter and getter for elements.
   inline Object* get(int index) const;
+  static Handle<Object> SetValue(Handle<JSObject> holder,
+                                 Handle<FixedArray> array, uint32_t index,
+                                 Handle<Object> value);
   static inline Handle<Object> get(Handle<FixedArray> array, int index);
   // Setter that uses write barrier.
   inline void set(int index, Object* value);
@@ -2574,6 +2533,10 @@ class FixedDoubleArray: public FixedArrayBase {
   inline double get_scalar(int index);
   inline uint64_t get_representation(int index);
   static inline Handle<Object> get(Handle<FixedDoubleArray> array, int index);
+  // This accessor has to get a Number as |value|.
+  static Handle<Object> SetValue(Handle<JSObject> holder,
+                                 Handle<FixedDoubleArray> array, uint32_t index,
+                                 Handle<Object> value);
   inline void set(int index, double value);
   inline void set_the_hole(int index);
 
@@ -5854,6 +5817,8 @@ class Map: public HeapObject {
   static Handle<Map> PrepareForDataProperty(Handle<Map> old_map,
                                             int descriptor_number,
                                             Handle<Object> value);
+  static Handle<Map> PrepareForDataElement(Handle<Map> old_map,
+                                           Handle<Object> value);
 
   static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode mode,
                                const char* reason);
@@ -9757,10 +9722,6 @@ class JSProxy: public JSReceiver {
  private:
   friend class JSReceiver;
 
-  MUST_USE_RESULT static inline MaybeHandle<Object> SetElementWithHandler(
-      Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index,
-      Handle<Object> value, LanguageMode language_mode);
-
   MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler(
       Handle<JSProxy> proxy, Handle<Name> name);
 
@@ -10348,7 +10309,7 @@ class ExecutableAccessorInfo: public AccessorInfo {
   static const int kDataOffset = kSetterOffset + kPointerSize;
   static const int kSize = kDataOffset + kPointerSize;
 
-  static inline void ClearSetter(Handle<ExecutableAccessorInfo> info);
+  static void ClearSetter(Handle<ExecutableAccessorInfo> info);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(ExecutableAccessorInfo);
index b6007789c4332fec8f7d92a7ab20671a0573f927..00b57612e828a1601337a9a45b26288fc79e751e 100644 (file)
@@ -944,7 +944,7 @@ function SameValueZero(x, y) {
 function ConcatIterableToArray(target, iterable) {
    var index = target.length;
    for (var element of iterable) {
-     %AddElement(target, index++, element, NONE);
+     %AddElement(target, index++, element);
    }
    return target;
 }
index 3f05540ef80d6d0b47d1139cec9674c24cfcef11..c468673dd5298f472a91d1a89edbdbf7ba4d2877 100644 (file)
@@ -101,7 +101,7 @@ RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
 
   // Strict not needed. Used for cycle detection in Array join implementation.
   RETURN_FAILURE_ON_EXCEPTION(
-      isolate, JSObject::SetFastElement(array, length, element, SLOPPY, true));
+      isolate, JSObject::AddDataElement(array, length, element, NONE));
   return isolate->heap()->true_value();
 }
 
index 51247b728cf60730d3089b4a5bce6472673172ab..3dbcc65eca6af1e5e5e9a0f80009d18dd8a73640 100644 (file)
@@ -203,8 +203,8 @@ RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
   uint32_t index;
   if (name->AsArrayIndex(&index)) {
     RETURN_FAILURE_ON_EXCEPTION(
-        isolate,
-        JSObject::SetOwnElement(object, index, function, DONT_ENUM, STRICT));
+        isolate, JSObject::SetOwnElementIgnoreAttributes(object, index,
+                                                         function, DONT_ENUM));
   } else {
     RETURN_FAILURE_ON_EXCEPTION(
         isolate, JSObject::SetOwnPropertyIgnoreAttributes(object, name,
@@ -357,11 +357,12 @@ static Object* StoreElementToSuper(Isolate* isolate,
   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
   if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
 
+  LookupIterator it(isolate, receiver, index, Handle<JSReceiver>::cast(proto));
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, result,
-      Object::SetElementWithReceiver(isolate, proto, receiver, index, value,
-                                     language_mode));
+      Object::SetSuperProperty(&it, value, language_mode,
+                               Object::MAY_BE_STORE_FROM_KEYED));
   return *result;
 }
 
index 6612f2c2d5cc1a246274a86f76c1f33e048f346c..2555086b07e2265ad7da2b00088bdf316b804d5c 100644 (file)
@@ -1885,9 +1885,9 @@ RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
       if (location.IsStepInLocation()) {
         Smi* position_value = Smi::FromInt(location.position());
         RETURN_FAILURE_ON_EXCEPTION(
-            isolate, JSObject::SetElement(
-                         array, index, Handle<Object>(position_value, isolate),
-                         NONE, SLOPPY));
+            isolate,
+            JSObject::SetElement(array, index, handle(position_value, isolate),
+                                 SLOPPY));
         index++;
       }
     }
index 522411829abe4fc7a0d556a96360a40ef14d8a13..52c1726dc65ea256c1fafeb5d7eea890cf1f161f 100644 (file)
@@ -94,8 +94,8 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
         // Array index as string (uint32).
         if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate);
-        maybe_result =
-            JSObject::SetOwnElement(boilerplate, element_index, value, SLOPPY);
+        maybe_result = JSObject::SetOwnElementIgnoreAttributes(
+            boilerplate, element_index, value, NONE);
       } else {
         Handle<String> name(String::cast(*key));
         DCHECK(!name->AsArrayIndex(&element_index));
@@ -105,8 +105,8 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
     } else if (key->ToArrayIndex(&element_index)) {
       // Array index (uint32).
       if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate);
-      maybe_result =
-          JSObject::SetOwnElement(boilerplate, element_index, value, SLOPPY);
+      maybe_result = JSObject::SetOwnElementIgnoreAttributes(
+          boilerplate, element_index, value, NONE);
     } else {
       // Non-uint32 number.
       DCHECK(key->IsNumber());
index e0e3764837a4cfdfb1d84b49db528127604e5c19..956fee9e838f46214ed47b017e7a0a226efedf99 100644 (file)
@@ -132,8 +132,8 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
       }
     }
 
-    MaybeHandle<Object> result = JSObject::SetElement(
-        js_object, index, value, NONE, language_mode, true, SET_PROPERTY);
+    MaybeHandle<Object> result =
+        JSObject::SetElement(js_object, index, value, language_mode);
     JSObject::ValidateElements(js_object);
 
     return result.is_null() ? result : value;
@@ -151,8 +151,7 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
               isolate, value, Execution::ToNumber(isolate, value), Object);
         }
       }
-      return JSObject::SetElement(js_object, index, value, NONE, language_mode,
-                                  true, SET_PROPERTY);
+      return JSObject::SetElement(js_object, index, value, language_mode);
     } else {
       if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
       return Object::SetProperty(object, name, value, language_mode);
@@ -169,8 +168,7 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
     // TODO(verwaest): Support non-JSObject receivers.
     if (!object->IsJSObject()) return value;
     Handle<JSObject> js_object = Handle<JSObject>::cast(object);
-    return JSObject::SetElement(js_object, index, value, NONE, language_mode,
-                                true, SET_PROPERTY);
+    return JSObject::SetElement(js_object, index, value, language_mode);
   }
   return Object::SetProperty(object, name, value, language_mode);
 }
@@ -184,43 +182,26 @@ MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object,
   // Check if the given key is an array index.
   uint32_t index = 0;
   if (key->ToArrayIndex(&index)) {
-    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
-    // of a string using [] notation.  We need to support this too in
-    // JavaScript.
-    // In the case of a String object we just need to redirect the assignment to
-    // the underlying string if the index is in range.  Since the underlying
-    // string does nothing with the assignment then we can ignore such
-    // assignments.
-    if (js_object->IsStringObjectWithCharacterAt(index)) {
-      return value;
-    }
-
-    return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false,
-                                DEFINE_PROPERTY);
+    return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value,
+                                                   attrs);
   }
 
+  Handle<Name> name;
   if (key->IsName()) {
-    Handle<Name> name = Handle<Name>::cast(key);
-    if (name->AsArrayIndex(&index)) {
-      return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false,
-                                  DEFINE_PROPERTY);
-    } else {
-      if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
-      return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
-                                                      attrs);
-    }
+    name = Handle<Name>::cast(key);
+  } else {
+    // Call-back into JavaScript to convert the key to a string.
+    Handle<Object> converted;
+    ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
+                               Execution::ToString(isolate, key), Object);
+    name = Handle<String>::cast(converted);
   }
 
-  // Call-back into JavaScript to convert the key to a string.
-  Handle<Object> converted;
-  ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
-                             Execution::ToString(isolate, key), Object);
-  Handle<String> name = Handle<String>::cast(converted);
-
   if (name->AsArrayIndex(&index)) {
-    return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false,
-                                DEFINE_PROPERTY);
+    return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value,
+                                                   attrs);
   } else {
+    if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
     return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
                                                     attrs);
   }
@@ -624,14 +605,14 @@ RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
   RUNTIME_ASSERT(args.length() == 4);
 
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
 
 #ifdef DEBUG
   uint32_t index = 0;
-  DCHECK(!key->ToArrayIndex(&index));
-  LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
+  DCHECK(!name->ToArrayIndex(&index));
+  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   if (!maybe.IsJust()) return isolate->heap()->exception();
   RUNTIME_ASSERT(!it.IsFound());
@@ -640,25 +621,7 @@ RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, result,
-      JSObject::SetOwnPropertyIgnoreAttributes(object, key, value, attrs));
-  return *result;
-}
-
-
-RUNTIME_FUNCTION(Runtime_SetProperty) {
-  HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 4);
-
-  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
-  CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
-  LanguageMode language_mode = language_mode_arg;
-
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
+      JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
   return *result;
 }
 
@@ -667,20 +630,32 @@ RUNTIME_FUNCTION(Runtime_SetProperty) {
 // This is used to create an indexed data property into an array.
 RUNTIME_FUNCTION(Runtime_AddElement) {
   HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 4);
+  RUNTIME_ASSERT(args.length() == 3);
 
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
-  CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
 
   uint32_t index = 0;
-  key->ToArrayIndex(&index);
+  CHECK(key->ToArrayIndex(&index));
+
+#ifdef DEBUG
+  LookupIterator it(isolate, object, index,
+                    LookupIterator::OWN_SKIP_INTERCEPTOR);
+  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
+  if (!maybe.IsJust()) return isolate->heap()->exception();
+  RUNTIME_ASSERT(!it.IsFound());
+
+  if (object->IsJSArray()) {
+    Handle<JSArray> array = Handle<JSArray>::cast(object);
+    RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
+  }
+#endif
 
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, JSObject::SetElement(object, index, value, attrs, SLOPPY,
-                                            false, DEFINE_PROPERTY));
+      isolate, result,
+      JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
   return *result;
 }
 
@@ -692,16 +667,34 @@ RUNTIME_FUNCTION(Runtime_AppendElement) {
   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
 
-  int index = Smi::cast(array->length())->value();
+  uint32_t index;
+  CHECK(array->length()->ToArrayIndex(&index));
 
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, JSObject::SetElement(array, index, value, NONE, SLOPPY,
-                                            false, DEFINE_PROPERTY));
+      isolate, result, JSObject::AddDataElement(array, index, value, NONE));
   return *array;
 }
 
 
+RUNTIME_FUNCTION(Runtime_SetProperty) {
+  HandleScope scope(isolate);
+  RUNTIME_ASSERT(args.length() == 4);
+
+  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
+  CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
+  LanguageMode language_mode = language_mode_arg;
+
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
+  return *result;
+}
+
+
 RUNTIME_FUNCTION(Runtime_DeleteProperty) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 3);
@@ -1375,19 +1368,6 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
     it.Next();
   }
 
-  // Take special care when attributes are different and there is already
-  // a property.
-  if (it.state() == LookupIterator::ACCESSOR) {
-    // Use IgnoreAttributes version since a readonly property may be
-    // overridden and SetProperty does not allow this.
-    Handle<Object> result;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result,
-        JSObject::SetOwnPropertyIgnoreAttributes(
-            js_object, name, obj_value, attrs, JSObject::DONT_FORCE_FIELD));
-    return *result;
-  }
-
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, result,
index 1ef6cbae011746cc35ac887221b7b2a9ed73af68..86502ee6ea4271049ebbd337303991c90e32bd1a 100644 (file)
@@ -434,7 +434,7 @@ namespace internal {
   F(KeyedGetProperty, 2, 1)                          \
   F(AddNamedProperty, 4, 1)                          \
   F(SetProperty, 4, 1)                               \
-  F(AddElement, 4, 1)                                \
+  F(AddElement, 3, 1)                                \
   F(AppendElement, 2, 1)                             \
   F(DeleteProperty, 3, 1)                            \
   F(HasOwnProperty, 2, 1)                            \
index 2fd67d834685b35494f5c539c7981e9e189d5811..9ffefe81c79fac9a189d1e6cceed80e24e08c510 100644 (file)
@@ -13266,12 +13266,11 @@ TEST(ForceSet) {
   CHECK_EQ(3, global->Get(access_property)->Int32Value());
   CHECK_EQ(1, force_set_set_count);
   CHECK_EQ(2, force_set_get_count);
-  // Forcing the property to be set should override the accessor without
-  // calling it
+  // ForceSet does not remove the accessors, but rather calls the setter.
   global->ForceSet(access_property, v8::Int32::New(isolate, 8));
-  CHECK_EQ(8, global->Get(access_property)->Int32Value());
-  CHECK_EQ(1, force_set_set_count);
-  CHECK_EQ(2, force_set_get_count);
+  CHECK_EQ(3, global->Get(access_property)->Int32Value());
+  CHECK_EQ(2, force_set_set_count);
+  CHECK_EQ(3, force_set_get_count);
 }
 
 
index 51b829bec20845bcbf67fa0522836e8a006a8fcc..3b163da600d70fdb7c34a381642246b783b39d59 100644 (file)
@@ -791,7 +791,7 @@ TEST(JSArray) {
   CHECK(array->HasFastSmiOrObjectElements());
 
   // array[length] = name.
-  JSReceiver::SetElement(array, 0, name, NONE, SLOPPY).Check();
+  JSReceiver::SetElement(array, 0, name, SLOPPY).Check();
   CHECK_EQ(Smi::FromInt(1), array->length());
   element = i::Object::GetElement(isolate, array, 0).ToHandleChecked();
   CHECK_EQ(*element, *name);
@@ -807,7 +807,7 @@ TEST(JSArray) {
   CHECK(array->HasDictionaryElements());  // Must be in slow mode.
 
   // array[length] = name.
-  JSReceiver::SetElement(array, int_length, name, NONE, SLOPPY).Check();
+  JSReceiver::SetElement(array, int_length, name, SLOPPY).Check();
   uint32_t new_int_length = 0;
   CHECK(array->length()->ToArrayIndex(&new_int_length));
   CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
@@ -838,8 +838,8 @@ TEST(JSObjectCopy) {
   JSReceiver::SetProperty(obj, first, one, SLOPPY).Check();
   JSReceiver::SetProperty(obj, second, two, SLOPPY).Check();
 
-  JSReceiver::SetElement(obj, 0, first, NONE, SLOPPY).Check();
-  JSReceiver::SetElement(obj, 1, second, NONE, SLOPPY).Check();
+  JSReceiver::SetElement(obj, 0, first, SLOPPY).Check();
+  JSReceiver::SetElement(obj, 1, second, SLOPPY).Check();
 
   // Make the clone.
   Handle<Object> value1, value2;
@@ -864,8 +864,8 @@ TEST(JSObjectCopy) {
   JSReceiver::SetProperty(clone, first, two, SLOPPY).Check();
   JSReceiver::SetProperty(clone, second, one, SLOPPY).Check();
 
-  JSReceiver::SetElement(clone, 0, second, NONE, SLOPPY).Check();
-  JSReceiver::SetElement(clone, 1, first, NONE, SLOPPY).Check();
+  JSReceiver::SetElement(clone, 0, second, SLOPPY).Check();
+  JSReceiver::SetElement(clone, 1, first, SLOPPY).Check();
 
   value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked();
   value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked();
index 544278575ce1e189bbe00a71abbf60e28f5d6328..a5eee5d7df0079cb62f6f8815923f70a545f228d 100644 (file)
@@ -508,8 +508,7 @@ TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
   CHECK(obj->map()->instance_descriptors()->GetValue(0)->IsAccessorPair());
 
   Handle<Object> value(Smi::FromInt(42), isolate);
-  JSObject::SetOwnPropertyIgnoreAttributes(
-      obj, foo_str, value, NONE, JSObject::DONT_FORCE_FIELD).ToHandleChecked();
+  JSObject::SetOwnPropertyIgnoreAttributes(obj, foo_str, value, NONE).Check();
 
   // Check that the property contains |value|.
   CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors());