@@ -22,130 +22,6 @@ namespace internal {
2222template <class T >
2323using TVariable = compiler::TypedCodeAssemblerVariable<T>;
2424
25- class BaseCollectionsAssembler : public CodeStubAssembler {
26- public:
27- explicit BaseCollectionsAssembler (compiler::CodeAssemblerState* state)
28- : CodeStubAssembler(state) {}
29-
30- virtual ~BaseCollectionsAssembler () = default ;
31-
32- protected:
33- enum Variant { kMap , kSet , kWeakMap , kWeakSet };
34-
35- // Adds an entry to a collection. For Maps, properly handles extracting the
36- // key and value from the entry (see LoadKeyValue()).
37- void AddConstructorEntry (Variant variant, TNode<Context> context,
38- TNode<Object> collection, TNode<Object> add_function,
39- TNode<Object> key_value,
40- Label* if_may_have_side_effects = nullptr ,
41- Label* if_exception = nullptr ,
42- TVariable<Object>* var_exception = nullptr );
43-
44- // Adds constructor entries to a collection. Choosing a fast path when
45- // possible.
46- void AddConstructorEntries (Variant variant, TNode<Context> context,
47- TNode<Context> native_context,
48- TNode<HeapObject> collection,
49- TNode<Object> initial_entries);
50-
51- // Fast path for adding constructor entries. Assumes the entries are a fast
52- // JS array (see CodeStubAssembler::BranchIfFastJSArray()).
53- void AddConstructorEntriesFromFastJSArray (Variant variant,
54- TNode<Context> context,
55- TNode<Context> native_context,
56- TNode<Object> collection,
57- TNode<JSArray> fast_jsarray,
58- Label* if_may_have_side_effects);
59-
60- // Adds constructor entries to a collection using the iterator protocol.
61- void AddConstructorEntriesFromIterable (Variant variant,
62- TNode<Context> context,
63- TNode<Context> native_context,
64- TNode<Object> collection,
65- TNode<Object> iterable);
66-
67- // Constructs a collection instance. Choosing a fast path when possible.
68- TNode<JSObject> AllocateJSCollection (TNode<Context> context,
69- TNode<JSFunction> constructor,
70- TNode<JSReceiver> new_target);
71-
72- // Fast path for constructing a collection instance if the constructor
73- // function has not been modified.
74- TNode<JSObject> AllocateJSCollectionFast (TNode<JSFunction> constructor);
75-
76- // Fallback for constructing a collection instance if the constructor function
77- // has been modified.
78- TNode<JSObject> AllocateJSCollectionSlow (TNode<Context> context,
79- TNode<JSFunction> constructor,
80- TNode<JSReceiver> new_target);
81-
82- // Allocates the backing store for a collection.
83- virtual TNode<HeapObject> AllocateTable (
84- Variant variant, TNode<IntPtrT> at_least_space_for) = 0;
85-
86- // Main entry point for a collection constructor builtin.
87- void GenerateConstructor (Variant variant,
88- Handle<String> constructor_function_name,
89- TNode<Object> new_target, TNode<IntPtrT> argc,
90- TNode<Context> context);
91-
92- // Retrieves the collection function that adds an entry. `set` for Maps and
93- // `add` for Sets.
94- TNode<Object> GetAddFunction (Variant variant, TNode<Context> context,
95- TNode<Object> collection);
96-
97- // Retrieves the collection constructor function.
98- TNode<JSFunction> GetConstructor (Variant variant,
99- TNode<Context> native_context);
100-
101- // Retrieves the initial collection function that adds an entry. Should only
102- // be called when it is certain that a collection prototype's map hasn't been
103- // changed.
104- TNode<JSFunction> GetInitialAddFunction (Variant variant,
105- TNode<Context> native_context);
106-
107- // Checks whether {collection}'s initial add/set function has been modified
108- // (depending on {variant}, loaded from {native_context}).
109- void GotoIfInitialAddFunctionModified (Variant variant,
110- TNode<NativeContext> native_context,
111- TNode<HeapObject> collection,
112- Label* if_modified);
113-
114- // Gets root index for the name of the add/set function.
115- RootIndex GetAddFunctionNameIndex (Variant variant);
116-
117- // Retrieves the offset to access the backing table from the collection.
118- int GetTableOffset (Variant variant);
119-
120- // Estimates the number of entries the collection will have after adding the
121- // entries passed in the constructor. AllocateTable() can use this to avoid
122- // the time of growing/rehashing when adding the constructor entries.
123- TNode<IntPtrT> EstimatedInitialSize (TNode<Object> initial_entries,
124- TNode<BoolT> is_fast_jsarray);
125-
126- void GotoIfCannotBeWeakKey (const TNode<Object> obj,
127- Label* if_cannot_be_weak_key);
128-
129- // Determines whether the collection's prototype has been modified.
130- TNode<BoolT> HasInitialCollectionPrototype (Variant variant,
131- TNode<Context> native_context,
132- TNode<Object> collection);
133-
134- // Gets the initial prototype map for given collection {variant}.
135- TNode<Map> GetInitialCollectionPrototype (Variant variant,
136- TNode<Context> native_context);
137-
138- // Loads an element from a fixed array. If the element is the hole, returns
139- // `undefined`.
140- TNode<Object> LoadAndNormalizeFixedArrayElement (TNode<FixedArray> elements,
141- TNode<IntPtrT> index);
142-
143- // Loads an element from a fixed double array. If the element is the hole,
144- // returns `undefined`.
145- TNode<Object> LoadAndNormalizeFixedDoubleArrayElement (
146- TNode<HeapObject> elements, TNode<IntPtrT> index);
147- };
148-
14925void BaseCollectionsAssembler::AddConstructorEntry (
15026 Variant variant, TNode<Context> context, TNode<Object> collection,
15127 TNode<Object> add_function, TNode<Object> key_value,
@@ -525,12 +401,23 @@ TNode<IntPtrT> BaseCollectionsAssembler::EstimatedInitialSize(
525401
526402void BaseCollectionsAssembler::GotoIfCannotBeWeakKey (
527403 const TNode<Object> obj, Label* if_cannot_be_weak_key) {
404+ Label check_symbol_key (this );
405+ Label end (this );
528406 GotoIf (TaggedIsSmi (obj), if_cannot_be_weak_key);
529407 TNode<Uint16T> instance_type = LoadMapInstanceType (LoadMap (CAST (obj)));
530- GotoIfNot (IsJSReceiverInstanceType (instance_type), if_cannot_be_weak_key );
408+ GotoIfNot (IsJSReceiverInstanceType (instance_type), &check_symbol_key );
531409 // TODO(v8:12547) Shared structs should only be able to point to shared values
532410 // in weak collections. For now, disallow them as weak collection keys.
533411 GotoIf (IsJSSharedStructInstanceType (instance_type), if_cannot_be_weak_key);
412+ Goto (&end);
413+ Bind (&check_symbol_key);
414+ GotoIfNot (HasHarmonySymbolAsWeakmapKeyFlag (), if_cannot_be_weak_key);
415+ GotoIfNot (IsSymbolInstanceType (instance_type), if_cannot_be_weak_key);
416+ TNode<Uint32T> flags = LoadSymbolFlags (CAST (obj));
417+ GotoIf (Word32And (flags, Symbol::IsInPublicSymbolTableBit::kMask ),
418+ if_cannot_be_weak_key);
419+ Goto (&end);
420+ Bind (&end);
534421}
535422
536423TNode<Map> BaseCollectionsAssembler::GetInitialCollectionPrototype (
@@ -2427,67 +2314,6 @@ TF_BUILTIN(FindOrderedHashMapEntry, CollectionsBuiltinsAssembler) {
24272314 Return (SmiConstant (-1 ));
24282315}
24292316
2430- class WeakCollectionsBuiltinsAssembler : public BaseCollectionsAssembler {
2431- public:
2432- explicit WeakCollectionsBuiltinsAssembler (compiler::CodeAssemblerState* state)
2433- : BaseCollectionsAssembler(state) {}
2434-
2435- protected:
2436- void AddEntry (TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
2437- TNode<Object> key, TNode<Object> value,
2438- TNode<IntPtrT> number_of_elements);
2439-
2440- TNode<HeapObject> AllocateTable (Variant variant,
2441- TNode<IntPtrT> at_least_space_for) override ;
2442-
2443- // Generates and sets the identity for a JSRececiver.
2444- TNode<Smi> CreateIdentityHash (TNode<Object> receiver);
2445- TNode<IntPtrT> EntryMask (TNode<IntPtrT> capacity);
2446-
2447- // Builds code that finds the EphemeronHashTable entry for a {key} using the
2448- // comparison code generated by {key_compare}. The key index is returned if
2449- // the {key} is found.
2450- using KeyComparator =
2451- std::function<void (TNode<Object> entry_key, Label* if_same)>;
2452- TNode<IntPtrT> FindKeyIndex (TNode<HeapObject> table, TNode<IntPtrT> key_hash,
2453- TNode<IntPtrT> entry_mask,
2454- const KeyComparator& key_compare);
2455-
2456- // Builds code that finds an EphemeronHashTable entry available for a new
2457- // entry.
2458- TNode<IntPtrT> FindKeyIndexForInsertion (TNode<HeapObject> table,
2459- TNode<IntPtrT> key_hash,
2460- TNode<IntPtrT> entry_mask);
2461-
2462- // Builds code that finds the EphemeronHashTable entry with key that matches
2463- // {key} and returns the entry's key index. If {key} cannot be found, jumps to
2464- // {if_not_found}.
2465- TNode<IntPtrT> FindKeyIndexForKey (TNode<HeapObject> table, TNode<Object> key,
2466- TNode<IntPtrT> hash,
2467- TNode<IntPtrT> entry_mask,
2468- Label* if_not_found);
2469-
2470- TNode<Word32T> InsufficientCapacityToAdd (TNode<IntPtrT> capacity,
2471- TNode<IntPtrT> number_of_elements,
2472- TNode<IntPtrT> number_of_deleted);
2473- TNode<IntPtrT> KeyIndexFromEntry (TNode<IntPtrT> entry);
2474-
2475- TNode<IntPtrT> LoadNumberOfElements (TNode<EphemeronHashTable> table,
2476- int offset);
2477- TNode<IntPtrT> LoadNumberOfDeleted (TNode<EphemeronHashTable> table,
2478- int offset = 0 );
2479- TNode<EphemeronHashTable> LoadTable (TNode<JSWeakCollection> collection);
2480- TNode<IntPtrT> LoadTableCapacity (TNode<EphemeronHashTable> table);
2481-
2482- void RemoveEntry (TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
2483- TNode<IntPtrT> number_of_elements);
2484- TNode<BoolT> ShouldRehash (TNode<IntPtrT> number_of_elements,
2485- TNode<IntPtrT> number_of_deleted);
2486- TNode<Word32T> ShouldShrink (TNode<IntPtrT> capacity,
2487- TNode<IntPtrT> number_of_elements);
2488- TNode<IntPtrT> ValueIndexFromKeyIndex (TNode<IntPtrT> key_index);
2489- };
2490-
24912317void WeakCollectionsBuiltinsAssembler::AddEntry (
24922318 TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
24932319 TNode<Object> key, TNode<Object> value, TNode<IntPtrT> number_of_elements) {
@@ -2503,6 +2329,25 @@ void WeakCollectionsBuiltinsAssembler::AddEntry(
25032329 SmiFromIntPtr (number_of_elements));
25042330}
25052331
2332+ TNode<IntPtrT> WeakCollectionsBuiltinsAssembler::GetHash (
2333+ const TNode<HeapObject> key, Label* if_no_hash) {
2334+ TVARIABLE (IntPtrT, var_hash);
2335+ Label if_symbol (this );
2336+ Label return_result (this );
2337+ GotoIfNot (IsJSReceiver (key), &if_symbol);
2338+ var_hash = LoadJSReceiverIdentityHash (CAST (key), if_no_hash);
2339+ Goto (&return_result);
2340+ Bind (&if_symbol);
2341+ CSA_DCHECK (this , IsSymbol (key));
2342+ CSA_DCHECK (this , Word32BinaryNot (
2343+ Word32And (LoadSymbolFlags (CAST (key)),
2344+ Symbol::IsInPublicSymbolTableBit::kMask )));
2345+ var_hash = ChangeInt32ToIntPtr (LoadNameHash (CAST (key), nullptr ));
2346+ Goto (&return_result);
2347+ Bind (&return_result);
2348+ return var_hash.value ();
2349+ }
2350+
25062351TNode<HeapObject> WeakCollectionsBuiltinsAssembler::AllocateTable (
25072352 Variant variant, TNode<IntPtrT> at_least_space_for) {
25082353 // See HashTable::New().
@@ -2732,8 +2577,7 @@ TF_BUILTIN(WeakMapLookupHashIndex, WeakCollectionsBuiltinsAssembler) {
27322577
27332578 GotoIfCannotBeWeakKey (key, &if_cannot_be_weak_key);
27342579
2735- TNode<IntPtrT> hash =
2736- LoadJSReceiverIdentityHash (CAST (key), &if_cannot_be_weak_key);
2580+ TNode<IntPtrT> hash = GetHash (CAST (key), &if_cannot_be_weak_key);
27372581 TNode<IntPtrT> capacity = LoadTableCapacity (table);
27382582 TNode<IntPtrT> key_index = FindKeyIndexForKey (
27392583 table, key, hash, EntryMask (capacity), &if_cannot_be_weak_key);
@@ -2798,8 +2642,7 @@ TF_BUILTIN(WeakCollectionDelete, WeakCollectionsBuiltinsAssembler) {
27982642
27992643 GotoIfCannotBeWeakKey (key, &if_cannot_be_weak_key);
28002644
2801- TNode<IntPtrT> hash =
2802- LoadJSReceiverIdentityHash (CAST (key), &if_cannot_be_weak_key);
2645+ TNode<IntPtrT> hash = GetHash (CAST (key), &if_cannot_be_weak_key);
28032646 TNode<EphemeronHashTable> table = LoadTable (collection);
28042647 TNode<IntPtrT> capacity = LoadTableCapacity (table);
28052648 TNode<IntPtrT> key_index = FindKeyIndexForKey (
@@ -2823,18 +2666,18 @@ TF_BUILTIN(WeakCollectionDelete, WeakCollectionsBuiltinsAssembler) {
28232666TF_BUILTIN (WeakCollectionSet, WeakCollectionsBuiltinsAssembler) {
28242667 auto context = Parameter<Context>(Descriptor::kContext );
28252668 auto collection = Parameter<JSWeakCollection>(Descriptor::kCollection );
2826- auto key = Parameter<JSReceiver >(Descriptor::kKey );
2669+ auto key = Parameter<HeapObject >(Descriptor::kKey );
28272670 auto value = Parameter<Object>(Descriptor::kValue );
28282671
2829- CSA_DCHECK (this , IsJSReceiver (key));
2672+ CSA_DCHECK (this , Word32Or ( IsJSReceiver (key), IsSymbol (key) ));
28302673
28312674 Label call_runtime (this ), if_no_hash (this ), if_not_found (this );
28322675
28332676 TNode<EphemeronHashTable> table = LoadTable (collection);
28342677 TNode<IntPtrT> capacity = LoadTableCapacity (table);
28352678 TNode<IntPtrT> entry_mask = EntryMask (capacity);
28362679
2837- TVARIABLE (IntPtrT, var_hash, LoadJSReceiverIdentityHash (key, &if_no_hash));
2680+ TVARIABLE (IntPtrT, var_hash, GetHash (key, &if_no_hash));
28382681 TNode<IntPtrT> key_index = FindKeyIndexForKey (table, key, var_hash.value (),
28392682 entry_mask, &if_not_found);
28402683
@@ -2843,6 +2686,7 @@ TF_BUILTIN(WeakCollectionSet, WeakCollectionsBuiltinsAssembler) {
28432686
28442687 BIND (&if_no_hash);
28452688 {
2689+ CSA_DCHECK (this , IsJSReceiver (key));
28462690 var_hash = SmiUntag (CreateIdentityHash (key));
28472691 Goto (&if_not_found);
28482692 }
0 commit comments