[builtins] Port Map.p.delete to CSA.

Bug: v8:5717
Change-Id: Iff5b71b9e27b3e4a790118cbd4877b4460d07b1d
Reviewed-on: https://chromium-review.googlesource.com/582810
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46839}
This commit is contained in:
Jaroslav Sevcik 2017-07-24 13:45:28 +02:00 committed by Commit Bot
parent e8c9649e25
commit b955d84289
4 changed files with 63 additions and 31 deletions

View File

@ -3028,6 +3028,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(prototype, "has", Builtins::kMapHas, 1, true);
native_context()->set_map_has(*map_has);
Handle<JSFunction> map_delete = SimpleInstallFunction(
prototype, "delete", Builtins::kMapDelete, 1, true);
native_context()->set_map_delete(*map_delete);
SimpleInstallFunction(prototype, "clear", Builtins::kMapClear, 0, true);
Handle<JSFunction> entries = SimpleInstallFunction(
prototype, "entries", Builtins::kMapPrototypeEntries, 0, true);

View File

@ -966,6 +966,64 @@ void CollectionsBuiltinsAssembler::StoreOrderedHashMapNewEntry(
SmiAdd(number_of_elements, SmiConstant(1)));
}
TF_BUILTIN(MapDelete, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* key = Parameter(Descriptor::kKey);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE,
"Map.prototype.delete");
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset);
VARIABLE(entry_start_position_or_hash, MachineType::PointerRepresentation(),
IntPtrConstant(0));
Label entry_found(this), not_found(this);
TryLookupOrderedHashMapIndex(table, key, context,
&entry_start_position_or_hash, &entry_found,
&not_found);
BIND(&not_found);
Return(FalseConstant());
BIND(&entry_found);
// If we found the entry, mark the entry as deleted.
StoreFixedArrayElement(table, entry_start_position_or_hash.value(),
TheHoleConstant(), UPDATE_WRITE_BARRIER,
kPointerSize * OrderedHashMap::kHashTableStartIndex);
StoreFixedArrayElement(table, entry_start_position_or_hash.value(),
TheHoleConstant(), UPDATE_WRITE_BARRIER,
kPointerSize * (OrderedHashMap::kHashTableStartIndex +
OrderedHashMap::kValueOffset));
// Decrement the number of elements, increment the number of deleted elements.
Node* const number_of_elements =
SmiSub(LoadObjectField(table, OrderedHashMap::kNumberOfElementsOffset),
SmiConstant(1));
StoreObjectFieldNoWriteBarrier(table, OrderedHashMap::kNumberOfElementsOffset,
number_of_elements);
Node* const number_of_deleted = SmiAdd(
LoadObjectField(table, OrderedHashMap::kNumberOfDeletedElementsOffset),
SmiConstant(1));
StoreObjectFieldNoWriteBarrier(
table, OrderedHashMap::kNumberOfDeletedElementsOffset, number_of_deleted);
Node* const number_of_buckets =
LoadFixedArrayElement(table, OrderedHashMap::kNumberOfBucketsIndex);
// If there fewer elements than #buckets / 2, shrink the table.
Label shrink(this);
GotoIf(SmiLessThan(SmiAdd(number_of_elements, number_of_elements),
number_of_buckets),
&shrink);
Return(TrueConstant());
BIND(&shrink);
CallRuntime(Runtime::kMapShrink, context, receiver);
Return(TrueConstant());
}
TF_BUILTIN(MapPrototypeEntries, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);

View File

@ -578,6 +578,7 @@ namespace internal {
TFS(MapLookupHashIndex, kTable, kKey) \
TFJ(MapConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(MapSet, 2, kKey, kValue) \
TFJ(MapDelete, 1, kKey) \
TFJ(MapGet, 1, kKey) \
TFJ(MapHas, 1, kKey) \
CPP(MapClear) \

View File

@ -186,41 +186,10 @@ DEFINE_METHODS(
}
);
// Harmony Map
//Set up the non-enumerable functions on the Map prototype object.
DEFINE_METHODS(
GlobalMap.prototype,
{
delete(key) {
if (!IS_MAP(this)) {
throw %make_type_error(kIncompatibleMethodReceiver,
'Map.prototype.delete', this);
}
var table = %_JSCollectionGetTable(this);
var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
var hash = GetHash(key);
var entry = MapFindEntry(table, numBuckets, key, hash);
if (entry === NOT_FOUND) return false;
var nof = ORDERED_HASH_TABLE_ELEMENT_COUNT(table) - 1;
var nod = ORDERED_HASH_TABLE_DELETED_COUNT(table) + 1;
var index = ORDERED_HASH_MAP_ENTRY_TO_INDEX(entry, numBuckets);
FIXED_ARRAY_SET(table, index, %_TheHole());
FIXED_ARRAY_SET(table, index + 1, %_TheHole());
ORDERED_HASH_TABLE_SET_ELEMENT_COUNT(table, nof);
ORDERED_HASH_TABLE_SET_DELETED_COUNT(table, nod);
if (nof < (numBuckets >>> 1)) %MapShrink(this);
return true;
}
}
);
// -----------------------------------------------------------------------
// Exports
%InstallToContext([
"map_delete", GlobalMap.prototype.delete,
"set_add", GlobalSet.prototype.add,
"set_delete", GlobalSet.prototype.delete,
]);