Commit 8d79ff46 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Clean-up refactoring to eliminate GetLocalElementKind.

Eliminates substantial amounts of fragile code duplication and special casing.

Also fixes "a".propertyIsEnumerable(0) to correctly return true.

R=mstarzinger@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12990 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3d1582c4
......@@ -5033,6 +5033,10 @@ bool JSReceiver::HasLocalProperty(String* name) {
PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
uint32_t index;
if (IsJSObject() && key->AsArrayIndex(&index)) {
return GetElementAttribute(index);
}
return GetPropertyAttributeWithReceiver(this, key);
}
......
......@@ -247,6 +247,18 @@ MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
}
Handle<Object> Object::GetProperty(Handle<Object> object, Handle<String> name) {
// TODO(rossberg): The index test should not be here but in the GetProperty
// method (or somewhere else entirely). Needs more global clean-up.
uint32_t index;
if (name->AsArrayIndex(&index)) return GetElement(object, index);
Isolate* isolate = object->IsHeapObject()
? Handle<HeapObject>::cast(object)->GetIsolate()
: Isolate::Current();
CALL_HEAP_FUNCTION(isolate, object->GetProperty(*name), Object);
}
Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
Isolate* isolate = object->IsHeapObject()
? Handle<HeapObject>::cast(object)->GetIsolate()
......@@ -3334,6 +3346,11 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
return GetElementAttributeWithInterceptor(receiver, index, continue_search);
}
// Handle [] on String objects.
if (this->IsStringObjectWithCharacterAt(index)) {
return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
}
return GetElementAttributeWithoutInterceptor(
receiver, index, continue_search);
}
......@@ -9628,8 +9645,10 @@ AccessorPair* JSObject::GetLocalPropertyAccessorPair(String* name) {
if (name->AsArrayIndex(&index)) {
return GetLocalElementAccessorPair(index);
}
LookupResult lookup(GetIsolate());
LocalLookup(name, &lookup);
LocalLookupRealNamedProperty(name, &lookup);
if (lookup.IsPropertyCallbacks() &&
lookup.GetCallbackObject()->IsAccessorPair()) {
return AccessorPair::cast(lookup.GetCallbackObject());
......@@ -9639,116 +9658,17 @@ AccessorPair* JSObject::GetLocalPropertyAccessorPair(String* name) {
AccessorPair* JSObject::GetLocalElementAccessorPair(uint32_t index) {
return GetElementsAccessor()->GetAccessorPair(this, this, index);
}
JSObject::LocalElementKind JSObject::GetLocalElementKind(uint32_t index) {
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
return UNDEFINED_ELEMENT;
}
}
if (IsJSGlobalProxy()) {
Object* proto = GetPrototype();
if (proto->IsNull()) return UNDEFINED_ELEMENT;
if (proto->IsNull()) return NULL;
ASSERT(proto->IsJSGlobalObject());
return JSObject::cast(proto)->GetLocalElementKind(index);
return JSObject::cast(proto)->GetLocalElementAccessorPair(index);
}
// Check for lookup interceptor
if (HasIndexedInterceptor()) {
return GetElementAttributeWithInterceptor(this, index, false) != ABSENT
? INTERCEPTED_ELEMENT : UNDEFINED_ELEMENT;
}
// Check for lookup interceptor.
if (HasIndexedInterceptor()) return NULL;
// Handle [] on String objects.
if (this->IsStringObjectWithCharacterAt(index)) {
return STRING_CHARACTER_ELEMENT;
}
switch (GetElementsKind()) {
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_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 FAST_ELEMENT;
}
break;
}
case FAST_DOUBLE_ELEMENTS:
case FAST_HOLEY_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 FAST_ELEMENT;
}
break;
}
case EXTERNAL_PIXEL_ELEMENTS: {
ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
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 FAST_ELEMENT;
break;
}
case DICTIONARY_ELEMENTS: {
if (element_dictionary()->FindEntry(index) !=
SeededNumberDictionary::kNotFound) {
return DICTIONARY_ELEMENT;
}
break;
}
case NON_STRICT_ARGUMENTS_ELEMENTS: {
// Aliased parameters and non-aliased elements in a fast backing store
// behave as FAST_ELEMENT. Non-aliased elements in a dictionary
// backing store behave as DICTIONARY_ELEMENT.
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 FAST_ELEMENT;
// If not aliased, check the arguments.
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
if (arguments->IsDictionary()) {
SeededNumberDictionary* dictionary =
SeededNumberDictionary::cast(arguments);
if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) {
return DICTIONARY_ELEMENT;
}
} else {
length = arguments->length();
probe = (index < length) ? arguments->get(index) : NULL;
if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
}
break;
}
}
return UNDEFINED_ELEMENT;
return GetElementsAccessor()->GetAccessorPair(this, this, index);
}
......
......@@ -973,6 +973,7 @@ class Object : public MaybeObject {
String* key,
PropertyAttributes* attributes);
static Handle<Object> GetProperty(Handle<Object> object, Handle<String> key);
static Handle<Object> GetProperty(Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
......@@ -1846,29 +1847,11 @@ class JSObject: public JSReceiver {
PropertyType GetLocalPropertyType(String* name);
PropertyType GetLocalElementType(uint32_t index);
// These methods do not perform access checks!
AccessorPair* GetLocalPropertyAccessorPair(String* name);
AccessorPair* GetLocalElementAccessorPair(uint32_t index);
// Tells whether the index'th element is present and how it is stored.
enum LocalElementKind {
// There is no element with given index.
UNDEFINED_ELEMENT,
// Element with given index is handled by interceptor.
INTERCEPTED_ELEMENT,
// Element with given index is character in string.
STRING_CHARACTER_ELEMENT,
// Element with given index is stored in fast backing store.
FAST_ELEMENT,
// Element with given index is stored in slow backing store.
DICTIONARY_ELEMENT
};
LocalElementKind GetLocalElementKind(uint32_t index);
MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
Object* value,
StrictModeFlag strict_mode,
......
This diff is collapsed.
......@@ -82,7 +82,7 @@ var o = Object("string");
// Non-string property on String object.
o[10] = 42;
assertTrue(o.propertyIsEnumerable(10));
assertFalse(o.propertyIsEnumerable(0));
assertTrue(o.propertyIsEnumerable(0));
// Fast elements.
var o = [1,2,3,4,5];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment