Use GetProperty for getting elements.
authorverwaest <verwaest@chromium.org>
Tue, 2 Jun 2015 10:42:16 +0000 (03:42 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 2 Jun 2015 10:42:29 +0000 (10:42 +0000)
This also fixes issues with
- kMaxUint32 being a valid length but not index cornercases
- exotic integer objects masking "exotic indexes" even though its in the prototype chain
- concating of holey sloppy arguments

BUG=v8:4137
LOG=n

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

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

26 files changed:
src/api.cc
src/array.js
src/builtins.cc
src/compiler/js-typed-lowering.cc
src/elements.cc
src/elements.h
src/ic/ic.cc
src/json-parser.h
src/json-stringifier.h
src/lookup-inl.h
src/lookup.cc
src/lookup.h
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime/runtime-array.cc
src/runtime/runtime-classes.cc
src/runtime/runtime-debug.cc
src/runtime/runtime-typedarray.cc
src/utils.h
test/cctest/test-api-interceptors.cc
test/cctest/test-api.cc
test/mjsunit/enumeration-order.js
test/mjsunit/es6/indexed-integer-exotics.js
test/mjsunit/regress/regress-581.js
test/mjsunit/regress/regress-splice-large-index.js

index 6ecdb4d4a207a2bcc6308d99773d363252456073..73617647c093e0e55e321f4a9a31b7b83d1b75ba 100644 (file)
@@ -6635,7 +6635,7 @@ size_t v8::ArrayBufferView::ByteLength() {
 
 size_t v8::TypedArray::Length() {
   i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
-  return static_cast<size_t>(obj->length()->Number());
+  return static_cast<size_t>(obj->length_value());
 }
 
 
index 55c59eb4a12ec9aa3af47ecc232bcce2df901b94..7a23fc8314f89a98180072b2141f7e5d1986d35a 100644 (file)
@@ -303,7 +303,7 @@ function SparseMove(array, start_i, del_count, len, num_additional_args) {
           if (!IS_UNDEFINED(current) || key in array) {
             var new_key = key - del_count + num_additional_args;
             new_array[new_key] = current;
-            if (new_key > 0xffffffff) {
+            if (new_key > 0xfffffffe) {
               big_indices = big_indices || new InternalArray();
               big_indices.push(new_key);
             }
index 26c0b210feaa5fbcea9759f546a50fd027526217..ee34cdc360bbf08aebe661b61c1124bc9e97944f 100644 (file)
@@ -438,7 +438,7 @@ BUILTIN(ArrayPop) {
   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
   DCHECK(!array->map()->is_observed());
 
-  int len = Smi::cast(array->length())->value();
+  uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
   if (len == 0) return isolate->heap()->undefined_value();
 
   if (JSArray::HasReadOnlyLength(array)) {
@@ -446,12 +446,11 @@ BUILTIN(ArrayPop) {
   }
 
   ElementsAccessor* accessor = array->GetElementsAccessor();
-  int new_length = len - 1;
-  Handle<Object> element =
-      accessor->Get(array, array, new_length, elms_obj).ToHandleChecked();
-  if (element->IsTheHole()) {
-    return CallJsBuiltin(isolate, "$arrayPop", args);
-  }
+  uint32_t new_length = len - 1;
+  Handle<Object> element;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, element, Object::GetElement(isolate, array, new_length));
+
   RETURN_FAILURE_ON_EXCEPTION(
       isolate,
       accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate)));
@@ -481,12 +480,9 @@ BUILTIN(ArrayShift) {
   }
 
   // Get first element
-  ElementsAccessor* accessor = array->GetElementsAccessor();
-  Handle<Object> first =
-    accessor->Get(array, array, 0, elms_obj).ToHandleChecked();
-  if (first->IsTheHole()) {
-    return CallJsBuiltin(isolate, "$arrayShift", args);
-  }
+  Handle<Object> first;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first,
+                                     Object::GetElement(isolate, array, 0));
 
   if (heap->CanMoveObjectStart(*elms_obj)) {
     array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1));
index 987f73fd83c6ae4ce616cb1e184db429e651f7fa..3a24ad7c7b47b4c2cba5e07bbe803b0d230e0572 100644 (file)
@@ -779,8 +779,7 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
         Node* effect = NodeProperties::GetEffectInput(node);
         Node* control = NodeProperties::GetControlInput(node);
         // Check if we can avoid the bounds check.
-        if (key_type->Min() >= 0 &&
-            key_type->Max() < array->length()->Number()) {
+        if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
           Node* load = graph()->NewNode(
               simplified()->LoadElement(
                   AccessBuilder::ForTypedArrayElement(array->type(), true)),
@@ -850,8 +849,7 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
           value = graph()->NewNode(simplified()->NumberToUint32(), value);
         }
         // Check if we can avoid the bounds check.
-        if (key_type->Min() >= 0 &&
-            key_type->Max() < array->length()->Number()) {
+        if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
           node->set_op(simplified()->StoreElement(
               AccessBuilder::ForTypedArrayElement(array->type(), true)));
           node->ReplaceInput(0, buffer);
index d204cc52c6e67994038f9753b458c0022d2c0086..bad3c5ba8b12c535d3d061c67df11cd1832fba13 100644 (file)
@@ -585,8 +585,8 @@ class ElementsAccessorBase : public ElementsAccessor {
 
   static bool HasElementImpl(Handle<JSObject> holder, uint32_t key,
                              Handle<FixedArrayBase> backing_store) {
-    return ElementsAccessorSubclass::GetAttributesImpl(holder, key,
-                                                       backing_store) != ABSENT;
+    return ElementsAccessorSubclass::GetAttributesImpl(
+               *holder, key, *backing_store) != ABSENT;
   }
 
   virtual bool HasElement(Handle<JSObject> holder, uint32_t key,
@@ -594,9 +594,8 @@ class ElementsAccessorBase : public ElementsAccessor {
     return ElementsAccessorSubclass::HasElementImpl(holder, key, backing_store);
   }
 
-  MUST_USE_RESULT virtual MaybeHandle<Object> Get(
-      Handle<Object> receiver, Handle<JSObject> holder, uint32_t key,
-      Handle<FixedArrayBase> backing_store) final {
+  virtual Handle<Object> Get(Handle<JSObject> holder, uint32_t key,
+                             Handle<FixedArrayBase> backing_store) final {
     if (!IsExternalArrayElementsKind(ElementsTraits::Kind) &&
         FLAG_trace_js_array_abuse) {
       CheckArrayAbuse(holder, "elements read", key);
@@ -607,15 +606,11 @@ class ElementsAccessorBase : public ElementsAccessor {
       CheckArrayAbuse(holder, "external elements read", key);
     }
 
-    return ElementsAccessorSubclass::GetImpl(
-        receiver, holder, key, backing_store);
+    return ElementsAccessorSubclass::GetImpl(holder, key, backing_store);
   }
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
+  static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> backing_store) {
     if (key < ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) {
       return BackingStore::get(Handle<BackingStore>::cast(backing_store), key);
     } else {
@@ -623,36 +618,29 @@ class ElementsAccessorBase : public ElementsAccessor {
     }
   }
 
-  MUST_USE_RESULT virtual PropertyAttributes GetAttributes(
-      Handle<JSObject> holder, uint32_t key,
-      Handle<FixedArrayBase> backing_store) final {
+  virtual PropertyAttributes GetAttributes(
+      JSObject* holder, uint32_t key, FixedArrayBase* backing_store) final {
     return ElementsAccessorSubclass::GetAttributesImpl(holder, key,
                                                        backing_store);
   }
 
-  MUST_USE_RESULT static PropertyAttributes GetAttributesImpl(
-        Handle<JSObject> obj,
-        uint32_t key,
-        Handle<FixedArrayBase> backing_store) {
-    if (key >=
-        ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) {
+  static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
+                                              FixedArrayBase* backing_store) {
+    if (key >= ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) {
       return ABSENT;
     }
-    return
-        Handle<BackingStore>::cast(backing_store)->is_the_hole(key)
-          ? ABSENT : NONE;
+    return BackingStore::cast(backing_store)->is_the_hole(key) ? ABSENT : NONE;
   }
 
-  MUST_USE_RESULT virtual MaybeHandle<AccessorPair> GetAccessorPair(
+  virtual MaybeHandle<AccessorPair> GetAccessorPair(
       Handle<JSObject> holder, uint32_t key,
       Handle<FixedArrayBase> backing_store) final {
     return ElementsAccessorSubclass::GetAccessorPairImpl(holder, key,
                                                          backing_store);
   }
 
-  MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl(
-      Handle<JSObject> obj,
-      uint32_t key,
+  static MaybeHandle<AccessorPair> GetAccessorPairImpl(
+      Handle<JSObject> obj, uint32_t key,
       Handle<FixedArrayBase> backing_store) {
     return MaybeHandle<AccessorPair>();
   }
@@ -734,7 +722,7 @@ class ElementsAccessorBase : public ElementsAccessor {
         from, from_start, *to, from_kind, to_start, packed_size, copy_size);
   }
 
-  virtual MaybeHandle<FixedArray> AddElementsToFixedArray(
+  virtual Handle<FixedArray> AddElementsToFixedArray(
       Handle<JSObject> receiver, Handle<FixedArray> to,
       FixedArray::KeyFilter filter) final {
     Handle<FixedArrayBase> from(receiver->elements());
@@ -758,15 +746,14 @@ class ElementsAccessorBase : public ElementsAccessor {
     // Compute how many elements are not in other.
     uint32_t extra = 0;
     for (uint32_t y = 0; y < len1; y++) {
-      uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y);
-      if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) {
-        Handle<Object> value;
-        ASSIGN_RETURN_ON_EXCEPTION(
-            isolate, value,
-            ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from),
-            FixedArray);
+      if (ElementsAccessorSubclass::HasIndexImpl(*from, y)) {
+        uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y);
+        Handle<Object> value =
+            ElementsAccessorSubclass::GetImpl(receiver, key, from);
 
         DCHECK(!value->IsTheHole());
+        DCHECK(!value->IsAccessorPair());
+        DCHECK(!value->IsExecutableAccessorInfo());
         if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) {
           continue;
         }
@@ -794,13 +781,12 @@ class ElementsAccessorBase : public ElementsAccessor {
     // Fill in the extra values.
     uint32_t index = 0;
     for (uint32_t y = 0; y < len1; y++) {
-      uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y);
-      if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) {
-        Handle<Object> value;
-        ASSIGN_RETURN_ON_EXCEPTION(
-            isolate, value,
-            ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from),
-            FixedArray);
+      if (ElementsAccessorSubclass::HasIndexImpl(*from, y)) {
+        uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y);
+        Handle<Object> value =
+            ElementsAccessorSubclass::GetImpl(receiver, key, from);
+        DCHECK(!value->IsAccessorPair());
+        DCHECK(!value->IsExecutableAccessorInfo());
         if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) {
           continue;
         }
@@ -824,6 +810,14 @@ class ElementsAccessorBase : public ElementsAccessor {
     return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store);
   }
 
+  static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) {
+    return true;
+  }
+
+  virtual bool HasIndex(FixedArrayBase* backing_store, uint32_t index) final {
+    return ElementsAccessorSubclass::HasIndexImpl(backing_store, index);
+  }
+
   static uint32_t GetKeyForIndexImpl(FixedArrayBase* backing_store,
                                      uint32_t index) {
     return index;
@@ -1008,6 +1002,10 @@ class FastElementsAccessor
     return !Handle<BackingStore>::cast(backing_store)->is_the_hole(key);
   }
 
+  static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) {
+    return !BackingStore::cast(backing_store)->is_the_hole(index);
+  }
+
   static void ValidateContents(Handle<JSObject> holder, int length) {
 #if DEBUG
     Isolate* isolate = holder->GetIsolate();
@@ -1284,11 +1282,8 @@ class TypedElementsAccessor
   friend class ElementsAccessorBase<AccessorClass,
                                     ElementsKindTraits<Kind> >;
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
+  static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> backing_store) {
     if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) {
       return BackingStore::get(Handle<BackingStore>::cast(backing_store), key);
     } else {
@@ -1296,12 +1291,10 @@ class TypedElementsAccessor
     }
   }
 
-  MUST_USE_RESULT static PropertyAttributes GetAttributesImpl(
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
-    return key < AccessorClass::GetCapacityImpl(*obj, *backing_store) ? NONE
-                                                                      : ABSENT;
+  static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
+                                              FixedArrayBase* backing_store) {
+    return key < AccessorClass::GetCapacityImpl(obj, backing_store) ? NONE
+                                                                    : ABSENT;
   }
 
   MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl(
@@ -1481,34 +1474,22 @@ class DictionaryElementsAccessor
     return DeleteCommon(obj, key, language_mode);
   }
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> store) {
+  static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> store) {
     Handle<SeededNumberDictionary> backing_store =
         Handle<SeededNumberDictionary>::cast(store);
     Isolate* isolate = backing_store->GetIsolate();
     int entry = backing_store->FindEntry(key);
     if (entry != SeededNumberDictionary::kNotFound) {
-      Handle<Object> element(backing_store->ValueAt(entry), isolate);
-      PropertyDetails details = backing_store->DetailsAt(entry);
-      if (details.type() == ACCESSOR_CONSTANT) {
-        return JSObject::GetElementWithCallback(
-            obj, receiver, element, key, obj);
-      } else {
-        return element;
-      }
+      return handle(backing_store->ValueAt(entry), isolate);
     }
     return isolate->factory()->the_hole_value();
   }
 
-  MUST_USE_RESULT static PropertyAttributes GetAttributesImpl(
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
-    Handle<SeededNumberDictionary> dictionary =
-        Handle<SeededNumberDictionary>::cast(backing_store);
+  static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
+                                              FixedArrayBase* backing_store) {
+    SeededNumberDictionary* dictionary =
+        SeededNumberDictionary::cast(backing_store);
     int entry = dictionary->FindEntry(key);
     if (entry != SeededNumberDictionary::kNotFound) {
       return dictionary->DetailsAt(entry).attributes();
@@ -1516,10 +1497,8 @@ class DictionaryElementsAccessor
     return ABSENT;
   }
 
-  MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl(
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> store) {
+  static MaybeHandle<AccessorPair> GetAccessorPairImpl(
+      Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) {
     Handle<SeededNumberDictionary> backing_store =
         Handle<SeededNumberDictionary>::cast(store);
     int entry = backing_store->FindEntry(key);
@@ -1538,6 +1517,13 @@ class DictionaryElementsAccessor
     return backing_store->FindEntry(key) != SeededNumberDictionary::kNotFound;
   }
 
+  static bool HasIndexImpl(FixedArrayBase* store, uint32_t index) {
+    DisallowHeapAllocation no_gc;
+    SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
+    Object* key = dict->KeyAt(index);
+    return !key->IsTheHole();
+  }
+
   static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) {
     DisallowHeapAllocation no_gc;
     SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
@@ -1575,14 +1561,11 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
       SloppyArgumentsElementsAccessor,
       ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >;
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetImpl(
-      Handle<Object> receiver,
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> parameters) {
+  static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
+                                Handle<FixedArrayBase> parameters) {
     Isolate* isolate = obj->GetIsolate();
     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
-    Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
+    Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
     if (!probe->IsTheHole()) {
       DisallowHeapAllocation no_gc;
       Context* context = Context::cast(parameter_map->get(0));
@@ -1593,12 +1576,8 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
       // Object is not mapped, defer to the arguments.
       Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
                                    isolate);
-      Handle<Object> result;
-      ASSIGN_RETURN_ON_EXCEPTION(
-          isolate, result,
-          ElementsAccessor::ForArray(arguments)->Get(
-              receiver, obj, key, arguments),
-          Object);
+      Handle<Object> result =
+          ElementsAccessor::ForArray(arguments)->Get(obj, key, arguments);
       // Elements of the arguments object in slow mode might be slow aliases.
       if (result->IsAliasedArgumentsEntry()) {
         DisallowHeapAllocation no_gc;
@@ -1613,28 +1592,25 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
     }
   }
 
-  MUST_USE_RESULT static PropertyAttributes GetAttributesImpl(
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) {
-    Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(backing_store);
-    Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
+  static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key,
+                                              FixedArrayBase* backing_store) {
+    FixedArray* parameter_map = FixedArray::cast(backing_store);
+    Object* probe = GetParameterMapArg(parameter_map, key);
     if (!probe->IsTheHole()) {
       return NONE;
     } else {
       // If not aliased, check the arguments.
-      Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
       return ElementsAccessor::ForArray(arguments)
           ->GetAttributes(obj, key, arguments);
     }
   }
 
-  MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl(
-      Handle<JSObject> obj,
-      uint32_t key,
-      Handle<FixedArrayBase> parameters) {
+  static MaybeHandle<AccessorPair> GetAccessorPairImpl(
+      Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) {
     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
-    Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
+    Handle<Object> probe(GetParameterMapArg(*parameter_map, key),
+                         obj->GetIsolate());
     if (!probe->IsTheHole()) {
       return MaybeHandle<AccessorPair>();
     } else {
@@ -1659,7 +1635,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
       Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final {
     Isolate* isolate = obj->GetIsolate();
     Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
-    Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
+    Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
     if (!probe->IsTheHole()) {
       // TODO(kmillikin): We could check if this was the last aliased
       // parameter, and revert to normal elements in that case.  That
@@ -1692,35 +1668,61 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
                                   FixedArrayBase* backing_store) {
     FixedArray* parameter_map = FixedArray::cast(backing_store);
     FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
-    return Max(static_cast<uint32_t>(parameter_map->length() - 2),
-               ForArray(arguments)->GetCapacity(holder, arguments));
+    return parameter_map->length() - 2 +
+           ForArray(arguments)->GetCapacity(holder, arguments);
   }
 
-  static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, uint32_t index) {
-    return index;
+  static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) {
+    FixedArray* parameter_map = FixedArray::cast(parameters);
+    uint32_t length = parameter_map->length() - 2;
+    if (index < length) {
+      return !GetParameterMapArg(parameter_map, index)->IsTheHole();
+    }
+
+    FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
+    return ForArray(arguments)->HasIndex(arguments, index - length);
   }
 
-  static uint32_t GetIndexForKeyImpl(FixedArrayBase* dict, uint32_t key) {
-    return key;
+  static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters,
+                                     uint32_t index) {
+    FixedArray* parameter_map = FixedArray::cast(parameters);
+    uint32_t length = parameter_map->length() - 2;
+    if (index < length) return index;
+
+    FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+    return ForArray(arguments)->GetKeyForIndex(arguments, index - length);
   }
 
-  static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
-                                        uint32_t index) {
-    return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
+  static uint32_t GetIndexForKeyImpl(FixedArrayBase* parameters, uint32_t key) {
+    FixedArray* parameter_map = FixedArray::cast(parameters);
+    Object* probe = GetParameterMapArg(parameter_map, key);
+    if (!probe->IsTheHole()) return key;
+
+    uint32_t length = parameter_map->length() - 2;
+    FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+    return length +
+           ElementsAccessor::ForArray(arguments)
+               ->GetIndexForKey(arguments, key);
   }
 
+  static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters,
+                                        uint32_t index) {
+    FixedArray* parameter_map = FixedArray::cast(parameters);
+    uint32_t length = parameter_map->length() - 2;
+    if (index < length) {
+      return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
+    }
+    index -= length;
+    FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+    return ElementsAccessor::ForArray(arguments)->GetDetails(arguments, index);
+  }
 
  private:
-  static Handle<Object> GetParameterMapArg(Handle<JSObject> holder,
-                                           Handle<FixedArray> parameter_map,
-                                           uint32_t key) {
-    Isolate* isolate = holder->GetIsolate();
-    uint32_t length = holder->IsJSArray()
-        ? Smi::cast(Handle<JSArray>::cast(holder)->length())->value()
-        : parameter_map->length();
-    return key < (length - 2)
-        ? handle(parameter_map->get(key + 2), isolate)
-        : Handle<Object>::cast(isolate->factory()->the_hole_value());
+  static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) {
+    uint32_t length = parameter_map->length() - 2;
+    return key < length
+               ? parameter_map->get(key + 2)
+               : Object::cast(parameter_map->GetHeap()->the_hole_value());
   }
 };
 
@@ -1801,7 +1803,7 @@ MaybeHandle<Object> ElementsAccessorBase<ElementsAccessorSubclass,
   // to slow elements is needed for other reasons.
   if (length->IsNumber()) {
     uint32_t value;
-    if (length->ToArrayIndex(&value)) {
+    if (length->ToArrayLength(&value)) {
       Handle<SeededNumberDictionary> dictionary =
           JSObject::NormalizeElements(array);
       DCHECK(!dictionary.is_null());
index f4d15fc828b751ab8f4c488e85f1586d4c001fa6..1065b1f73df63aa492a766cefa3e309dbbf2bb64 100644 (file)
@@ -48,17 +48,11 @@ class ElementsAccessor {
   // can optionally pass in the backing store to use for the check, which must
   // be compatible with the ElementsKind of the ElementsAccessor. If
   // backing_store is NULL, the holder->elements() is used as the backing store.
-  MUST_USE_RESULT virtual MaybeHandle<Object> Get(
-      Handle<Object> receiver,
-      Handle<JSObject> holder,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) = 0;
+  virtual Handle<Object> Get(Handle<JSObject> holder, uint32_t key,
+                             Handle<FixedArrayBase> backing_store) = 0;
 
-  MUST_USE_RESULT inline MaybeHandle<Object> Get(
-      Handle<Object> receiver,
-      Handle<JSObject> holder,
-      uint32_t key) {
-    return Get(receiver, holder, key, handle(holder->elements()));
+  inline Handle<Object> Get(Handle<JSObject> holder, uint32_t key) {
+    return Get(holder, key, handle(holder->elements()));
   }
 
   // Returns an element's attributes, or ABSENT if there is no such
@@ -66,15 +60,12 @@ class ElementsAccessor {
   // can optionally pass in the backing store to use for the check, which must
   // be compatible with the ElementsKind of the ElementsAccessor. If
   // backing_store is NULL, the holder->elements() is used as the backing store.
-  MUST_USE_RESULT virtual PropertyAttributes GetAttributes(
-      Handle<JSObject> holder,
-      uint32_t key,
-      Handle<FixedArrayBase> backing_store) = 0;
+  virtual PropertyAttributes GetAttributes(JSObject* holder, uint32_t key,
+                                           FixedArrayBase* backing_store) = 0;
 
-  MUST_USE_RESULT inline PropertyAttributes GetAttributes(
-      Handle<JSObject> holder,
-      uint32_t key) {
-    return GetAttributes(holder, key, handle(holder->elements()));
+  inline PropertyAttributes GetAttributes(Handle<JSObject> holder,
+                                          uint32_t key) {
+    return GetAttributes(*holder, key, holder->elements());
   }
 
   // Returns an element's accessors, or NULL if the element does not exist or
@@ -82,14 +73,12 @@ class ElementsAccessor {
   // can optionally pass in the backing store to use for the check, which must
   // be compatible with the ElementsKind of the ElementsAccessor. If
   // backing_store is NULL, the holder->elements() is used as the backing store.
-  MUST_USE_RESULT virtual MaybeHandle<AccessorPair> GetAccessorPair(
-      Handle<JSObject> holder,
-      uint32_t key,
+  virtual MaybeHandle<AccessorPair> GetAccessorPair(
+      Handle<JSObject> holder, uint32_t key,
       Handle<FixedArrayBase> backing_store) = 0;
 
-  MUST_USE_RESULT inline MaybeHandle<AccessorPair> GetAccessorPair(
-      Handle<JSObject> holder,
-      uint32_t key) {
+  inline MaybeHandle<AccessorPair> GetAccessorPair(Handle<JSObject> holder,
+                                                   uint32_t key) {
     return GetAccessorPair(holder, key, handle(holder->elements()));
   }
 
@@ -158,7 +147,7 @@ class ElementsAccessor {
       *from_holder, 0, from_kind, to, 0, kCopyToEndAndInitializeToHole);
   }
 
-  MUST_USE_RESULT virtual MaybeHandle<FixedArray> AddElementsToFixedArray(
+  virtual Handle<FixedArray> AddElementsToFixedArray(
       Handle<JSObject> receiver, Handle<FixedArray> to,
       FixedArray::KeyFilter filter) = 0;
 
@@ -196,6 +185,7 @@ class ElementsAccessor {
                                   uint32_t key) = 0;
   virtual PropertyDetails GetDetails(FixedArrayBase* backing_store,
                                      uint32_t index) = 0;
+  virtual bool HasIndex(FixedArrayBase* backing_store, uint32_t key) = 0;
 
  private:
   static ElementsAccessor** elements_accessors_;
index a75142fe9cc77957cd3b3427777faac23fb25ed9..a8323ffe5aa0f8087be9fbe6b81a8effef08532d 100644 (file)
@@ -2855,14 +2855,14 @@ RUNTIME_FUNCTION(StorePropertyWithInterceptor) {
 
 
 RUNTIME_FUNCTION(LoadElementWithInterceptor) {
+  // TODO(verwaest): This should probably get the holder and receiver as input.
   HandleScope scope(isolate);
   Handle<JSObject> receiver = args.at<JSObject>(0);
   DCHECK(args.smi_at(1) >= 0);
   uint32_t index = args.smi_at(1);
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      JSObject::GetElementWithInterceptor(receiver, receiver, index, true));
+      isolate, result, Object::GetElement(isolate, receiver, index));
   return *result;
 }
 
index b5dc33eb5713bd521444370c5de7fbd7017c3e5e..973e9a0fe3b279cc79bb9fab9c2a8a66824489de 100644 (file)
@@ -311,7 +311,7 @@ ParseElementResult JsonParser<seq_one_byte>::ParseElement(
   } else {
     do {
       int d = c0_ - '0';
-      if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
+      if (index > 429496729U - ((d + 3) >> 3)) break;
       index = (index * 10) + d;
       Advance();
     } while (IsDecimalDigit(c0_));
index 9579c78ff0774f4c18ae8e3ca79b427b939ba57a..a28691503d12c7799ff3df9f0c99f130b211dd6b 100644 (file)
@@ -439,7 +439,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
   Result stack_push = StackPush(object);
   if (stack_push != SUCCESS) return stack_push;
   uint32_t length = 0;
-  CHECK(object->length()->ToArrayIndex(&length));
+  CHECK(object->length()->ToArrayLength(&length));
   builder_.AppendCharacter('[');
   switch (object->GetElementsKind()) {
     case FAST_SMI_ELEMENTS: {
index ff704aa06ef7e69262faf0bf503cb26c3614e75d..bae910da99120d04da60f94ed7bae62c5960c40a 100644 (file)
@@ -58,11 +58,16 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
     // Fall through.
     case INTERCEPTOR:
       if (IsElement()) {
+        // TODO(verwaest): Optimize.
         JSObject* js_object = JSObject::cast(holder);
         ElementsAccessor* accessor = js_object->GetElementsAccessor();
         FixedArrayBase* backing_store = js_object->elements();
         number_ = accessor->GetIndexForKey(backing_store, index_);
         if (number_ == kMaxUInt32) return NOT_FOUND;
+        if (accessor->GetAttributes(js_object, index_, backing_store) ==
+            ABSENT) {
+          return NOT_FOUND;
+        }
         property_details_ = accessor->GetDetails(backing_store, number_);
       } else if (holder->IsGlobalObject()) {
         GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary();
index eb83be5662a57cbde064feeb7d7d7963ca05dac2..38cc522c6e0833fb740b9a8cbb00fd88d8e3d185 100644 (file)
@@ -234,6 +234,10 @@ void LookupIterator::TransitionToAccessorProperty(
 
 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
   DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
+  return InternalHolderIsReceiverOrHiddenPrototype();
+}
+
+bool LookupIterator::InternalHolderIsReceiverOrHiddenPrototype() const {
   // Optimization that only works if configuration_ is not mutable.
   if (!check_prototype_chain()) return true;
   DisallowHeapAllocation no_gc;
@@ -258,7 +262,11 @@ bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
 Handle<Object> LookupIterator::FetchValue() const {
   Object* result = NULL;
   Handle<JSObject> holder = GetHolder<JSObject>();
-  if (holder_map_->IsGlobalObjectMap()) {
+  if (IsElement()) {
+    // TODO(verwaest): Optimize.
+    ElementsAccessor* accessor = holder->GetElementsAccessor();
+    return accessor->Get(holder, index_);
+  } else if (holder_map_->IsGlobalObjectMap()) {
     result = holder->global_dictionary()->ValueAt(number_);
     DCHECK(result->IsPropertyCell());
     result = PropertyCell::cast(result)->value();
@@ -287,6 +295,7 @@ int LookupIterator::GetConstantIndex() const {
   DCHECK(has_property_);
   DCHECK(!holder_map_->is_dictionary_map());
   DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type());
+  DCHECK(!IsElement());
   return descriptor_number();
 }
 
@@ -295,6 +304,7 @@ FieldIndex LookupIterator::GetFieldIndex() const {
   DCHECK(has_property_);
   DCHECK(!holder_map_->is_dictionary_map());
   DCHECK_EQ(v8::internal::DATA, property_details_.type());
+  DCHECK(!IsElement());
   int index =
       holder_map_->instance_descriptors()->GetFieldIndex(descriptor_number());
   bool is_double = representation().IsDouble();
@@ -313,6 +323,7 @@ Handle<HeapType> LookupIterator::GetFieldType() const {
 
 
 Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
+  DCHECK(!IsElement());
   Handle<JSObject> holder = GetHolder<JSObject>();
   Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
   Object* value = global->global_dictionary()->ValueAt(dictionary_entry());
@@ -336,6 +347,7 @@ Handle<Object> LookupIterator::GetDataValue() const {
 
 void LookupIterator::WriteDataValue(Handle<Object> value) {
   DCHECK_EQ(DATA, state_);
+  DCHECK(!IsElement());
   Handle<JSObject> holder = GetHolder<JSObject>();
   if (holder->IsGlobalObject()) {
     Handle<GlobalDictionary> property_dictionary =
@@ -359,10 +371,16 @@ bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) {
   // Currently typed arrays are the only such objects.
   if (!holder->IsJSTypedArray()) return false;
   if (exotic_index_state_ == ExoticIndexState::kExotic) return true;
+  if (!InternalHolderIsReceiverOrHiddenPrototype()) {
+    exotic_index_state_ = ExoticIndexState::kNotExotic;
+    return false;
+  }
   DCHECK(exotic_index_state_ == ExoticIndexState::kUninitialized);
   bool result = false;
   // Compute and cache result.
-  if (name()->IsString()) {
+  if (IsElement()) {
+    result = index_ >= JSTypedArray::cast(holder)->length_value();
+  } else if (name()->IsString()) {
     Handle<String> name_string = Handle<String>::cast(name());
     if (name_string->length() != 0) {
       result = IsSpecialIndex(isolate_->unicode_cache(), *name_string);
@@ -388,14 +406,18 @@ bool LookupIterator::HasInterceptor(Map* map) const {
 
 Handle<InterceptorInfo> LookupIterator::GetInterceptor() const {
   DCHECK_EQ(INTERCEPTOR, state_);
-  Handle<JSObject> js_holder = Handle<JSObject>::cast(holder_);
-  if (IsElement()) return handle(js_holder->GetIndexedInterceptor(), isolate_);
-  return handle(js_holder->GetNamedInterceptor(), isolate_);
+  return handle(GetInterceptor(JSObject::cast(*holder_)), isolate_);
+}
+
+
+InterceptorInfo* LookupIterator::GetInterceptor(JSObject* holder) const {
+  if (IsElement()) return holder->GetIndexedInterceptor();
+  return holder->GetNamedInterceptor();
 }
 
 
 bool LookupIterator::SkipInterceptor(JSObject* holder) {
-  auto info = holder->GetNamedInterceptor();
+  auto info = GetInterceptor(holder);
   // TODO(dcarney): check for symbol/can_intercept_symbols here as well.
   if (info->non_masking()) {
     switch (interceptor_state_) {
index b8e7c4d2b3b3640572fecdb0cc04fa9e810bfde4..ed54a7ef7306c7603f626f7b0c529f624a0590b6 100644 (file)
@@ -86,7 +86,7 @@ class LookupIterator final BASE_EMBEDDED {
                  Configuration configuration = PROTOTYPE_CHAIN)
       : configuration_(configuration),
         state_(NOT_FOUND),
-        exotic_index_state_(ExoticIndexState::kNotExotic),
+        exotic_index_state_(ExoticIndexState::kUninitialized),
         interceptor_state_(InterceptorState::kUninitialized),
         property_details_(PropertyDetails::Empty()),
         isolate_(isolate),
@@ -107,7 +107,7 @@ class LookupIterator final BASE_EMBEDDED {
                  Configuration configuration = PROTOTYPE_CHAIN)
       : configuration_(configuration),
         state_(NOT_FOUND),
-        exotic_index_state_(ExoticIndexState::kNotExotic),
+        exotic_index_state_(ExoticIndexState::kUninitialized),
         interceptor_state_(InterceptorState::kUninitialized),
         property_details_(PropertyDetails::Empty()),
         isolate_(isolate),
@@ -222,6 +222,8 @@ class LookupIterator final BASE_EMBEDDED {
   void ReloadPropertyInformation();
   bool SkipInterceptor(JSObject* holder);
   bool HasInterceptor(Map* map) const;
+  bool InternalHolderIsReceiverOrHiddenPrototype() const;
+  InterceptorInfo* GetInterceptor(JSObject* holder) const;
 
   bool IsBootstrapping() const;
 
index b21c900c1633a646fb6102dcf22d81c96cd46678..f8d5d1d9872abcf3986d17c936a09ab7ff039712 100644 (file)
@@ -1171,11 +1171,8 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
 MaybeHandle<Object> Object::GetElement(Isolate* isolate,
                                        Handle<Object> object,
                                        uint32_t index) {
-  // GetElement can trigger a getter which can cause allocation.
-  // This was not always the case. This DCHECK is here to catch
-  // leftover incorrect uses.
-  DCHECK(AllowHeapAllocation::IsAllowed());
-  return Object::GetElementWithReceiver(isolate, object, object, index);
+  LookupIterator it(isolate, object, index);
+  return GetProperty(&it);
 }
 
 
@@ -1214,14 +1211,6 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate,
 }
 
 
-MaybeHandle<Object> JSProxy::GetElementWithHandler(Handle<JSProxy> proxy,
-                                                   Handle<Object> receiver,
-                                                   uint32_t index) {
-  return GetPropertyWithHandler(
-      proxy, receiver, proxy->GetIsolate()->factory()->Uint32ToString(index));
-}
-
-
 MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
                                                    Handle<JSReceiver> receiver,
                                                    uint32_t index,
@@ -2231,7 +2220,7 @@ void Struct::InitializeBody(int object_size) {
 }
 
 
-bool Object::ToArrayIndex(uint32_t* index) {
+bool Object::ToArrayLength(uint32_t* index) {
   if (IsSmi()) {
     int value = Smi::cast(this)->value();
     if (value < 0) return false;
@@ -2250,6 +2239,11 @@ bool Object::ToArrayIndex(uint32_t* index) {
 }
 
 
+bool Object::ToArrayIndex(uint32_t* index) {
+  return ToArrayLength(index) && *index != kMaxUInt32;
+}
+
+
 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
   if (!this->IsJSValue()) return false;
 
@@ -6547,6 +6541,14 @@ Object* JSTypedArray::length() const {
 }
 
 
+uint32_t JSTypedArray::length_value() const {
+  if (WasNeutered()) return 0;
+  uint32_t index = 0;
+  CHECK(Object::cast(READ_FIELD(this, kLengthOffset))->ToArrayLength(&index));
+  return index;
+}
+
+
 void JSTypedArray::set_length(Object* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kLengthOffset, value);
   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kLengthOffset, value, mode);
@@ -6858,7 +6860,7 @@ bool StringHasher::UpdateIndex(uint16_t c) {
       return false;
     }
   }
-  if (array_index_ > 429496729U - ((d + 2) >> 3)) {
+  if (array_index_ > 429496729U - ((d + 3) >> 3)) {
     is_array_index_ = false;
     return false;
   }
index 241ce77bb82eae274185ab2512979169312c6e9d..db30fe99c5473ea38f53287137e4557eab9645ee 100644 (file)
@@ -611,28 +611,6 @@ static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
 }
 
 
-MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
-    Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
-    uint32_t index) {
-  Handle<JSObject> holder = object;
-  PrototypeIterator::WhereToStart where_to_start =
-      PrototypeIterator::START_AT_RECEIVER;
-  while (true) {
-    auto all_can_read_holder =
-        FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
-    if (!all_can_read_holder.ToHandle(&holder)) break;
-    auto result =
-        JSObject::GetElementWithInterceptor(holder, receiver, index, false);
-    if (isolate->has_scheduled_exception()) break;
-    if (!result.is_null()) return result;
-    where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
-  }
-  isolate->ReportFailedAccessCheck(object);
-  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-  return isolate->factory()->undefined_value();
-}
-
-
 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
     Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
     uint32_t index) {
@@ -655,58 +633,6 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
 }
 
 
-MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
-                                                   Handle<Object> object,
-                                                   Handle<Object> receiver,
-                                                   uint32_t index) {
-  DCHECK(!object->IsUndefined());
-
-  // Iterate up the prototype chain until an element is found or the null
-  // prototype is encountered.
-  for (PrototypeIterator iter(isolate, object,
-                              object->IsJSProxy() || object->IsJSObject()
-                                  ? PrototypeIterator::START_AT_RECEIVER
-                                  : PrototypeIterator::START_AT_PROTOTYPE);
-       !iter.IsAtEnd(); iter.Advance()) {
-    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
-      return JSProxy::GetElementWithHandler(
-          Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
-          index);
-    }
-
-    // Inline the case for JSObjects. Doing so significantly improves the
-    // performance of fetching elements where checking the prototype chain is
-    // necessary.
-    Handle<JSObject> js_object =
-        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
-
-    // Check access rights if needed.
-    if (js_object->IsAccessCheckNeeded()) {
-      if (!isolate->MayAccess(js_object)) {
-        return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
-                                                         receiver, index);
-      }
-    }
-
-    if (js_object->HasIndexedInterceptor()) {
-      return JSObject::GetElementWithInterceptor(js_object, receiver, index,
-                                                 true);
-    }
-
-    if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
-      Handle<Object> result;
-      ASSIGN_RETURN_ON_EXCEPTION(
-          isolate, result,
-          js_object->GetElementsAccessor()->Get(receiver, js_object, index),
-          Object);
-      if (!result->IsTheHole()) return result;
-    }
-  }
-
-  return isolate->factory()->undefined_value();
-}
-
-
 MaybeHandle<Object> Object::SetElementWithReceiver(
     Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
     uint32_t index, Handle<Object> value, LanguageMode language_mode) {
@@ -8250,10 +8176,8 @@ MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
     Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
   ElementsAccessor* accessor = array->GetElementsAccessor();
-  Handle<FixedArray> result;
-  ASSIGN_RETURN_ON_EXCEPTION(
-      array->GetIsolate(), result,
-      accessor->AddElementsToFixedArray(array, content, filter), FixedArray);
+  Handle<FixedArray> result =
+      accessor->AddElementsToFixedArray(array, content, filter);
 
 #ifdef ENABLE_SLOW_DCHECKS
   if (FLAG_enable_slow_asserts) {
@@ -12299,9 +12223,9 @@ MaybeHandle<Object> JSArray::SetElementsLength(
   List<Handle<Object> > old_values;
   Handle<Object> old_length_handle(array->length(), isolate);
   uint32_t old_length = 0;
-  CHECK(old_length_handle->ToArrayIndex(&old_length));
+  CHECK(old_length_handle->ToArrayLength(&old_length));
   uint32_t new_length = 0;
-  CHECK(new_length_handle->ToArrayIndex(&new_length));
+  CHECK(new_length_handle->ToArrayLength(&new_length));
 
   static const PropertyAttributes kNoAttrFilter = NONE;
   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
@@ -12331,7 +12255,7 @@ MaybeHandle<Object> JSArray::SetElementsLength(
       array->GetElementsAccessor()->SetLength(array, new_length_handle),
       Object);
 
-  CHECK(array->length()->ToArrayIndex(&new_length));
+  CHECK(array->length()->ToArrayLength(&new_length));
   if (old_length == new_length) return hresult;
 
   RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
@@ -12827,54 +12751,6 @@ MaybeHandle<Object> JSObject::SetElementWithInterceptor(
 }
 
 
-MaybeHandle<Object> JSObject::GetElementWithCallback(
-    Handle<JSObject> object,
-    Handle<Object> receiver,
-    Handle<Object> structure,
-    uint32_t index,
-    Handle<Object> holder) {
-  Isolate* isolate = object->GetIsolate();
-  DCHECK(!structure->IsForeign());
-  // api style callbacks.
-  if (structure->IsExecutableAccessorInfo()) {
-    Handle<ExecutableAccessorInfo> data =
-        Handle<ExecutableAccessorInfo>::cast(structure);
-    Object* fun_obj = data->getter();
-    v8::AccessorNameGetterCallback call_fun =
-        v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj);
-    if (call_fun == NULL) return isolate->factory()->undefined_value();
-    Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
-    Handle<String> key = isolate->factory()->Uint32ToString(index);
-    LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
-    PropertyCallbackArguments
-        args(isolate, data->data(), *receiver, *holder_handle);
-    v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
-    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-    if (result.IsEmpty()) return isolate->factory()->undefined_value();
-    Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
-    result_internal->VerifyApiCallResultType();
-    // Rebox handle before return.
-    return handle(*result_internal, isolate);
-  }
-
-  // __defineGetter__ callback
-  if (structure->IsAccessorPair()) {
-    Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
-                          isolate);
-    if (getter->IsSpecFunction()) {
-      // TODO(rossberg): nicer would be to cast to some JSCallable here...
-      return GetPropertyWithDefinedGetter(
-          receiver, Handle<JSReceiver>::cast(getter));
-    }
-    // Getter is not a function.
-    return isolate->factory()->undefined_value();
-  }
-
-  UNREACHABLE();
-  return MaybeHandle<Object>();
-}
-
-
 MaybeHandle<Object> JSObject::SetElementWithCallback(
     Handle<Object> object, Handle<Object> structure, uint32_t index,
     Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) {
@@ -12989,7 +12865,8 @@ MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
   bool must_update_array_length = false;
   bool introduces_holes = true;
   if (object->IsJSArray()) {
-    CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
+    CHECK(
+        Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
     introduces_holes = index > array_length;
     if (index >= array_length) {
       must_update_array_length = true;
@@ -13184,7 +13061,8 @@ MaybeHandle<Object> JSObject::SetDictionaryElement(
   if (object->ShouldConvertToFastElements()) {
     uint32_t new_length = 0;
     if (object->IsJSArray()) {
-      CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
+      CHECK(
+          Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length));
     } else {
       new_length = dictionary->max_number_key() + 1;
     }
@@ -13239,7 +13117,7 @@ MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
   bool introduces_holes = true;
   uint32_t length = elms_length;
   if (object->IsJSArray()) {
-    CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
+    CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length));
     introduces_holes = index > length;
   } else {
     introduces_holes = index >= elms_length;
@@ -13276,8 +13154,8 @@ MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
     if (object->IsJSArray()) {
       // Update the length of the array if needed.
       uint32_t array_length = 0;
-      CHECK(
-          Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
+      CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(
+          &array_length));
       if (index >= array_length) {
         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
       }
@@ -13438,8 +13316,8 @@ MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
                                  isolate);
       uint32_t old_length = 0;
       uint32_t new_length = 0;
-      CHECK(old_length_handle->ToArrayIndex(&old_length));
-      CHECK(new_length_handle->ToArrayIndex(&new_length));
+      CHECK(old_length_handle->ToArrayLength(&old_length));
+      CHECK(new_length_handle->ToArrayLength(&new_length));
 
       RETURN_ON_EXCEPTION(
           isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object);
@@ -13627,7 +13505,7 @@ void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
       // If the array is huge, it's not likely to be defined in a local
       // function, so we shouldn't make new instances of it very often.
       uint32_t length = 0;
-      CHECK(transition_info->length()->ToArrayIndex(&length));
+      CHECK(transition_info->length()->ToArrayLength(&length));
       if (length <= kMaximumArrayBytesToPretransition) {
         if (FLAG_trace_track_allocation_sites) {
           bool is_nested = site->IsNestedSite();
@@ -13741,7 +13619,7 @@ void JSObject::TransitionElementsKind(Handle<JSObject> object,
       // elements, assume a length of zero.
       length = 0;
     } else {
-      CHECK(raw_length->ToArrayIndex(&length));
+      CHECK(raw_length->ToArrayLength(&length));
     }
   }
 
@@ -13784,7 +13662,7 @@ void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
                                            uint32_t index,
                                            Handle<Object> value) {
   uint32_t old_len = 0;
-  CHECK(array->length()->ToArrayIndex(&old_len));
+  CHECK(array->length()->ToArrayLength(&old_len));
   // Check to see if we need to update the length. For now, we make
   // sure that the length stays within 32-bits (unsigned).
   if (index >= old_len && index != 0xffffffff) {
@@ -13808,7 +13686,7 @@ bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
                                         uint32_t index) {
   uint32_t length = 0;
-  CHECK(array->length()->ToArrayIndex(&length));
+  CHECK(array->length()->ToArrayLength(&length));
   if (length <= index) return HasReadOnlyLength(array);
   return false;
 }
@@ -13824,50 +13702,6 @@ MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
 }
 
 
-MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
-                                                        Handle<Object> receiver,
-                                                        uint32_t index,
-                                                        bool check_prototype) {
-  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(), isolate);
-  if (!interceptor->getter()->IsUndefined()) {
-    v8::IndexedPropertyGetterCallback getter =
-        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
-    LOG(isolate,
-        ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
-    PropertyCallbackArguments
-        args(isolate, interceptor->data(), *receiver, *object);
-    v8::Handle<v8::Value> result = args.Call(getter, index);
-    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-    if (!result.IsEmpty()) {
-      Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
-      result_internal->VerifyApiCallResultType();
-      // Rebox handle before return.
-      return handle(*result_internal, isolate);
-    }
-  }
-
-  if (!check_prototype) return MaybeHandle<Object>();
-
-  ElementsAccessor* handler = object->GetElementsAccessor();
-  Handle<Object> result;
-  ASSIGN_RETURN_ON_EXCEPTION(
-      isolate, result, handler->Get(receiver,  object, index),
-      Object);
-  if (!result->IsTheHole()) return result;
-
-  PrototypeIterator iter(isolate, object);
-  if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
-  return Object::GetElementWithReceiver(
-      isolate, PrototypeIterator::GetCurrent(iter), receiver, index);
-}
-
-
 bool JSObject::HasDenseElements() {
   int capacity = 0;
   int used = 0;
@@ -14011,7 +13845,7 @@ bool JSObject::ShouldConvertToFastElements() {
   // the object should have fast elements.
   uint32_t array_size = 0;
   if (IsJSArray()) {
-    CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
+    CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size));
   } else {
     array_size = dictionary->max_number_key();
   }
index ee3db8d1d8f4266ea35f94190123e9b20a97176d..5e4272ff742d877e3a7959ad196a6e96b9980ff7 100644 (file)
@@ -1214,12 +1214,6 @@ class Object {
       Handle<Object> object,
       uint32_t index);
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetElementWithReceiver(
-      Isolate* isolate,
-      Handle<Object> object,
-      Handle<Object> receiver,
-      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);
@@ -1252,8 +1246,13 @@ class Object {
   // by ES6 Map and Set.
   bool SameValueZero(Object* other);
 
-  // Tries to convert an object to an array index.  Returns true and sets
-  // the output parameter if it succeeds.
+  // Tries to convert an object to an array length. Returns true and sets the
+  // output parameter if it succeeds.
+  inline bool ToArrayLength(uint32_t* index);
+
+  // Tries to convert an object to an array index. Returns true and sets the
+  // output parameter if it succeeds. Equivalent to ToArrayLength, but does not
+  // allow kMaxUInt32.
   inline bool ToArrayIndex(uint32_t* index);
 
   // Returns true if this is a JSValue containing a string and the index is
@@ -2003,12 +2002,6 @@ class JSObject: public JSReceiver {
       PropertyAttributes attributes, LanguageMode language_mode,
       bool check_prototype = true, SetPropertyMode set_mode = SET_PROPERTY);
 
-  // Returns the index'th element.
-  // The undefined object if index is out of bounds.
-  MUST_USE_RESULT static MaybeHandle<Object> GetElementWithInterceptor(
-      Handle<JSObject> object, Handle<Object> receiver, uint32_t index,
-      bool check_prototype);
-
   enum SetFastElementsCapacitySmiMode {
     kAllowSmiElements,
     kForceSmiElements,
@@ -2306,13 +2299,6 @@ class JSObject: public JSReceiver {
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck(
       LookupIterator* it);
 
-  MUST_USE_RESULT static MaybeHandle<Object> GetElementWithCallback(
-      Handle<JSObject> object,
-      Handle<Object> receiver,
-      Handle<Object> structure,
-      uint32_t index,
-      Handle<Object> holder);
-
   MUST_USE_RESULT static Maybe<PropertyAttributes>
       GetElementAttributeWithInterceptor(Handle<JSObject> object,
                                          Handle<JSReceiver> receiver,
@@ -2361,9 +2347,6 @@ class JSObject: public JSReceiver {
   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> GetElementWithFailedAccessCheck(
-      Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
-      uint32_t index);
   MUST_USE_RESULT static Maybe<PropertyAttributes>
   GetElementAttributesWithFailedAccessCheck(Isolate* isolate,
                                             Handle<JSObject> object,
@@ -10020,10 +10003,6 @@ class JSProxy: public JSReceiver {
       Handle<JSProxy> proxy,
       Handle<Object> receiver,
       Handle<Name> name);
-  MUST_USE_RESULT static inline MaybeHandle<Object> GetElementWithHandler(
-      Handle<JSProxy> proxy,
-      Handle<Object> receiver,
-      uint32_t index);
 
   // If the handler defines an accessor property with a setter, invoke it.
   // If it defines an accessor property without a setter, or a data property
@@ -10425,6 +10404,7 @@ class JSTypedArray: public JSArrayBufferView {
  public:
   // [length]: length of typed array in elements.
   DECL_ACCESSORS(length, Object)
+  inline uint32_t length_value() const;
 
   DECLARE_CAST(JSTypedArray)
 
index e2f6d794a231005be249fd5e175999008fc6e85c..3f05540ef80d6d0b47d1139cec9674c24cfcef11 100644 (file)
@@ -705,16 +705,13 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
       break;
     }
     case SLOPPY_ARGUMENTS_ELEMENTS: {
-      ElementsAccessor* accessor = receiver->GetElementsAccessor();
       for (uint32_t index = 0; index < length; index++) {
         HandleScope loop_scope(isolate);
-        if (accessor->HasElement(receiver, index)) {
-          Handle<Object> element;
-          ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-              isolate, element, accessor->Get(receiver, receiver, index),
-              false);
-          visitor->visit(index, element);
-        }
+        Handle<Object> element;
+        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+            isolate, element, Object::GetElement(isolate, receiver, index),
+            false);
+        visitor->visit(index, element);
       }
       break;
     }
index 3f63276db4b3095bd17513ec21610d6fcb058e63..b4b1ba7773d1db862e48055dde679fdfc7619f00 100644 (file)
@@ -281,10 +281,9 @@ static Object* LoadElementFromSuper(Isolate* isolate, Handle<Object> receiver,
   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::GetElementWithReceiver(isolate, proto, receiver, index));
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
   return *result;
 }
 
index 91b6ee5db2d1e78742424458a5c9ab681f2b723a..6612f2c2d5cc1a246274a86f76c1f33e048f346c 100644 (file)
@@ -422,9 +422,8 @@ RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
   Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      JSObject::GetElementWithInterceptor(obj, obj, index, true));
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
+                                     Object::GetElement(isolate, obj, index));
   return *result;
 }
 
index a92a642bbc936cb8129386ef692acf73324060e7..1f50b84f329eb7feb85420895bb0c3fbb7d9e3a0 100644 (file)
@@ -286,12 +286,14 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
   RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
 
   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
+  size_t length = 0;
   if (source->IsJSTypedArray() &&
       JSTypedArray::cast(*source)->type() == array_type) {
-    length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
+    length_obj = handle(JSTypedArray::cast(*source)->length(), isolate);
+    length = JSTypedArray::cast(*source)->length_value();
+  } else {
+    RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length));
   }
-  size_t length = 0;
-  RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length));
 
   if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
       (length > (kMaxInt / element_size))) {
@@ -363,7 +365,7 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
 #define BUFFER_VIEW_GETTER(Type, getter, accessor)   \
   RUNTIME_FUNCTION(Runtime_##Type##Get##getter) {    \
     HandleScope scope(isolate);                      \
-    DCHECK(args.length() == 1);                      \
+    DCHECK_EQ(1, args.length());                     \
     CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0); \
     return holder->accessor();                       \
   }
@@ -377,7 +379,7 @@ BUFFER_VIEW_GETTER(DataView, Buffer, buffer)
 
 RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
   return *holder->GetBuffer();
 }
@@ -417,8 +419,8 @@ RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
   size_t offset = 0;
   RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset));
-  size_t target_length = NumberToSize(isolate, target->length());
-  size_t source_length = NumberToSize(isolate, source->length());
+  size_t target_length = target->length_value();
+  size_t source_length = source->length_value();
   size_t target_byte_length = NumberToSize(isolate, target->byte_length());
   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
   if (offset > target_length || offset + source_length > target_length ||
index d8879ac00b46fce28357da24a0bc52356674570f..8b2f1137e0fa708a0701440a048120aedf8ec2d8 100644 (file)
@@ -1690,7 +1690,7 @@ bool StringToArrayIndex(Stream* stream, uint32_t* index) {
     d = stream->GetNext() - '0';
     if (d < 0 || d > 9) return false;
     // Check that the new result is below the 32 bit limit.
-    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
+    if (result > 429496729U - ((d + 3) >> 3)) return false;
     result = (result * 10) + d;
   }
 
index aba08e23d72f9403c67844a677263ad93bcd9726..982a4fe6f96b5cfb918731b3e582b90444ecf89d 100644 (file)
@@ -2021,9 +2021,9 @@ THREADED_TEST(Enumerators) {
       "k.a = 0;"
       "k[5] = 0;"
       "k.b = 0;"
-      "k[4294967295] = 0;"
+      "k[4294967294] = 0;"
       "k.c = 0;"
-      "k[4294967296] = 0;"
+      "k[4294967295] = 0;"
       "k.d = 0;"
       "k[140000] = 0;"
       "k.e = 0;"
@@ -2046,7 +2046,7 @@ THREADED_TEST(Enumerators) {
   CHECK(v8_str("10")->Equals(result->Get(v8::Integer::New(isolate, 1))));
   CHECK(v8_str("140000")->Equals(result->Get(v8::Integer::New(isolate, 2))));
   CHECK(
-      v8_str("4294967295")->Equals(result->Get(v8::Integer::New(isolate, 3))));
+      v8_str("4294967294")->Equals(result->Get(v8::Integer::New(isolate, 3))));
   // Indexed interceptor properties in the order they are returned
   // from the enumerator interceptor.
   CHECK(v8_str("0")->Equals(result->Get(v8::Integer::New(isolate, 4))));
@@ -2056,7 +2056,7 @@ THREADED_TEST(Enumerators) {
   CHECK(v8_str("b")->Equals(result->Get(v8::Integer::New(isolate, 7))));
   CHECK(v8_str("c")->Equals(result->Get(v8::Integer::New(isolate, 8))));
   CHECK(
-      v8_str("4294967296")->Equals(result->Get(v8::Integer::New(isolate, 9))));
+      v8_str("4294967295")->Equals(result->Get(v8::Integer::New(isolate, 9))));
   CHECK(v8_str("d")->Equals(result->Get(v8::Integer::New(isolate, 10))));
   CHECK(v8_str("e")->Equals(result->Get(v8::Integer::New(isolate, 11))));
   CHECK(v8_str("30000000000")
index 93ed66b2180fa6ab8410a2de300ee36aca9e27cb..9abccae75067cf98a461dc5815ef79c1da73d042 100644 (file)
@@ -7433,10 +7433,10 @@ THREADED_TEST(ToArrayIndex) {
   str = v8_str("-42");
   index = str->ToArrayIndex();
   CHECK(index.IsEmpty());
-  str = v8_str("4294967295");
+  str = v8_str("4294967294");
   index = str->ToArrayIndex();
   CHECK(!index.IsEmpty());
-  CHECK_EQ(4294967295.0, index->Uint32Value());
+  CHECK_EQ(4294967294.0, index->Uint32Value());
   v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
   index = num->ToArrayIndex();
   CHECK(!index.IsEmpty());
index 70942ee13c163fcaf88af54af26df55815c7385d..d2ac90485ebc31cef291d920ea1e1bf9b66a3d8e 100644 (file)
@@ -71,9 +71,9 @@ proto2.a = 0;
 proto2[2] = 0;
 proto2[3] = 0;  // also on the 'proto1' object
 proto2.b = 0;
-proto2[4294967295] = 0;
+proto2[4294967294] = 0;
 proto2.c = 0;
-proto2[4294967296] = 0;
+proto2[4294967295] = 0;
 
 var proto1 = {};
 proto1[5] = 0;
@@ -98,8 +98,8 @@ var expected = ['23', '42',  // indexed from 'o'
                 '-23', '300000000000', 'f', 'g', '-4',  // named from 'o'
                 '3', '5',  // indexed from 'proto1'
                 'd', 'e',  // named from 'proto1'
-                '2', '140000', '4294967295',  // indexed from 'proto2'
-                'a', 'b', 'c', '4294967296'];  // named from 'proto2'
+                '2', '140000', '4294967294',  // indexed from 'proto2'
+                'a', 'b', 'c', '4294967295'];  // named from 'proto2'
 var actual = [];
 for (var p in o) actual.push(p);
 assertArrayEquals(expected, actual);
index 7aefd78c4ffa4cd84f5504793cb69d8793cbfe76..ebc18ef5e27d3ef5b42e5a79bbc72bfa94d2ddf4 100644 (file)
@@ -8,7 +8,7 @@ Object.prototype["10"] = "unreachable";
 Object.prototype["7"] = "unreachable";
 Object.prototype["-1"] = "unreachable";
 Object.prototype["-0"] = "unreachable";
-Object.prototype["4294967296"] = "unreachable";
+Object.prototype["4294967295"] = "unreachable";
 
 var array = new Int32Array(10);
 
@@ -17,12 +17,12 @@ function check() {
     assertEquals(undefined, array["-1"]);
     assertEquals(undefined, array["-0"]);
     assertEquals(undefined, array["10"]);
-    assertEquals(undefined, array["4294967296"]);
+    assertEquals(undefined, array["4294967295"]);
   }
   assertEquals("unreachable", array.__proto__["-1"]);
   assertEquals("unreachable", array.__proto__["-0"]);
   assertEquals("unreachable", array.__proto__["10"]);
-  assertEquals("unreachable", array.__proto__["4294967296"]);
+  assertEquals("unreachable", array.__proto__["4294967295"]);
 }
 
 check();
@@ -30,19 +30,19 @@ check();
 array["-1"] = "unreachable";
 array["-0"] = "unreachable";
 array["10"] = "unreachable";
-array["4294967296"] = "unreachable";
+array["4294967295"] = "unreachable";
 
 check();
 
 delete array["-0"];
 delete array["-1"];
 delete array["10"];
-delete array["4294967296"];
+delete array["4294967295"];
 
 assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-1"));
 assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-0"));
 assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "10"));
-assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "4294967296"));
+assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "4294967295"));
 assertEquals(10, Object.keys(array).length);
 
 check();
@@ -58,6 +58,6 @@ assertEquals(undefined, f());
 Object.defineProperty(new Int32Array(), "-1", {'value': 1});
 Object.defineProperty(new Int32Array(), "-0", {'value': 1});
 Object.defineProperty(new Int32Array(), "-10", {'value': 1});
-Object.defineProperty(new Int32Array(), "4294967296", {'value': 1});
+Object.defineProperty(new Int32Array(), "4294967295", {'value': 1});
 
 check();
index 65cd87de010c06a91952c3a7c41a4e7ab46b914e..ab345a9b61e0a8d78a79180b9a7c978f22babcab 100644 (file)
@@ -35,11 +35,13 @@ assertEquals(pow31 + 1, a.length);
 assertThrows(function() { a.concat(a); }, RangeError);
 
 var b = [];
-b[pow31 - 2] = 32;
+b[pow31 - 3] = 32;
+b[pow31 - 2] = "out_of_bounds";
 var ab = a.concat(b);
 assertEquals(2 * pow31 - 1, ab.length);
 assertEquals(31, ab[pow31]);
-assertEquals(32, ab[2 * pow31 - 1]);
+assertEquals(32, ab[2 * pow31 - 2]);
+assertEquals(undefined, ab[2 * pow31 - 1]);
 
 var c = [];
 c[pow30] = 30;
index 5da17eecf1fa57699af86521adefc3fbe62a262f..1f4eb9ce59c614751ff88e2aae0dbf39db364796 100644 (file)
@@ -30,6 +30,7 @@ a[0xfffffffe] = 10;
 assertThrows("a.unshift(1);", RangeError);
 assertEquals(0xffffffff, a.length);
 assertEquals(10, a[0xffffffff]);
+assertEquals(0xffffffff, a.length);
 assertEquals(undefined, a[0xfffffffe]);
 
 a = [1,2,3];