Commit c25744c2 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[Collections] Port Map.get to CSA/C++

Bug: v8:5717, v8:6354, v8:6410
Change-Id: Ie652f4358f2a68c7ea76d546e26a6b4fb815df4a
Reviewed-on: https://chromium-review.googlesource.com/518923
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45664}
parent 51d38345
...@@ -1589,6 +1589,13 @@ ExternalReference ExternalReference::search_string_raw(Isolate* isolate) { ...@@ -1589,6 +1589,13 @@ ExternalReference ExternalReference::search_string_raw(Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f))); return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
} }
template <typename CollectionType, int entrysize>
ExternalReference ExternalReference::orderedhashtable_get_raw(
Isolate* isolate) {
auto f = OrderedHashTable<CollectionType, entrysize>::Get;
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f)));
}
ExternalReference ExternalReference::try_internalize_string_function( ExternalReference ExternalReference::try_internalize_string_function(
Isolate* isolate) { Isolate* isolate) {
return ExternalReference(Redirect( return ExternalReference(Redirect(
...@@ -1619,6 +1626,11 @@ ExternalReference::search_string_raw<const uc16, const uint8_t>(Isolate*); ...@@ -1619,6 +1626,11 @@ ExternalReference::search_string_raw<const uc16, const uint8_t>(Isolate*);
template ExternalReference template ExternalReference
ExternalReference::search_string_raw<const uc16, const uc16>(Isolate*); ExternalReference::search_string_raw<const uc16, const uc16>(Isolate*);
template ExternalReference
ExternalReference::orderedhashtable_get_raw<OrderedHashMap, 2>(Isolate*);
template ExternalReference
ExternalReference::orderedhashtable_get_raw<OrderedHashSet, 1>(Isolate*);
ExternalReference ExternalReference::page_flags(Page* page) { ExternalReference ExternalReference::page_flags(Page* page) {
return ExternalReference(reinterpret_cast<Address>(page) + return ExternalReference(reinterpret_cast<Address>(page) +
MemoryChunk::kFlagsOffset); MemoryChunk::kFlagsOffset);
......
...@@ -1024,6 +1024,9 @@ class ExternalReference BASE_EMBEDDED { ...@@ -1024,6 +1024,9 @@ class ExternalReference BASE_EMBEDDED {
template <typename SubjectChar, typename PatternChar> template <typename SubjectChar, typename PatternChar>
static ExternalReference search_string_raw(Isolate* isolate); static ExternalReference search_string_raw(Isolate* isolate);
template <typename CollectionType, int entrysize>
static ExternalReference orderedhashtable_get_raw(Isolate* isolate);
static ExternalReference page_flags(Page* page); static ExternalReference page_flags(Page* page);
static ExternalReference ForDeoptEntry(Address entry); static ExternalReference ForDeoptEntry(Address entry);
......
...@@ -2945,6 +2945,11 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -2945,6 +2945,11 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
prototype, factory->to_string_tag_symbol(), factory->Map_string(), prototype, factory->to_string_tag_symbol(), factory->Map_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY)); static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> map_get =
SimpleInstallFunction(prototype, "get", Builtins::kMapGet, 1, true);
InstallWithIntrinsicDefaultProto(isolate, map_get,
Context::MAP_GET_METHOD_INDEX);
InstallSpeciesGetter(js_map_fun); InstallSpeciesGetter(js_map_fun);
} }
......
...@@ -19,6 +19,9 @@ class CollectionsBuiltinsAssembler : public CodeStubAssembler { ...@@ -19,6 +19,9 @@ class CollectionsBuiltinsAssembler : public CodeStubAssembler {
protected: protected:
Node* AllocateJSMap(Node* js_map_function); Node* AllocateJSMap(Node* js_map_function);
template <typename CollectionType, int entrysize>
Node* CallGetRaw(Node* const table, Node* const key);
}; };
Node* CollectionsBuiltinsAssembler::AllocateJSMap(Node* js_map_function) { Node* CollectionsBuiltinsAssembler::AllocateJSMap(Node* js_map_function) {
...@@ -152,5 +155,34 @@ TF_BUILTIN(MapConstructor, CollectionsBuiltinsAssembler) { ...@@ -152,5 +155,34 @@ TF_BUILTIN(MapConstructor, CollectionsBuiltinsAssembler) {
Return(var_result.value()); Return(var_result.value());
} }
template <typename CollectionType, int entrysize>
Node* CollectionsBuiltinsAssembler::CallGetRaw(Node* const table,
Node* const key) {
Node* const function_addr = ExternalConstant(
ExternalReference::orderedhashtable_get_raw<CollectionType, entrysize>(
isolate()));
Node* const isolate_ptr =
ExternalConstant(ExternalReference::isolate_address(isolate()));
MachineType type_ptr = MachineType::Pointer();
MachineType type_tagged = MachineType::AnyTagged();
Node* const result =
CallCFunction3(type_tagged, type_ptr, type_tagged, type_tagged,
function_addr, isolate_ptr, table, key);
return result;
}
TF_BUILTIN(MapGet, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const key = Parameter(Descriptor::kKey);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.get");
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset);
Return(CallGetRaw<OrderedHashMap, 2>(table, key));
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -540,6 +540,7 @@ namespace internal { ...@@ -540,6 +540,7 @@ namespace internal {
\ \
/* Map */ \ /* Map */ \
TFJ(MapConstructor, 1, kIterable) \ TFJ(MapConstructor, 1, kIterable) \
TFJ(MapGet, 1, kKey) \
\ \
/* Math */ \ /* Math */ \
/* ES6 #sec-math.abs */ \ /* ES6 #sec-math.abs */ \
......
...@@ -529,6 +529,7 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) { ...@@ -529,6 +529,7 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kDatePrototypeValueOf: case Builtins::kDatePrototypeValueOf:
// Map builtins. // Map builtins.
case Builtins::kMapConstructor: case Builtins::kMapConstructor:
case Builtins::kMapGet:
// Math builtins. // Math builtins.
case Builtins::kMathAbs: case Builtins::kMathAbs:
case Builtins::kMathAcos: case Builtins::kMathAcos:
......
...@@ -271,6 +271,12 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) { ...@@ -271,6 +271,12 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) {
Add(ExternalReference::search_string_raw<const uc16, const uc16>(isolate) Add(ExternalReference::search_string_raw<const uc16, const uc16>(isolate)
.address(), .address(),
"search_string_raw<1-byte, 2-byte>"); "search_string_raw<1-byte, 2-byte>");
Add(ExternalReference::orderedhashtable_get_raw<OrderedHashMap, 2>(isolate)
.address(),
"orderedhashtable_get_raw<OrderedHashMap, 2>");
Add(ExternalReference::orderedhashtable_get_raw<OrderedHashSet, 1>(isolate)
.address(),
"orderedhashtable_get_raw<OrderedHashSet, 1>");
Add(ExternalReference::log_enter_external_function(isolate).address(), Add(ExternalReference::log_enter_external_function(isolate).address(),
"Logger::EnterExternal"); "Logger::EnterExternal");
Add(ExternalReference::log_leave_external_function(isolate).address(), Add(ExternalReference::log_leave_external_function(isolate).address(),
......
...@@ -275,20 +275,6 @@ utils.InstallFunctions(GlobalSet.prototype, DONT_ENUM, [ ...@@ -275,20 +275,6 @@ utils.InstallFunctions(GlobalSet.prototype, DONT_ENUM, [
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Harmony Map // Harmony Map
function MapGet(key) {
if (!IS_MAP(this)) {
throw %make_type_error(kIncompatibleMethodReceiver,
'Map.prototype.get', this);
}
var table = %_JSCollectionGetTable(this);
var numBuckets = ORDERED_HASH_TABLE_BUCKET_COUNT(table);
var hash = GetExistingHash(key);
if (IS_UNDEFINED(hash)) return UNDEFINED;
var entry = MapFindEntry(table, numBuckets, key, hash);
if (entry === NOT_FOUND) return UNDEFINED;
return ORDERED_HASH_MAP_VALUE_AT(table, entry, numBuckets);
}
function MapSet(key, value) { function MapSet(key, value) {
if (!IS_MAP(this)) { if (!IS_MAP(this)) {
...@@ -414,7 +400,6 @@ function MapForEach(f, receiver) { ...@@ -414,7 +400,6 @@ function MapForEach(f, receiver) {
// Set up the non-enumerable functions on the Map prototype object. // Set up the non-enumerable functions on the Map prototype object.
utils.InstallGetter(GlobalMap.prototype, "size", MapGetSize); utils.InstallGetter(GlobalMap.prototype, "size", MapGetSize);
utils.InstallFunctions(GlobalMap.prototype, DONT_ENUM, [ utils.InstallFunctions(GlobalMap.prototype, DONT_ENUM, [
"get", MapGet,
"set", MapSet, "set", MapSet,
"has", MapHas, "has", MapHas,
"delete", MapDelete, "delete", MapDelete,
...@@ -426,7 +411,6 @@ utils.InstallFunctions(GlobalMap.prototype, DONT_ENUM, [ ...@@ -426,7 +411,6 @@ utils.InstallFunctions(GlobalMap.prototype, DONT_ENUM, [
// Exports // Exports
%InstallToContext([ %InstallToContext([
"map_get", MapGet,
"map_set", MapSet, "map_set", MapSet,
"map_has", MapHas, "map_has", MapHas,
"map_delete", MapDelete, "map_delete", MapDelete,
......
...@@ -7087,12 +7087,6 @@ Handle<ObjectHashTable> ObjectHashTable::Shrink( ...@@ -7087,12 +7087,6 @@ Handle<ObjectHashTable> ObjectHashTable::Shrink(
return DerivedHashTable::Shrink(table, key); return DerivedHashTable::Shrink(table, key);
} }
Object* OrderedHashMap::ValueAt(int entry) {
return get(EntryToIndex(entry) + kValueOffset);
}
template <int entrysize> template <int entrysize>
bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) { bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) {
if (other->IsWeakCell()) other = WeakCell::cast(other)->value(); if (other->IsWeakCell()) other = WeakCell::cast(other)->value();
......
...@@ -18757,6 +18757,22 @@ bool OrderedHashTable<Derived, entrysize>::HasKey(Handle<Derived> table, ...@@ -18757,6 +18757,22 @@ bool OrderedHashTable<Derived, entrysize>::HasKey(Handle<Derived> table,
return false; return false;
} }
template <class Derived, int entrysize>
Object* OrderedHashTable<Derived, entrysize>::Get(Isolate* isolate,
Derived* table, Object* key) {
DCHECK(table->IsOrderedHashTable());
DisallowHeapAllocation no_gc;
int entry = table->KeyToFirstEntry(isolate, key);
// Walk the chain in the bucket to find the key.
while (entry != kNotFound) {
Object* candidate_key = table->KeyAt(entry);
if (candidate_key->SameValueZero(key)) {
return table->ValueAt(entry);
}
entry = table->NextChainEntry(entry);
}
return isolate->heap()->undefined_value();
}
Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table, Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
Handle<Object> key) { Handle<Object> key) {
...@@ -18872,6 +18888,10 @@ template Handle<OrderedHashSet> OrderedHashTable<OrderedHashSet, 1>::Clear( ...@@ -18872,6 +18888,10 @@ template Handle<OrderedHashSet> OrderedHashTable<OrderedHashSet, 1>::Clear(
template bool OrderedHashTable<OrderedHashSet, 1>::HasKey( template bool OrderedHashTable<OrderedHashSet, 1>::HasKey(
Handle<OrderedHashSet> table, Handle<Object> key); Handle<OrderedHashSet> table, Handle<Object> key);
template Object* OrderedHashTable<OrderedHashSet, 1>::Get(Isolate* isolate,
OrderedHashSet* table,
Object* key);
template Handle<OrderedHashMap> OrderedHashTable<OrderedHashMap, 2>::Allocate( template Handle<OrderedHashMap> OrderedHashTable<OrderedHashMap, 2>::Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure); Isolate* isolate, int capacity, PretenureFlag pretenure);
...@@ -18887,6 +18907,9 @@ template Handle<OrderedHashMap> OrderedHashTable<OrderedHashMap, 2>::Clear( ...@@ -18887,6 +18907,9 @@ template Handle<OrderedHashMap> OrderedHashTable<OrderedHashMap, 2>::Clear(
template bool OrderedHashTable<OrderedHashMap, 2>::HasKey( template bool OrderedHashTable<OrderedHashMap, 2>::HasKey(
Handle<OrderedHashMap> table, Handle<Object> key); Handle<OrderedHashMap> table, Handle<Object> key);
template Object* OrderedHashTable<OrderedHashMap, 2>::Get(Isolate* isolate,
OrderedHashMap* table,
Object* key);
template <> template <>
Handle<SmallOrderedHashSet> Handle<SmallOrderedHashSet>
SmallOrderedHashTable<SmallOrderedHashSet>::Allocate(Isolate* isolate, SmallOrderedHashTable<SmallOrderedHashSet>::Allocate(Isolate* isolate,
......
...@@ -401,6 +401,10 @@ class OrderedHashTable : public FixedArray { ...@@ -401,6 +401,10 @@ class OrderedHashTable : public FixedArray {
// Returns a true if the OrderedHashTable contains the key // Returns a true if the OrderedHashTable contains the key
static bool HasKey(Handle<Derived> table, Handle<Object> key); static bool HasKey(Handle<Derived> table, Handle<Object> key);
// Returns a value if the OrderedHashTable contains the key,
// otherwise returns undefined.
static Object* Get(Isolate* isolate, Derived* table, Object* key);
int NumberOfElements() { int NumberOfElements() {
return Smi::cast(get(kNumberOfElementsIndex))->value(); return Smi::cast(get(kNumberOfElementsIndex))->value();
} }
...@@ -431,6 +435,14 @@ class OrderedHashTable : public FixedArray { ...@@ -431,6 +435,14 @@ class OrderedHashTable : public FixedArray {
} }
int KeyToFirstEntry(Isolate* isolate, Object* key) { int KeyToFirstEntry(Isolate* isolate, Object* key) {
// This special cases for Smi, so that we avoid the HandleScope
// creation below.
if (key->IsSmi()) {
uint32_t hash =
ComputeIntegerHash(Smi::cast(key)->value(), kZeroHashSeed);
return HashToEntry(hash & Smi::kMaxValue);
}
HandleScope scope(isolate);
Object* hash = key->GetHash(); Object* hash = key->GetHash();
// If the object does not have an identity hash, it was never used as a key // If the object does not have an identity hash, it was never used as a key
if (hash->IsUndefined(isolate)) return kNotFound; if (hash->IsUndefined(isolate)) return kNotFound;
...@@ -448,6 +460,11 @@ class OrderedHashTable : public FixedArray { ...@@ -448,6 +460,11 @@ class OrderedHashTable : public FixedArray {
return get(EntryToIndex(entry)); return get(EntryToIndex(entry));
} }
Object* ValueAt(int entry) {
DCHECK_LT(entry, this->UsedCapacity());
return get(EntryToIndex(entry) + Derived::kValueOffset);
}
bool IsObsolete() { return !get(kNextTableIndex)->IsSmi(); } bool IsObsolete() { return !get(kNextTableIndex)->IsSmi(); }
// The next newer table. This is only valid if the table is obsolete. // The next newer table. This is only valid if the table is obsolete.
...@@ -528,14 +545,13 @@ class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> { ...@@ -528,14 +545,13 @@ class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> {
Handle<Object> value); Handle<Object> value);
static Handle<FixedArray> ConvertToKeysArray(Handle<OrderedHashSet> table, static Handle<FixedArray> ConvertToKeysArray(Handle<OrderedHashSet> table,
GetKeysConversion convert); GetKeysConversion convert);
static const int kValueOffset = 0;
}; };
class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> { class OrderedHashMap : public OrderedHashTable<OrderedHashMap, 2> {
public: public:
DECLARE_CAST(OrderedHashMap) DECLARE_CAST(OrderedHashMap)
inline Object* ValueAt(int entry);
static const int kValueOffset = 1; static const int kValueOffset = 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