From 5ce20b338775b00b5d26fb8022ff65556aa1825f Mon Sep 17 00:00:00 2001 From: "danno@chromium.org" Date: Mon, 5 Mar 2012 16:14:34 +0000 Subject: [PATCH] Recfactor core HasElement functionality into ElementsAccessors Review URL: https://chromiumcodereview.appspot.com/9572014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10926 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/elements.cc | 96 +++++++++++++++----------- src/elements.h | 24 +++---- src/objects.cc | 175 +++++------------------------------------------- src/objects.h | 4 -- 4 files changed, 87 insertions(+), 212 deletions(-) diff --git a/src/elements.cc b/src/elements.cc index d951b0ee5..63bf09074 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -173,12 +173,12 @@ class ElementsAccessorBase : public ElementsAccessor { if (len1 == 0) return to; // Compute how many elements are not in other. - int extra = 0; + uint32_t extra = 0; for (uint32_t y = 0; y < len1; y++) { - if (ElementsAccessorSubclass::HasElementAtIndexImpl( - backing_store, y, holder, receiver)) { - uint32_t key = - ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); + uint32_t key = + ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); + if (ElementsAccessorSubclass::HasElementImpl( + backing_store, key, holder, receiver)) { MaybeObject* maybe_value = ElementsAccessorSubclass::GetImpl(backing_store, key, holder, receiver); @@ -210,12 +210,12 @@ class ElementsAccessorBase : public ElementsAccessor { } } // Fill in the extra values. - int index = 0; + uint32_t index = 0; for (uint32_t y = 0; y < len1; y++) { - if (ElementsAccessorSubclass::HasElementAtIndexImpl( - backing_store, y, holder, receiver)) { - uint32_t key = - ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); + uint32_t key = + ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); + if (ElementsAccessorSubclass::HasElementImpl( + backing_store, key, holder, receiver)) { MaybeObject* maybe_value = ElementsAccessorSubclass::GetImpl(backing_store, key, holder, receiver); @@ -241,23 +241,21 @@ class ElementsAccessorBase : public ElementsAccessor { BackingStoreClass::cast(backing_store)); } - static bool HasElementAtIndexImpl(BackingStoreClass* backing_store, - uint32_t index, - JSObject* holder, - Object* receiver) { - uint32_t key = - ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index); + static bool HasElementImpl(BackingStoreClass* backing_store, + uint32_t key, + JSObject* holder, + Object* receiver) { MaybeObject* element = ElementsAccessorSubclass::GetImpl(backing_store, key, holder, receiver); return !element->IsTheHole(); } - virtual bool HasElementAtIndex(FixedArrayBase* backing_store, - uint32_t index, - JSObject* holder, - Object* receiver) { - return ElementsAccessorSubclass::HasElementAtIndexImpl( - BackingStoreClass::cast(backing_store), index, holder, receiver); + virtual bool HasElement(FixedArrayBase* backing_store, + uint32_t key, + JSObject* holder, + Object* receiver) { + return ElementsAccessorSubclass::HasElementImpl( + BackingStoreClass::cast(backing_store), key, holder, receiver); } static uint32_t GetKeyForIndexImpl(BackingStoreClass* backing_store, @@ -266,7 +264,7 @@ class ElementsAccessorBase : public ElementsAccessor { } virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, - uint32_t index) { + uint32_t index) { return ElementsAccessorSubclass::GetKeyForIndexImpl( BackingStoreClass::cast(backing_store), index); } @@ -441,11 +439,11 @@ class FastDoubleElementsAccessor return obj->GetHeap()->true_value(); } - static bool HasElementAtIndexImpl(FixedDoubleArray* backing_store, - uint32_t index, - JSObject* holder, - Object* receiver) { - return !backing_store->is_the_hole(index); + static bool HasElementImpl(FixedDoubleArray* backing_store, + uint32_t key, + JSObject* holder, + Object* receiver) { + return !backing_store->is_the_hole(key); } }; @@ -484,6 +482,15 @@ class ExternalElementsAccessor // External arrays always ignore deletes. return obj->GetHeap()->true_value(); } + + static bool HasElementImpl(ExternalArray* backing_store, + uint32_t key, + JSObject* holder, + Object* receiver) { + uint32_t capacity = + ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); + return key < capacity; + } }; @@ -677,6 +684,14 @@ class DictionaryElementsAccessor return obj->GetHeap()->the_hole_value(); } + static bool HasElementImpl(SeededNumberDictionary* backing_store, + uint32_t key, + JSObject* holder, + Object* receiver) { + return backing_store->FindEntry(key) != + SeededNumberDictionary::kNotFound; + } + static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, uint32_t index) { Object* key = dict->KeyAt(index); @@ -696,7 +711,7 @@ class NonStrictArgumentsElementsAccessor uint32_t key, JSObject* obj, Object* receiver) { - Object* probe = GetParameterMapArg(parameter_map, key); + Object* probe = GetParameterMapArg(obj, parameter_map, key); if (!probe->IsTheHole()) { Context* context = Context::cast(parameter_map->get(0)); int context_index = Smi::cast(probe)->value(); @@ -735,7 +750,7 @@ class NonStrictArgumentsElementsAccessor uint32_t key, JSReceiver::DeleteMode mode) { FixedArray* parameter_map = FixedArray::cast(obj->elements()); - Object* probe = GetParameterMapArg(parameter_map, key); + Object* probe = GetParameterMapArg(obj, parameter_map, key); if (!probe->IsTheHole()) { // TODO(kmillikin): We could check if this was the last aliased // parameter, and revert to normal elements in that case. That @@ -763,24 +778,27 @@ class NonStrictArgumentsElementsAccessor return index; } - static bool HasElementAtIndexImpl(FixedArray* parameter_map, - uint32_t index, - JSObject* holder, - Object* receiver) { - Object* probe = GetParameterMapArg(parameter_map, index); + static bool HasElementImpl(FixedArray* parameter_map, + uint32_t key, + JSObject* holder, + Object* receiver) { + Object* probe = GetParameterMapArg(holder, parameter_map, key); if (!probe->IsTheHole()) { return true; } else { FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); - return !accessor->Get(arguments, index, holder, receiver)->IsTheHole(); + return !accessor->Get(arguments, key, holder, receiver)->IsTheHole(); } } private: - static Object* GetParameterMapArg(FixedArray* parameter_map, + static Object* GetParameterMapArg(JSObject* holder, + FixedArray* parameter_map, uint32_t key) { - uint32_t length = parameter_map->length(); + uint32_t length = holder->IsJSArray() + ? Smi::cast(JSArray::cast(holder)->length())->value() + : parameter_map->length(); return key < (length - 2 ) ? parameter_map->get(key + 2) : parameter_map->GetHeap()->the_hole_value(); diff --git a/src/elements.h b/src/elements.h index a2a184d52..615d5f90a 100644 --- a/src/elements.h +++ b/src/elements.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -66,6 +66,11 @@ class ElementsAccessor { uint32_t key, JSReceiver::DeleteMode mode) = 0; + virtual bool HasElement(FixedArrayBase* backing_store, + uint32_t key, + JSObject* holder, + Object* receiver) = 0; + virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from, FixedArray* to, JSObject* holder, @@ -86,19 +91,14 @@ class ElementsAccessor { virtual uint32_t GetCapacity(FixedArrayBase* backing_store) = 0; - virtual bool HasElementAtIndex(FixedArrayBase* backing_store, - uint32_t index, - JSObject* holder, - Object* receiver) = 0; - - // Element handlers distinguish between indexes and keys when the manipulate + // Element handlers distinguish between indexes and keys when they manipulate // elements. Indexes refer to elements in terms of their location in the - // underlying storage's backing store representation, and are between 0 + // underlying storage's backing store representation, and are between 0 and // GetCapacity. Keys refer to elements in terms of the value that would be - // specific in JavaScript to access the element. In most implementations, keys - // are equivalent to indexes, and GetKeyForIndex returns the same value it is - // passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps the - // index to a key using the KeyAt method on the NumberDictionary. + // specified in JavaScript to access the element. In most implementations, + // keys are equivalent to indexes, and GetKeyForIndex returns the same value + // it is passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps + // the index to a key using the KeyAt method on the NumberDictionary. virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, uint32_t index) = 0; diff --git a/src/objects.cc b/src/objects.cc index 9e93b2812..721681bc4 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -8917,78 +8917,6 @@ MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, } -bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { - switch (GetElementsKind()) { - case FAST_SMI_ONLY_ELEMENTS: - case FAST_ELEMENTS: { - uint32_t length = IsJSArray() ? - static_cast - (Smi::cast(JSArray::cast(this)->length())->value()) : - static_cast(FixedArray::cast(elements())->length()); - if ((index < length) && - !FixedArray::cast(elements())->get(index)->IsTheHole()) { - return true; - } - break; - } - case FAST_DOUBLE_ELEMENTS: { - uint32_t length = IsJSArray() ? - static_cast - (Smi::cast(JSArray::cast(this)->length())->value()) : - static_cast(FixedDoubleArray::cast(elements())->length()); - if ((index < length) && - !FixedDoubleArray::cast(elements())->is_the_hole(index)) { - return true; - } - break; - } - case EXTERNAL_PIXEL_ELEMENTS: { - ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); - if (index < static_cast(pixels->length())) { - return true; - } - break; - } - case EXTERNAL_BYTE_ELEMENTS: - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: - case EXTERNAL_SHORT_ELEMENTS: - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: - case EXTERNAL_INT_ELEMENTS: - case EXTERNAL_UNSIGNED_INT_ELEMENTS: - case EXTERNAL_FLOAT_ELEMENTS: - case EXTERNAL_DOUBLE_ELEMENTS: { - ExternalArray* array = ExternalArray::cast(elements()); - if (index < static_cast(array->length())) { - return true; - } - break; - } - case DICTIONARY_ELEMENTS: { - if (element_dictionary()->FindEntry(index) - != SeededNumberDictionary::kNotFound) { - return true; - } - break; - } - case NON_STRICT_ARGUMENTS_ELEMENTS: - UNREACHABLE(); - break; - } - - // Handle [] on String objects. - if (this->IsStringObjectWithCharacterAt(index)) return true; - - Object* pt = GetPrototype(); - if (pt->IsNull()) return false; - if (pt->IsJSProxy()) { - // We need to follow the spec and simulate a call to [[GetOwnProperty]]. - return JSProxy::cast(pt)->GetElementAttributeWithHandler( - receiver, index) != ABSENT; - } - return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); -} - - bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) { Isolate* isolate = GetIsolate(); // Make sure that the top context does not change when doing @@ -9028,7 +8956,21 @@ bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) { } if (!result.IsEmpty()) return true; } - return holder_handle->HasElementPostInterceptor(*receiver_handle, index); + + if (holder_handle->GetElementsAccessor()->HasElement( + holder_handle->elements(), index, *holder_handle, *receiver_handle)) { + return true; + } + + if (holder_handle->IsStringObjectWithCharacterAt(index)) return true; + Object* pt = holder_handle->GetPrototype(); + if (pt->IsJSProxy()) { + // We need to follow the spec and simulate a call to [[GetOwnProperty]]. + return JSProxy::cast(pt)->GetElementAttributeWithHandler( + receiver, index) != ABSENT; + } + if (pt->IsNull()) return false; + return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index); } @@ -9138,28 +9080,6 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { } -bool JSObject::HasElementInElements(FixedArray* elements, - ElementsKind kind, - uint32_t index) { - ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); - if (kind == FAST_ELEMENTS) { - int length = IsJSArray() - ? Smi::cast(JSArray::cast(this)->length())->value() - : elements->length(); - if (index < static_cast(length) && - !elements->get(index)->IsTheHole()) { - return true; - } - } else { - if (SeededNumberDictionary::cast(elements)->FindEntry(index) != - SeededNumberDictionary::kNotFound) { - return true; - } - } - return false; -} - - bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { // Check access rights if needed. if (IsAccessCheckNeeded()) { @@ -9175,68 +9095,9 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { return HasElementWithInterceptor(receiver, index); } - ElementsKind kind = GetElementsKind(); - switch (kind) { - case FAST_SMI_ONLY_ELEMENTS: - case FAST_ELEMENTS: { - uint32_t length = IsJSArray() ? - static_cast - (Smi::cast(JSArray::cast(this)->length())->value()) : - static_cast(FixedArray::cast(elements())->length()); - if ((index < length) && - !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; - break; - } - case FAST_DOUBLE_ELEMENTS: { - uint32_t length = IsJSArray() ? - static_cast - (Smi::cast(JSArray::cast(this)->length())->value()) : - static_cast(FixedDoubleArray::cast(elements())->length()); - if ((index < length) && - !FixedDoubleArray::cast(elements())->is_the_hole(index)) return true; - break; - } - case EXTERNAL_PIXEL_ELEMENTS: { - ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); - if (index < static_cast(pixels->length())) { - return true; - } - break; - } - case EXTERNAL_BYTE_ELEMENTS: - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: - case EXTERNAL_SHORT_ELEMENTS: - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: - case EXTERNAL_INT_ELEMENTS: - case EXTERNAL_UNSIGNED_INT_ELEMENTS: - case EXTERNAL_FLOAT_ELEMENTS: - case EXTERNAL_DOUBLE_ELEMENTS: { - ExternalArray* array = ExternalArray::cast(elements()); - if (index < static_cast(array->length())) { - return true; - } - break; - } - case DICTIONARY_ELEMENTS: { - if (element_dictionary()->FindEntry(index) - != SeededNumberDictionary::kNotFound) { - return true; - } - break; - } - case NON_STRICT_ARGUMENTS_ELEMENTS: { - FixedArray* parameter_map = FixedArray::cast(elements()); - uint32_t length = parameter_map->length(); - Object* probe = - (index < length - 2) ? parameter_map->get(index + 2) : NULL; - if (probe != NULL && !probe->IsTheHole()) return true; - - // Not a mapped parameter, check the arguments. - FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); - kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; - if (HasElementInElements(arguments, kind, index)) return true; - break; - } + ElementsAccessor* accessor = GetElementsAccessor(); + if (accessor->HasElement(elements(), index, this, receiver)) { + return true; } // Handle [] on String objects. diff --git a/src/objects.h b/src/objects.h index 2b8888b9e..3b0443cdb 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1752,7 +1752,6 @@ class JSObject: public JSReceiver { LocalElementType HasLocalElement(uint32_t index); bool HasElementWithInterceptor(JSReceiver* receiver, uint32_t index); - bool HasElementPostInterceptor(JSReceiver* receiver, uint32_t index); MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index, Object* value, @@ -2152,9 +2151,6 @@ class JSObject: public JSReceiver { bool ReferencesObjectFromElements(FixedArray* elements, ElementsKind kind, Object* object); - bool HasElementInElements(FixedArray* elements, - ElementsKind kind, - uint32_t index); // Returns true if most of the elements backing storage is used. bool HasDenseElements(); -- 2.34.1