@@ -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,
@@ -523,16 +399,28 @@ TNode<IntPtrT> BaseCollectionsAssembler::EstimatedInitialSize(
523399 [=] { return IntPtrConstant (0 ); });
524400}
525401
402+ // https://tc39.es/proposal-symbols-as-weakmap-keys/#sec-canbeheldweakly-abstract-operation
526403void BaseCollectionsAssembler::GotoIfCannotBeWeakKey (
527404 const TNode<Object> obj, Label* if_cannot_be_weak_key) {
405+ Label check_symbol_key (this );
406+ Label end (this );
528407 GotoIf (TaggedIsSmi (obj), if_cannot_be_weak_key);
529408 TNode<Uint16T> instance_type = LoadMapInstanceType (LoadMap (CAST (obj)));
530- GotoIfNot (IsJSReceiverInstanceType (instance_type), if_cannot_be_weak_key );
409+ GotoIfNot (IsJSReceiverInstanceType (instance_type), &check_symbol_key );
531410 // TODO(v8:12547) Shared structs and arrays should only be able to point
532411 // to shared values in weak collections. For now, disallow them as weak
533412 // collection keys.
534413 GotoIf (IsJSSharedStructInstanceType (instance_type), if_cannot_be_weak_key);
535414 GotoIf (IsJSSharedArrayInstanceType (instance_type), if_cannot_be_weak_key);
415+ Goto (&end);
416+ Bind (&check_symbol_key);
417+ GotoIfNot (HasHarmonySymbolAsWeakmapKeyFlag (), if_cannot_be_weak_key);
418+ GotoIfNot (IsSymbolInstanceType (instance_type), if_cannot_be_weak_key);
419+ TNode<Uint32T> flags = LoadSymbolFlags (CAST (obj));
420+ GotoIf (Word32And (flags, Symbol::IsInPublicSymbolTableBit::kMask ),
421+ if_cannot_be_weak_key);
422+ Goto (&end);
423+ Bind (&end);
536424}
537425
538426TNode<Map> BaseCollectionsAssembler::GetInitialCollectionPrototype (
@@ -2414,67 +2302,6 @@ TF_BUILTIN(FindOrderedHashSetEntry, CollectionsBuiltinsAssembler) {
24142302 Return (SmiConstant (-1 ));
24152303}
24162304
2417- class WeakCollectionsBuiltinsAssembler : public BaseCollectionsAssembler {
2418- public:
2419- explicit WeakCollectionsBuiltinsAssembler (compiler::CodeAssemblerState* state)
2420- : BaseCollectionsAssembler(state) {}
2421-
2422- protected:
2423- void AddEntry (TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
2424- TNode<Object> key, TNode<Object> value,
2425- TNode<IntPtrT> number_of_elements);
2426-
2427- TNode<HeapObject> AllocateTable (Variant variant,
2428- TNode<IntPtrT> at_least_space_for) override ;
2429-
2430- // Generates and sets the identity for a JSRececiver.
2431- TNode<Smi> CreateIdentityHash (TNode<Object> receiver);
2432- TNode<IntPtrT> EntryMask (TNode<IntPtrT> capacity);
2433-
2434- // Builds code that finds the EphemeronHashTable entry for a {key} using the
2435- // comparison code generated by {key_compare}. The key index is returned if
2436- // the {key} is found.
2437- using KeyComparator =
2438- std::function<void (TNode<Object> entry_key, Label* if_same)>;
2439- TNode<IntPtrT> FindKeyIndex (TNode<HeapObject> table, TNode<IntPtrT> key_hash,
2440- TNode<IntPtrT> entry_mask,
2441- const KeyComparator& key_compare);
2442-
2443- // Builds code that finds an EphemeronHashTable entry available for a new
2444- // entry.
2445- TNode<IntPtrT> FindKeyIndexForInsertion (TNode<HeapObject> table,
2446- TNode<IntPtrT> key_hash,
2447- TNode<IntPtrT> entry_mask);
2448-
2449- // Builds code that finds the EphemeronHashTable entry with key that matches
2450- // {key} and returns the entry's key index. If {key} cannot be found, jumps to
2451- // {if_not_found}.
2452- TNode<IntPtrT> FindKeyIndexForKey (TNode<HeapObject> table, TNode<Object> key,
2453- TNode<IntPtrT> hash,
2454- TNode<IntPtrT> entry_mask,
2455- Label* if_not_found);
2456-
2457- TNode<Word32T> InsufficientCapacityToAdd (TNode<IntPtrT> capacity,
2458- TNode<IntPtrT> number_of_elements,
2459- TNode<IntPtrT> number_of_deleted);
2460- TNode<IntPtrT> KeyIndexFromEntry (TNode<IntPtrT> entry);
2461-
2462- TNode<IntPtrT> LoadNumberOfElements (TNode<EphemeronHashTable> table,
2463- int offset);
2464- TNode<IntPtrT> LoadNumberOfDeleted (TNode<EphemeronHashTable> table,
2465- int offset = 0 );
2466- TNode<EphemeronHashTable> LoadTable (TNode<JSWeakCollection> collection);
2467- TNode<IntPtrT> LoadTableCapacity (TNode<EphemeronHashTable> table);
2468-
2469- void RemoveEntry (TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
2470- TNode<IntPtrT> number_of_elements);
2471- TNode<BoolT> ShouldRehash (TNode<IntPtrT> number_of_elements,
2472- TNode<IntPtrT> number_of_deleted);
2473- TNode<Word32T> ShouldShrink (TNode<IntPtrT> capacity,
2474- TNode<IntPtrT> number_of_elements);
2475- TNode<IntPtrT> ValueIndexFromKeyIndex (TNode<IntPtrT> key_index);
2476- };
2477-
24782305void WeakCollectionsBuiltinsAssembler::AddEntry (
24792306 TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
24802307 TNode<Object> key, TNode<Object> value, TNode<IntPtrT> number_of_elements) {
@@ -2490,6 +2317,25 @@ void WeakCollectionsBuiltinsAssembler::AddEntry(
24902317 SmiFromIntPtr (number_of_elements));
24912318}
24922319
2320+ TNode<IntPtrT> WeakCollectionsBuiltinsAssembler::GetHash (
2321+ const TNode<HeapObject> key, Label* if_no_hash) {
2322+ TVARIABLE (IntPtrT, var_hash);
2323+ Label if_symbol (this );
2324+ Label return_result (this );
2325+ GotoIfNot (IsJSReceiver (key), &if_symbol);
2326+ var_hash = LoadJSReceiverIdentityHash (CAST (key), if_no_hash);
2327+ Goto (&return_result);
2328+ Bind (&if_symbol);
2329+ CSA_DCHECK (this , IsSymbol (key));
2330+ CSA_DCHECK (this , Word32BinaryNot (
2331+ Word32And (LoadSymbolFlags (CAST (key)),
2332+ Symbol::IsInPublicSymbolTableBit::kMask )));
2333+ var_hash = ChangeInt32ToIntPtr (LoadNameHash (CAST (key), nullptr ));
2334+ Goto (&return_result);
2335+ Bind (&return_result);
2336+ return var_hash.value ();
2337+ }
2338+
24932339TNode<HeapObject> WeakCollectionsBuiltinsAssembler::AllocateTable (
24942340 Variant variant, TNode<IntPtrT> at_least_space_for) {
24952341 // See HashTable::New().
@@ -2719,8 +2565,7 @@ TF_BUILTIN(WeakMapLookupHashIndex, WeakCollectionsBuiltinsAssembler) {
27192565
27202566 GotoIfCannotBeWeakKey (key, &if_cannot_be_weak_key);
27212567
2722- TNode<IntPtrT> hash =
2723- LoadJSReceiverIdentityHash (CAST (key), &if_cannot_be_weak_key);
2568+ TNode<IntPtrT> hash = GetHash (CAST (key), &if_cannot_be_weak_key);
27242569 TNode<IntPtrT> capacity = LoadTableCapacity (table);
27252570 TNode<IntPtrT> key_index = FindKeyIndexForKey (
27262571 table, key, hash, EntryMask (capacity), &if_cannot_be_weak_key);
@@ -2785,8 +2630,7 @@ TF_BUILTIN(WeakCollectionDelete, WeakCollectionsBuiltinsAssembler) {
27852630
27862631 GotoIfCannotBeWeakKey (key, &if_cannot_be_weak_key);
27872632
2788- TNode<IntPtrT> hash =
2789- LoadJSReceiverIdentityHash (CAST (key), &if_cannot_be_weak_key);
2633+ TNode<IntPtrT> hash = GetHash (CAST (key), &if_cannot_be_weak_key);
27902634 TNode<EphemeronHashTable> table = LoadTable (collection);
27912635 TNode<IntPtrT> capacity = LoadTableCapacity (table);
27922636 TNode<IntPtrT> key_index = FindKeyIndexForKey (
@@ -2810,18 +2654,18 @@ TF_BUILTIN(WeakCollectionDelete, WeakCollectionsBuiltinsAssembler) {
28102654TF_BUILTIN (WeakCollectionSet, WeakCollectionsBuiltinsAssembler) {
28112655 auto context = Parameter<Context>(Descriptor::kContext );
28122656 auto collection = Parameter<JSWeakCollection>(Descriptor::kCollection );
2813- auto key = Parameter<JSReceiver >(Descriptor::kKey );
2657+ auto key = Parameter<HeapObject >(Descriptor::kKey );
28142658 auto value = Parameter<Object>(Descriptor::kValue );
28152659
2816- CSA_DCHECK (this , IsJSReceiver (key));
2660+ CSA_DCHECK (this , Word32Or ( IsJSReceiver (key), IsSymbol (key) ));
28172661
28182662 Label call_runtime (this ), if_no_hash (this ), if_not_found (this );
28192663
28202664 TNode<EphemeronHashTable> table = LoadTable (collection);
28212665 TNode<IntPtrT> capacity = LoadTableCapacity (table);
28222666 TNode<IntPtrT> entry_mask = EntryMask (capacity);
28232667
2824- TVARIABLE (IntPtrT, var_hash, LoadJSReceiverIdentityHash (key, &if_no_hash));
2668+ TVARIABLE (IntPtrT, var_hash, GetHash (key, &if_no_hash));
28252669 TNode<IntPtrT> key_index = FindKeyIndexForKey (table, key, var_hash.value (),
28262670 entry_mask, &if_not_found);
28272671
@@ -2830,6 +2674,7 @@ TF_BUILTIN(WeakCollectionSet, WeakCollectionsBuiltinsAssembler) {
28302674
28312675 BIND (&if_no_hash);
28322676 {
2677+ CSA_DCHECK (this , IsJSReceiver (key));
28332678 var_hash = SmiUntag (CreateIdentityHash (key));
28342679 Goto (&if_not_found);
28352680 }
0 commit comments