| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 45ab2d9aa8a30e9b1ef2f7dfed104e1c19633d2a..9cfcceec24cadeea63fd15c452cff71a3b08caf8 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -37,6 +37,20 @@ namespace internal {
|
| ElementsAccessor** ElementsAccessor::elements_accessors_;
|
|
|
|
|
| +bool HasKey(FixedArray* array, Object* key) {
|
| + int len0 = array->length();
|
| + for (int i = 0; i < len0; i++) {
|
| + Object* element = array->get(i);
|
| + if (element->IsSmi() && element == key) return true;
|
| + if (element->IsString() &&
|
| + key->IsString() && String::cast(element)->Equals(String::cast(key))) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| // Base class for element handler implementations. Contains the
|
| // the common logic for objects with different ElementsKinds.
|
| // Subclasses must specialize method for which the element
|
| @@ -73,6 +87,78 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| uint32_t index,
|
| JSReceiver::DeleteMode mode) = 0;
|
|
|
| + virtual MaybeObject* AddJSArrayKeysToFixedArray(JSArray* other,
|
| + FixedArray* keys) {
|
| + int len0 = keys->length();
|
| +#ifdef DEBUG
|
| + if (FLAG_enable_slow_asserts) {
|
| + for (int i = 0; i < len0; i++) {
|
| + ASSERT(keys->get(i)->IsString() || keys->get(i)->IsNumber());
|
| + }
|
| + }
|
| +#endif
|
| + int len1 = ElementsAccessorSubclass::GetCapacity(other);
|
| +
|
| + // Optimize if 'other' is empty.
|
| + // We cannot optimize if 'this' is empty, as other may have holes
|
| + // or non keys.
|
| + if (len1 == 0) return keys;
|
| +
|
| + // Compute how many elements are not in other.
|
| + int extra = 0;
|
| + for (int y = 0; y < len1; y++) {
|
| + Object* value;
|
| + MaybeObject* maybe_value =
|
| + ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y);
|
| + if (!maybe_value->ToObject(&value)) return maybe_value;
|
| + if (!value->IsTheHole() && !HasKey(keys, value)) extra++;
|
| + }
|
| +
|
| + if (extra == 0) return keys;
|
| +
|
| + // Allocate the result
|
| + FixedArray* result;
|
| + MaybeObject* maybe_obj =
|
| + other->GetHeap()->AllocateFixedArray(len0 + extra);
|
| + if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
|
| +
|
| + // Fill in the content
|
| + {
|
| + AssertNoAllocation no_gc;
|
| + WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
|
| + for (int i = 0; i < len0; i++) {
|
| + Object* e = keys->get(i);
|
| + ASSERT(e->IsString() || e->IsNumber());
|
| + result->set(i, e, mode);
|
| + }
|
| + }
|
| + // Fill in the extra keys.
|
| + int index = 0;
|
| + for (int y = 0; y < len1; y++) {
|
| + MaybeObject* maybe_value =
|
| + ElementsAccessorSubclass::GetElementAtCapacityIndex(other, y);
|
| + Object* value;
|
| + if (!maybe_value->ToObject(&value)) return maybe_value;
|
| + if (!value->IsTheHole() && !HasKey(keys, value)) {
|
| + ASSERT(value->IsString() || value->IsNumber());
|
| + result->set(len0 + index, value);
|
| + index++;
|
| + }
|
| + }
|
| + ASSERT(extra == index);
|
| + return result;
|
| + }
|
| +
|
| + static uint32_t GetCapacity(JSObject* obj) {
|
| + return ElementsAccessorSubclass::GetBackingStore(obj)->length();
|
| + }
|
| +
|
| + static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) {
|
| + BackingStoreClass* backing_store =
|
| + ElementsAccessorSubclass::GetBackingStore(obj);
|
| + return backing_store->get(index);
|
| + }
|
| +
|
| protected:
|
| static BackingStoreClass* GetBackingStore(JSObject* obj) {
|
| return BackingStoreClass::cast(obj->elements());
|
| @@ -325,6 +411,19 @@ class DictionaryElementsAccessor
|
| obj->element_dictionary(),
|
| index);
|
| }
|
| +
|
| + static uint32_t GetCapacity(JSObject* obj) {
|
| + return obj->element_dictionary()->Capacity();
|
| + }
|
| +
|
| + static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) {
|
| + NumberDictionary* dict = obj->element_dictionary();
|
| + if (dict->IsKey(dict->KeyAt(index))) {
|
| + return dict->ValueAt(index);
|
| + } else {
|
| + return obj->GetHeap()->the_hole_value();
|
| + }
|
| + }
|
| };
|
|
|
|
|
| @@ -382,6 +481,18 @@ class NonStrictArgumentsElementsAccessor
|
| }
|
| return obj->GetHeap()->true_value();
|
| }
|
| +
|
| + static uint32_t GetCapacity(JSObject* obj) {
|
| + // TODO(danno): Return max of parameter map length or backing store
|
| + // capacity.
|
| + return 0;
|
| + }
|
| +
|
| + static MaybeObject* GetElementAtCapacityIndex(JSObject* obj, int index) {
|
| + // TODO(danno): Return either value from parameter map of backing
|
| + // store value at index.
|
| + return obj->GetHeap()->the_hole_value();
|
| + }
|
| };
|
|
|
|
|
|
|