Commit 9aab9f13 authored by adamk's avatar adamk Committed by Commit bot

Create optimized versions of the Map/Set clear method

This completes the first round of optimizations for Map and Set.
All non-key-dependent methods now have a Hydrogen version, and
for keyed methods, string versions are optimized.

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

Cr-Commit-Position: refs/heads/master@{#25763}
parent 33f0cf5a
...@@ -92,7 +92,7 @@ function SetClearJS() { ...@@ -92,7 +92,7 @@ function SetClearJS() {
throw MakeTypeError('incompatible_method_receiver', throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.clear', this]); ['Set.prototype.clear', this]);
} }
%SetClear(this); %_SetClear(this);
} }
...@@ -245,7 +245,7 @@ function MapClearJS() { ...@@ -245,7 +245,7 @@ function MapClearJS() {
throw MakeTypeError('incompatible_method_receiver', throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.clear', this]); ['Map.prototype.clear', this]);
} }
%MapClear(this); %_MapClear(this);
} }
......
...@@ -6367,6 +6367,11 @@ class HObjectAccess FINAL { ...@@ -6367,6 +6367,11 @@ class HObjectAccess FINAL {
Representation::Smi()); Representation::Smi());
} }
template <typename CollectionType>
static HObjectAccess ForOrderedHashTableNextTable() {
return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
}
template <typename CollectionType> template <typename CollectionType>
static HObjectAccess ForOrderedHashTableBucket(int bucket) { static HObjectAccess ForOrderedHashTableBucket(int bucket) {
return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset + return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
......
...@@ -12727,6 +12727,46 @@ void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) { ...@@ -12727,6 +12727,46 @@ void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
} }
template <typename CollectionType>
void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
HValue* old_table =
Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL),
HObjectAccess::ForJSCollectionTable());
HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
Add<HStoreNamedField>(
old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
new_table);
Add<HStoreNamedField>(
old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
CollectionType>(),
Add<HConstant>(CollectionType::kClearedTableSentinel));
Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
new_table);
}
void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* receiver = Pop();
NoObservableSideEffectsScope no_effects(this);
BuildOrderedHashTableClear<OrderedHashSet>(receiver);
return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}
void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* receiver = Pop();
NoObservableSideEffectsScope no_effects(this);
BuildOrderedHashTableClear<OrderedHashMap>(receiver);
return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}
void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1); DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
......
...@@ -2434,6 +2434,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2434,6 +2434,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
template <typename CollectionType> template <typename CollectionType>
HValue* BuildAllocateOrderedHashTable(); HValue* BuildAllocateOrderedHashTable();
template <typename CollectionType> template <typename CollectionType>
void BuildOrderedHashTableClear(HValue* receiver);
template <typename CollectionType>
void BuildJSCollectionDelete(CallRuntime* call, void BuildJSCollectionDelete(CallRuntime* call,
const Runtime::Function* c_function); const Runtime::Function* c_function);
template <typename CollectionType> template <typename CollectionType>
......
...@@ -16025,7 +16025,7 @@ Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear( ...@@ -16025,7 +16025,7 @@ Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED); table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
table->SetNextTable(*new_table); table->SetNextTable(*new_table);
table->SetNumberOfDeletedElements(-1); table->SetNumberOfDeletedElements(kClearedTableSentinel);
return new_table; return new_table;
} }
...@@ -16270,8 +16270,7 @@ void OrderedHashTableIterator<Derived, TableType>::Transition() { ...@@ -16270,8 +16270,7 @@ void OrderedHashTableIterator<Derived, TableType>::Transition() {
if (index > 0) { if (index > 0) {
int nod = table->NumberOfDeletedElements(); int nod = table->NumberOfDeletedElements();
// When we clear the table we set the number of deleted elements to -1. if (nod == TableType::kClearedTableSentinel) {
if (nod == -1) {
index = 0; index = 0;
} else { } else {
int old_index = index; int old_index = index;
......
...@@ -3933,6 +3933,7 @@ class OrderedHashTable: public FixedArray { ...@@ -3933,6 +3933,7 @@ class OrderedHashTable: public FixedArray {
static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1;
static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1; static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1;
static const int kNextTableIndex = kNumberOfElementsIndex;
static const int kNumberOfBucketsOffset = static const int kNumberOfBucketsOffset =
kHeaderSize + kNumberOfBucketsIndex * kPointerSize; kHeaderSize + kNumberOfBucketsIndex * kPointerSize;
...@@ -3942,12 +3943,19 @@ class OrderedHashTable: public FixedArray { ...@@ -3942,12 +3943,19 @@ class OrderedHashTable: public FixedArray {
kHeaderSize + kNumberOfDeletedElementsIndex * kPointerSize; kHeaderSize + kNumberOfDeletedElementsIndex * kPointerSize;
static const int kHashTableStartOffset = static const int kHashTableStartOffset =
kHeaderSize + kHashTableStartIndex * kPointerSize; kHeaderSize + kHashTableStartIndex * kPointerSize;
static const int kNextTableOffset =
kHeaderSize + kNextTableIndex * kPointerSize;
static const int kEntrySize = entrysize + 1; static const int kEntrySize = entrysize + 1;
static const int kChainOffset = entrysize; static const int kChainOffset = entrysize;
static const int kLoadFactor = 2; static const int kLoadFactor = 2;
// NumberOfDeletedElements is set to kClearedTableSentinel when
// the table is cleared, which allows iterator transitions to
// optimize that case.
static const int kClearedTableSentinel = -1;
private: private:
static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity); static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity);
...@@ -3989,7 +3997,6 @@ class OrderedHashTable: public FixedArray { ...@@ -3989,7 +3997,6 @@ class OrderedHashTable: public FixedArray {
return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index)); return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index));
} }
static const int kNextTableIndex = kNumberOfElementsIndex;
static const int kRemovedHolesIndex = kHashTableStartIndex; static const int kRemovedHolesIndex = kHashTableStartIndex;
static const int kMaxCapacity = static const int kMaxCapacity =
......
...@@ -300,17 +300,11 @@ namespace internal { ...@@ -300,17 +300,11 @@ namespace internal {
F(GetConstructTrap, 1, 1) \ F(GetConstructTrap, 1, 1) \
F(Fix, 1, 1) \ F(Fix, 1, 1) \
\ \
/* Harmony sets */ \ /* ES6 collection iterators */ \
F(SetClear, 1, 1) \
\
F(SetIteratorInitialize, 3, 1) \ F(SetIteratorInitialize, 3, 1) \
F(SetIteratorClone, 1, 1) \ F(SetIteratorClone, 1, 1) \
F(SetIteratorNext, 2, 1) \ F(SetIteratorNext, 2, 1) \
F(SetIteratorDetails, 1, 1) \ F(SetIteratorDetails, 1, 1) \
\
/* Harmony maps */ \
F(MapClear, 1, 1) \
\
F(MapIteratorInitialize, 3, 1) \ F(MapIteratorInitialize, 3, 1) \
F(MapIteratorClone, 1, 1) \ F(MapIteratorClone, 1, 1) \
F(MapIteratorNext, 2, 1) \ F(MapIteratorNext, 2, 1) \
...@@ -721,6 +715,7 @@ namespace internal { ...@@ -721,6 +715,7 @@ namespace internal {
F(MathSqrtRT, 1, 1) \ F(MathSqrtRT, 1, 1) \
F(MathLogRT, 1, 1) \ F(MathLogRT, 1, 1) \
/* ES6 Collections */ \ /* ES6 Collections */ \
F(MapClear, 1, 1) \
F(MapDelete, 2, 1) \ F(MapDelete, 2, 1) \
F(MapGet, 2, 1) \ F(MapGet, 2, 1) \
F(MapGetSize, 1, 1) \ F(MapGetSize, 1, 1) \
...@@ -728,6 +723,7 @@ namespace internal { ...@@ -728,6 +723,7 @@ namespace internal {
F(MapInitialize, 1, 1) \ F(MapInitialize, 1, 1) \
F(MapSet, 3, 1) \ F(MapSet, 3, 1) \
F(SetAdd, 2, 1) \ F(SetAdd, 2, 1) \
F(SetClear, 1, 1) \
F(SetDelete, 2, 1) \ F(SetDelete, 2, 1) \
F(SetGetSize, 1, 1) \ F(SetGetSize, 1, 1) \
F(SetHas, 2, 1) \ F(SetHas, 2, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment