Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/elements.cc b/src/elements.cc
index 6c257ac..d7e49cd 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -189,7 +189,7 @@
int entry = from->FindEntry(i + from_start);
if (entry != SeededNumberDictionary::kNotFound) {
Object* value = from->ValueAt(entry);
- DCHECK(!value->IsTheHole());
+ DCHECK(!value->IsTheHole(from->GetIsolate()));
to->set(i + to_start, value, write_barrier_mode);
} else {
to->set_the_hole(i + to_start);
@@ -352,7 +352,7 @@
for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size);
from_start < from_end; from_start++, to_start++) {
Object* smi = from->get(from_start);
- DCHECK(!smi->IsTheHole());
+ DCHECK(!smi->IsTheHole(from->GetIsolate()));
to->set(to_start, Smi::cast(smi)->value());
}
}
@@ -445,6 +445,28 @@
JavaScriptFrame::PrintTop(isolate, stdout, false, true);
}
+static void SortIndices(
+ Handle<FixedArray> indices, uint32_t sort_size,
+ WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER) {
+ struct {
+ bool operator()(Object* a, Object* b) {
+ if (a->IsSmi() || !a->IsUndefined(HeapObject::cast(a)->GetIsolate())) {
+ if (!b->IsSmi() && b->IsUndefined(HeapObject::cast(b)->GetIsolate())) {
+ return true;
+ }
+ return a->Number() < b->Number();
+ }
+ return !b->IsSmi() && b->IsUndefined(HeapObject::cast(b)->GetIsolate());
+ }
+ } cmp;
+ Object** start =
+ reinterpret_cast<Object**>(indices->GetFirstElementAddress());
+ std::sort(start, start + sort_size, cmp);
+ if (write_barrier_mode != SKIP_WRITE_BARRIER) {
+ FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(indices->GetIsolate()->heap(), *indices,
+ 0, sort_size);
+ }
+}
// Base class for element handler implementations. Contains the
// the common logic for objects with different ElementsKinds.
@@ -709,8 +731,7 @@
JSObject::ValidateElements(array);
}
- static uint32_t GetIterationLength(JSObject* receiver,
- FixedArrayBase* elements) {
+ static uint32_t GetMaxIndex(JSObject* receiver, FixedArrayBase* elements) {
if (receiver->IsJSArray()) {
DCHECK(JSArray::cast(receiver)->length()->IsSmi());
return static_cast<uint32_t>(
@@ -719,6 +740,11 @@
return Subclass::GetCapacityImpl(receiver, elements);
}
+ static uint32_t GetMaxNumberOfEntries(JSObject* receiver,
+ FixedArrayBase* elements) {
+ return Subclass::GetMaxIndex(receiver, elements);
+ }
+
static Handle<FixedArrayBase> ConvertElementsWithCapacity(
Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
ElementsKind from_kind, uint32_t capacity) {
@@ -862,8 +888,8 @@
Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
PropertyFilter filter) {
int count = 0;
- KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES);
- accumulator.NextPrototype();
+ KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
+ ALL_PROPERTIES);
Subclass::CollectElementIndicesImpl(
object, handle(object->elements(), isolate), &accumulator);
Handle<FixedArray> keys = accumulator.GetKeys();
@@ -909,11 +935,12 @@
KeyAccumulator* keys) {
DCHECK_NE(DICTIONARY_ELEMENTS, kind());
// Non-dictionary elements can't have all-can-read accessors.
- uint32_t length = GetIterationLength(*object, *backing_store);
+ uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
PropertyFilter filter = keys->filter();
+ Factory* factory = keys->isolate()->factory();
for (uint32_t i = 0; i < length; i++) {
if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
- keys->AddKey(i);
+ keys->AddKey(factory->NewNumberFromUint(i));
}
}
}
@@ -923,10 +950,10 @@
Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
uint32_t insertion_index = 0) {
- uint32_t length = Subclass::GetIterationLength(*object, *backing_store);
+ uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
for (uint32_t i = 0; i < length; i++) {
if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
- if (convert == CONVERT_TO_STRING) {
+ if (convert == GetKeysConversion::kConvertToString) {
Handle<String> index_string = isolate->factory()->Uint32ToString(i);
list->set(insertion_index, *index_string);
} else {
@@ -968,22 +995,11 @@
// Sort the indices list if necessary.
if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) {
- struct {
- bool operator()(Object* a, Object* b) {
- if (!a->IsUndefined()) {
- if (b->IsUndefined()) return true;
- return a->Number() < b->Number();
- }
- return !b->IsUndefined();
- }
- } cmp;
- Object** start =
- reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress());
- std::sort(start, start + nof_indices, cmp);
+ SortIndices(combined_keys, nof_indices, SKIP_WRITE_BARRIER);
uint32_t array_length = 0;
// Indices from dictionary elements should only be converted after
// sorting.
- if (convert == CONVERT_TO_STRING) {
+ if (convert == GetKeysConversion::kConvertToString) {
for (uint32_t i = 0; i < nof_indices; i++) {
Handle<Object> index_string = isolate->factory()->Uint32ToString(
combined_keys->get(i)->Number());
@@ -1044,7 +1060,7 @@
? index
: kMaxUInt32;
} else {
- uint32_t length = GetIterationLength(holder, backing_store);
+ uint32_t length = Subclass::GetMaxIndex(holder, backing_store);
return index < length ? index : kMaxUInt32;
}
}
@@ -1081,17 +1097,15 @@
: ElementsAccessorBase<DictionaryElementsAccessor,
ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
- static uint32_t GetIterationLength(JSObject* receiver,
- FixedArrayBase* elements) {
- uint32_t length;
- if (receiver->IsJSArray()) {
- // Special-case GetIterationLength for dictionary elements since the
- // length of the array might be a HeapNumber.
- JSArray::cast(receiver)->length()->ToArrayLength(&length);
- } else {
- length = GetCapacityImpl(receiver, elements);
- }
- return length;
+ static uint32_t GetMaxIndex(JSObject* receiver, FixedArrayBase* elements) {
+ // We cannot properly estimate this for dictionaries.
+ UNREACHABLE();
+ }
+
+ static uint32_t GetMaxNumberOfEntries(JSObject* receiver,
+ FixedArrayBase* backing_store) {
+ SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
+ return dict->NumberOfElements();
}
static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
@@ -1162,7 +1176,7 @@
uint32_t index = GetIndexForEntryImpl(*dict, entry);
Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry);
USE(result);
- DCHECK(result->IsTrue());
+ DCHECK(result->IsTrue(dict->GetIsolate()));
Handle<FixedArray> new_elements =
SeededNumberDictionary::Shrink(dict, index);
obj->set_elements(*new_elements);
@@ -1174,12 +1188,10 @@
SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
if (!dict->requires_slow_elements()) return false;
int capacity = dict->Capacity();
- Heap* heap = holder->GetHeap();
- Object* undefined = heap->undefined_value();
- Object* the_hole = heap->the_hole_value();
+ Isolate* isolate = dict->GetIsolate();
for (int i = 0; i < capacity; i++) {
Object* key = dict->KeyAt(i);
- if (key == the_hole || key == undefined) continue;
+ if (!dict->IsKey(isolate, key)) continue;
DCHECK(!dict->IsDeleted(i));
PropertyDetails details = dict->DetailsAt(i);
if (details.type() == ACCESSOR_CONSTANT) return true;
@@ -1244,7 +1256,7 @@
DisallowHeapAllocation no_gc;
SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
Object* index = dict->KeyAt(entry);
- return !index->IsTheHole();
+ return !index->IsTheHole(dict->GetIsolate());
}
static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) {
@@ -1289,23 +1301,12 @@
return static_cast<uint32_t>(raw_key->Number());
}
- static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
+ static uint32_t GetKeyForEntryImpl(Isolate* isolate,
+ Handle<SeededNumberDictionary> dictionary,
int entry, PropertyFilter filter) {
DisallowHeapAllocation no_gc;
Object* raw_key = dictionary->KeyAt(entry);
- if (!dictionary->IsKey(raw_key)) return kMaxUInt32;
- return FilterKey(dictionary, entry, raw_key, filter);
- }
-
- static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
- int entry, PropertyFilter filter,
- Object* undefined, Object* the_hole) {
- DisallowHeapAllocation no_gc;
- Object* raw_key = dictionary->KeyAt(entry);
- // Replace the IsKey check with a direct comparison which is much faster.
- if (raw_key == undefined || raw_key == the_hole) {
- return kMaxUInt32;
- }
+ if (!dictionary->IsKey(isolate, raw_key)) return kMaxUInt32;
return FilterKey(dictionary, entry, raw_key, filter);
}
@@ -1314,20 +1315,24 @@
KeyAccumulator* keys) {
if (keys->filter() & SKIP_STRINGS) return;
Isolate* isolate = keys->isolate();
- Handle<Object> undefined = isolate->factory()->undefined_value();
- Handle<Object> the_hole = isolate->factory()->the_hole_value();
Handle<SeededNumberDictionary> dictionary =
Handle<SeededNumberDictionary>::cast(backing_store);
int capacity = dictionary->Capacity();
+ Handle<FixedArray> elements = isolate->factory()->NewFixedArray(
+ GetMaxNumberOfEntries(*object, *backing_store));
+ int insertion_index = 0;
PropertyFilter filter = keys->filter();
for (int i = 0; i < capacity; i++) {
- uint32_t key =
- GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
+ uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
if (key == kMaxUInt32) continue;
- keys->AddKey(key);
+ Handle<Object> key_handle = isolate->factory()->NewNumberFromUint(key);
+ elements->set(insertion_index, *key_handle);
+ insertion_index++;
}
-
- keys->SortCurrentElementsList();
+ SortIndices(elements, insertion_index);
+ for (int i = 0; i < insertion_index; i++) {
+ keys->AddKey(elements->get(i));
+ }
}
static Handle<FixedArray> DirectCollectElementIndicesImpl(
@@ -1338,14 +1343,11 @@
if (filter & SKIP_STRINGS) return list;
if (filter & ONLY_ALL_CAN_READ) return list;
- Handle<Object> undefined = isolate->factory()->undefined_value();
- Handle<Object> the_hole = isolate->factory()->the_hole_value();
Handle<SeededNumberDictionary> dictionary =
Handle<SeededNumberDictionary>::cast(backing_store);
uint32_t capacity = dictionary->Capacity();
for (uint32_t i = 0; i < capacity; i++) {
- uint32_t key =
- GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
+ uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
if (key == kMaxUInt32) continue;
Handle<Object> index = isolate->factory()->NewNumberFromUint(key);
list->set(insertion_index, *index);
@@ -1370,7 +1372,7 @@
if (k == *the_hole) continue;
if (dictionary->IsDeleted(i)) continue;
Object* value = dictionary->ValueAt(i);
- DCHECK(!value->IsTheHole());
+ DCHECK(!value->IsTheHole(isolate));
DCHECK(!value->IsAccessorPair());
DCHECK(!value->IsAccessorInfo());
accumulator->AddKey(value, convert);
@@ -1552,8 +1554,8 @@
KeyAccumulator* accumulator,
AddKeyConversion convert) {
Handle<FixedArrayBase> elements(receiver->elements(),
- receiver->GetIsolate());
- uint32_t length = Subclass::GetIterationLength(*receiver, *elements);
+ accumulator->isolate());
+ uint32_t length = Subclass::GetMaxNumberOfEntries(*receiver, *elements);
for (uint32_t i = 0; i < length; i++) {
if (IsFastPackedElementsKind(KindTraits::Kind) ||
HasEntryImpl(*elements, i)) {
@@ -1801,7 +1803,7 @@
}
Subclass::SetLengthImpl(isolate, receiver, new_length, backing_store);
- if (IsHoleyElementsKind(kind) && result->IsTheHole()) {
+ if (IsHoleyElementsKind(kind) && result->IsTheHole(isolate)) {
return isolate->factory()->undefined_value();
}
return result;
@@ -1853,7 +1855,7 @@
WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc);
for (uint32_t i = 0; i < copy_size; i++) {
Object* argument = (*args)[src_index + i];
- DCHECK(!argument->IsTheHole());
+ DCHECK(!argument->IsTheHole(raw_backing_store->GetIsolate()));
Subclass::SetImpl(raw_backing_store, dst_index + i, argument, mode);
}
}
@@ -2230,7 +2232,7 @@
Object* probe = parameter_map->get(entry + 2);
Context* context = Context::cast(parameter_map->get(0));
int context_entry = Smi::cast(probe)->value();
- DCHECK(!context->get(context_entry)->IsTheHole());
+ DCHECK(!context->get(context_entry)->IsTheHole(isolate));
return handle(context->get(context_entry), isolate);
} else {
// Object is not mapped, defer to the arguments.
@@ -2242,7 +2244,7 @@
AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(*result);
Context* context = Context::cast(parameter_map->get(0));
int context_entry = alias->aliased_context_slot();
- DCHECK(!context->get(context_entry)->IsTheHole());
+ DCHECK(!context->get(context_entry)->IsTheHole(isolate));
return handle(context->get(context_entry), isolate);
}
return result;
@@ -2267,7 +2269,7 @@
Object* probe = parameter_map->get(entry + 2);
Context* context = Context::cast(parameter_map->get(0));
int context_entry = Smi::cast(probe)->value();
- DCHECK(!context->get(context_entry)->IsTheHole());
+ DCHECK(!context->get(context_entry)->IsTheHole(store->GetIsolate()));
context->set(context_entry, value);
} else {
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
@@ -2276,7 +2278,7 @@
AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(current);
Context* context = Context::cast(parameter_map->get(0));
int context_entry = alias->aliased_context_slot();
- DCHECK(!context->get(context_entry)->IsTheHole());
+ DCHECK(!context->get(context_entry)->IsTheHole(store->GetIsolate()));
context->set(context_entry, value);
} else {
ArgumentsAccessor::SetImpl(arguments, entry - length, value);
@@ -2315,7 +2317,8 @@
FixedArray* parameter_map = FixedArray::cast(parameters);
uint32_t length = parameter_map->length() - 2;
if (entry < length) {
- return !GetParameterMapArg(parameter_map, entry)->IsTheHole();
+ return !GetParameterMapArg(parameter_map, entry)
+ ->IsTheHole(parameter_map->GetIsolate());
}
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
@@ -2344,7 +2347,7 @@
uint32_t index, PropertyFilter filter) {
FixedArray* parameter_map = FixedArray::cast(parameters);
Object* probe = GetParameterMapArg(parameter_map, index);
- if (!probe->IsTheHole()) return index;
+ if (!probe->IsTheHole(holder->GetIsolate())) return index;
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments,
@@ -2386,18 +2389,16 @@
static void CollectElementIndicesImpl(Handle<JSObject> object,
Handle<FixedArrayBase> backing_store,
KeyAccumulator* keys) {
- FixedArray* parameter_map = FixedArray::cast(*backing_store);
- uint32_t length = parameter_map->length() - 2;
- for (uint32_t i = 0; i < length; ++i) {
- if (!parameter_map->get(i + 2)->IsTheHole()) {
- keys->AddKey(i);
- }
- }
-
- Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
- ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys);
- if (Subclass::kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
- keys->SortCurrentElementsList();
+ Isolate* isolate = keys->isolate();
+ uint32_t nof_indices = 0;
+ Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
+ GetCapacityImpl(*object, *backing_store));
+ DirectCollectElementIndicesImpl(isolate, object, backing_store,
+ GetKeysConversion::kKeepNumbers,
+ ENUMERABLE_STRINGS, indices, &nof_indices);
+ SortIndices(indices, nof_indices);
+ for (uint32_t i = 0; i < nof_indices; i++) {
+ keys->AddKey(indices->get(i));
}
}
@@ -2410,8 +2411,8 @@
uint32_t length = parameter_map->length() - 2;
for (uint32_t i = 0; i < length; ++i) {
- if (parameter_map->get(i + 2)->IsTheHole()) continue;
- if (convert == CONVERT_TO_STRING) {
+ if (parameter_map->get(i + 2)->IsTheHole(isolate)) continue;
+ if (convert == GetKeysConversion::kConvertToString) {
Handle<String> index_string = isolate->factory()->Uint32ToString(i);
list->set(insertion_index, *index_string);
} else {
@@ -2446,7 +2447,7 @@
uint32_t index = GetIndexForEntryImpl(*dict, entry);
Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry);
USE(result);
- DCHECK(result->IsTrue());
+ DCHECK(result->IsTrue(dict->GetIsolate()));
Handle<FixedArray> new_elements =
SeededNumberDictionary::Shrink(dict, index);
parameter_map->set(1, *new_elements);
@@ -2479,25 +2480,25 @@
PropertyAttributes attributes) {
Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
uint32_t length = parameter_map->length() - 2;
+ Isolate* isolate = store->GetIsolate();
if (entry < length) {
Object* probe = parameter_map->get(entry + 2);
- DCHECK(!probe->IsTheHole());
+ DCHECK(!probe->IsTheHole(isolate));
Context* context = Context::cast(parameter_map->get(0));
int context_entry = Smi::cast(probe)->value();
- DCHECK(!context->get(context_entry)->IsTheHole());
+ DCHECK(!context->get(context_entry)->IsTheHole(isolate));
context->set(context_entry, *value);
// Redefining attributes of an aliased element destroys fast aliasing.
parameter_map->set_the_hole(entry + 2);
// For elements that are still writable we re-establish slow aliasing.
if ((attributes & READ_ONLY) == 0) {
- Isolate* isolate = store->GetIsolate();
value = isolate->factory()->NewAliasedArgumentsEntry(context_entry);
}
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
Handle<SeededNumberDictionary> arguments(
- SeededNumberDictionary::cast(parameter_map->get(1)));
+ SeededNumberDictionary::cast(parameter_map->get(1)), isolate);
arguments = SeededNumberDictionary::AddNumberEntry(
arguments, entry, value, details, object->map()->is_prototype_map());
// If the attributes were NONE, we would have called set rather than
@@ -2507,7 +2508,7 @@
parameter_map->set(1, *arguments);
} else {
Handle<FixedArrayBase> arguments(
- FixedArrayBase::cast(parameter_map->get(1)));
+ FixedArrayBase::cast(parameter_map->get(1)), isolate);
DictionaryElementsAccessor::ReconfigureImpl(
object, arguments, entry - length, value, attributes);
}
@@ -2745,8 +2746,9 @@
Handle<FixedArrayBase> backing_store,
KeyAccumulator* keys) {
uint32_t length = GetString(*object)->length();
+ Factory* factory = keys->isolate()->factory();
for (uint32_t i = 0; i < length; i++) {
- keys->AddKey(i);
+ keys->AddKey(factory->NewNumberFromUint(i));
}
BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store,
keys);