Skip to content

Commit 1ce901b

Browse files
joyeecheungrichardlau
authored andcommitted
deps: V8: cherry-pick c400af48b5ef
Original commit message: [symbol-as-weakmap-key] Implement Symbol as WeakMap Keys Allow non-registered symbols as keys in weakmap and weakset. Allow non-registered symbols as target and unregisterToken in WeakRef and FinalizationRegistry. Bug: v8:12947 Change-Id: Ieb63bda66e3cc378879ac651e23300b71caed627 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3865056 Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Commit-Queue: Marja Hölttä <marja@chromium.org> Reviewed-by: Jakob Linke <jgruber@chromium.org> Cr-Commit-Position: refs/heads/main@{#83313} Refs: v8/v8@c400af4 PR-URL: #51004 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 902d8b3 commit 1ce901b

27 files changed

+534
-261
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
# Reset this number to 0 on major V8 upgrades.
3838
# Increment by one for each non-official patch applied to deps/v8.
39-
'v8_embedder_string': '-node.28',
39+
'v8_embedder_string': '-node.29',
4040

4141
##### V8 defaults for Node.js #####
4242

deps/v8/src/builtins/base.tq

+5-5
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,9 @@ extern enum MessageTemplate {
438438
kWasmTrapArrayOutOfBounds,
439439
kWasmTrapArrayTooLarge,
440440
kWeakRefsRegisterTargetAndHoldingsMustNotBeSame,
441-
kWeakRefsRegisterTargetMustBeObject,
442-
kWeakRefsUnregisterTokenMustBeObject,
443-
kWeakRefsWeakRefConstructorTargetMustBeObject,
441+
kInvalidWeakRefsRegisterTarget,
442+
kInvalidWeakRefsUnregisterToken,
443+
kInvalidWeakRefsWeakRefConstructorTarget,
444444
...
445445
}
446446

@@ -906,10 +906,10 @@ macro Float64IsNaN(n: float64): bool {
906906
// The type of all tagged values that can safely be compared with TaggedEqual.
907907
@if(V8_ENABLE_WEBASSEMBLY)
908908
type TaggedWithIdentity = JSReceiver | FixedArrayBase | Oddball | Map |
909-
WeakCell | Context | EmptyString | WasmInternalFunction;
909+
WeakCell | Context | EmptyString | Symbol | WasmInternalFunction;
910910
@ifnot(V8_ENABLE_WEBASSEMBLY)
911911
type TaggedWithIdentity = JSReceiver | FixedArrayBase | Oddball | Map |
912-
WeakCell | Context | EmptyString;
912+
WeakCell | Context | EmptyString | Symbol;
913913

914914
extern operator '==' macro TaggedEqual(TaggedWithIdentity, Object): bool;
915915
extern operator '==' macro TaggedEqual(Object, TaggedWithIdentity): bool;

deps/v8/src/builtins/builtins-collections-gen.cc

+37-193
Original file line numberDiff line numberDiff line change
@@ -22,130 +22,6 @@ namespace internal {
2222
template <class T>
2323
using 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-
14925
void 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

526402
void 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

536423
TNode<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-
24912317
void 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+
25062351
TNode<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) {
28232666
TF_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

Comments
 (0)