@@ -22,130 +22,6 @@ namespace internal {
22
22
template <class T >
23
23
using TVariable = compiler::TypedCodeAssemblerVariable<T>;
24
24
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
-
149
25
void BaseCollectionsAssembler::AddConstructorEntry (
150
26
Variant variant, TNode<Context> context, TNode<Object> collection,
151
27
TNode<Object> add_function, TNode<Object> key_value,
@@ -525,12 +401,23 @@ TNode<IntPtrT> BaseCollectionsAssembler::EstimatedInitialSize(
525
401
526
402
void BaseCollectionsAssembler::GotoIfCannotBeWeakKey (
527
403
const TNode<Object> obj, Label* if_cannot_be_weak_key) {
404
+ Label check_symbol_key (this );
405
+ Label end (this );
528
406
GotoIf (TaggedIsSmi (obj), if_cannot_be_weak_key);
529
407
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 );
531
409
// TODO(v8:12547) Shared structs should only be able to point to shared values
532
410
// in weak collections. For now, disallow them as weak collection keys.
533
411
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);
534
421
}
535
422
536
423
TNode<Map> BaseCollectionsAssembler::GetInitialCollectionPrototype (
@@ -2427,67 +2314,6 @@ TF_BUILTIN(FindOrderedHashMapEntry, CollectionsBuiltinsAssembler) {
2427
2314
Return (SmiConstant (-1 ));
2428
2315
}
2429
2316
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
-
2491
2317
void WeakCollectionsBuiltinsAssembler::AddEntry (
2492
2318
TNode<EphemeronHashTable> table, TNode<IntPtrT> key_index,
2493
2319
TNode<Object> key, TNode<Object> value, TNode<IntPtrT> number_of_elements) {
@@ -2503,6 +2329,25 @@ void WeakCollectionsBuiltinsAssembler::AddEntry(
2503
2329
SmiFromIntPtr (number_of_elements));
2504
2330
}
2505
2331
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
+
2506
2351
TNode<HeapObject> WeakCollectionsBuiltinsAssembler::AllocateTable (
2507
2352
Variant variant, TNode<IntPtrT> at_least_space_for) {
2508
2353
// See HashTable::New().
@@ -2732,8 +2577,7 @@ TF_BUILTIN(WeakMapLookupHashIndex, WeakCollectionsBuiltinsAssembler) {
2732
2577
2733
2578
GotoIfCannotBeWeakKey (key, &if_cannot_be_weak_key);
2734
2579
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);
2737
2581
TNode<IntPtrT> capacity = LoadTableCapacity (table);
2738
2582
TNode<IntPtrT> key_index = FindKeyIndexForKey (
2739
2583
table, key, hash, EntryMask (capacity), &if_cannot_be_weak_key);
@@ -2798,8 +2642,7 @@ TF_BUILTIN(WeakCollectionDelete, WeakCollectionsBuiltinsAssembler) {
2798
2642
2799
2643
GotoIfCannotBeWeakKey (key, &if_cannot_be_weak_key);
2800
2644
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);
2803
2646
TNode<EphemeronHashTable> table = LoadTable (collection);
2804
2647
TNode<IntPtrT> capacity = LoadTableCapacity (table);
2805
2648
TNode<IntPtrT> key_index = FindKeyIndexForKey (
@@ -2823,18 +2666,18 @@ TF_BUILTIN(WeakCollectionDelete, WeakCollectionsBuiltinsAssembler) {
2823
2666
TF_BUILTIN (WeakCollectionSet, WeakCollectionsBuiltinsAssembler) {
2824
2667
auto context = Parameter<Context>(Descriptor::kContext );
2825
2668
auto collection = Parameter<JSWeakCollection>(Descriptor::kCollection );
2826
- auto key = Parameter<JSReceiver >(Descriptor::kKey );
2669
+ auto key = Parameter<HeapObject >(Descriptor::kKey );
2827
2670
auto value = Parameter<Object>(Descriptor::kValue );
2828
2671
2829
- CSA_DCHECK (this , IsJSReceiver (key));
2672
+ CSA_DCHECK (this , Word32Or ( IsJSReceiver (key), IsSymbol (key) ));
2830
2673
2831
2674
Label call_runtime (this ), if_no_hash (this ), if_not_found (this );
2832
2675
2833
2676
TNode<EphemeronHashTable> table = LoadTable (collection);
2834
2677
TNode<IntPtrT> capacity = LoadTableCapacity (table);
2835
2678
TNode<IntPtrT> entry_mask = EntryMask (capacity);
2836
2679
2837
- TVARIABLE (IntPtrT, var_hash, LoadJSReceiverIdentityHash (key, &if_no_hash));
2680
+ TVARIABLE (IntPtrT, var_hash, GetHash (key, &if_no_hash));
2838
2681
TNode<IntPtrT> key_index = FindKeyIndexForKey (table, key, var_hash.value (),
2839
2682
entry_mask, &if_not_found);
2840
2683
@@ -2843,6 +2686,7 @@ TF_BUILTIN(WeakCollectionSet, WeakCollectionsBuiltinsAssembler) {
2843
2686
2844
2687
BIND (&if_no_hash);
2845
2688
{
2689
+ CSA_DCHECK (this , IsJSReceiver (key));
2846
2690
var_hash = SmiUntag (CreateIdentityHash (key));
2847
2691
Goto (&if_not_found);
2848
2692
}
0 commit comments