Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ Handle<Map> map(isolate()->native_context()->generator_result_map());
// Allocate and populate an object with this form: { value: VAL, done: DONE }
// in runtime.js:
// var $Array = global.Array;
+var ARRAY_ITERATOR_KIND_KEYS = 1;
+var ARRAY_ITERATOR_KIND_VALUES = 2;
+var ARRAY_ITERATOR_KIND_ENTRIES = 3;
+// The spec draft also has "sparse" but it is never used.
+
var arrayIteratorObjectSymbol = GLOBAL_PRIVATE("ArrayIterator#object");
var arrayIteratorNextIndexSymbol = GLOBAL_PRIVATE("ArrayIterator#next");
var arrayIterationKindSymbol = GLOBAL_PRIVATE("ArrayIterator#kind");
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);
- if (itemKind == ITERATOR_KIND_VALUES)
+ if (itemKind == ARRAY_ITERATOR_KIND_VALUES)
return CreateIteratorResultObject(array[index], false);
- if (itemKind == ITERATOR_KIND_ENTRIES)
+ if (itemKind == ARRAY_ITERATOR_KIND_ENTRIES)
return CreateIteratorResultObject([index, array[index]], false);
return CreateIteratorResultObject(index, false);
}
function ArrayEntries() {
- return CreateArrayIterator(this, ITERATOR_KIND_ENTRIES);
+ return CreateArrayIterator(this, ARRAY_ITERATOR_KIND_ENTRIES);
}
function ArrayValues() {
- return CreateArrayIterator(this, ITERATOR_KIND_VALUES);
+ return CreateArrayIterator(this, ARRAY_ITERATOR_KIND_VALUES);
}
function ArrayKeys() {
- return CreateArrayIterator(this, ITERATOR_KIND_KEYS);
+ return CreateArrayIterator(this, ARRAY_ITERATOR_KIND_KEYS);
}
function SetUpArrayIterator() {
isolate()->initial_object_prototype(),
Builtins::kIllegal, true, true);
}
- { // -- S e t I t e r a t o r
- Handle<Map> map = isolate()->factory()->NewMap(
- JS_SET_ITERATOR_TYPE, JSSetIterator::kSize);
- native_context()->set_set_iterator_map(*map);
- }
- { // -- M a p I t e r a t o r
- Handle<Map> map = isolate()->factory()->NewMap(
- JS_MAP_ITERATOR_TYPE, JSMapIterator::kSize);
- native_context()->set_map_iterator_map(*map);
- }
}
if (FLAG_harmony_weak_collections) {
*generator_object_prototype);
native_context()->set_generator_object_prototype_map(
*generator_object_prototype_map);
- }
-
- if (FLAG_harmony_collections || FLAG_harmony_generators) {
- // Collection forEach uses an iterator result object.
- // Generators return iteraror result objects.
- STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2);
- Handle<JSFunction> object_function(native_context()->object_function());
+ // Create a map for generator result objects.
ASSERT(object_function->initial_map()->inobject_properties() == 0);
- Handle<Map> iterator_result_map = Map::Create(
+ STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2);
+ Handle<Map> generator_result_map = Map::Create(
object_function, JSGeneratorObject::kResultPropertyCount);
- ASSERT(iterator_result_map->inobject_properties() ==
+ ASSERT(generator_result_map->inobject_properties() ==
JSGeneratorObject::kResultPropertyCount);
Map::EnsureDescriptorSlack(
- iterator_result_map, JSGeneratorObject::kResultPropertyCount);
+ generator_result_map, JSGeneratorObject::kResultPropertyCount);
- FieldDescriptor value_descr(isolate()->factory()->value_string(),
+ Handle<String> value_string = factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("value"));
+ FieldDescriptor value_descr(value_string,
JSGeneratorObject::kResultValuePropertyIndex,
NONE,
Representation::Tagged());
- iterator_result_map->AppendDescriptor(&value_descr);
+ generator_result_map->AppendDescriptor(&value_descr);
- FieldDescriptor done_descr(isolate()->factory()->done_string(),
+ Handle<String> done_string = factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("done"));
+ FieldDescriptor done_descr(done_string,
JSGeneratorObject::kResultDonePropertyIndex,
NONE,
Representation::Tagged());
- iterator_result_map->AppendDescriptor(&done_descr);
+ generator_result_map->AppendDescriptor(&done_descr);
- iterator_result_map->set_unused_property_fields(0);
+ generator_result_map->set_unused_property_fields(0);
ASSERT_EQ(JSGeneratorObject::kResultSize,
- iterator_result_map->instance_size());
- native_context()->set_iterator_result_map(*iterator_result_map);
+ generator_result_map->instance_size());
+ native_context()->set_generator_result_map(*generator_result_map);
}
}
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.clear', this]);
}
- %SetClear(this);
-}
-
-
-function SetForEach(f, receiver) {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.forEach', this]);
- }
-
- if (!IS_SPEC_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [f]);
- }
-
- var iterator = %SetCreateIterator(this, ITERATOR_KIND_VALUES);
- var entry;
- try {
- while (!(entry = %SetIteratorNext(iterator)).done) {
- %_CallFunction(receiver, entry.value, entry.value, this, f);
- }
- } finally {
- %SetIteratorClose(iterator);
- }
+ // Replace the internal table with a new empty table.
+ %SetInitialize(this);
}
%FunctionSetPrototype($Set, new $Object());
%SetProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
- %FunctionSetLength(SetForEach, 1);
-
// Set up the non-enumerable functions on the Set prototype object.
InstallGetter($Set.prototype, "size", SetGetSize);
InstallFunctions($Set.prototype, DONT_ENUM, $Array(
"add", SetAdd,
"has", SetHas,
"delete", SetDelete,
- "clear", SetClear,
- "forEach", SetForEach
+ "clear", SetClear
));
}
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.clear', this]);
}
- %MapClear(this);
-}
-
-
-function MapForEach(f, receiver) {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.forEach', this]);
- }
-
- if (!IS_SPEC_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [f]);
- }
-
- var iterator = %MapCreateIterator(this, ITERATOR_KIND_ENTRIES);
- var entry;
- try {
- while (!(entry = %MapIteratorNext(iterator)).done) {
- %_CallFunction(receiver, entry.value[1], entry.value[0], this, f);
- }
- } finally {
- %MapIteratorClose(iterator);
- }
+ // Replace the internal table with a new empty table.
+ %MapInitialize(this);
}
%FunctionSetPrototype($Map, new $Object());
%SetProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
- %FunctionSetLength(MapForEach, 1);
-
// Set up the non-enumerable functions on the Map prototype object.
InstallGetter($Map.prototype, "size", MapGetSize);
InstallFunctions($Map.prototype, DONT_ENUM, $Array(
"set", MapSet,
"has", MapHas,
"delete", MapDelete,
- "clear", MapClear,
- "forEach", MapForEach
+ "clear", MapClear
));
}
V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \
generator_object_prototype_map) \
- V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
- V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \
- V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map)
+ V(GENERATOR_RESULT_MAP_INDEX, Map, generator_result_map)
// JSFunctions are pairs (context, function code), sometimes also called
// closures. A Context object is used to represent function contexts and
SLOPPY_GENERATOR_FUNCTION_MAP_INDEX,
STRICT_GENERATOR_FUNCTION_MAP_INDEX,
GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
- ITERATOR_RESULT_MAP_INDEX,
- MAP_ITERATOR_MAP_INDEX,
- SET_ITERATOR_MAP_INDEX,
+ GENERATOR_RESULT_MAP_INDEX,
// Properties from here are treated as weak references by the full GC.
// Scavenge treats them as strong references.
}
-Handle<JSObject> Factory::NewIteratorResultObject(Handle<Object> value,
- bool done) {
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
- Handle<JSObject> result = NewJSObjectFromMap(map, NOT_TENURED, false);
- result->InObjectPropertyAtPut(
- JSGeneratorObject::kResultValuePropertyIndex, *value);
- result->InObjectPropertyAtPut(
- JSGeneratorObject::kResultDonePropertyIndex, *ToBoolean(done));
- return result;
-}
-
-
Handle<ScopeInfo> Factory::NewScopeInfo(int length) {
Handle<FixedArray> array = NewFixedArray(length, TENURED);
array->set_map_no_write_barrier(*scope_info_map());
return value ? true_value() : false_value();
}
-
} } // namespace v8::internal
Handle<Object> NewEvalError(const char* message,
Vector< Handle<Object> > args);
- Handle<JSObject> NewIteratorResultObject(Handle<Object> value, bool done);
-
Handle<String> NumberToString(Handle<Object> number,
bool check_number_string_cache = true);
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
const PROPERTY_ATTRIBUTES_STRING = 8;
const PROPERTY_ATTRIBUTES_SYMBOLIC = 16;
const PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL = 32;
-
-# Use for keys, values and entries iterators.
-const ITERATOR_KIND_KEYS = 1;
-const ITERATOR_KIND_VALUES = 2;
-const ITERATOR_KIND_ENTRIES = 3;
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), v0, a2, a3, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapVerify();
break;
- case JS_SET_ITERATOR_TYPE:
- JSSetIterator::cast(this)->JSSetIteratorVerify();
- break;
- case JS_MAP_ITERATOR_TYPE:
- JSMapIterator::cast(this)->JSMapIteratorVerify();
- break;
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapVerify();
break;
JSObjectVerify();
VerifyHeapPointer(table());
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
- // TODO(arv): Verify OrderedHashTable too.
}
JSObjectVerify();
VerifyHeapPointer(table());
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
- // TODO(arv): Verify OrderedHashTable too.
-}
-
-
-void JSSetIterator::JSSetIteratorVerify() {
- CHECK(IsJSSetIterator());
- JSObjectVerify();
- VerifyHeapPointer(table());
- CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
- CHECK(index()->IsSmi());
- CHECK(count()->IsSmi());
- CHECK(kind()->IsSmi());
- VerifyHeapPointer(next_iterator());
- CHECK(next_iterator()->IsJSSetIterator() || next_iterator()->IsUndefined());
- VerifyHeapPointer(table());
- CHECK(previous_iterator()->IsJSSetIterator()
- || previous_iterator()->IsUndefined());
-}
-
-
-void JSMapIterator::JSMapIteratorVerify() {
- CHECK(IsJSMapIterator());
- JSObjectVerify();
- VerifyHeapPointer(table());
- CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
- CHECK(index()->IsSmi());
- CHECK(count()->IsSmi());
- CHECK(kind()->IsSmi());
- VerifyHeapPointer(next_iterator());
- CHECK(next_iterator()->IsJSMapIterator() || next_iterator()->IsUndefined());
- VerifyHeapPointer(table());
- CHECK(previous_iterator()->IsJSMapIterator()
- || previous_iterator()->IsUndefined());
}
TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
-TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
-TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
return JSSet::kSize;
case JS_MAP_TYPE:
return JSMap::kSize;
- case JS_SET_ITERATOR_TYPE:
- return JSSetIterator::kSize;
- case JS_MAP_ITERATOR_TYPE:
- return JSMapIterator::kSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize;
case JS_WEAK_SET_TYPE:
CAST_ACCESSOR(JSFunctionProxy)
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSMap)
-CAST_ACCESSOR(JSSetIterator)
-CAST_ACCESSOR(JSMapIterator)
CAST_ACCESSOR(JSWeakMap)
CAST_ACCESSOR(JSWeakSet)
CAST_ACCESSOR(Foreign)
ACCESSORS(JSSet, table, Object, kTableOffset)
ACCESSORS(JSMap, table, Object, kTableOffset)
-
-
-#define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \
- template<class Derived, class TableType> \
- type* OrderedHashTableIterator<Derived, TableType>::name() { \
- return type::cast(READ_FIELD(this, offset)); \
- } \
- template<class Derived, class TableType> \
- void OrderedHashTableIterator<Derived, TableType>::set_##name( \
- type* value, WriteBarrierMode mode) { \
- WRITE_FIELD(this, offset, value); \
- CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
- }
-
-ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset)
-ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Smi, kIndexOffset)
-ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(count, Smi, kCountOffset)
-ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Smi, kKindOffset)
-ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(next_iterator, Object,
- kNextIteratorOffset)
-ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(previous_iterator, Object,
- kPreviousIteratorOffset)
-
-#undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS
-
-
ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
}
-Handle<JSSetIterator> JSSetIterator::Create(
- Handle<OrderedHashSet> table,
- int kind) {
- return CreateInternal(table->GetIsolate()->set_iterator_map(), table, kind);
-}
-
-
-Handle<JSMapIterator> JSMapIterator::Create(
- Handle<OrderedHashMap> table,
- int kind) {
- return CreateInternal(table->GetIsolate()->map_iterator_map(), table, kind);
-}
-
-
bool Name::IsHashFieldComputed(uint32_t field) {
return (field & kHashNotComputedMask) == 0;
}
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapPrint(out);
break;
- case JS_SET_ITERATOR_TYPE:
- JSSetIterator::cast(this)->JSSetIteratorPrint(out);
- break;
- case JS_MAP_ITERATOR_TYPE:
- JSMapIterator::cast(this)->JSMapIteratorPrint(out);
- break;
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapPrint(out);
break;
PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - handler = ");
handler()->Print(out);
- PrintF(out, "\n - hash = ");
+ PrintF(out, " - hash = ");
hash()->Print(out);
PrintF(out, "\n");
}
PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - handler = ");
handler()->Print(out);
- PrintF(out, "\n - call_trap = ");
+ PrintF(out, " - call_trap = ");
call_trap()->Print(out);
- PrintF(out, "\n - construct_trap = ");
+ PrintF(out, " - construct_trap = ");
construct_trap()->Print(out);
PrintF(out, "\n");
}
}
-template<class Derived, class TableType>
-void OrderedHashTableIterator<Derived, TableType>::
- OrderedHashTableIteratorPrint(FILE* out) {
- PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
- PrintF(out, " - table = ");
- table()->ShortPrint(out);
- PrintF(out, "\n - index = ");
- index()->ShortPrint(out);
- PrintF(out, "\n - count = ");
- count()->ShortPrint(out);
- PrintF(out, "\n - kind = ");
- kind()->ShortPrint(out);
- PrintF(out, "\n - next_iterator = ");
- next_iterator()->ShortPrint(out);
- PrintF(out, "\n - previous_iterator = ");
- previous_iterator()->ShortPrint(out);
- PrintF(out, "\n");
-}
-
-
-void JSSetIterator::JSSetIteratorPrint(FILE* out) {
- HeapObject::PrintHeader(out, "JSSetIterator");
- OrderedHashTableIteratorPrint(out);
-}
-
-
-void JSMapIterator::JSMapIteratorPrint(FILE* out) {
- HeapObject::PrintHeader(out, "JSMapIterator");
- OrderedHashTableIteratorPrint(out);
-}
-
-
void JSWeakMap::JSWeakMapPrint(FILE* out) {
HeapObject::PrintHeader(out, "JSWeakMap");
PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
- case JS_SET_ITERATOR_TYPE:
- case JS_MAP_ITERATOR_TYPE:
return GetVisitorIdForSize(kVisitJSObject,
kVisitJSObjectGeneric,
instance_size);
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
- case JS_SET_ITERATOR_TYPE:
- case JS_MAP_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
case JS_REGEXP_TYPE:
}
-template<class Derived, class Iterator, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
+template<class Derived, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, entrysize>::Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure) {
// Capacity must be a power of two, since we depend on being able
// to divide and multiple by 2 (kLoadFactor) to derive capacity
// from number of buckets. If we decide to change kLoadFactor
// to something other than 2, capacity should be stored as another
// field of this object.
+ const int kMinCapacity = 4;
capacity = RoundUpToPowerOf2(Max(kMinCapacity, capacity));
if (capacity > kMaxCapacity) {
v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
table->SetNumberOfBuckets(num_buckets);
table->SetNumberOfElements(0);
table->SetNumberOfDeletedElements(0);
- table->set_iterators(isolate->heap()->undefined_value());
return table;
}
-template<class Derived, class Iterator, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
+template<class Derived, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable(
Handle<Derived> table) {
int nof = table->NumberOfElements();
int nod = table->NumberOfDeletedElements();
}
-template<class Derived, class Iterator, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
+template<class Derived, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, entrysize>::Shrink(
Handle<Derived> table) {
int nof = table->NumberOfElements();
int capacity = table->Capacity();
}
-template<class Derived, class Iterator, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
- Handle<Derived> table) {
- Handle<Derived> new_table =
- Allocate(table->GetIsolate(),
- kMinCapacity,
- table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
-
- new_table->set_iterators(table->iterators());
- table->set_iterators(table->GetHeap()->undefined_value());
-
- DisallowHeapAllocation no_allocation;
- for (Object* object = new_table->iterators();
- !object->IsUndefined();
- object = Iterator::cast(object)->next_iterator()) {
- Iterator::cast(object)->TableCleared();
- Iterator::cast(object)->set_table(*new_table);
- }
-
- return new_table;
-}
-
-
-template<class Derived, class Iterator, int entrysize>
-Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
+template<class Derived, int entrysize>
+Handle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
Handle<Derived> table, int new_capacity) {
Handle<Derived> new_table =
Allocate(table->GetIsolate(),
++new_entry;
}
new_table->SetNumberOfElements(nof);
-
- new_table->set_iterators(table->iterators());
- table->set_iterators(table->GetHeap()->undefined_value());
-
- DisallowHeapAllocation no_allocation;
- for (Object* object = new_table->iterators();
- !object->IsUndefined();
- object = Iterator::cast(object)->next_iterator()) {
- Iterator::cast(object)->TableCompacted();
- Iterator::cast(object)->set_table(*new_table);
- }
-
return new_table;
}
-template<class Derived, class Iterator, int entrysize>
-int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(Object* key) {
+template<class Derived, int entrysize>
+int OrderedHashTable<Derived, entrysize>::FindEntry(Object* key) {
ASSERT(!key->IsTheHole());
Object* hash = key->GetHash();
if (hash->IsUndefined()) return kNotFound;
}
-template<class Derived, class Iterator, int entrysize>
-int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
- int entry = UsedCapacity();
+template<class Derived, int entrysize>
+int OrderedHashTable<Derived, entrysize>::AddEntry(int hash) {
+ int entry = NumberOfElements() + NumberOfDeletedElements();
int bucket = HashToBucket(hash);
int index = EntryToIndex(entry);
Object* chain_entry = get(kHashTableStartIndex + bucket);
}
-template<class Derived, class Iterator, int entrysize>
-void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
+template<class Derived, int entrysize>
+void OrderedHashTable<Derived, entrysize>::RemoveEntry(int entry) {
int index = EntryToIndex(entry);
for (int i = 0; i < entrysize; ++i) {
set_the_hole(index + i);
}
SetNumberOfElements(NumberOfElements() - 1);
SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
-
- DisallowHeapAllocation no_allocation;
- for (Object* object = iterators();
- !object->IsUndefined();
- object = Iterator::cast(object)->next_iterator()) {
- Iterator::cast(object)->EntryRemoved(entry);
- }
}
-template int OrderedHashTable<OrderedHashSet, JSSetIterator,
- 1>::FindEntry(Object* key);
-template int OrderedHashTable<OrderedHashMap, JSMapIterator,
- 2>::FindEntry(Object* key);
-
-
-template class OrderedHashTable<OrderedHashSet, JSSetIterator, 1>;
-template class OrderedHashTable<OrderedHashMap, JSMapIterator, 2>;
+template class OrderedHashTable<OrderedHashSet, 1>;
+template class OrderedHashTable<OrderedHashMap, 2>;
bool OrderedHashSet::Contains(Object* key) {
int entry = table->FindEntry(*key);
if (entry == kNotFound) return table;
table->RemoveEntry(entry);
+ // TODO(adamk): Don't shrink if we're being iterated over
return Shrink(table);
}
if (value->IsTheHole()) {
if (entry == kNotFound) return table;
table->RemoveEntry(entry);
+ // TODO(adamk): Only shrink if not iterating
return Shrink(table);
}
}
-template<class Derived, class TableType>
-void OrderedHashTableIterator<Derived, TableType>::EntryRemoved(int index) {
- int i = this->index()->value();
- if (index < i) {
- set_count(Smi::FromInt(count()->value() - 1));
- }
- if (index == i) {
- Seek();
- }
-}
-
-
-template<class Derived, class TableType>
-void OrderedHashTableIterator<Derived, TableType>::Close() {
- if (Closed()) return;
-
- DisallowHeapAllocation no_allocation;
-
- Object* undefined = GetHeap()->undefined_value();
- TableType* table = TableType::cast(this->table());
- Object* previous = previous_iterator();
- Object* next = next_iterator();
-
- if (previous == undefined) {
- ASSERT_EQ(table->iterators(), this);
- table->set_iterators(next);
- } else {
- ASSERT_EQ(Derived::cast(previous)->next_iterator(), this);
- Derived::cast(previous)->set_next_iterator(next);
- }
-
- if (!next->IsUndefined()) {
- ASSERT_EQ(Derived::cast(next)->previous_iterator(), this);
- Derived::cast(next)->set_previous_iterator(previous);
- }
-
- set_previous_iterator(undefined);
- set_next_iterator(undefined);
- set_table(undefined);
-}
-
-
-template<class Derived, class TableType>
-void OrderedHashTableIterator<Derived, TableType>::Seek() {
- ASSERT(!Closed());
-
- DisallowHeapAllocation no_allocation;
-
- int index = this->index()->value();
-
- TableType* table = TableType::cast(this->table());
- int used_capacity = table->UsedCapacity();
-
- while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
- index++;
- }
- set_index(Smi::FromInt(index));
-}
-
-
-template<class Derived, class TableType>
-void OrderedHashTableIterator<Derived, TableType>::MoveNext() {
- ASSERT(!Closed());
-
- set_index(Smi::FromInt(index()->value() + 1));
- set_count(Smi::FromInt(count()->value() + 1));
- Seek();
-}
-
-
-template<class Derived, class TableType>
-Handle<JSObject> OrderedHashTableIterator<Derived, TableType>::Next(
- Handle<Derived> iterator) {
- Isolate* isolate = iterator->GetIsolate();
- Factory* factory = isolate->factory();
-
- Handle<Object> object(iterator->table(), isolate);
-
- if (!object->IsUndefined()) {
- Handle<TableType> table = Handle<TableType>::cast(object);
- int index = iterator->index()->value();
- if (index < table->UsedCapacity()) {
- int entry_index = table->EntryToIndex(index);
- iterator->MoveNext();
- Handle<Object> value = Derived::ValueForKind(iterator, entry_index);
- return factory->NewIteratorResultObject(value, false);
- } else {
- iterator->Close();
- }
- }
-
- return factory->NewIteratorResultObject(factory->undefined_value(), true);
-}
-
-
-template<class Derived, class TableType>
-Handle<Derived> OrderedHashTableIterator<Derived, TableType>::CreateInternal(
- Handle<Map> map,
- Handle<TableType> table,
- int kind) {
- Isolate* isolate = table->GetIsolate();
-
- Handle<Object> undefined = isolate->factory()->undefined_value();
-
- Handle<Derived> new_iterator = Handle<Derived>::cast(
- isolate->factory()->NewJSObjectFromMap(map));
- new_iterator->set_previous_iterator(*undefined);
- new_iterator->set_table(*table);
- new_iterator->set_index(Smi::FromInt(0));
- new_iterator->set_count(Smi::FromInt(0));
- new_iterator->set_kind(Smi::FromInt(kind));
-
- Handle<Object> old_iterator(table->iterators(), isolate);
- if (!old_iterator->IsUndefined()) {
- Handle<Derived>::cast(old_iterator)->set_previous_iterator(*new_iterator);
- new_iterator->set_next_iterator(*old_iterator);
- } else {
- new_iterator->set_next_iterator(*undefined);
- }
-
- table->set_iterators(*new_iterator);
-
- return new_iterator;
-}
-
-
-template Handle<JSObject> OrderedHashTableIterator<JSSetIterator,
- OrderedHashSet>::Next(Handle<JSSetIterator> iterator);
-template Handle<JSObject> OrderedHashTableIterator<JSMapIterator,
- OrderedHashMap>::Next(Handle<JSMapIterator> iterator);
-
-
-template class OrderedHashTableIterator<JSSetIterator, OrderedHashSet>;
-template class OrderedHashTableIterator<JSMapIterator, OrderedHashMap>;
-
-
-Handle<Object> JSSetIterator::ValueForKind(
- Handle<JSSetIterator> iterator, int entry_index) {
- int kind = iterator->kind()->value();
- // Set.prototype only has values and entries.
- ASSERT(kind == kKindValues || kind == kKindEntries);
-
- Isolate* isolate = iterator->GetIsolate();
- Factory* factory = isolate->factory();
-
- Handle<OrderedHashSet> table(
- OrderedHashSet::cast(iterator->table()), isolate);
- Handle<Object> value = Handle<Object>(table->get(entry_index), isolate);
-
- if (kind == kKindEntries) {
- Handle<FixedArray> array = factory->NewFixedArray(2);
- array->set(0, *value);
- array->set(1, *value);
- return factory->NewJSArrayWithElements(array);
- }
-
- return value;
-}
-
-
-Handle<Object> JSMapIterator::ValueForKind(
- Handle<JSMapIterator> iterator, int entry_index) {
- int kind = iterator->kind()->value();
- ASSERT(kind == kKindKeys || kind == kKindValues || kind == kKindEntries);
-
- Isolate* isolate = iterator->GetIsolate();
- Factory* factory = isolate->factory();
-
- Handle<OrderedHashMap> table(
- OrderedHashMap::cast(iterator->table()), isolate);
-
- switch (kind) {
- case kKindKeys:
- return Handle<Object>(table->get(entry_index), isolate);
-
- case kKindValues:
- return Handle<Object>(table->get(entry_index + 1), isolate);
-
- case kKindEntries: {
- Handle<Object> key(table->get(entry_index), isolate);
- Handle<Object> value(table->get(entry_index + 1), isolate);
- Handle<FixedArray> array = factory->NewFixedArray(2);
- array->set(0, *key);
- array->set(1, *value);
- return factory->NewJSArrayWithElements(array);
- }
- }
-
- UNREACHABLE();
- return factory->undefined_value();
-}
-
-
DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
DeclaredAccessorDescriptor* descriptor)
: array_(descriptor->serialized_data()->GetDataStartAddress()),
// - JSDataView
// - JSSet
// - JSMap
-// - JSSetIterator
-// - JSMapIterator
// - JSWeakCollection
// - JSWeakMap
// - JSWeakSet
V(JS_PROXY_TYPE) \
V(JS_SET_TYPE) \
V(JS_MAP_TYPE) \
- V(JS_SET_ITERATOR_TYPE) \
- V(JS_MAP_ITERATOR_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_WEAK_SET_TYPE) \
V(JS_REGEXP_TYPE) \
JS_DATA_VIEW_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
- JS_SET_ITERATOR_TYPE,
- JS_MAP_ITERATOR_TYPE,
JS_WEAK_MAP_TYPE,
JS_WEAK_SET_TYPE,
V(JSFunctionProxy) \
V(JSSet) \
V(JSMap) \
- V(JSSetIterator) \
- V(JSMapIterator) \
V(JSWeakCollection) \
V(JSWeakMap) \
V(JSWeakSet) \
// [0]: bucket count
// [1]: element count
// [2]: deleted element count
-// [3]: live iterators (doubly-linked list)
-// [4..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset
+// [3..(NumberOfBuckets() - 1)]: "hash table", where each item is an offset
// into the data table (see below) where the
// first item in this bucket is stored.
-// [4 + NumberOfBuckets()..length]: "data table", an array of length
+// [3 + NumberOfBuckets()..length]: "data table", an array of length
// Capacity() * kEntrySize, where the first entrysize
// items are handled by the derived class and the
// item at kChainOffset is another entry into the
// data table indicating the next entry in this hash
// bucket.
-template<class Derived, class Iterator, int entrysize>
+template<class Derived, int entrysize>
class OrderedHashTable: public FixedArray {
public:
// Returns an OrderedHashTable with a capacity of at least |capacity|.
// if possible.
static Handle<Derived> Shrink(Handle<Derived> table);
- // Returns a new empty OrderedHashTable and updates all the iterators to
- // point to the new table.
- static Handle<Derived> Clear(Handle<Derived> table);
-
// Returns kNotFound if the key isn't present.
int FindEntry(Object* key);
return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
}
- int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); }
-
int NumberOfBuckets() {
return Smi::cast(get(kNumberOfBucketsIndex))->value();
}
- Object* iterators() { return get(kIteratorsIndex); }
-
- void set_iterators(Object* value) { set(kIteratorsIndex, value); }
-
// Returns the index into the data table where the new entry
// should be placed. The table is assumed to have enough space
// for a new entry.
return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize);
}
- Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
-
static const int kNotFound = -1;
- static const int kMinCapacity = 4;
private:
static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity);
return NumberOfBuckets() * kLoadFactor;
}
+ Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
+
// Returns the next entry for the given entry.
int ChainAt(int entry) {
return Smi::cast(get(EntryToIndex(entry) + kChainOffset))->value();
static const int kNumberOfBucketsIndex = 0;
static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1;
static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
- static const int kIteratorsIndex = kNumberOfDeletedElementsIndex + 1;
- static const int kHashTableStartIndex = kIteratorsIndex + 1;
+ static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1;
static const int kEntrySize = entrysize + 1;
static const int kChainOffset = entrysize;
};
-class JSSetIterator;
-
-
-class OrderedHashSet: public OrderedHashTable<
- OrderedHashSet, JSSetIterator, 1> {
+class OrderedHashSet: public OrderedHashTable<OrderedHashSet, 1> {
public:
static OrderedHashSet* cast(Object* obj) {
ASSERT(obj->IsOrderedHashTable());
};
-class JSMapIterator;
-
-
-class OrderedHashMap:public OrderedHashTable<
- OrderedHashMap, JSMapIterator, 2> {
+class OrderedHashMap: public OrderedHashTable<OrderedHashMap, 2> {
public:
static OrderedHashMap* cast(Object* obj) {
ASSERT(obj->IsOrderedHashTable());
enum ResumeMode { NEXT, THROW };
// Yielding from a generator returns an object with the following inobject
- // properties. See Context::iterator_result_map() for the map.
+ // properties. See Context::generator_result_map() for the map.
static const int kResultValuePropertyIndex = 0;
static const int kResultDonePropertyIndex = 1;
static const int kResultPropertyCount = 2;
};
-// OrderedHashTableIterator is an iterator that iterates over the keys and
-// values of an OrderedHashTable.
-//
-// The hash table has a reference to the iterator and the iterators themselves
-// have references to the [next_iterator] and [previous_iterator], thus creating
-// a double linked list.
-//
-// When the hash table changes the iterators are called to update their [index]
-// and [count]. The hash table calls [EntryRemoved], [TableCompacted] as well
-// as [TableCleared].
-//
-// When an iterator is done it closes itself. It removes itself from the double
-// linked list and it sets its [table] to undefined, no longer keeping the
-// [table] alive.
-template<class Derived, class TableType>
-class OrderedHashTableIterator: public JSObject {
- public:
- // [table]: the backing hash table mapping keys to values.
- DECL_ACCESSORS(table, Object)
-
- // [index]: The index into the data table.
- DECL_ACCESSORS(index, Smi)
-
- // [count]: The logical index into the data table, ignoring the holes.
- DECL_ACCESSORS(count, Smi)
-
- // [kind]: The kind of iteration this is. One of the [Kind] enum values.
- DECL_ACCESSORS(kind, Smi)
-
- // [next_iterator]: Used as a double linked list for the live iterators.
- DECL_ACCESSORS(next_iterator, Object)
-
- // [previous_iterator]: Used as a double linked list for the live iterators.
- DECL_ACCESSORS(previous_iterator, Object)
-
-#ifdef OBJECT_PRINT
- void OrderedHashTableIteratorPrint(FILE* out);
-#endif
-
- static const int kTableOffset = JSObject::kHeaderSize;
- static const int kIndexOffset = kTableOffset + kPointerSize;
- static const int kCountOffset = kIndexOffset + kPointerSize;
- static const int kKindOffset = kCountOffset + kPointerSize;
- static const int kNextIteratorOffset = kKindOffset + kPointerSize;
- static const int kPreviousIteratorOffset = kNextIteratorOffset + kPointerSize;
- static const int kSize = kPreviousIteratorOffset + kPointerSize;
-
- enum Kind {
- kKindKeys = 1,
- kKindValues = 2,
- kKindEntries = 3
- };
-
- // Called by the underlying [table] when an entry is removed.
- void EntryRemoved(int index);
-
- // Called by the underlying [table] when it is compacted/rehashed.
- void TableCompacted() {
- // All holes have been removed so index is now same as count.
- set_index(count());
- }
-
- // Called by the underlying [table] when it is cleared.
- void TableCleared() {
- set_index(Smi::FromInt(0));
- set_count(Smi::FromInt(0));
- }
-
- // Removes the iterator from the double linked list and removes its reference
- // back to the [table].
- void Close();
-
- // Returns an iterator result object: {value: any, done: boolean} and moves
- // the index to the next valid entry. Closes the iterator if moving past the
- // end.
- static Handle<JSObject> Next(Handle<Derived> iterator);
-
- protected:
- static Handle<Derived> CreateInternal(
- Handle<Map> map, Handle<TableType> table, int kind);
-
- private:
- // Ensures [index] is not pointing to a hole.
- void Seek();
-
- // Moves [index] to next valid entry. Closes the iterator if moving past the
- // end.
- void MoveNext();
-
- bool Closed() {
- return table()->IsUndefined();
- }
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator);
-};
-
-
-class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
- OrderedHashSet> {
- public:
- // Creates a new iterator associated with [table].
- // [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
- static inline Handle<JSSetIterator> Create(
- Handle<OrderedHashSet> table, int kind);
-
- // Dispatched behavior.
- DECLARE_PRINTER(JSSetIterator)
- DECLARE_VERIFIER(JSSetIterator)
-
- // Casting.
- static inline JSSetIterator* cast(Object* obj);
-
- static Handle<Object> ValueForKind(
- Handle<JSSetIterator> iterator, int entry_index);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator);
-};
-
-
-class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
- OrderedHashMap> {
- public:
- // Creates a new iterator associated with [table].
- // [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
- static inline Handle<JSMapIterator> Create(
- Handle<OrderedHashMap> table, int kind);
-
- // Dispatched behavior.
- DECLARE_PRINTER(JSMapIterator)
- DECLARE_VERIFIER(JSMapIterator)
-
- // Casting.
- static inline JSMapIterator* cast(Object* obj);
-
- static Handle<Object> ValueForKind(
- Handle<JSMapIterator> iterator, int entry_index);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator);
-};
-
-
// Base class for both JSWeakMap and JSWeakSet
class JSWeakCollection: public JSObject {
public:
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetClear) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
- table = OrderedHashSet::Clear(table);
- holder->set_table(*table);
- return isolate->heap()->undefined_value();
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCreateIterator) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- CONVERT_SMI_ARG_CHECKED(kind, 1)
- ASSERT(kind == JSSetIterator::kKindValues
- || kind == JSSetIterator::kKindEntries);
- Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
- Handle<JSSetIterator> iterator = JSSetIterator::Create(table, kind);
- return *iterator;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIteratorNext) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
- Handle<JSObject> result = JSSetIterator::Next(holder);
- return *result;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIteratorClose) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
- holder->Close();
- return isolate->heap()->undefined_value();
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapClear) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
- Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
- table = OrderedHashMap::Clear(table);
- holder->set_table(*table);
- return isolate->heap()->undefined_value();
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapCreateIterator) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
- CONVERT_SMI_ARG_CHECKED(kind, 1)
- ASSERT(kind == JSMapIterator::kKindKeys
- || kind == JSMapIterator::kKindValues
- || kind == JSMapIterator::kKindEntries);
- Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
- Handle<JSMapIterator> iterator = JSMapIterator::Create(table, kind);
- return *iterator;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapIteratorNext) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
- Handle<JSObject> result = JSMapIterator::Next(holder);
- return *result;
-}
-
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_MapIteratorClose) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
- holder->Close();
- return isolate->heap()->undefined_value();
-}
-
-
static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
Handle<JSWeakCollection> weak_collection) {
ASSERT(weak_collection->map()->inobject_properties() == 0);
F(SetAdd, 2, 1) \
F(SetHas, 2, 1) \
F(SetDelete, 2, 1) \
- F(SetClear, 1, 1) \
F(SetGetSize, 1, 1) \
- F(SetCreateIterator, 2, 1) \
- \
- F(SetIteratorNext, 1, 1) \
- F(SetIteratorClose, 1, 1) \
\
/* Harmony maps */ \
F(MapInitialize, 1, 1) \
F(MapGet, 2, 1) \
F(MapHas, 2, 1) \
F(MapDelete, 2, 1) \
- F(MapClear, 1, 1) \
F(MapSet, 3, 1) \
F(MapGetSize, 1, 1) \
- F(MapCreateIterator, 2, 1) \
- \
- F(MapIteratorNext, 1, 1) \
- F(MapIteratorClose, 1, 1) \
\
/* Harmony weak maps and sets */ \
F(WeakCollectionInitialize, 1, 1) \
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
using namespace v8::internal;
-
-void CheckIterResultObject(Isolate* isolate,
- Handle<JSObject> result,
- Handle<Object> value,
- bool done) {
- CHECK(Object::GetProperty(isolate, result, "value").ToHandleChecked()
- ->SameValue(*value));
- CHECK(Object::GetProperty(isolate, result, "done").ToHandleChecked()
- ->IsBoolean());
- CHECK_EQ(Object::GetProperty(isolate, result, "done").ToHandleChecked()
- ->BooleanValue(), done);
-}
-
-
TEST(Set) {
- i::FLAG_harmony_collections = true;
-
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
CHECK_EQ(0, ordered_set->NumberOfElements());
CHECK_EQ(0, ordered_set->NumberOfDeletedElements());
- Handle<JSSetIterator> value_iterator =
- JSSetIterator::Create(ordered_set, JSSetIterator::kKindValues);
- Handle<JSSetIterator> value_iterator_2 =
- JSSetIterator::Create(ordered_set, JSSetIterator::kKindValues);
-
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
CHECK(!ordered_set->Contains(*obj));
CHECK(ordered_set->Contains(*obj2));
CHECK(ordered_set->Contains(*obj3));
- // Test iteration
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator), obj1, false);
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator), obj2, false);
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator), obj3, false);
- CheckIterResultObject(isolate,
- JSSetIterator::Next(value_iterator),
- factory->undefined_value(),
- true);
-
// Test growth
ordered_set = OrderedHashSet::Add(ordered_set, obj);
Handle<JSObject> obj4 = factory->NewJSObjectFromMap(map);
CHECK_EQ(0, ordered_set->NumberOfDeletedElements());
CHECK_EQ(4, ordered_set->NumberOfBuckets());
- // Test iteration after growth
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator_2), obj1, false);
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator_2), obj2, false);
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator_2), obj3, false);
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator_2), obj, false);
- CheckIterResultObject(
- isolate, JSSetIterator::Next(value_iterator_2), obj4, false);
- CheckIterResultObject(isolate,
- JSSetIterator::Next(value_iterator_2),
- factory->undefined_value(),
- true);
-
// Test shrinking
ordered_set = OrderedHashSet::Remove(ordered_set, obj);
ordered_set = OrderedHashSet::Remove(ordered_set, obj1);
TEST(Map) {
- i::FLAG_harmony_collections = true;
-
LocalContext context;
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
CHECK_EQ(0, ordered_map->NumberOfElements());
CHECK_EQ(0, ordered_map->NumberOfDeletedElements());
- Handle<JSMapIterator> value_iterator =
- JSMapIterator::Create(ordered_map, JSMapIterator::kKindValues);
- Handle<JSMapIterator> key_iterator =
- JSMapIterator::Create(ordered_map, JSMapIterator::kKindKeys);
-
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
Handle<JSObject> val = factory->NewJSObjectFromMap(map);
CHECK(ordered_map->Lookup(*obj2)->SameValue(*val2));
CHECK(ordered_map->Lookup(*obj3)->SameValue(*val3));
- // Test iteration
- CheckIterResultObject(
- isolate, JSMapIterator::Next(value_iterator), val1, false);
- CheckIterResultObject(
- isolate, JSMapIterator::Next(value_iterator), val2, false);
- CheckIterResultObject(
- isolate, JSMapIterator::Next(value_iterator), val3, false);
- CheckIterResultObject(isolate,
- JSMapIterator::Next(value_iterator),
- factory->undefined_value(),
- true);
-
// Test growth
ordered_map = OrderedHashMap::Put(ordered_map, obj, val);
Handle<JSObject> obj4 = factory->NewJSObjectFromMap(map);
CHECK_EQ(5, ordered_map->NumberOfElements());
CHECK_EQ(4, ordered_map->NumberOfBuckets());
- // Test iteration after growth
- CheckIterResultObject(
- isolate, JSMapIterator::Next(key_iterator), obj1, false);
- CheckIterResultObject(
- isolate, JSMapIterator::Next(key_iterator), obj2, false);
- CheckIterResultObject(
- isolate, JSMapIterator::Next(key_iterator), obj3, false);
- CheckIterResultObject(
- isolate, JSMapIterator::Next(key_iterator), obj, false);
- CheckIterResultObject(
- isolate, JSMapIterator::Next(key_iterator), obj4, false);
- CheckIterResultObject(isolate,
- JSMapIterator::Next(key_iterator),
- factory->undefined_value(),
- true);
-
// Test shrinking
ordered_map = OrderedHashMap::Put(
ordered_map, obj, factory->the_hole_value());
assertEquals('minus', m.get(0));
assertEquals('minus', m.get(-0));
})();
-
-
-(function TestSetForEachInvalidTypes() {
- assertThrows(function() {
- Set.prototype.set.forEach.call({});
- }, TypeError);
-
- var set = new Set();
- assertThrows(function() {
- set.forEach({});
- }, TypeError);
-})();
-
-
-(function TestSetForEach() {
- var set = new Set();
- set.add('a');
- set.add('b');
- set.add('c');
-
- var buffer = '';
- var receiver = {};
- set.forEach(function(v, k, s) {
- assertSame(v, k);
- assertSame(set, s);
- assertSame(this, receiver);
- buffer += v;
- if (v === 'a') {
- set.delete('b');
- set.add('d');
- set.add('e');
- set.add('f');
- } else if (v === 'c') {
- set.add('b');
- set.delete('e');
- }
- }, receiver);
-
- assertEquals('acdfb', buffer);
-})();
-
-
-(function TestSetForEachAddAtEnd() {
- var set = new Set();
- set.add('a');
- set.add('b');
-
- var buffer = '';
- set.forEach(function(v) {
- buffer += v;
- if (v === 'b') {
- set.add('c');
- }
- });
-
- assertEquals('abc', buffer);
-})();
-
-
-(function TestSetForEachDeleteNext() {
- var set = new Set();
- set.add('a');
- set.add('b');
- set.add('c');
-
- var buffer = '';
- set.forEach(function(v) {
- buffer += v;
- if (v === 'b') {
- set.delete('c');
- }
- });
-
- assertEquals('ab', buffer);
-})();
-
-
-(function TestSetForEachDeleteVisitedAndAddAgain() {
- var set = new Set();
- set.add('a');
- set.add('b');
- set.add('c');
-
- var buffer = '';
- set.forEach(function(v) {
- buffer += v;
- if (v === 'b') {
- set.delete('a');
- } else if (v === 'c') {
- set.add('a');
- }
- });
-
- assertEquals('abca', buffer);
-})();
-
-
-(function TestSetForEachClear() {
- var set = new Set();
- set.add('a');
- set.add('b');
- set.add('c');
-
- var buffer = '';
- set.forEach(function(v) {
- buffer += v;
- if (v === 'a') {
- set.clear();
- set.add('d');
- set.add('e');
- }
- });
-
- assertEquals('ade', buffer);
-})();
-
-
-(function TestSetForEachNested() {
- var set = new Set();
- set.add('a');
- set.add('b');
- set.add('c');
-
- var buffer = '';
- set.forEach(function(v) {
- buffer += v;
- set.forEach(function(v) {
- buffer += v;
- if (v === 'a') {
- set.delete('b');
- }
- });
- });
-
- assertEquals('aaccac', buffer);
-})();
-
-
-(function TestSetForEachEarlyExit() {
- var set = new Set();
- set.add('a');
- set.add('b');
- set.add('c');
-
- var buffer = '';
- var ex = {};
- try {
- set.forEach(function(v) {
- buffer += v;
- throw ex;
- });
- } catch (e) {
- assertEquals(ex, e);
- }
- assertEquals('a', buffer);
-})();
-
-
-(function TestSetForEachGC() {
- var set = new Set();
- for (var i = 0; i < 100; i++) {
- set.add(i);
- }
-
- var accumulated = 0;
- set.forEach(function(v) {
- accumulated += v;
- if (v % 10 === 0) {
- gc();
- }
- });
- assertEquals(4950, accumulated);
-})();
-
-(function TestMapForEachInvalidTypes() {
- assertThrows(function() {
- Map.prototype.map.forEach.call({});
- }, TypeError);
-
- var map = new Map();
- assertThrows(function() {
- map.forEach({});
- }, TypeError);
-})();
-
-
-(function TestMapForEach() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
- map.set(2, 'c');
-
- var buffer = [];
- var receiver = {};
- map.forEach(function(v, k, m) {
- assertEquals(map, m);
- assertEquals(this, receiver);
- buffer.push(k, v);
- if (k === 0) {
- map.delete(1);
- map.set(3, 'd');
- map.set(4, 'e');
- map.set(5, 'f');
- } else if (k === 2) {
- map.set(1, 'B');
- map.delete(4);
- }
- }, receiver);
-
- assertArrayEquals([0, 'a', 2, 'c', 3, 'd', 5, 'f', 1, 'B'], buffer);
-})();
-
-
-(function TestMapForEachAddAtEnd() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
-
- var buffer = [];
- map.forEach(function(v, k) {
- buffer.push(k, v);
- if (k === 1) {
- map.set(2, 'c');
- }
- });
-
- assertArrayEquals([0, 'a', 1, 'b', 2, 'c'], buffer);
-})();
-
-
-(function TestMapForEachDeleteNext() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
- map.set(2, 'c');
-
- var buffer = [];
- map.forEach(function(v, k) {
- buffer.push(k, v);
- if (k === 1) {
- map.delete(2);
- }
- });
-
- assertArrayEquals([0, 'a', 1, 'b'], buffer);
-})();
-
-
-(function TestSetForEachDeleteVisitedAndAddAgain() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
- map.set(2, 'c');
-
- var buffer = [];
- map.forEach(function(v, k) {
- buffer.push(k, v);
- if (k === 1) {
- map.delete(0);
- } else if (k === 2) {
- map.set(0, 'a');
- }
- });
-
- assertArrayEquals([0, 'a', 1, 'b', 2, 'c', 0, 'a'], buffer);
-})();
-
-
-(function TestMapForEachClear() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
- map.set(2, 'c');
-
- var buffer = [];
- map.forEach(function(v, k) {
- buffer.push(k, v);
- if (k === 0) {
- map.clear();
- map.set(3, 'd');
- map.set(4, 'e');
- }
- });
-
- assertArrayEquals([0, 'a', 3, 'd', 4, 'e'], buffer);
-})();
-
-
-(function TestMapForEachNested() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
- map.set(2, 'c');
-
- var buffer = [];
- map.forEach(function(v, k) {
- buffer.push(k, v);
- map.forEach(function(v, k) {
- buffer.push(k, v);
- if (k === 0) {
- map.delete(1);
- }
- });
- });
-
- assertArrayEquals([0, 'a', 0, 'a', 2, 'c', 2, 'c', 0, 'a', 2, 'c'], buffer);
-})();
-
-
-(function TestMapForEachEarlyExit() {
- var map = new Map();
- map.set(0, 'a');
- map.set(1, 'b');
- map.set(2, 'c');
-
- var buffer = [];
- var ex = {};
- try {
- map.forEach(function(v, k) {
- buffer.push(k, v);
- throw ex;
- });
- } catch (e) {
- assertEquals(ex, e);
- }
- assertArrayEquals([0, 'a'], buffer);
-})();
-
-
-(function TestMapForEachGC() {
- var map = new Map();
- for (var i = 0; i < 100; i++) {
- map.set(i, i);
- }
-
- var accumulated = 0;
- map.forEach(function(v) {
- accumulated += v;
- if (v % 10 === 0) {
- gc();
- }
- });
- assertEquals(4950, accumulated);
-})();