-// 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:
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);
}
}
// 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);
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,
}
virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
- uint32_t index) {
+ uint32_t index) {
return ElementsAccessorSubclass::GetKeyForIndexImpl(
BackingStoreClass::cast(backing_store), index);
}
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);
}
};
// 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;
+ }
};
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);
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();
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
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();
-// 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:
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,
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;
}
-bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) {
- switch (GetElementsKind()) {
- case FAST_SMI_ONLY_ELEMENTS:
- case FAST_ELEMENTS: {
- uint32_t length = IsJSArray() ?
- static_cast<uint32_t>
- (Smi::cast(JSArray::cast(this)->length())->value()) :
- static_cast<uint32_t>(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<uint32_t>
- (Smi::cast(JSArray::cast(this)->length())->value()) :
- static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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
}
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);
}
}
-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<uint32_t>(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()) {
return HasElementWithInterceptor(receiver, index);
}
- ElementsKind kind = GetElementsKind();
- switch (kind) {
- case FAST_SMI_ONLY_ELEMENTS:
- case FAST_ELEMENTS: {
- uint32_t length = IsJSArray() ?
- static_cast<uint32_t>
- (Smi::cast(JSArray::cast(this)->length())->value()) :
- static_cast<uint32_t>(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<uint32_t>
- (Smi::cast(JSArray::cast(this)->length())->value()) :
- static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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.
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,
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();