Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index d86951f06cd8134c9bd1a1dceca556bc4245960d..57d239102f5ad28ba32d10c6206de19ea4d0fe1a 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2678,19 +2678,13 @@ MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, |
DeleteMode mode) { |
Heap* heap = GetHeap(); |
ASSERT(!HasExternalArrayElements()); |
+ // We don't have to handle strict mode deletion of non-configurable |
+ // properties. |
+ ASSERT(mode != STRICT_DELETION); |
switch (GetElementsKind()) { |
case FAST_ELEMENTS: { |
- Object* obj; |
- { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
- if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
- } |
- 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())->set_the_hole(index); |
- } |
- break; |
+ FixedArray* elements = FixedArray::cast(this->elements()); |
+ return DeleteFromElements(elements, FAST_ELEMENTS, index, mode); |
} |
case DICTIONARY_ELEMENTS: { |
NumberDictionary* dictionary = element_dictionary(); |
@@ -2752,34 +2746,38 @@ MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
} |
-void JSObject::DeleteFromFastElements(FixedArray* elements, uint32_t index) { |
- ASSERT(elements->map() != elements->GetHeap()->fixed_cow_array_map()); |
- int length = IsJSArray() |
- ? Smi::cast(JSArray::cast(this)->length())->value() |
- : elements->length(); |
- if (index < static_cast<uint32_t>(length)) { |
- elements->set_the_hole(index); |
- } |
-} |
- |
- |
-MaybeObject* JSObject::DeleteFromDictionaryElements(NumberDictionary* elements, |
- uint32_t index, |
- DeleteMode mode) { |
+MaybeObject* JSObject::DeleteFromElements(FixedArray* elements, |
+ ElementsKind kind, |
+ uint32_t index, |
+ DeleteMode mode) { |
+ ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); |
Isolate* isolate = GetIsolate(); |
- int entry = elements->FindEntry(index); |
- if (entry != NumberDictionary::kNotFound) { |
- Object* result = elements->DeleteProperty(entry, mode); |
- if (mode == STRICT_DELETION && result == isolate->heap()->false_value()) { |
- // In strict mode, attempting to delete a non-configurable property |
- // throws an exception. |
- HandleScope scope(isolate); |
- Handle<Object> name = isolate->factory()->NewNumberFromUint(index); |
- Handle<Object> args[2] = { name, Handle<Object>(this) }; |
- Handle<Object> error = |
- isolate->factory()->NewTypeError("strict_delete_property", |
- HandleVector(args, 2)); |
- return isolate->Throw(*error); |
+ if (kind == FAST_ELEMENTS) { |
+ Object* object; |
+ MaybeObject* maybe_object = EnsureWritableFastElements(); |
+ if (!maybe_object->ToObject(&object)) return maybe_object; |
+ int length = IsJSArray() |
+ ? Smi::cast(JSArray::cast(this)->length())->value() |
+ : elements->length(); |
+ if (index < static_cast<uint32_t>(length)) { |
+ elements->set_the_hole(index); |
+ } |
+ } else { |
+ NumberDictionary* dictionary = NumberDictionary::cast(elements); |
+ int entry = dictionary->FindEntry(index); |
+ if (entry != NumberDictionary::kNotFound) { |
+ Object* result = dictionary->DeleteProperty(entry, mode); |
+ if (mode == STRICT_DELETION && result == isolate->heap()->false_value()) { |
+ // In strict mode, attempting to delete a non-configurable property |
+ // throws an exception. |
+ HandleScope scope(isolate); |
+ Handle<Object> name = isolate->factory()->NewNumberFromUint(index); |
+ Handle<Object> args[2] = { name, Handle<Object>(this) }; |
+ Handle<Object> error = |
+ isolate->factory()->NewTypeError("strict_delete_property", |
+ HandleVector(args, 2)); |
+ return isolate->Throw(*error); |
+ } |
} |
} |
return isolate->heap()->true_value(); |
@@ -2804,20 +2802,17 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
if (HasIndexedInterceptor()) { |
// Skip interceptor if forcing deletion. |
- if (mode == FORCE_DELETION) { |
- return DeleteElementPostInterceptor(index, mode); |
- } |
- return DeleteElementWithInterceptor(index); |
+ return (mode == FORCE_DELETION) |
+ ? DeleteElementPostInterceptor(index, FORCE_DELETION) |
+ : DeleteElementWithInterceptor(index); |
} |
- switch (GetElementsKind()) { |
- case FAST_ELEMENTS: { |
- Object* obj; |
- { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
- if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
- } |
- DeleteFromFastElements(FixedArray::cast(elements()), index); |
- break; |
+ ElementsKind kind = GetElementsKind(); |
+ switch (kind) { |
+ case FAST_ELEMENTS: |
+ case DICTIONARY_ELEMENTS: { |
+ FixedArray* elements = FixedArray::cast(this->elements()); |
+ return DeleteFromElements(elements, kind, index, mode); |
} |
case EXTERNAL_PIXEL_ELEMENTS: |
@@ -2832,28 +2827,20 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
// silently ignore here. |
break; |
- case DICTIONARY_ELEMENTS: |
- return DeleteFromDictionaryElements(element_dictionary(), index, mode); |
- |
case NON_STRICT_ARGUMENTS_ELEMENTS: { |
FixedArray* parameter_map = FixedArray::cast(elements()); |
uint32_t length = parameter_map->length(); |
Object* probe = |
(index + 2) < length ? parameter_map->get(index + 2) : NULL; |
- if (probe != NULL && !probe->IsTheHole()) { |
- // TODO(kmillikin): We could check if this was the last aliased |
- // parameter, and revert to normal elements in that case. That |
- // would enable GC of the context. |
- parameter_map->set_the_hole(index + 2); |
- } else { |
+ if (probe == NULL || probe->IsTheHole()) { |
FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
- if (arguments->IsDictionary()) { |
- NumberDictionary* dictionary = NumberDictionary::cast(arguments); |
- return DeleteFromDictionaryElements(dictionary, index, mode); |
- } else { |
- DeleteFromFastElements(arguments, index); |
- } |
+ kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
+ return DeleteFromElements(arguments, kind, index, mode); |
} |
+ // TODO(kmillikin): We could check if this was the last aliased |
+ // parameter, and revert to normal elements in that case. That |
+ // would enable GC of the context. |
+ parameter_map->set_the_hole(index + 2); |
break; |
} |
} |
@@ -2918,6 +2905,26 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
} |
+bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
+ ElementsKind kind, |
+ Object* object) { |
+ ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); |
+ if (kind == FAST_ELEMENTS) { |
+ int length = IsJSArray() |
+ ? Smi::cast(JSArray::cast(this)->length())->value() |
+ : elements->length(); |
+ for (int i = 0; i < length; ++i) { |
+ Object* element = elements->get(i); |
+ if (!element->IsTheHole() && element == object) return true; |
+ } |
+ } else { |
+ Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); |
+ if (!key->IsUndefined()) return true; |
+ } |
+ return false; |
+} |
+ |
+ |
// Check whether this object references another object. |
bool JSObject::ReferencesObject(Object* obj) { |
Heap* heap = GetHeap(); |
@@ -2940,7 +2947,8 @@ bool JSObject::ReferencesObject(Object* obj) { |
} |
// Check if the object is among the indexed properties. |
- switch (GetElementsKind()) { |
+ ElementsKind kind = GetElementsKind(); |
+ switch (kind) { |
case EXTERNAL_PIXEL_ELEMENTS: |
case EXTERNAL_BYTE_ELEMENTS: |
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
@@ -2952,23 +2960,10 @@ bool JSObject::ReferencesObject(Object* obj) { |
// Raw pixels and external arrays do not reference other |
// objects. |
break; |
- case FAST_ELEMENTS: { |
- int length = IsJSArray() ? |
- Smi::cast(JSArray::cast(this)->length())->value() : |
- FixedArray::cast(elements())->length(); |
- for (int i = 0; i < length; i++) { |
- Object* element = FixedArray::cast(elements())->get(i); |
- if (!element->IsTheHole() && element == obj) { |
- return true; |
- } |
- } |
- break; |
- } |
+ case FAST_ELEMENTS: |
case DICTIONARY_ELEMENTS: { |
- key = element_dictionary()->SlowReverseLookup(obj); |
- if (!key->IsUndefined()) { |
- return true; |
- } |
+ FixedArray* elements = FixedArray::cast(this->elements()); |
+ if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
break; |
} |
case NON_STRICT_ARGUMENTS_ELEMENTS: { |
@@ -2981,17 +2976,8 @@ bool JSObject::ReferencesObject(Object* obj) { |
} |
// Check the arguments. |
FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
- if (arguments->IsDictionary()) { |
- NumberDictionary* dictionary = NumberDictionary::cast(arguments); |
- key = dictionary->SlowReverseLookup(obj); |
- if (key != heap->undefined_value()) return true; |
- } else { |
- int count = arguments->length(); |
- for (int i = 0; i < count; ++i) { |
- Object* value = arguments->get(i); |
- if (!value->IsTheHole() && value == obj) return true; |
- } |
- } |
+ kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
+ if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
break; |
} |
} |
@@ -7139,6 +7125,28 @@ 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<uint32_t>(length) && |
+ !elements->get(index)->IsTheHole()) { |
+ return true; |
+ } |
+ } else { |
+ if (NumberDictionary::cast(elements)->FindEntry(index) != |
+ NumberDictionary::kNotFound) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
Heap* heap = GetHeap(); |
@@ -7154,14 +7162,12 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
return HasElementWithInterceptor(receiver, index); |
} |
- switch (GetElementsKind()) { |
- 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; |
+ ElementsKind kind = GetElementsKind(); |
+ switch (kind) { |
+ case FAST_ELEMENTS: |
+ case DICTIONARY_ELEMENTS: { |
+ FixedArray* elements = FixedArray::cast(this->elements()); |
+ if (HasElementInElements(elements, kind, index)) return true; |
break; |
} |
case EXTERNAL_PIXEL_ELEMENTS: { |
@@ -7184,13 +7190,6 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
} |
break; |
} |
- case DICTIONARY_ELEMENTS: { |
- if (element_dictionary()->FindEntry(index) |
- != NumberDictionary::kNotFound) { |
- return true; |
- } |
- break; |
- } |
case NON_STRICT_ARGUMENTS_ELEMENTS: { |
FixedArray* parameter_map = FixedArray::cast(elements()); |
uint32_t length = parameter_map->length(); |
@@ -7200,15 +7199,8 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
// Not a mapped parameter, check the arguments. |
FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
- if (arguments->IsDictionary()) { |
- if (NumberDictionary::cast(arguments)->FindEntry(index) != |
- NumberDictionary::kNotFound) { |
- return true; |
- } |
- } else if (index < static_cast<uint32_t>(arguments->length()) && |
- !arguments->get(index)->IsTheHole()) { |
- return true; |
- } |
+ kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
+ if (HasElementInElements(arguments, kind, index)) return true; |
break; |
} |
} |