Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(595)

Unified Diff: src/objects.cc

Issue 7172030: Revert "Merge arguments branch to bleeding merge." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 7a833b6c614dd88246687abc41be7340d3c1700a..6185e2dcf049484646a37600c1f944222e18b4b9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1897,7 +1897,7 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
pt != heap->null_value();
pt = pt->GetPrototype()) {
if (!JSObject::cast(pt)->HasDictionaryElements()) {
- continue;
+ continue;
}
NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
int entry = dictionary->FindEntry(index);
@@ -2804,31 +2804,29 @@ MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
MaybeObject* JSObject::NormalizeElements() {
ASSERT(!HasExternalArrayElements());
+ if (HasDictionaryElements()) return this;
+ Map* old_map = map();
+ ASSERT(old_map->has_fast_elements() || old_map->has_fast_double_elements());
- // Find the backing store.
- FixedArray* array = FixedArray::cast(elements());
- Map* old_map = array->map();
- bool is_arguments =
- (old_map == old_map->heap()->non_strict_arguments_elements_map());
- if (is_arguments) {
- array = FixedArray::cast(array->get(1));
- }
- if (array->IsDictionary()) return array;
-
- ASSERT(HasFastElements() || HasFastArgumentsElements());
- // Compute the effective length and allocate a new backing store.
- int length = IsJSArray()
- ? Smi::cast(JSArray::cast(this)->length())->value()
- : array->length();
- NumberDictionary* dictionary = NULL;
- { Object* object;
- MaybeObject* maybe = NumberDictionary::Allocate(length);
- if (!maybe->ToObject(&object)) return maybe;
- dictionary = NumberDictionary::cast(object);
- }
-
- // Copy the elements to the new backing store.
+ Object* obj;
+ { MaybeObject* maybe_obj = old_map->GetSlowElementsMap();
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+ Map* new_map = Map::cast(obj);
+
+ // Get number of entries.
+ FixedArrayBase* array = FixedArrayBase::cast(elements());
+
+ // Compute the effective length.
+ int length = IsJSArray() ?
+ Smi::cast(JSArray::cast(this)->length())->value() :
+ array->length();
+ { MaybeObject* maybe_obj = NumberDictionary::Allocate(length);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
bool has_double_elements = old_map->has_fast_double_elements();
+ NumberDictionary* dictionary = NumberDictionary::cast(obj);
+ // Copy entries.
for (int i = 0; i < length; i++) {
Object* value = NULL;
if (has_double_elements) {
@@ -2846,7 +2844,8 @@ MaybeObject* JSObject::NormalizeElements() {
}
} else {
ASSERT(old_map->has_fast_elements());
- value = array->get(i);
+ FixedArray* fixed_array = FixedArray::cast(array);
+ value = fixed_array->get(i);
}
PropertyDetails details = PropertyDetails(NONE, NORMAL);
if (!value->IsTheHole()) {
@@ -2857,21 +2856,14 @@ MaybeObject* JSObject::NormalizeElements() {
dictionary = NumberDictionary::cast(result);
}
}
+ // Switch to using the dictionary as the backing storage for
+ // elements. Set the new map first to satify the elements type
+ // assert in set_elements().
+ set_map(new_map);
+ set_elements(dictionary);
- // Switch to using the dictionary as the backing storage for elements.
- if (is_arguments) {
- FixedArray::cast(elements())->set(1, dictionary);
- } else {
- // Set the new map first to satify the elements type assert in
- // set_elements().
- Object* new_map;
- MaybeObject* maybe = map()->GetSlowElementsMap();
- if (!maybe->ToObject(&new_map)) return maybe;
- set_map(Map::cast(new_map));
- set_elements(dictionary);
- }
-
- old_map->isolate()->counters()->elements_to_dictionary()->Increment();
+ new_map->heap()->isolate()->counters()->elements_to_dictionary()->
+ Increment();
#ifdef DEBUG
if (FLAG_trace_normalization) {
@@ -2880,8 +2872,7 @@ MaybeObject* JSObject::NormalizeElements() {
}
#endif
- ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
- return dictionary;
+ return this;
}
@@ -3001,56 +2992,6 @@ MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
}
-MaybeObject* JSObject::DeleteFastElement(uint32_t index) {
- ASSERT(HasFastElements() || HasFastArgumentsElements());
- Heap* heap = GetHeap();
- FixedArray* backing_store = FixedArray::cast(elements());
- if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
- backing_store = FixedArray::cast(backing_store->get(1));
- } else {
- Object* writable;
- MaybeObject* maybe = EnsureWritableFastElements();
- if (!maybe->ToObject(&writable)) return maybe;
- backing_store = FixedArray::cast(writable);
- }
- int length = IsJSArray()
- ? Smi::cast(JSArray::cast(this)->length())->value()
- : backing_store->length();
- if (index < static_cast<uint32_t>(length)) {
- backing_store->set_the_hole(index);
- }
- return heap->true_value();
-}
-
-
-MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index,
- DeleteMode mode) {
- Isolate* isolate = GetIsolate();
- Heap* heap = isolate->heap();
- FixedArray* backing_store = FixedArray::cast(elements());
- if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
- backing_store = FixedArray::cast(backing_store->get(1));
- }
- NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
- int entry = dictionary->FindEntry(index);
- if (entry != NumberDictionary::kNotFound) {
- Object* result = dictionary->DeleteProperty(entry, mode);
- if (mode == STRICT_DELETION && result == 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 heap->true_value();
-}
-
-
MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
Isolate* isolate = GetIsolate();
// Check access rights if needed.
@@ -3069,18 +3010,26 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
if (HasIndexedInterceptor()) {
// Skip interceptor if forcing deletion.
- return (mode == FORCE_DELETION)
- ? DeleteElementPostInterceptor(index, FORCE_DELETION)
- : DeleteElementWithInterceptor(index);
+ if (mode == FORCE_DELETION) {
+ return DeleteElementPostInterceptor(index, mode);
+ }
+ return DeleteElementWithInterceptor(index);
}
switch (GetElementsKind()) {
- case FAST_ELEMENTS:
- return DeleteFastElement(index);
-
- case DICTIONARY_ELEMENTS:
- return DeleteDictionaryElement(index, mode);
-
+ case FAST_ELEMENTS: {
+ Object* obj;
+ { MaybeObject* maybe_obj = EnsureWritableFastElements();
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+ int length = IsJSArray()
+ ? Smi::cast(JSArray::cast(this)->length())->value()
+ : FixedArray::cast(elements())->length();
+ if (index < static_cast<uint32_t>(length)) {
+ FixedArray::cast(elements())->set_the_hole(index);
+ }
+ break;
+ }
case FAST_DOUBLE_ELEMENTS: {
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
@@ -3102,27 +3051,29 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
// Pixel and external array elements cannot be deleted. Just
// silently ignore here.
break;
-
- 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 {
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- return DeleteDictionaryElement(index, mode);
- } else {
- return DeleteFastElement(index);
+ case DICTIONARY_ELEMENTS: {
+ NumberDictionary* dictionary = element_dictionary();
+ 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, deleting a non-configurable property throws
+ // exception. dictionary->DeleteProperty will return false_value()
+ // if a non-configurable property is being deleted.
+ HandleScope scope;
+ Handle<Object> self(this);
+ Handle<Object> i = isolate->factory()->NewNumberFromUint(index);
+ Handle<Object> args[2] = { i, self };
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_delete_property", HandleVector(args, 2)));
}
}
break;
}
+ default:
+ UNREACHABLE();
+ break;
}
return isolate->heap()->true_value();
}
@@ -3185,26 +3136,6 @@ 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) {
Map* map_of_this = map();
@@ -3228,8 +3159,7 @@ bool JSObject::ReferencesObject(Object* obj) {
}
// Check if the object is among the indexed properties.
- ElementsKind kind = GetElementsKind();
- switch (kind) {
+ switch (GetElementsKind()) {
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
@@ -3239,30 +3169,31 @@ bool JSObject::ReferencesObject(Object* obj) {
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
// Raw pixels and external arrays do not reference other
// objects.
break;
- case FAST_ELEMENTS:
- case DICTIONARY_ELEMENTS: {
- FixedArray* elements = FixedArray::cast(this->elements());
- if (ReferencesObjectFromElements(elements, kind, obj)) return true;
+ 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 NON_STRICT_ARGUMENTS_ELEMENTS: {
- FixedArray* parameter_map = FixedArray::cast(elements());
- // Check the mapped parameters.
- int length = parameter_map->length();
- for (int i = 2; i < length; ++i) {
- Object* value = parameter_map->get(i);
- if (!value->IsTheHole() && value == obj) return true;
- }
- // Check the arguments.
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
- if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
+ case DICTIONARY_ELEMENTS: {
+ key = element_dictionary()->SlowReverseLookup(obj);
+ if (!key->IsUndefined()) {
+ return true;
+ }
break;
}
+ default:
+ UNREACHABLE();
+ break;
}
// For functions check the context.
@@ -3297,9 +3228,9 @@ bool JSObject::ReferencesObject(Object* obj) {
}
}
- // Check the context extension if any.
- if (context->has_extension()) {
- return context->extension()->ReferencesObject(obj);
+ // Check the context extension (if any) if it can have references.
+ if (context->has_extension() && !context->IsCatchContext()) {
+ return JSObject::cast(context->extension())->ReferencesObject(obj);
}
}
@@ -3327,11 +3258,11 @@ MaybeObject* JSObject::PreventExtensions() {
// If there are fast elements we normalize.
if (HasFastElements()) {
- MaybeObject* result = NormalizeElements();
- if (result->IsFailure()) return result;
+ Object* ok;
+ { MaybeObject* maybe_ok = NormalizeElements();
+ if (!maybe_ok->ToObject(&ok)) return maybe_ok;
+ }
}
- // TODO(kmillikin): Handle arguments object with dictionary elements.
- ASSERT(HasDictionaryElements());
// Make sure that we never go back to fast case.
element_dictionary()->set_requires_slow_elements();
@@ -3488,24 +3419,6 @@ void JSObject::LookupCallback(String* name, LookupResult* result) {
}
-// Search for a getter or setter in an elements dictionary. Returns either
-// undefined if the element is read-only, or the getter/setter pair (fixed
-// array) if there is an existing one, or the hole value if the element does
-// not exist or is a normal non-getter/setter data element.
-static Object* FindGetterSetterInDictionary(NumberDictionary* dictionary,
- uint32_t index,
- Heap* heap) {
- int entry = dictionary->FindEntry(index);
- if (entry != NumberDictionary::kNotFound) {
- Object* result = dictionary->ValueAt(entry);
- PropertyDetails details = dictionary->DetailsAt(entry);
- if (details.IsReadOnly()) return heap->undefined_value();
- if (details.type() == CALLBACKS && result->IsFixedArray()) return result;
- }
- return heap->the_hole_value();
-}
-
-
MaybeObject* JSObject::DefineGetterSetter(String* name,
PropertyAttributes attributes) {
Heap* heap = GetHeap();
@@ -3536,35 +3449,29 @@ MaybeObject* JSObject::DefineGetterSetter(String* name,
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
// Ignore getters and setters on pixel and external array
// elements.
return heap->undefined_value();
case DICTIONARY_ELEMENTS: {
- Object* probe =
- FindGetterSetterInDictionary(element_dictionary(), index, heap);
- if (!probe->IsTheHole()) return probe;
- // Otherwise allow to override it.
- break;
- }
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
- // Ascertain whether we have read-only properties or an existing
- // getter/setter pair in an arguments elements dictionary backing
- // store.
- 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()) {
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- NumberDictionary* dictionary = NumberDictionary::cast(arguments);
- probe = FindGetterSetterInDictionary(dictionary, index, heap);
- if (!probe->IsTheHole()) return probe;
+ // Lookup the index.
+ NumberDictionary* dictionary = element_dictionary();
+ int entry = dictionary->FindEntry(index);
+ if (entry != NumberDictionary::kNotFound) {
+ Object* result = dictionary->ValueAt(entry);
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ if (details.IsReadOnly()) return heap->undefined_value();
+ if (details.type() == CALLBACKS) {
+ if (result->IsFixedArray()) {
+ return result;
+ }
+ // Otherwise allow to override it.
}
}
break;
}
+ default:
+ UNREACHABLE();
+ break;
}
} else {
// Lookup the name.
@@ -3627,39 +3534,23 @@ MaybeObject* JSObject::SetElementCallback(uint32_t index,
PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
// Normalize elements to make this operation simple.
- NumberDictionary* dictionary = NULL;
- { Object* result;
- MaybeObject* maybe = NormalizeElements();
- if (!maybe->ToObject(&result)) return maybe;
- dictionary = NumberDictionary::cast(result);
+ Object* ok;
+ { MaybeObject* maybe_ok = NormalizeElements();
+ if (!maybe_ok->ToObject(&ok)) return maybe_ok;
}
- ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
// Update the dictionary with the new CALLBACKS property.
- { Object* result;
- MaybeObject* maybe = dictionary->Set(index, structure, details);
- if (!maybe->ToObject(&result)) return maybe;
- dictionary = NumberDictionary::cast(result);
- }
-
- dictionary->set_requires_slow_elements();
- // Update the dictionary backing store on the object.
- if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
- // Also delete any parameter alias.
- //
- // TODO(kmillikin): when deleting the last parameter alias we could
- // switch to a direct backing store without the parameter map. This
- // would allow GC of the context.
- FixedArray* parameter_map = FixedArray::cast(elements());
- uint32_t length = parameter_map->length();
- if (index + 2 < length) {
- parameter_map->set(index + 2, GetHeap()->the_hole_value());
- }
- parameter_map->set(1, dictionary);
- } else {
- set_elements(dictionary);
+ Object* dict;
+ { MaybeObject* maybe_dict =
+ element_dictionary()->Set(index, structure, details);
+ if (!maybe_dict->ToObject(&dict)) return maybe_dict;
}
+ NumberDictionary* elements = NumberDictionary::cast(dict);
+ elements->set_requires_slow_elements();
+ // Set the potential new dictionary on the object.
+ set_elements(elements);
+
return structure;
}
@@ -3785,14 +3676,13 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
// Ignore getters and setters on pixel and external array
// elements.
return isolate->heap()->undefined_value();
case DICTIONARY_ELEMENTS:
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
+ default:
+ UNREACHABLE();
break;
}
@@ -4579,20 +4469,8 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
// Compute the union of this and the temporary fixed array.
return UnionOfKeys(key_array);
}
- case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
- break;
- case JSObject::EXTERNAL_BYTE_ELEMENTS:
- case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- case JSObject::EXTERNAL_SHORT_ELEMENTS:
- case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- case JSObject::EXTERNAL_INT_ELEMENTS:
- case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
- case JSObject::EXTERNAL_FLOAT_ELEMENTS:
- case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
- case JSObject::EXTERNAL_PIXEL_ELEMENTS:
- case JSObject::FAST_DOUBLE_ELEMENTS:
- break;
+ default:
+ UNREACHABLE();
}
UNREACHABLE();
return GetHeap()->null_value(); // Failure case needs to "return" a value.
@@ -7178,7 +7056,6 @@ void Code::Disassemble(const char* name, FILE* out) {
Disassembler::Decode(out, this);
PrintF(out, "\n");
-#ifdef DEBUG
if (kind() == FUNCTION) {
DeoptimizationOutputData* data =
DeoptimizationOutputData::cast(this->deoptimization_data());
@@ -7189,7 +7066,6 @@ void Code::Disassemble(const char* name, FILE* out) {
data->DeoptimizationInputDataPrint(out);
}
PrintF("\n");
-#endif
if (kind() == OPTIMIZED_FUNCTION) {
SafepointTable table(this);
@@ -7236,80 +7112,33 @@ void Code::Disassemble(const char* name, FILE* out) {
#endif // ENABLE_DISASSEMBLER
-static void CopyFastElementsToFast(FixedArray* source,
- FixedArray* destination,
- WriteBarrierMode mode) {
- uint32_t count = static_cast<uint32_t>(source->length());
- for (uint32_t i = 0; i < count; ++i) {
- destination->set(i, source->get(i), mode);
- }
-}
-
-
-static void CopySlowElementsToFast(NumberDictionary* source,
- FixedArray* destination,
- WriteBarrierMode mode) {
- for (int i = 0; i < source->Capacity(); ++i) {
- Object* key = source->KeyAt(i);
- if (key->IsNumber()) {
- uint32_t entry = static_cast<uint32_t>(key->Number());
- destination->set(entry, source->ValueAt(i), mode);
- }
- }
-}
-
-
MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
int length) {
Heap* heap = GetHeap();
// We should never end in here with a pixel or external array.
ASSERT(!HasExternalArrayElements());
- // Allocate a new fast elements backing store.
- FixedArray* new_elements = NULL;
- { Object* object;
- MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
- if (!maybe->ToObject(&object)) return maybe;
- new_elements = FixedArray::cast(object);
+ Object* obj;
+ { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
+ FixedArray* elems = FixedArray::cast(obj);
- // Find the new map to use for this object if there is a map change.
- Map* new_map = NULL;
- if (elements()->map() != heap->non_strict_arguments_elements_map()) {
- Object* object;
- MaybeObject* maybe = map()->GetFastElementsMap();
- if (!maybe->ToObject(&object)) return maybe;
- new_map = Map::cast(object);
+ { MaybeObject* maybe_obj = map()->GetFastElementsMap();
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
+ Map* new_map = Map::cast(obj);
- AssertNoAllocation no_gc;
- WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
switch (GetElementsKind()) {
- case FAST_ELEMENTS:
- CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
- set_map(new_map);
- set_elements(new_elements);
- break;
- case DICTIONARY_ELEMENTS:
- CopySlowElementsToFast(NumberDictionary::cast(elements()),
- new_elements,
- mode);
- set_map(new_map);
- set_elements(new_elements);
- break;
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
- // The object's map and the parameter map are unchanged, the unaliased
- // arguments are copied to the new backing store.
- FixedArray* parameter_map = FixedArray::cast(elements());
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- CopySlowElementsToFast(NumberDictionary::cast(arguments),
- new_elements,
- mode);
- } else {
- CopyFastElementsToFast(arguments, new_elements, mode);
+ case FAST_ELEMENTS: {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
+ FixedArray* old_elements = FixedArray::cast(elements());
+ uint32_t old_length = static_cast<uint32_t>(old_elements->length());
+ // Fill out the new array with this content and array holes.
+ for (uint32_t i = 0; i < old_length; i++) {
+ elems->set(i, old_elements->get(i), mode);
}
- parameter_map->set(1, new_elements);
break;
}
case FAST_DOUBLE_ELEMENTS: {
@@ -7330,30 +7159,37 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
// elems->GetWriteBarrierMode(), since it requires an
// AssertNoAllocation stack object that would have to be positioned
// after the HeapNumber allocation anyway.
- new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
+ elems->set(i, obj, UPDATE_WRITE_BARRIER);
}
}
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:
- case EXTERNAL_PIXEL_ELEMENTS:
+ case DICTIONARY_ELEMENTS: {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
+ NumberDictionary* dictionary = NumberDictionary::cast(elements());
+ for (int i = 0; i < dictionary->Capacity(); i++) {
+ Object* key = dictionary->KeyAt(i);
+ if (key->IsNumber()) {
+ uint32_t entry = static_cast<uint32_t>(key->Number());
+ elems->set(entry, dictionary->ValueAt(i), mode);
+ }
+ }
+ break;
+ }
+ default:
UNREACHABLE();
break;
}
- // Update the length if necessary.
+ set_map(new_map);
+ set_elements(elems);
+
if (IsJSArray()) {
JSArray::cast(this)->set_length(Smi::FromInt(length));
}
- return new_elements;
+ return this;
}
@@ -7417,8 +7253,10 @@ MaybeObject* JSObject::SetSlowElements(Object* len) {
// Make sure we never try to shrink dense arrays into sparse arrays.
ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
new_length);
- MaybeObject* result = NormalizeElements();
- if (result->IsFailure()) return result;
+ Object* obj;
+ { MaybeObject* maybe_obj = NormalizeElements();
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
// Update length for JSArrays.
if (IsJSArray()) JSArray::cast(this)->set_length(len);
@@ -7433,19 +7271,7 @@ MaybeObject* JSObject::SetSlowElements(Object* len) {
}
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
- 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:
- case EXTERNAL_PIXEL_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
+ default:
UNREACHABLE();
break;
}
@@ -7525,9 +7351,11 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
int new_capacity = value > min ? value : min;
if (new_capacity <= kMaxFastElementsLength ||
!ShouldConvertToSlowElements(new_capacity)) {
- MaybeObject* result =
- SetFastElementsCapacityAndLength(new_capacity, value);
- if (result->IsFailure()) return result;
+ Object* obj;
+ { MaybeObject* maybe_obj =
+ SetFastElementsCapacityAndLength(new_capacity, value);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
return this;
}
break;
@@ -7552,17 +7380,7 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
}
return this;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- 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:
- case EXTERNAL_PIXEL_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
+ default:
UNREACHABLE();
break;
}
@@ -7759,8 +7577,7 @@ bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) {
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
- case EXTERNAL_DOUBLE_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS: {
+ case EXTERNAL_DOUBLE_ELEMENTS: {
ExternalArray* array = ExternalArray::cast(elements());
if (index < static_cast<uint32_t>(array->length())) {
return true;
@@ -7774,7 +7591,7 @@ bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) {
}
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ default:
UNREACHABLE();
break;
}
@@ -7888,67 +7705,22 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
break;
}
- case FAST_DOUBLE_ELEMENTS:
- UNREACHABLE();
- break;
case DICTIONARY_ELEMENTS: {
if (element_dictionary()->FindEntry(index) !=
- NumberDictionary::kNotFound) {
+ NumberDictionary::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 + 2) < length ? 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()) {
- NumberDictionary* dictionary = NumberDictionary::cast(arguments);
- if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) {
- return DICTIONARY_ELEMENT;
- }
- } else {
- length = arguments->length();
- probe = (index < length) ? arguments->get(index) : NULL;
- if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
- }
+ default:
+ UNREACHABLE();
break;
- }
}
return UNDEFINED_ELEMENT;
}
-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(JSReceiver* receiver, uint32_t index) {
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
@@ -7964,8 +7736,7 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
return HasElementWithInterceptor(receiver, index);
}
- ElementsKind kind = GetElementsKind();
- switch (kind) {
+ switch (GetElementsKind()) {
case FAST_ELEMENTS: {
uint32_t length = IsJSArray() ?
static_cast<uint32_t>
@@ -7996,9 +7767,6 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
}
break;
}
- case FAST_DOUBLE_ELEMENTS:
- UNREACHABLE();
- break;
case DICTIONARY_ELEMENTS: {
if (element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound) {
@@ -8006,19 +7774,9 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
}
break;
}
- 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()) 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;
+ default:
+ UNREACHABLE();
break;
- }
}
// Handle [] on String objects.
@@ -8084,7 +7842,7 @@ MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
Handle<JSObject> self(JSObject::cast(receiver));
Handle<JSObject> holder_handle(JSObject::cast(holder));
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
- Handle<String> key = isolate->factory()->NumberToString(number);
+ Handle<String> key(isolate->factory()->NumberToString(number));
LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
CustomArguments args(isolate, data->data(), *self, *holder_handle);
v8::AccessorInfo info(args.end());
@@ -8179,30 +7937,6 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure,
}
-bool JSObject::HasFastArgumentsElements() {
- Heap* heap = GetHeap();
- if (!elements()->IsFixedArray()) return false;
- FixedArray* elements = FixedArray::cast(this->elements());
- if (elements->map() != heap->non_strict_arguments_elements_map()) {
- return false;
- }
- FixedArray* arguments = FixedArray::cast(elements->get(1));
- return !arguments->IsDictionary();
-}
-
-
-bool JSObject::HasDictionaryArgumentsElements() {
- Heap* heap = GetHeap();
- if (!elements()->IsFixedArray()) return false;
- FixedArray* elements = FixedArray::cast(this->elements());
- if (elements->map() != heap->non_strict_arguments_elements_map()) {
- return false;
- }
- FixedArray* arguments = FixedArray::cast(elements->get(1));
- return arguments->IsDictionary();
-}
-
-
// Adding n elements in fast case is O(n*n).
// Note: revisit design to have dual undefined values to capture absent
// elements.
@@ -8210,21 +7944,17 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
Object* value,
StrictModeFlag strict_mode,
bool check_prototype) {
- ASSERT(HasFastElements() || HasFastArgumentsElements());
+ ASSERT(HasFastElements());
- FixedArray* backing_store = FixedArray::cast(elements());
- if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
- backing_store = FixedArray::cast(backing_store->get(1));
- } else {
- Object* writable;
- MaybeObject* maybe = EnsureWritableFastElements();
- if (!maybe->ToObject(&writable)) return maybe;
- backing_store = FixedArray::cast(writable);
+ Object* elms_obj;
+ { MaybeObject* maybe_elms_obj = EnsureWritableFastElements();
+ if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
- uint32_t length = static_cast<uint32_t>(backing_store->length());
+ FixedArray* elms = FixedArray::cast(elms_obj);
+ uint32_t elms_length = static_cast<uint32_t>(elms->length());
if (check_prototype &&
- (index >= length || backing_store->get(index)->IsTheHole())) {
+ (index >= elms_length || elms->get(index)->IsTheHole())) {
bool found;
MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
value,
@@ -8234,8 +7964,8 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
}
// Check whether there is extra space in fixed array..
- if (index < length) {
- backing_store->set(index, value);
+ if (index < elms_length) {
+ elms->set(index, value);
if (IsJSArray()) {
// Update the length of the array if needed.
uint32_t array_length = 0;
@@ -8248,129 +7978,29 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
}
// Allow gap in fast case.
- if ((index - length) < kMaxGap) {
+ if ((index - elms_length) < kMaxGap) {
// Try allocating extra space.
- int new_capacity = NewElementsCapacity(index + 1);
+ int new_capacity = NewElementsCapacity(index+1);
if (new_capacity <= kMaxFastElementsLength ||
!ShouldConvertToSlowElements(new_capacity)) {
ASSERT(static_cast<uint32_t>(new_capacity) > index);
- Object* new_elements;
- MaybeObject* maybe =
- SetFastElementsCapacityAndLength(new_capacity, index + 1);
- if (!maybe->ToObject(&new_elements)) return maybe;
- FixedArray::cast(new_elements)->set(index, value);
+ Object* obj;
+ { MaybeObject* maybe_obj =
+ SetFastElementsCapacityAndLength(new_capacity, index + 1);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+ FixedArray::cast(elements())->set(index, value);
return value;
}
}
// Otherwise default to slow case.
- MaybeObject* result = NormalizeElements();
- if (result->IsFailure()) return result;
- return SetDictionaryElement(index, value, strict_mode, check_prototype);
-}
-
-
-MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
- Object* value,
- StrictModeFlag strict_mode,
- bool check_prototype) {
- ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
- Isolate* isolate = GetIsolate();
- Heap* heap = isolate->heap();
-
- // Insert element in the dictionary.
- FixedArray* elements = FixedArray::cast(this->elements());
- bool is_arguments =
- (elements->map() == heap->non_strict_arguments_elements_map());
- NumberDictionary* dictionary = NULL;
- if (is_arguments) {
- dictionary = NumberDictionary::cast(elements->get(1));
- } else {
- dictionary = NumberDictionary::cast(elements);
- }
-
- int entry = dictionary->FindEntry(index);
- if (entry != NumberDictionary::kNotFound) {
- Object* element = dictionary->ValueAt(entry);
- PropertyDetails details = dictionary->DetailsAt(entry);
- if (details.type() == CALLBACKS) {
- return SetElementWithCallback(element, index, value, this, strict_mode);
- } else {
- dictionary->UpdateMaxNumberKey(index);
- // If put fails in strict mode, throw an exception.
- if (!dictionary->ValueAtPut(entry, value) && strict_mode == kStrictMode) {
- Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
- Handle<Object> holder(this);
- Handle<Object> args[2] = { number, holder };
- Handle<Object> error =
- isolate->factory()->NewTypeError("strict_read_only_property",
- HandleVector(args, 2));
- return isolate->Throw(*error);
- }
- }
- } else {
- // Index not already used. Look for an accessor in the prototype chain.
- if (check_prototype) {
- bool found;
- MaybeObject* result =
- SetElementWithCallbackSetterInPrototypes(
- index, value, &found, strict_mode);
- if (found) return result;
- }
- // When we set the is_extensible flag to false we always force the
- // element into dictionary mode (and force them to stay there).
- if (!map()->is_extensible()) {
- if (strict_mode == kNonStrictMode) {
- return isolate->heap()->undefined_value();
- } else {
- Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
- Handle<String> name = isolate->factory()->NumberToString(number);
- Handle<Object> args[1] = { name };
- Handle<Object> error =
- isolate->factory()->NewTypeError("object_not_extensible",
- HandleVector(args, 1));
- return isolate->Throw(*error);
- }
- }
- Object* new_dictionary;
- MaybeObject* maybe = dictionary->AtNumberPut(index, value);
- if (!maybe->ToObject(&new_dictionary)) return maybe;
- if (dictionary != NumberDictionary::cast(new_dictionary)) {
- if (is_arguments) {
- elements->set(1, new_dictionary);
- } else {
- set_elements(HeapObject::cast(new_dictionary));
- }
- dictionary = NumberDictionary::cast(new_dictionary);
- }
- }
-
- // Update the array length if this JSObject is an array.
- if (IsJSArray()) {
- MaybeObject* result =
- JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
- if (result->IsFailure()) return result;
- }
-
- // Attempt to put this object back in fast case.
- if (ShouldConvertToFastElements()) {
- uint32_t new_length = 0;
- if (IsJSArray()) {
- CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
- } else {
- new_length = dictionary->max_number_key() + 1;
- }
- MaybeObject* result =
- SetFastElementsCapacityAndLength(new_length, new_length);
- if (result->IsFailure()) return result;
-#ifdef DEBUG
- if (FLAG_trace_normalization) {
- PrintF("Object elements are fast case again:\n");
- Print();
- }
-#endif
+ Object* obj;
+ { MaybeObject* maybe_obj = NormalizeElements();
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
- return value;
+ ASSERT(HasDictionaryElements());
+ return SetElement(index, value, strict_mode, check_prototype);
}
@@ -8504,6 +8134,7 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
Isolate* isolate = GetIsolate();
switch (GetElementsKind()) {
case FAST_ELEMENTS:
+ // Fast case.
return SetFastElement(index, value, strict_mode, check_prototype);
case FAST_DOUBLE_ELEMENTS:
return SetFastDoubleElement(index, value, strict_mode, check_prototype);
@@ -8546,29 +8177,118 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
return array->SetValue(index, value);
}
- case DICTIONARY_ELEMENTS:
- return SetDictionaryElement(index, value, strict_mode, check_prototype);
- 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()) {
- Context* context = Context::cast(parameter_map->get(0));
- int context_index = Smi::cast(probe)->value();
- ASSERT(!context->get(context_index)->IsTheHole());
- context->set(context_index, value);
- return value;
+ case DICTIONARY_ELEMENTS: {
+ // Insert element in the dictionary.
+ FixedArray* elms = FixedArray::cast(elements());
+ NumberDictionary* dictionary = NumberDictionary::cast(elms);
+
+ int entry = dictionary->FindEntry(index);
+ if (entry != NumberDictionary::kNotFound) {
+ Object* element = dictionary->ValueAt(entry);
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ if (details.type() == CALLBACKS) {
+ return SetElementWithCallback(element,
+ index,
+ value,
+ this,
+ strict_mode);
+ } else {
+ dictionary->UpdateMaxNumberKey(index);
+ // If put fails instrict mode, throw exception.
+ if (!dictionary->ValueAtPut(entry, value) &&
+ strict_mode == kStrictMode) {
+ Handle<Object> holder(this);
+ Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
+ Handle<Object> args[2] = { number, holder };
+ return isolate->Throw(
+ *isolate->factory()->NewTypeError("strict_read_only_property",
+ HandleVector(args, 2)));
+ }
+ }
} else {
- // Object is not mapped, defer to the arguments.
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- return SetDictionaryElement(index, value, strict_mode,
- check_prototype);
+ // Index not already used. Look for an accessor in the prototype chain.
+ if (check_prototype) {
+ bool found;
+ MaybeObject* result =
+ // Strict mode not needed. No-setter case already handled.
+ SetElementWithCallbackSetterInPrototypes(index,
+ value,
+ &found,
+ strict_mode);
+ if (found) return result;
+ }
+ // When we set the is_extensible flag to false we always force
+ // the element into dictionary mode (and force them to stay there).
+ if (!map()->is_extensible()) {
+ if (strict_mode == kNonStrictMode) {
+ return isolate->heap()->undefined_value();
+ } else {
+ Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
+ Handle<String> index_string(
+ isolate->factory()->NumberToString(number));
+ Handle<Object> args[1] = { index_string };
+ return isolate->Throw(
+ *isolate->factory()->NewTypeError("object_not_extensible",
+ HandleVector(args, 1)));
+ }
+ }
+ Object* result;
+ { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ if (elms != FixedArray::cast(result)) {
+ set_elements(FixedArray::cast(result));
+ }
+ }
+
+ // Update the array length if this JSObject is an array.
+ if (IsJSArray()) {
+ JSArray* array = JSArray::cast(this);
+ Object* return_value;
+ { MaybeObject* maybe_return_value =
+ array->JSArrayUpdateLengthFromIndex(index, value);
+ if (!maybe_return_value->ToObject(&return_value)) {
+ return maybe_return_value;
+ }
+ }
+ }
+
+ // Attempt to put this object back in fast case.
+ if (ShouldConvertToFastElements()) {
+ uint32_t new_length = 0;
+ if (IsJSArray()) {
+ CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
} else {
- return SetFastElement(index, value, strict_mode, check_prototype);
+ new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
+ }
+ if (ShouldConvertToFastDoubleElements()) {
+ Object* obj;
+ { MaybeObject* maybe_obj =
+ SetFastDoubleElementsCapacityAndLength(new_length, new_length);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+#ifdef DEBUG
+ if (FLAG_trace_normalization) {
+ PrintF("Object elements are fast double case again:\n");
+ Print();
+ }
+#endif
+ } else {
+ Object* obj;
+ { MaybeObject* maybe_obj =
+ SetFastElementsCapacityAndLength(new_length, new_length);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+#ifdef DEBUG
+ if (FLAG_trace_normalization) {
+ PrintF("Object elements are fast case again:\n");
+ Print();
+ }
+#endif
}
}
+
+ return value;
}
}
// All possible cases have been handled above. Add a return to avoid the
@@ -8649,8 +8369,8 @@ MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver,
}
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
+ default:
+ UNREACHABLE();
break;
}
@@ -8762,40 +8482,6 @@ MaybeObject* JSObject::GetElementWithReceiver(Object* receiver,
}
break;
}
- 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()) {
- Context* context = Context::cast(parameter_map->get(0));
- int context_index = Smi::cast(probe)->value();
- ASSERT(!context->get(context_index)->IsTheHole());
- return context->get(context_index);
- } else {
- // Object is not mapped, defer to the arguments.
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- NumberDictionary* dictionary = NumberDictionary::cast(arguments);
- int entry = dictionary->FindEntry(index);
- if (entry != NumberDictionary::kNotFound) {
- Object* element = dictionary->ValueAt(entry);
- PropertyDetails details = dictionary->DetailsAt(entry);
- if (details.type() == CALLBACKS) {
- return GetElementWithCallback(receiver,
- element,
- index,
- this);
- }
- return element;
- }
- } else if (index < static_cast<uint32_t>(arguments->length())) {
- Object* value = arguments->get(index);
- if (!value->IsTheHole()) return value;
- }
- }
- break;
- }
}
Object* pt = GetPrototype();
@@ -8889,9 +8575,6 @@ MaybeObject* JSObject::GetExternalElement(uint32_t index) {
case DICTIONARY_ELEMENTS:
UNREACHABLE();
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
- break;
}
return GetHeap()->undefined_value();
}
@@ -8901,28 +8584,14 @@ bool JSObject::HasDenseElements() {
int capacity = 0;
int number_of_elements = 0;
- FixedArray* backing_store = FixedArray::cast(elements());
switch (GetElementsKind()) {
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- backing_store = FixedArray::cast(backing_store->get(1));
- if (backing_store->IsDictionary()) {
- NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
- capacity = dictionary->Capacity();
- number_of_elements = dictionary->NumberOfElements();
- break;
- }
- // Fall through.
- case FAST_ELEMENTS:
- capacity = backing_store->length();
- for (int i = 0; i < capacity; ++i) {
- if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
+ case FAST_ELEMENTS: {
+ FixedArray* elms = FixedArray::cast(elements());
+ capacity = elms->length();
+ for (int i = 0; i < capacity; i++) {
+ if (!elms->get(i)->IsTheHole()) number_of_elements++;
}
break;
- case DICTIONARY_ELEMENTS: {
- NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
- capacity = dictionary->Capacity();
- number_of_elements = dictionary->NumberOfElements();
- break;
}
case FAST_DOUBLE_ELEMENTS: {
FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
@@ -8943,8 +8612,19 @@ bool JSObject::HasDenseElements() {
case EXTERNAL_DOUBLE_ELEMENTS: {
return true;
}
+ case DICTIONARY_ELEMENTS: {
+ NumberDictionary* dictionary = NumberDictionary::cast(elements());
+ capacity = dictionary->Capacity();
+ number_of_elements = dictionary->NumberOfElements();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
}
- return (capacity == 0) || (number_of_elements > (capacity / 2));
+
+ if (capacity == 0) return true;
+ return (number_of_elements > (capacity / 2));
}
@@ -8953,10 +8633,7 @@ bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
// almost filled and if the new capacity is no more than twice the
// old capacity.
int elements_length = 0;
- if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
- FixedArray* backing_store = FixedArray::cast(elements());
- elements_length = FixedArray::cast(backing_store->get(1))->length();
- } else if (HasFastElements()) {
+ if (HasFastElements()) {
elements_length = FixedArray::cast(elements())->length();
} else if (HasFastDoubleElements()) {
elements_length = FixedDoubleArray::cast(elements())->length();
@@ -8968,23 +8645,16 @@ bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
bool JSObject::ShouldConvertToFastElements() {
- ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
+ ASSERT(HasDictionaryElements());
+ NumberDictionary* dictionary = NumberDictionary::cast(elements());
// If the elements are sparse, we should not go back to fast case.
if (!HasDenseElements()) return false;
- // An object requiring access checks is never allowed to have fast
- // elements. If it had fast elements we would skip security checks.
- if (IsAccessCheckNeeded()) return false;
-
- FixedArray* elements = FixedArray::cast(this->elements());
- NumberDictionary* dictionary = NULL;
- if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
- dictionary = NumberDictionary::cast(elements->get(1));
- } else {
- dictionary = NumberDictionary::cast(elements);
- }
// If an element has been added at a very high index in the elements
// dictionary, we cannot go back to fast case.
if (dictionary->requires_slow_elements()) return false;
+ // An object requiring access checks is never allowed to have fast
+ // elements. If it had fast elements we would skip security checks.
+ if (IsAccessCheckNeeded()) return false;
// If the dictionary backing storage takes up roughly half as much
// space as a fast-case backing storage would the array should have
// fast elements.
@@ -9204,15 +8874,12 @@ bool JSObject::HasRealElementProperty(uint32_t index) {
ExternalArray* array = ExternalArray::cast(elements());
return index < static_cast<uint32_t>(array->length());
}
- case FAST_DOUBLE_ELEMENTS:
- UNREACHABLE();
- break;
case DICTIONARY_ELEMENTS: {
return element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
+ default:
+ UNREACHABLE();
break;
}
// All possibilities have been handled above already.
@@ -9456,41 +9123,16 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
ASSERT(!storage || storage->length() >= counter);
break;
}
- case FAST_DOUBLE_ELEMENTS:
- UNREACHABLE();
- break;
case DICTIONARY_ELEMENTS: {
if (storage != NULL) {
element_dictionary()->CopyKeysTo(storage, filter);
}
- counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
+ counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
- FixedArray* parameter_map = FixedArray::cast(elements());
- int length = parameter_map->length();
- for (int i = 2; i < length; ++i) {
- if (!parameter_map->get(i)->IsTheHole()) {
- if (storage != NULL) storage->set(i - 2, Smi::FromInt(i - 2));
- ++counter;
- }
- }
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- NumberDictionary* dictionary = NumberDictionary::cast(arguments);
- if (storage != NULL) dictionary->CopyKeysTo(storage, filter);
- counter += dictionary->NumberOfElementsFilterAttributes(filter);
- } else {
- int length = arguments->length();
- for (int i = 0; i < length; ++i) {
- if (!arguments->get(i)->IsTheHole()) {
- if (storage != NULL) storage->set(i, Smi::FromInt(i));
- ++counter;
- }
- }
- }
+ default:
+ UNREACHABLE();
break;
- }
}
if (this->IsJSValue()) {
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698