Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (275260 => 275261)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2021-03-31 02:55:38 UTC (rev 275261)
@@ -1098,8 +1098,11 @@
runtime/VMTraps.h
runtime/VarOffset.h
runtime/Watchdog.h
+ runtime/WeakGCHashTable.h
runtime/WeakGCMap.h
runtime/WeakGCMapInlines.h
+ runtime/WeakGCSet.h
+ runtime/WeakGCSetInlines.h
runtime/WriteBarrier.h
runtime/WriteBarrierInlines.h
Modified: trunk/Source/_javascript_Core/ChangeLog (275260 => 275261)
--- trunk/Source/_javascript_Core/ChangeLog 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-03-31 02:55:38 UTC (rev 275261)
@@ -1,3 +1,104 @@
+2021-03-30 Sam Weinig <wei...@apple.com>
+
+ JSGlobalObject's m_customGetterFunctionMap and m_customSetterFunctionMap should be sets, not maps, and should use both the identifier and function pointer as the key
+ https://bugs.webkit.org/show_bug.cgi?id=223613
+
+ Reviewed by Saam Barati.
+
+ - Adds a generic WeakGCSet class to go with the existing WeakGCMap.
+ - Renames WeakGCMapBase to WeakGCHashTable, moves it to its own file
+ and now uses it as the base class of both WeakGCSet and WeakGCMap.
+ - Replaces JSGlobalObject's customGetterFunctionMap/customSetterFunctionMap
+ with customGetterFunctionSet/customSetterFunctionSet, using the new
+ WeakGCSet, and updates them to use both the function pointer and
+ property name for the key, rather than just the function pointer which
+ is what the previous code did. This allows multiple custom functions
+ to use the same underlying function pointer as long as they have distinct
+ property names, which is going to be used to optimize the bindings for
+ CSSStyleDeclaration.
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ Add new files.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::runEndPhase):
+ (JSC::Heap::pruneStaleEntriesFromWeakGCHashTables):
+ (JSC::Heap::registerWeakGCHashTable):
+ (JSC::Heap::unregisterWeakGCHashTable):
+ (JSC::Heap::pruneStaleEntriesFromWeakGCMaps): Deleted.
+ (JSC::Heap::registerWeakGCMap): Deleted.
+ (JSC::Heap::unregisterWeakGCMap): Deleted.
+ * heap/Heap.h:
+ Update for new name. WeakGCMapBase -> WeakGCHashTable.
+
+ * runtime/JSCInlines.h:
+ Add WeakGCSetInlines.h
+
+ * runtime/JSCustomGetterFunction.cpp:
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ (JSC::JSCustomGetterFunction::JSCustomGetterFunction):
+ (JSC::JSCustomGetterFunction::create):
+ * runtime/JSCustomGetterFunction.h:
+ * runtime/JSCustomSetterFunction.cpp:
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ (JSC::JSCustomSetterFunction::JSCustomSetterFunction):
+ (JSC::JSCustomSetterFunction::create):
+ * runtime/JSCustomSetterFunction.h:
+ Add helper type CustomFunctionPointer and helper function customFunctionPointer()
+ to allow some generic hashing code to run on either JSCustomGetterFunction
+ or JSCustomSetterFunction.
+
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::JSGlobalObject):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::WeakCustomGetterOrSetterHash::hash):
+ (JSC::JSGlobalObject::WeakCustomGetterOrSetterHash::equal):
+ (JSC::JSGlobalObject::customGetterFunctionSet):
+ (JSC::JSGlobalObject::customSetterFunctionSet):
+ (JSC::JSGlobalObject::customGetterFunctionMap): Deleted.
+ (JSC::JSGlobalObject::customSetterFunctionMap): Deleted.
+ Replace m_customGetterFunctionMap/m_customSetterFunctionMap with
+ m_customGetterFunctionSet/m_customSetterFunctionSet. As the key is included
+ in the value, it saves space to use a set rather than a map. We now also
+ hash and compare both the function pointer and the property name to allow
+ sharing implementations.
+
+ * runtime/JSObject.cpp:
+ (JSC::WeakCustomGetterOrSetterHashTranslator::hash):
+ (JSC::WeakCustomGetterOrSetterHashTranslator::equal):
+ (JSC::createCustomGetterFunction):
+ (JSC::createCustomSetterFunction):
+ Update creation functions to use the new sets, making use of the
+ ensureValue function and a HashTranslator allowing the use of a
+ std::pair<PropertyName, FunctionPointer> as an alternative lookup
+ key. This allows us to avoid creating the JSCustomGetterFunction/JSCustomSetterFunction
+ pointer if one with the same property name and function pointer are
+ already in the set.
+
+ * runtime/WeakGCHashTable.h: Added.
+ (JSC::WeakGCHashTable::~WeakGCHashTable):
+ Moved from WeakGCMap and renamed as it is now the base of both
+ WeakGCMap and WeakGCSet.
+
+ * runtime/WeakGCMap.h:
+ Update to use new WeakGCHashTable base class.
+
+ * runtime/WeakGCMapInlines.h:
+ (JSC::KeyTraitsArg>::WeakGCMap):
+ (JSC::KeyTraitsArg>::~WeakGCMap):
+ Update for new Heap function names for WeakGCHashTable.
+
+ * runtime/WeakGCSet.h: Added.
+ * runtime/WeakGCSetInlines.h: Added.
+ (JSC::TraitsArg>::WeakGCSet):
+ (JSC::TraitsArg>::~WeakGCSet):
+ (JSC::TraitsArg>::find):
+ (JSC::TraitsArg>::find const):
+ (JSC::TraitsArg>::contains const):
+ (JSC::TraitsArg>::pruneStaleEntries):
+ Added a minimal WeakGCSet based on WeakGCMap.
+
2021-03-30 Mark Lam <mark....@apple.com>
Add disableForwardingVPrintfStdErrToOSLog() and use it in the jsc shell.
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (275260 => 275261)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2021-03-31 02:55:38 UTC (rev 275261)
@@ -1729,6 +1729,9 @@
BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD203480E17135E002C7E82 /* DatePrototype.h */; };
BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */; };
BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDE3AB10E6C82CF001453A7 /* Structure.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ BCE2FAFB260916EF000A510F /* WeakGCSet.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE2FAFA260916EF000A510F /* WeakGCSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ BCE2FAFD260916FF000A510F /* WeakGCSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE2FAFC260916FF000A510F /* WeakGCSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ BCE2FAFF26091782000A510F /* WeakGCHashTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE2FAFE26091782000A510F /* WeakGCHashTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCF605140E203EF800B9A64D /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
BDFCB2BBE90F41349E1B0BED /* JSSourceCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3032175DF1AD47D8998B34E1 /* JSSourceCode.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4893,6 +4896,9 @@
BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes.cpp; sourceTree = "<group>"; };
BCDE3AB00E6C82CF001453A7 /* Structure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Structure.cpp; sourceTree = "<group>"; };
BCDE3AB10E6C82CF001453A7 /* Structure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Structure.h; sourceTree = "<group>"; };
+ BCE2FAFA260916EF000A510F /* WeakGCSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakGCSet.h; sourceTree = "<group>"; };
+ BCE2FAFC260916FF000A510F /* WeakGCSetInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakGCSetInlines.h; sourceTree = "<group>"; };
+ BCE2FAFE26091782000A510F /* WeakGCHashTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakGCHashTable.h; sourceTree = "<group>"; };
BCF605110E203EF800B9A64D /* ArgList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArgList.cpp; sourceTree = "<group>"; };
BCF605120E203EF800B9A64D /* ArgList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgList.h; sourceTree = "<group>"; };
BCFD8C900EEB2EE700283848 /* JumpTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpTable.cpp; sourceTree = "<group>"; };
@@ -7895,8 +7901,11 @@
FE6F56DD1E64E92000D17801 /* VMTraps.h */,
FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
+ BCE2FAFE26091782000A510F /* WeakGCHashTable.h */,
14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */,
+ BCE2FAFA260916EF000A510F /* WeakGCSet.h */,
+ BCE2FAFC260916FF000A510F /* WeakGCSetInlines.h */,
A7CA3ADD17DA41AE006538AF /* WeakMapConstructor.cpp */,
A7CA3ADE17DA41AE006538AF /* WeakMapConstructor.h */,
E3A32BC51FC8312D007D7E76 /* WeakMapImpl.cpp */,
@@ -9218,6 +9227,7 @@
8BC0648B1E1ABA9400B2B8CA /* AsyncGeneratorFunctionConstructor.h in Headers */,
8BC0648A1E1ABA7B00B2B8CA /* AsyncGeneratorFunctionPrototype.h in Headers */,
8BC064921E1ADCC400B2B8CA /* AsyncGeneratorPrototype.h in Headers */,
+ BCE2FAFF26091782000A510F /* WeakGCHashTable.h in Headers */,
8B3BF5E41E3D368B0076A87A /* AsyncGeneratorPrototype.lut.h in Headers */,
8BC064961E1D845C00B2B8CA /* AsyncIteratorPrototype.h in Headers */,
6A38CFAA1E32B5AB0060206F /* AsyncStackTrace.h in Headers */,
@@ -9682,6 +9692,7 @@
14386A751DD69895008652C4 /* DirectEvalExecutable.h in Headers */,
0F37308F1C0CD68500052BFA /* DisallowMacroScratchRegisterUsage.h in Headers */,
FE54DEFF1E8D76FA00A892C5 /* DisallowScope.h in Headers */,
+ BCE2FAFB260916EF000A510F /* WeakGCSet.h in Headers */,
FE54DEFB1E8C6D8800A892C5 /* DisallowVMEntry.h in Headers */,
0FF42731158EBD54004CB9FF /* Disassembler.h in Headers */,
E31618131EC5FE170006A218 /* DOMAnnotation.h in Headers */,
@@ -10339,6 +10350,7 @@
14F79F70216EAFD200046D39 /* Opcode.h in Headers */,
FE64872E2141D04800AB0D3E /* OpcodeInlines.h in Headers */,
14A4680D216FA56A000D2B1A /* OpcodeSize.h in Headers */,
+ BCE2FAFD260916FF000A510F /* WeakGCSetInlines.h in Headers */,
0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */,
A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */,
BC18C4480E16F5CD00B34460 /* Operations.h in Headers */,
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (275260 => 275261)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2021-03-31 02:55:38 UTC (rev 275261)
@@ -1510,7 +1510,7 @@
m_structureIDTable.flushOldTables();
reapWeakHandles();
- pruneStaleEntriesFromWeakGCMaps();
+ pruneStaleEntriesFromWeakGCHashTables();
sweepArrayBuffers();
snapshotUnswept();
finalizeUnconditionalFinalizers(); // We rely on these unconditional finalizers running before clearCurrentlyExecuting since CodeBlock's finalizer relies on querying currently executing.
@@ -2217,12 +2217,12 @@
m_objectSpace.reapWeakSets();
}
-void Heap::pruneStaleEntriesFromWeakGCMaps()
+void Heap::pruneStaleEntriesFromWeakGCHashTables()
{
if (!m_collectionScope || m_collectionScope.value() != CollectionScope::Full)
return;
- for (WeakGCMapBase* weakGCMap : m_weakGCMaps)
- weakGCMap->pruneStaleEntries();
+ for (auto* weakGCHashTable : m_weakGCHashTables)
+ weakGCHashTable->pruneStaleEntries();
}
void Heap::sweepArrayBuffers()
@@ -2674,14 +2674,14 @@
collectIfNecessaryOrDefer();
}
-void Heap::registerWeakGCMap(WeakGCMapBase* weakGCMap)
+void Heap::registerWeakGCHashTable(WeakGCHashTable* weakGCHashTable)
{
- m_weakGCMaps.add(weakGCMap);
+ m_weakGCHashTables.add(weakGCHashTable);
}
-void Heap::unregisterWeakGCMap(WeakGCMapBase* weakGCMap)
+void Heap::unregisterWeakGCHashTable(WeakGCHashTable* weakGCHashTable)
{
- m_weakGCMaps.remove(weakGCMap);
+ m_weakGCHashTables.remove(weakGCHashTable);
}
void Heap::didAllocateBlock(size_t capacity)
Modified: trunk/Source/_javascript_Core/heap/Heap.h (275260 => 275261)
--- trunk/Source/_javascript_Core/heap/Heap.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -87,7 +87,7 @@
class SweepingScope;
class VM;
class VerifierSlotVisitor;
-class WeakGCMapBase;
+class WeakGCHashTable;
struct CurrentThreadState;
#ifdef JSC_GLIB_API_ENABLED
@@ -289,8 +289,8 @@
void releaseSoon(std::unique_ptr<JSCGLibWrapperObject>&&);
#endif
- JS_EXPORT_PRIVATE void registerWeakGCMap(WeakGCMapBase* weakGCMap);
- JS_EXPORT_PRIVATE void unregisterWeakGCMap(WeakGCMapBase* weakGCMap);
+ JS_EXPORT_PRIVATE void registerWeakGCHashTable(WeakGCHashTable*);
+ JS_EXPORT_PRIVATE void unregisterWeakGCHashTable(WeakGCHashTable*);
void addLogicallyEmptyWeakBlock(WeakBlock*);
@@ -526,7 +526,7 @@
void endMarking();
void reapWeakHandles();
- void pruneStaleEntriesFromWeakGCMaps();
+ void pruneStaleEntriesFromWeakGCHashTables();
void sweepArrayBuffers();
void snapshotUnswept();
void deleteSourceProviderCaches();
@@ -689,7 +689,7 @@
#endif
unsigned m_deferralDepth { 0 };
- HashSet<WeakGCMapBase*> m_weakGCMaps;
+ HashSet<WeakGCHashTable*> m_weakGCHashTables;
std::unique_ptr<MarkStackArray> m_sharedCollectorMarkStack;
std::unique_ptr<MarkStackArray> m_sharedMutatorMarkStack;
Modified: trunk/Source/_javascript_Core/runtime/JSCInlines.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSCInlines.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSCInlines.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -54,3 +54,4 @@
#include "StructureInlines.h"
#include "ThrowScope.h"
#include "WeakGCMapInlines.h"
+#include "WeakGCSetInlines.h"
Modified: trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.cpp (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.cpp 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.cpp 2021-03-31 02:55:38 UTC (rev 275261)
@@ -40,7 +40,7 @@
JSCustomGetterFunction* customGetterFunction = jsCast<JSCustomGetterFunction*>(callFrame->jsCallee());
JSValue thisValue = callFrame->thisValue();
- GetValueFunc getter = customGetterFunction->getter();
+ auto getter = customGetterFunction->getter();
if (auto domAttribute = customGetterFunction->domAttribute()) {
if (!thisValue.inherits(vm, domAttribute->classInfo))
@@ -50,7 +50,7 @@
RELEASE_AND_RETURN(scope, getter(globalObject, JSValue::encode(thisValue), customGetterFunction->propertyName()));
}
-JSCustomGetterFunction::JSCustomGetterFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, const PropertyName& propertyName, GetValueFunc getter, Optional<DOMAttributeAnnotation> domAttribute)
+JSCustomGetterFunction::JSCustomGetterFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, const PropertyName& propertyName, CustomFunctionPointer getter, Optional<DOMAttributeAnnotation> domAttribute)
: Base(vm, executable, globalObject, structure)
, m_propertyName(Identifier::fromUid(vm, propertyName.uid()))
, m_getter(getter)
@@ -58,7 +58,7 @@
{
}
-JSCustomGetterFunction* JSCustomGetterFunction::create(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, GetValueFunc getter, Optional<DOMAttributeAnnotation> domAttribute)
+JSCustomGetterFunction* JSCustomGetterFunction::create(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, CustomFunctionPointer getter, Optional<DOMAttributeAnnotation> domAttribute)
{
ASSERT(getter);
NativeExecutable* executable = vm.getHostFunction(customGetterFunctionCall, callHostFunctionAsConstructor, String(propertyName.publicName()));
Modified: trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSCustomGetterFunction.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -34,6 +34,8 @@
typedef JSFunction Base;
static constexpr unsigned StructureFlags = Base::StructureFlags;
+ using CustomFunctionPointer = GetValueFunc;
+
static constexpr bool needsDestruction = true;
static void destroy(JSCell*);
@@ -49,19 +51,20 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
}
- JS_EXPORT_PRIVATE static JSCustomGetterFunction* create(VM&, JSGlobalObject*, const PropertyName&, GetValueFunc, Optional<DOMAttributeAnnotation> = WTF::nullopt);
+ JS_EXPORT_PRIVATE static JSCustomGetterFunction* create(VM&, JSGlobalObject*, const PropertyName&, CustomFunctionPointer, Optional<DOMAttributeAnnotation> = WTF::nullopt);
DECLARE_EXPORT_INFO;
const Identifier& propertyName() const { return m_propertyName; }
- GetValueFunc getter() const { return m_getter; };
+ CustomFunctionPointer getter() const { return m_getter; };
+ CustomFunctionPointer customFunctionPointer() const { return m_getter; };
Optional<DOMAttributeAnnotation> domAttribute() const { return m_domAttribute; };
private:
- JSCustomGetterFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, const PropertyName&, GetValueFunc, Optional<DOMAttributeAnnotation>);
+ JSCustomGetterFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, const PropertyName&, CustomFunctionPointer, Optional<DOMAttributeAnnotation>);
Identifier m_propertyName;
- GetValueFunc m_getter;
+ CustomFunctionPointer m_getter;
Optional<DOMAttributeAnnotation> m_domAttribute;
};
Modified: trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.cpp (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.cpp 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.cpp 2021-03-31 02:55:38 UTC (rev 275261)
@@ -36,12 +36,12 @@
JSC_DEFINE_HOST_FUNCTION(customSetterFunctionCall, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
auto customSetterFunction = jsCast<JSCustomSetterFunction*>(callFrame->jsCallee());
- PutValueFunc setter = customSetterFunction->setter();
+ auto setter = customSetterFunction->setter();
setter(globalObject, JSValue::encode(callFrame->thisValue()), JSValue::encode(callFrame->argument(0)), customSetterFunction->propertyName());
return JSValue::encode(jsUndefined());
}
-JSCustomSetterFunction::JSCustomSetterFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, const PropertyName& propertyName, PutValueFunc setter)
+JSCustomSetterFunction::JSCustomSetterFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, const PropertyName& propertyName, CustomFunctionPointer setter)
: Base(vm, executable, globalObject, structure)
, m_propertyName(Identifier::fromUid(vm, propertyName.uid()))
, m_setter(setter)
@@ -48,7 +48,7 @@
{
}
-JSCustomSetterFunction* JSCustomSetterFunction::create(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, PutValueFunc setter)
+JSCustomSetterFunction* JSCustomSetterFunction::create(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, CustomFunctionPointer setter)
{
ASSERT(setter);
NativeExecutable* executable = vm.getHostFunction(customSetterFunctionCall, callHostFunctionAsConstructor, String(propertyName.publicName()));
Modified: trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -34,6 +34,8 @@
typedef JSFunction Base;
static constexpr unsigned StructureFlags = Base::StructureFlags;
+ using CustomFunctionPointer = PutValueFunc;
+
static constexpr bool needsDestruction = true;
static void destroy(JSCell*);
@@ -49,18 +51,19 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
}
- JS_EXPORT_PRIVATE static JSCustomSetterFunction* create(VM&, JSGlobalObject*, const PropertyName&, PutValueFunc);
+ JS_EXPORT_PRIVATE static JSCustomSetterFunction* create(VM&, JSGlobalObject*, const PropertyName&, CustomFunctionPointer);
DECLARE_EXPORT_INFO;
const Identifier& propertyName() const { return m_propertyName; }
- PutValueFunc setter() const { return m_setter; };
+ CustomFunctionPointer setter() const { return m_setter; };
+ CustomFunctionPointer customFunctionPointer() const { return m_setter; };
private:
- JSCustomSetterFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, const PropertyName&, PutValueFunc);
+ JSCustomSetterFunction(VM&, NativeExecutable*, JSGlobalObject*, Structure*, const PropertyName&, CustomFunctionPointer);
Identifier m_propertyName;
- PutValueFunc m_setter;
+ CustomFunctionPointer m_setter;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2021-03-31 02:55:38 UTC (rev 275261)
@@ -507,8 +507,8 @@
, m_numberToStringWatchpointSet(IsWatched)
, m_runtimeFlags()
, m_stackTraceLimit(Options::defaultErrorStackTraceLimit())
- , m_customGetterFunctionMap(vm)
- , m_customSetterFunctionMap(vm)
+ , m_customGetterFunctionSet(vm)
+ , m_customSetterFunctionSet(vm)
, m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
{
}
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -35,8 +35,8 @@
#include "JSPromise.h"
#include "JSSegmentedVariableObject.h"
#include "JSWeakObjectMapRefInternal.h"
+#include "LazyClassStructure.h"
#include "LazyProperty.h"
-#include "LazyClassStructure.h"
#include "NumberPrototype.h"
#include "ParserModes.h"
#include "RegExpGlobalData.h"
@@ -45,6 +45,7 @@
#include "SymbolPrototype.h"
#include "VM.h"
#include "Watchpoint.h"
+#include "WeakGCSet.h"
#include <_javascript_Core/JSBase.h>
#include <array>
#include <wtf/HashSet.h>
@@ -546,8 +547,6 @@
bool isMapPrototypeSetFastAndNonObservable();
bool isSetPrototypeAddFastAndNonObservable();
- WeakGCMap<GetValueFunc, JSCustomGetterFunction>& customGetterFunctionMap() { return m_customGetterFunctionMap; }
- WeakGCMap<PutValueFunc, JSCustomSetterFunction>& customSetterFunctionMap() { return m_customSetterFunctionMap; }
#if ENABLE(DFG_JIT)
using ReferencedGlobalPropertyWatchpointSets = HashMap<RefPtr<UniquedStringImpl>, Ref<WatchpointSet>, IdentifierRepHash>;
@@ -563,9 +562,22 @@
RuntimeFlags m_runtimeFlags;
ConsoleClient* m_consoleClient { nullptr };
Optional<unsigned> m_stackTraceLimit;
- WeakGCMap<GetValueFunc, JSCustomGetterFunction> m_customGetterFunctionMap;
- WeakGCMap<PutValueFunc, JSCustomSetterFunction> m_customSetterFunctionMap;
+ template<typename T>
+ struct WeakCustomGetterOrSetterHash {
+ static unsigned hash(const Weak<T>&);
+ static bool equal(const Weak<T>&, const Weak<T>&);
+ static unsigned hash(const PropertyName&, typename T::CustomFunctionPointer);
+
+ static constexpr bool safeToCompareToEmptyOrDeleted = false;
+ };
+
+ WeakGCSet<JSCustomGetterFunction, WeakCustomGetterOrSetterHash<JSCustomGetterFunction>> m_customGetterFunctionSet;
+ WeakGCSet<JSCustomSetterFunction, WeakCustomGetterOrSetterHash<JSCustomSetterFunction>> m_customSetterFunctionSet;
+
+ WeakGCSet<JSCustomGetterFunction, WeakCustomGetterOrSetterHash<JSCustomGetterFunction>>& customGetterFunctionSet() { return m_customGetterFunctionSet; }
+ WeakGCSet<JSCustomSetterFunction, WeakCustomGetterOrSetterHash<JSCustomSetterFunction>>& customSetterFunctionSet() { return m_customSetterFunctionSet; }
+
#if ASSERT_ENABLED
const JSGlobalObject* m_globalObjectAtDebuggerEntry { nullptr };
#endif
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectInlines.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectInlines.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectInlines.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -29,6 +29,8 @@
#include "ArrayConstructor.h"
#include "ArrayPrototype.h"
+#include "JSCustomGetterFunction.h"
+#include "JSCustomSetterFunction.h"
#include "JSFunction.h"
#include "LinkTimeConstant.h"
#include "ObjectPrototype.h"
@@ -124,4 +126,29 @@
return globalObject->vm();
}
+template<typename T>
+inline unsigned JSGlobalObject::WeakCustomGetterOrSetterHash<T>::hash(const Weak<T>& value)
+{
+ if (!value)
+ return 0;
+ return hash(value->propertyName(), value->customFunctionPointer());
+}
+
+template<typename T>
+inline bool JSGlobalObject::WeakCustomGetterOrSetterHash<T>::equal(const Weak<T>& a, const Weak<T>& b)
+{
+ if (!a || !b)
+ return false;
+ return a == b;
+}
+
+template<typename T>
+inline unsigned JSGlobalObject::WeakCustomGetterOrSetterHash<T>::hash(const PropertyName& propertyName, typename T::CustomFunctionPointer functionPointer)
+{
+ unsigned hash = DefaultHash<typename T::CustomFunctionPointer>::hash(functionPointer);
+ if (!propertyName.isNull())
+ hash = WTF::pairIntHash(hash, propertyName.uid()->existingSymbolAwareHash());
+ return hash;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2021-03-31 02:55:38 UTC (rev 275261)
@@ -3521,12 +3521,33 @@
return Butterfly::createOrGrowPropertyStorage(butterfly(), vm, this, structure(vm), oldSize, newSize);
}
+template<typename T>
+struct WeakCustomGetterOrSetterHashTranslator {
+ using BaseHash = JSGlobalObject::WeakCustomGetterOrSetterHash<T>;
+
+ using Key = std::pair<PropertyName, typename T::CustomFunctionPointer>;
+
+ static unsigned hash(const Key& key)
+ {
+ return BaseHash::hash(std::get<0>(key), std::get<1>(key));
+ }
+
+ static bool equal(const Weak<T>& a, const Key& b)
+ {
+ if (!a)
+ return false;
+ return a->propertyName() == std::get<0>(b) && a->customFunctionPointer() == std::get<1>(b);
+ }
+};
+
static JSCustomGetterFunction* createCustomGetterFunction(JSGlobalObject* globalObject, VM& vm, PropertyName propertyName, GetValueFunc getValueFunc, Optional<DOMAttributeAnnotation> domAttribute)
{
- // WeakGCMap::ensureValue's functor must not invoke GC since GC can modify WeakGCMap in the middle of HashMap::ensure.
- // We use DeferGC here (1) not to invoke GC when executing WeakGCMap::ensureValue and (2) to avoid looking up HashMap twice.
+ using Translator = WeakCustomGetterOrSetterHashTranslator<JSCustomGetterFunction>;
+
+ // WeakGCSet::ensureValue's functor must not invoke GC since GC can modify WeakGCSet in the middle of HashSet::ensure.
+ // We use DeferGC here (1) not to invoke GC when executing WeakGCSet::ensureValue and (2) to avoid looking up HashSet twice.
DeferGC deferGC(vm.heap);
- return globalObject->customGetterFunctionMap().ensureValue(getValueFunc, [&] {
+ return globalObject->customGetterFunctionSet().ensureValue<Translator>(std::make_pair(propertyName, getValueFunc), [&] {
return JSCustomGetterFunction::create(vm, globalObject, propertyName, getValueFunc, domAttribute);
});
}
@@ -3533,10 +3554,12 @@
static JSCustomSetterFunction* createCustomSetterFunction(JSGlobalObject* globalObject, VM& vm, PropertyName propertyName, PutValueFunc putValueFunc)
{
- // WeakGCMap::ensureValue's functor must not invoke GC since GC can modify WeakGCMap in the middle of HashMap::ensure.
- // We use DeferGC here (1) not to invoke GC when executing WeakGCMap::ensureValue and (2) to avoid looking up HashMap twice.
+ using Translator = WeakCustomGetterOrSetterHashTranslator<JSCustomSetterFunction>;
+
+ // WeakGCSet::ensureValue's functor must not invoke GC since GC can modify WeakGCSet in the middle of HashSet::ensure.
+ // We use DeferGC here (1) not to invoke GC when executing WeakGCSet::ensureValue and (2) to avoid looking up HashSet twice.
DeferGC deferGC(vm.heap);
- return globalObject->customSetterFunctionMap().ensureValue(putValueFunc, [&] {
+ return globalObject->customSetterFunctionSet().ensureValue<Translator>(std::make_pair(propertyName, putValueFunc), [&] {
return JSCustomSetterFunction::create(vm, globalObject, propertyName, putValueFunc);
});
}
Copied: trunk/Source/_javascript_Core/runtime/WeakGCHashTable.h (from rev 275260, trunk/Source/_javascript_Core/runtime/JSCustomSetterFunction.h) (0 => 275261)
--- trunk/Source/_javascript_Core/runtime/WeakGCHashTable.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/WeakGCHashTable.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace JSC {
+
+class WeakGCHashTable {
+public:
+ virtual ~WeakGCHashTable() { }
+ virtual void pruneStaleEntries() = 0;
+};
+
+}
Modified: trunk/Source/_javascript_Core/runtime/WeakGCMap.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/WeakGCMap.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMap.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -27,6 +27,7 @@
#include "DeferGC.h"
#include "Weak.h"
+#include "WeakGCHashTable.h"
#include <wtf/HashMap.h>
namespace JSC {
@@ -33,15 +34,8 @@
// A HashMap with Weak<JSCell> values, which automatically removes values once they're garbage collected.
-class WeakGCMapBase {
-public:
- virtual ~WeakGCMapBase() { }
- virtual void pruneStaleEntries() = 0;
-};
-
-template<typename KeyArg, typename ValueArg, typename HashArg = DefaultHash<KeyArg>,
- typename KeyTraitsArg = HashTraits<KeyArg>>
-class WeakGCMap final : public WeakGCMapBase {
+template<typename KeyArg, typename ValueArg, typename HashArg = DefaultHash<KeyArg>, typename KeyTraitsArg = HashTraits<KeyArg>>
+class WeakGCMap final : public WeakGCHashTable {
WTF_MAKE_FAST_ALLOCATED;
typedef Weak<ValueArg> ValueType;
typedef HashMap<KeyArg, ValueType, HashArg, KeyTraitsArg> HashMapType;
Modified: trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h (275260 => 275261)
--- trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -35,13 +35,13 @@
inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::WeakGCMap(VM& vm)
: m_vm(vm)
{
- vm.heap.registerWeakGCMap(this);
+ vm.heap.registerWeakGCHashTable(this);
}
template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::~WeakGCMap()
{
- m_vm.heap.unregisterWeakGCMap(this);
+ m_vm.heap.unregisterWeakGCHashTable(this);
}
template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
Added: trunk/Source/_javascript_Core/runtime/WeakGCSet.h (0 => 275261)
--- trunk/Source/_javascript_Core/runtime/WeakGCSet.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/WeakGCSet.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Weak.h"
+#include "WeakGCHashTable.h"
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+// A HashSet with Weak<JSCell> values, which automatically removes values once they're garbage collected.
+
+template<typename T>
+struct WeakGCSetHashTraits : HashTraits<Weak<T>> {
+ static constexpr bool hasIsReleasedWeakValueFunction = true;
+ static bool isReleasedWeakValue(const Weak<T>& value)
+ {
+ return !value.isHashTableDeletedValue() && !value.isHashTableEmptyValue() && !value;
+ }
+};
+
+template<typename ValueArg, typename HashArg = DefaultHash<Weak<ValueArg>>, typename TraitsArg = WeakGCSetHashTraits<ValueArg>>
+class WeakGCSet final : public WeakGCHashTable {
+ WTF_MAKE_FAST_ALLOCATED;
+ using ValueType = Weak<ValueArg>;
+ using HashSetType = HashSet<ValueType, HashArg, TraitsArg>;
+
+public:
+ using AddResult = typename HashSetType::AddResult;
+ using iterator = typename HashSetType::iterator;
+ using const_iterator = typename HashSetType::const_iterator;
+
+ explicit WeakGCSet(VM&);
+ ~WeakGCSet() final;
+
+ void clear()
+ {
+ m_set.clear();
+ }
+
+ template<typename HashTranslator, typename T, typename Functor>
+ ValueArg* ensureValue(T&& key, Functor&& functor)
+ {
+ // If functor invokes GC, GC can prune WeakGCSet, and manipulate HashSet while we are touching it in the ensure function.
+ // The functor must not invoke GC.
+ DisallowGC disallowGC;
+
+ auto result = m_set.template ensure<HashTranslator>(std::forward<T>(key), std::forward<Functor>(functor));
+ return result.iterator->get();
+ }
+
+ inline iterator find(const ValueType& key);
+ inline const_iterator find(const ValueType& key) const;
+ inline bool contains(const ValueType&) const;
+
+private:
+ void pruneStaleEntries() final;
+
+ HashSetType m_set;
+ VM& m_vm;
+};
+
+} // namespace JSC
Added: trunk/Source/_javascript_Core/runtime/WeakGCSetInlines.h (0 => 275261)
--- trunk/Source/_javascript_Core/runtime/WeakGCSetInlines.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/WeakGCSetInlines.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "HeapInlines.h"
+#include "WeakGCSet.h"
+#include "WeakInlines.h"
+
+namespace JSC {
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+inline WeakGCSet<ValueArg, HashArg, TraitsArg>::WeakGCSet(VM& vm)
+ : m_vm(vm)
+{
+ vm.heap.registerWeakGCHashTable(this);
+}
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+inline WeakGCSet<ValueArg, HashArg, TraitsArg>::~WeakGCSet()
+{
+ m_vm.heap.unregisterWeakGCHashTable(this);
+}
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+inline typename WeakGCSet<ValueArg, HashArg, TraitsArg>::iterator WeakGCSet<ValueArg, HashArg, TraitsArg>::find(const ValueType& value)
+{
+ iterator it = m_set.find(value);
+ iterator end = m_set.end();
+ if (it != end && !*it) // Found a zombie value.
+ return end;
+ return it;
+}
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+inline typename WeakGCSet<ValueArg, HashArg, TraitsArg>::const_iterator WeakGCSet<ValueArg, HashArg, TraitsArg>::find(const ValueType& value) const
+{
+ return const_cast<WeakGCSet*>(this)->find(value);
+}
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+inline bool WeakGCSet<ValueArg, HashArg, TraitsArg>::contains(const ValueType& value) const
+{
+ return find(value) != m_set.end();
+}
+
+template<typename ValueArg, typename HashArg, typename TraitsArg>
+NEVER_INLINE void WeakGCSet<ValueArg, HashArg, TraitsArg>::pruneStaleEntries()
+{
+ m_set.removeIf([](auto& entry) {
+ return !entry;
+ });
+}
+
+} // namespace JSC
Modified: trunk/Source/WTF/ChangeLog (275260 => 275261)
--- trunk/Source/WTF/ChangeLog 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/WTF/ChangeLog 2021-03-31 02:55:38 UTC (rev 275261)
@@ -1,3 +1,41 @@
+2021-03-30 Sam Weinig <wei...@apple.com>
+
+ JSGlobalObject's m_customGetterFunctionMap and m_customSetterFunctionMap should be sets, not maps, and should use both the identifier and function pointer as the key
+ https://bugs.webkit.org/show_bug.cgi?id=223613
+
+ Reviewed by Saam Barati.
+
+ Adds a heterogenous HashSet::ensure, which allows lazy construction of the value to
+ insert into the HashSet only if the heterogenous key (e.g. a key + HashTranslator
+ that are not the same as the HashSet's ValueType) does not match any item in the
+ set. For example given a set of ExpensiveToConstruct, but uniquely identifiable
+ by CheapToConstruct:
+
+ HashSet<ExpensiveToConstruct> hashSet;
+ ...
+ struct Translator {
+ static unsigned hash(const CheapToConstruct& key)
+ {
+ return key.hash();
+ }
+ static bool equal(const ExpensiveToConstruct& a, const CheapToConstruct& b)
+ {
+ return a == b;
+ }
+ };
+
+ hashSet.ensure<Translator>(CheapToConstruct { ... }, [] {
+ return ExpensiveToConstruct { ... };
+ });
+
+ This will be used by the custom getter/setter sets to avoid constructing the GC objects
+ unless they are really needed.
+
+ Also took the opertunity to replace some typedefs with usings, and fixed some comments.
+
+ * wtf/HashSet.h:
+ (WTF::Traits>::ensure):
+
2021-03-30 Mark Lam <mark....@apple.com>
Add disableForwardingVPrintfStdErrToOSLog() and use it in the jsc shell.
Modified: trunk/Source/WTF/wtf/HashSet.h (275260 => 275261)
--- trunk/Source/WTF/wtf/HashSet.h 2021-03-31 02:52:37 UTC (rev 275260)
+++ trunk/Source/WTF/wtf/HashSet.h 2021-03-31 02:55:38 UTC (rev 275261)
@@ -33,36 +33,30 @@
class HashSet final {
WTF_MAKE_FAST_ALLOCATED;
private:
- typedef HashArg HashFunctions;
- typedef TraitsArg ValueTraits;
- typedef typename ValueTraits::TakeType TakeType;
+ using HashFunctions = HashArg;
+ using ValueTraits = TraitsArg;
+ using TakeType = typename ValueTraits::TakeType;
public:
- typedef typename ValueTraits::TraitType ValueType;
+ using ValueType = typename ValueTraits::TraitType;
private:
- typedef HashTable<ValueType, ValueType, IdentityExtractor,
- HashFunctions, ValueTraits, ValueTraits> HashTableType;
+ using HashTableType = HashTable<ValueType, ValueType, IdentityExtractor, HashFunctions, ValueTraits, ValueTraits>;
public:
- /*
- * Since figuring out the entries of an iterator is confusing, here is a cheat sheet:
- * const KeyType& key = iterator->key;
- */
- typedef HashTableConstIteratorAdapter<HashTableType, ValueType> iterator;
- typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
+ // HashSet iterators have the following structure:
+ // const ValueType* get() const;
+ // const ValueType& operator*() const;
+ // const ValueType* operator->() const;
+ using iterator = HashTableConstIteratorAdapter<HashTableType, ValueType>;
+ using const_iterator = HashTableConstIteratorAdapter<HashTableType, ValueType>;
- /*
- * Since figuring out the entries of an AddResult is confusing, here is a cheat sheet:
- * iterator iter = addResult.iterator;
- * bool isNewEntry = addResult.isNewEntry;
- */
- typedef typename HashTableType::AddResult AddResult;
+ // HashSet AddResults have the following fields:
+ // IteratorType iterator;
+ // bool isNewEntry;
+ using AddResult = typename HashTableType::AddResult;
- HashSet()
- {
- }
-
+ HashSet() = default;
HashSet(std::initializer_list<ValueArg> initializerList)
{
for (const auto& value : initializerList)
@@ -93,6 +87,7 @@
template<typename HashTranslator, typename T> iterator find(const T&) const;
template<typename HashTranslator, typename T> bool contains(const T&) const;
+
// The return value includes both an iterator to the added value's location,
// and an isNewEntry bool that indicates if it is a new or existing entry in the set.
AddResult add(const ValueType&);
@@ -110,6 +105,16 @@
// static translate(ValueType&, const T&, unsigned hashCode);
template<typename HashTranslator, typename T> AddResult add(const T&);
+ // An alternate version of translated add(), ensure() will still do translation
+ // by hashing and comparing with some other type, to avoid the cost of type
+ // conversion if the object is already in the table, but rather than a static
+ // translate() function, uses the passed in functor to perform lazy creation of
+ // the value only if it is not already there. HashTranslator must have the following
+ // function members:
+ // static unsigned hash(const T&);
+ // static bool equal(const ValueType&, const T&);
+ template<typename HashTranslator, typename T, typename Functor> AddResult ensure(T&&, Functor&&);
+
// Attempts to add a list of things to the set. Returns true if any of
// them are new to the set. Returns false if the set is unchanged.
template<typename IteratorType>
@@ -171,6 +176,16 @@
}
};
+template<typename ValueTraits, typename Translator>
+struct HashSetEnsureTranslatorAdaptor {
+ template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
+ template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
+ template<typename T, typename U, typename Functor> static void translate(T& location, U&&, Functor&& functor)
+ {
+ ValueTraits::assignToEmpty(location, functor());
+ }
+};
+
template<typename T, typename U, typename V>
inline void HashSet<T, U, V>::swap(HashSet& other)
{
@@ -233,6 +248,13 @@
return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator>>(value);
}
+template<typename Value, typename HashFunctions, typename Traits>
+template<typename HashTranslator, typename T, typename Functor>
+inline auto HashSet<Value, HashFunctions, Traits>::ensure(T&& key, Functor&& functor) -> AddResult
+{
+ return m_impl.template add<HashSetEnsureTranslatorAdaptor<Traits, HashTranslator>>(std::forward<T>(key), std::forward<Functor>(functor));
+}
+
template<typename T, typename U, typename V>
inline auto HashSet<T, U, V>::add(const ValueType& value) -> AddResult
{