Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (223026 => 223027)
--- trunk/Source/_javascript_Core/ChangeLog 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-10-08 03:15:56 UTC (rev 223027)
@@ -1,5 +1,116 @@
2017-10-07 Filip Pizlo <[email protected]>
+ direct-construct-arity-mismatch.js can have GCs that take ~70ms if you force poly proto and disable generational GC
+ https://bugs.webkit.org/show_bug.cgi?id=178051
+
+ Reviewed by Saam Barati.
+
+ After I studied the profile of this test, I found two pathologies in our code relating to
+ prototypes. I think that now that we support poly proto, it's more likely for these pathologies to
+ happen. Also, the fact that we force poly proto in some tests, it's possible for one of our tests
+ to trigger these pathologies.
+
+ - WeakGCMap::m_prototoypes is the set of all prototypes. That's super dangerous. This patch turns
+ this into a bit in the JSCell header. It uses the last spare bit in indexingTypeAndMisc. Note
+ that we still have 6 spare bits in cellState, but those are a bit more annoying to get at.
+
+ - WeakGCMap registers itself with GC using a std::function. That means allocating things in the
+ malloc heap. This changes it to a virtual method on WeakGCMap. I don't know for sure that this is
+ a problem area, but there are places where we could allocate a lot of WeakGCMaps, like if we have
+ a lot of transition tables. It's good to reduce the amount of memory those require.
+
+ Also, I saw a FIXME about turning the std::tuple in PrototypeMap into a struct, so I did that while
+ I was at it. I initially thought that this would have to be part of my solution, but it turned out
+ not to be. I think it's worth landing anyway since it makes the code a lot more clear.
+
+ This fixes the timeout in that test and probably reduces memory consumption.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * dfg/DFGOperations.cpp:
+ * heap/Heap.cpp:
+ (JSC::Heap::pruneStaleEntriesFromWeakGCMaps):
+ (JSC::Heap::registerWeakGCMap):
+ (JSC::Heap::unregisterWeakGCMap):
+ * heap/Heap.h:
+ * inspector/JSInjectedScriptHostPrototype.cpp:
+ (Inspector::JSInjectedScriptHostPrototype::finishCreation):
+ * inspector/JSJavaScriptCallFramePrototype.cpp:
+ (Inspector::JSJavaScriptCallFramePrototype::finishCreation):
+ * runtime/ArrayIteratorPrototype.cpp:
+ (JSC::ArrayIteratorPrototype::finishCreation):
+ * runtime/ArrayPrototype.cpp:
+ (JSC::ArrayPrototype::finishCreation):
+ * runtime/AsyncFromSyncIteratorPrototype.cpp:
+ (JSC::AsyncFromSyncIteratorPrototype::finishCreation):
+ * runtime/AsyncFunctionPrototype.cpp:
+ (JSC::AsyncFunctionPrototype::finishCreation):
+ * runtime/AsyncGeneratorFunctionPrototype.cpp:
+ (JSC::AsyncGeneratorFunctionPrototype::finishCreation):
+ * runtime/AsyncGeneratorPrototype.cpp:
+ (JSC::AsyncGeneratorPrototype::finishCreation):
+ * runtime/AsyncIteratorPrototype.cpp:
+ (JSC::AsyncIteratorPrototype::finishCreation):
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/GeneratorFunctionPrototype.cpp:
+ (JSC::GeneratorFunctionPrototype::finishCreation):
+ * runtime/GeneratorPrototype.cpp:
+ (JSC::GeneratorPrototype::finishCreation):
+ * runtime/IndexingType.h:
+ * runtime/IteratorPrototype.cpp:
+ (JSC::IteratorPrototype::finishCreation):
+ * runtime/JSCInlines.h:
+ * runtime/JSCell.h:
+ * runtime/JSCellInlines.h:
+ (JSC::JSCell::mayBePrototype const):
+ (JSC::JSCell::didBecomePrototype):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::notifyPresenceOfIndexedAccessors):
+ (JSC::JSObject::setPrototypeDirect):
+ * runtime/JSProxy.cpp:
+ (JSC::JSProxy::setTarget):
+ * runtime/MapIteratorPrototype.cpp:
+ (JSC::MapIteratorPrototype::finishCreation):
+ * runtime/MapPrototype.cpp:
+ (JSC::MapPrototype::finishCreation):
+ * runtime/ObjectPrototype.cpp:
+ (JSC::ObjectPrototype::finishCreation):
+ * runtime/PrototypeKey.h: Added.
+ (JSC::PrototypeKey::PrototypeKey):
+ (JSC::PrototypeKey::prototype const):
+ (JSC::PrototypeKey::inlineCapacity const):
+ (JSC::PrototypeKey::classInfo const):
+ (JSC::PrototypeKey::globalObject const):
+ (JSC::PrototypeKey::operator== const):
+ (JSC::PrototypeKey::operator!= const):
+ (JSC::PrototypeKey::operator bool const):
+ (JSC::PrototypeKey::isHashTableDeletedValue const):
+ (JSC::PrototypeKey::hash const):
+ (JSC::PrototypeKeyHash::hash):
+ (JSC::PrototypeKeyHash::equal):
+ * runtime/PrototypeMap.cpp:
+ (JSC::PrototypeMap::createEmptyStructure):
+ (JSC::PrototypeMap::clearEmptyObjectStructureForPrototype):
+ * runtime/PrototypeMap.h:
+ (JSC::PrototypeMap::PrototypeMap):
+ * runtime/PrototypeMapInlines.h: Removed.
+ * runtime/SetIteratorPrototype.cpp:
+ (JSC::SetIteratorPrototype::finishCreation):
+ * runtime/SetPrototype.cpp:
+ (JSC::SetPrototype::finishCreation):
+ * runtime/StringIteratorPrototype.cpp:
+ (JSC::StringIteratorPrototype::finishCreation):
+ * runtime/WeakGCMap.h:
+ (JSC::WeakGCMapBase::~WeakGCMapBase):
+ * runtime/WeakGCMapInlines.h:
+ (JSC::KeyTraitsArg>::WeakGCMap):
+ * runtime/WeakMapPrototype.cpp:
+ (JSC::WeakMapPrototype::finishCreation):
+ * runtime/WeakSetPrototype.cpp:
+ (JSC::WeakSetPrototype::finishCreation):
+
+2017-10-07 Filip Pizlo <[email protected]>
+
Octane/splay can leak memory due to stray pointers on the stack when run from the command line
https://bugs.webkit.org/show_bug.cgi?id=178054
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (223026 => 223027)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-10-08 03:15:56 UTC (rev 223027)
@@ -381,6 +381,7 @@
0F725CA81C503DED00AD943A /* B3EliminateCommonSubexpressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CA41C503DED00AD943A /* B3EliminateCommonSubexpressions.h */; };
0F725CAA1C503DED00AD943A /* B3PureCSE.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CA61C503DED00AD943A /* B3PureCSE.h */; };
0F725CB01C506D3B00AD943A /* B3FoldPathConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F725CAE1C506D3B00AD943A /* B3FoldPathConstants.h */; };
+ 0F74B93B1F89614800B935D3 /* PrototypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F74B93A1F89614500B935D3 /* PrototypeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2A15A8CC34008F363E /* JITStubRoutineSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F766D3015A8DCE2008F363E /* GCAwareJITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D2E15A8DCDD008F363E /* GCAwareJITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F766D1C15A5028D008F363E /* JITStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -447,7 +448,6 @@
0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */; };
0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */; };
0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0FA131711D8DD72B00EC130A /* PrototypeMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA131701D8DD72900EC130A /* PrototypeMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FA2C17C17D7CF84009D015F /* TestRunnerUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA2C17A17D7CF84009D015F /* TestRunnerUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */; };
0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */; };
@@ -2363,6 +2363,7 @@
0F725CA61C503DED00AD943A /* B3PureCSE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PureCSE.h; path = b3/B3PureCSE.h; sourceTree = "<group>"; };
0F725CAD1C506D3B00AD943A /* B3FoldPathConstants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3FoldPathConstants.cpp; path = b3/B3FoldPathConstants.cpp; sourceTree = "<group>"; };
0F725CAE1C506D3B00AD943A /* B3FoldPathConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3FoldPathConstants.h; path = b3/B3FoldPathConstants.h; sourceTree = "<group>"; };
+ 0F74B93A1F89614500B935D3 /* PrototypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrototypeKey.h; sourceTree = "<group>"; };
0F766D1C15A5028D008F363E /* JITStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubRoutine.h; sourceTree = "<group>"; };
0F766D2615A8CC1B008F363E /* JITStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutine.cpp; sourceTree = "<group>"; };
0F766D2915A8CC34008F363E /* JITStubRoutineSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITStubRoutineSet.cpp; sourceTree = "<group>"; };
@@ -2479,7 +2480,6 @@
0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStackLayoutPhase.cpp; path = dfg/DFGStackLayoutPhase.cpp; sourceTree = "<group>"; };
0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStackLayoutPhase.h; path = dfg/DFGStackLayoutPhase.h; sourceTree = "<group>"; };
0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutKind.h; sourceTree = "<group>"; };
- 0FA131701D8DD72900EC130A /* PrototypeMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrototypeMapInlines.h; sourceTree = "<group>"; };
0FA2C17917D7CF84009D015F /* TestRunnerUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestRunnerUtils.cpp; sourceTree = "<group>"; };
0FA2C17A17D7CF84009D015F /* TestRunnerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestRunnerUtils.h; sourceTree = "<group>"; };
0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeFlags.cpp; path = dfg/DFGNodeFlags.cpp; sourceTree = "<group>"; };
@@ -6323,9 +6323,9 @@
E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */,
E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */,
+ A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
A7A8AF2C17ADB5F3005AB174 /* Int16Array.h */,
A7A8AF2D17ADB5F3005AB174 /* Int32Array.h */,
- A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
BC11667A0E199C05008066DD /* InternalFunction.h */,
A1B9E2331B4E0D6700BC7FED /* IntlCollator.cpp */,
@@ -6421,9 +6421,9 @@
BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */,
BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */,
79B819921DD25CF500DDC714 /* JSGlobalObjectInlines.h */,
+ 0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
0F2B66CA17B6B5AB00A7AE3F /* JSInt16Array.h */,
0F2B66CB17B6B5AB00A7AE3F /* JSInt32Array.h */,
- 0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
E33F507E1B8429A400413856 /* JSInternalPromise.cpp */,
E33F507F1B8429A400413856 /* JSInternalPromise.h */,
E33F50761B84225700413856 /* JSInternalPromiseConstructor.cpp */,
@@ -6511,10 +6511,10 @@
53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */,
53917E7C1B791106000EBD33 /* JSTypedArrayViewPrototype.h */,
6507D2970E871E4A00D7D896 /* JSTypeInfo.h */,
+ 0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
+ 0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
0F2B66D417B6B5AB00A7AE3F /* JSUint16Array.h */,
0F2B66D517B6B5AB00A7AE3F /* JSUint32Array.h */,
- 0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
- 0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
A7CA3AE117DA41AE006538AF /* JSWeakMap.cpp */,
A7CA3AE217DA41AE006538AF /* JSWeakMap.h */,
709FB8611AE335C60039D069 /* JSWeakSet.cpp */,
@@ -6600,9 +6600,9 @@
0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */,
AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */,
65C02FBB0637462A003E7EE6 /* Protect.h */,
+ 0F74B93A1F89614500B935D3 /* PrototypeKey.h */,
14D844A216AA2C7000A65AF0 /* PrototypeMap.cpp */,
14D844A316AA2C7000A65AF0 /* PrototypeMap.h */,
- 0FA131701D8DD72900EC130A /* PrototypeMapInlines.h */,
79B00CB81C6AB07E0088C65D /* ProxyConstructor.cpp */,
79B00CB91C6AB07E0088C65D /* ProxyConstructor.h */,
79B00CBA1C6AB07E0088C65D /* ProxyObject.cpp */,
@@ -6727,11 +6727,11 @@
0F2D4DE019832D91007D4B19 /* TypeProfilerLog.h */,
0F2D4DE319832D91007D4B19 /* TypeSet.cpp */,
0F2D4DE419832D91007D4B19 /* TypeSet.h */,
+ A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
+ A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */,
866739D113BFDE710023D87C /* Uint16WithFraction.h */,
A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */,
- A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
- A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
0FE050231AA9095600D33B33 /* VarOffset.cpp */,
0FE050241AA9095600D33B33 /* VarOffset.h */,
E18E3A570DF9278C00D90B34 /* VM.cpp */,
@@ -8935,8 +8935,8 @@
BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */,
0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */,
BC18C4560E16F5CD00B34460 /* Protect.h in Headers */,
+ 0F74B93B1F89614800B935D3 /* PrototypeKey.h in Headers */,
1474C33B16AA2D950062F01D /* PrototypeMap.h in Headers */,
- 0FA131711D8DD72B00EC130A /* PrototypeMapInlines.h in Headers */,
534E03561E53BEDE00213F64 /* ProxyableAccessCase.h in Headers */,
79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */,
79B00CBF1C6AB07E0088C65D /* ProxyObject.h in Headers */,
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -249,7 +249,7 @@
if (structure->hasPolyProto()) {
JSObject* prototype = jsCast<JSFunction*>(constructor)->prototypeForConstruction(vm, exec);
result->putDirect(vm, structure->polyProtoOffset(), prototype);
- vm.prototypeMap.addPrototype(prototype);
+ prototype->didBecomePrototype();
}
return result;
}
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -2115,8 +2115,8 @@
{
if (m_collectionScope != CollectionScope::Full)
return;
- for (auto& pruneCallback : m_weakGCMaps.values())
- pruneCallback();
+ for (WeakGCMapBase* weakGCMap : m_weakGCMaps)
+ weakGCMap->pruneStaleEntries();
}
void Heap::sweepArrayBuffers()
@@ -2546,12 +2546,12 @@
collectIfNecessaryOrDefer();
}
-void Heap::registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback)
+void Heap::registerWeakGCMap(WeakGCMapBase* weakGCMap)
{
- m_weakGCMaps.add(weakGCMap, WTFMove(pruningCallback));
+ m_weakGCMaps.add(weakGCMap);
}
-void Heap::unregisterWeakGCMap(void* weakGCMap)
+void Heap::unregisterWeakGCMap(WeakGCMapBase* weakGCMap)
{
m_weakGCMaps.remove(weakGCMap);
}
Modified: trunk/Source/_javascript_Core/heap/Heap.h (223026 => 223027)
--- trunk/Source/_javascript_Core/heap/Heap.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -84,6 +84,7 @@
class StopIfNecessaryTimer;
class SweepingScope;
class VM;
+class WeakGCMapBase;
struct CurrentThreadState;
namespace DFG {
@@ -269,8 +270,8 @@
template<typename T> void releaseSoon(RetainPtr<T>&&);
#endif
- JS_EXPORT_PRIVATE void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
- JS_EXPORT_PRIVATE void unregisterWeakGCMap(void* weakGCMap);
+ JS_EXPORT_PRIVATE void registerWeakGCMap(WeakGCMapBase* weakGCMap);
+ JS_EXPORT_PRIVATE void unregisterWeakGCMap(WeakGCMapBase* weakGCMap);
void addLogicallyEmptyWeakBlock(WeakBlock*);
@@ -620,7 +621,7 @@
unsigned m_delayedReleaseRecursionCount;
#endif
- HashMap<void*, std::function<void()>> m_weakGCMaps;
+ HashSet<WeakGCMapBase*> m_weakGCMaps;
Lock m_visitRaceLock;
Modified: trunk/Source/_javascript_Core/inspector/JSInjectedScriptHostPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/inspector/JSInjectedScriptHostPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/inspector/JSInjectedScriptHostPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -59,7 +59,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("subtype", jsInjectedScriptHostPrototypeFunctionSubtype, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("functionDetails", jsInjectedScriptHostPrototypeFunctionFunctionDetails, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
Modified: trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFramePrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFramePrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/inspector/JSJavaScriptCallFramePrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -57,7 +57,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluateWithScopeExtension", jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scopeDescriptions", jsJavaScriptCallFramePrototypeFunctionScopeDescriptions, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
Modified: trunk/Source/_javascript_Core/runtime/ArrayIteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/ArrayIteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/ArrayIteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -50,7 +50,7 @@
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Array Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
// ------------------------------ Array Functions ----------------------------
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -82,7 +82,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
putDirectWithoutTransition(vm, vm.propertyNames->toString, globalObject->arrayProtoToStringFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), globalObject->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
Modified: trunk/Source/_javascript_Core/runtime/AsyncFromSyncIteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/AsyncFromSyncIteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/AsyncFromSyncIteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -44,7 +44,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", asyncFromSyncIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("return", asyncFromSyncIteratorPrototypeReturnCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
Modified: trunk/Source/_javascript_Core/runtime/AsyncFunctionPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/AsyncFunctionPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/AsyncFunctionPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -51,7 +51,7 @@
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "AsyncFunction"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/AsyncGeneratorFunctionPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/AsyncGeneratorFunctionPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/AsyncGeneratorFunctionPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -51,7 +51,7 @@
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "AsyncGeneratorFunction"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/AsyncGeneratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/AsyncGeneratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/AsyncGeneratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -49,7 +49,7 @@
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "AsyncGenerator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/AsyncIteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/AsyncIteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/AsyncIteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -39,7 +39,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSFunction* asyncIteratorPrototypeFunction = JSFunction::create(vm, asyncIteratorPrototypeSymbolAsyncIteratorGetterCodeGenerator(vm), globalObject);
putDirectWithoutTransition(vm, vm.propertyNames->asyncIteratorSymbol, asyncIteratorPrototypeFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -249,7 +249,7 @@
if (structure->hasPolyProto()) {
JSObject* prototype = constructor->prototypeForConstruction(vm, exec);
result->putDirect(vm, structure->polyProtoOffset(), prototype);
- vm.prototypeMap.addPrototype(prototype);
+ prototype->didBecomePrototype();
}
} else {
// http://ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
Modified: trunk/Source/_javascript_Core/runtime/GeneratorFunctionPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/GeneratorFunctionPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/GeneratorFunctionPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -53,7 +53,7 @@
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "GeneratorFunction"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/GeneratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/GeneratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/GeneratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -49,7 +49,7 @@
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Generator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/IndexingType.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/IndexingType.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/IndexingType.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -69,9 +69,11 @@
// masked off unless you ask for them directly.
static const IndexingType MayHaveIndexedAccessors = 0x10;
-// The IndexingType field of JSCells is stolen for locks.
+// The IndexingType field of JSCells is stolen for locks and remembering if the object has been a
+// prototype.
static const IndexingType IndexingTypeLockIsHeld = 0x20;
static const IndexingType IndexingTypeLockHasParked = 0x40;
+static const IndexingType IndexingTypeMayBePrototype = 0x80;
// List of acceptable array types.
static const IndexingType NonArray = 0x0;
Modified: trunk/Source/_javascript_Core/runtime/IteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/IteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/IteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -39,7 +39,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->iteratorSymbol, iteratorPrototypeSymbolIteratorGetterCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
}
Modified: trunk/Source/_javascript_Core/runtime/JSCInlines.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/JSCInlines.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/JSCInlines.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -49,7 +49,6 @@
#include "JSProxy.h"
#include "JSString.h"
#include "Operations.h"
-#include "PrototypeMapInlines.h"
#include "SlotVisitorInlines.h"
#include "StructureInlines.h"
#include "ThrowScope.h"
Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/JSCell.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -132,6 +132,9 @@
void clearStructure() { m_structureID = 0; }
TypeInfo::InlineTypeFlags inlineTypeFlags() const { return m_flags; }
+
+ bool mayBePrototype() const;
+ void didBecomePrototype();
const char* className(VM&) const;
Modified: trunk/Source/_javascript_Core/runtime/JSCellInlines.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/JSCellInlines.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/JSCellInlines.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -352,6 +352,16 @@
return IndexingTypeLockAlgorithm::isLocked(*lock);
}
+inline bool JSCell::mayBePrototype() const
+{
+ return m_indexingTypeAndMisc & IndexingTypeMayBePrototype;
+}
+
+inline void JSCell::didBecomePrototype()
+{
+ m_indexingTypeAndMisc |= IndexingTypeMayBePrototype;
+}
+
inline JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const
{
if (isObject())
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -43,7 +43,6 @@
#include "ObjectPrototype.h"
#include "PropertyDescriptor.h"
#include "PropertyNameArray.h"
-#include "PrototypeMapInlines.h"
#include "ProxyObject.h"
#include "SlotVisitorInlines.h"
#include "TypeError.h"
@@ -1005,7 +1004,7 @@
setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AddIndexedAccessors));
- if (!vm.prototypeMap.isPrototype(this))
+ if (!mayBePrototype())
return;
globalObject(vm)->haveABadTime(vm);
@@ -1632,7 +1631,7 @@
{
ASSERT(prototype);
if (prototype.isObject())
- vm.prototypeMap.addPrototype(asObject(prototype));
+ prototype.asCell()->didBecomePrototype();
if (structure(vm)->hasMonoProto()) {
Structure* newStructure = Structure::changePrototypeTransition(vm, structure(vm), prototype);
@@ -1643,7 +1642,7 @@
if (!anyObjectInChainMayInterceptIndexedAccesses())
return;
- if (vm.prototypeMap.isPrototype(this)) {
+ if (mayBePrototype()) {
structure(vm)->globalObject()->haveABadTime(vm);
return;
}
Modified: trunk/Source/_javascript_Core/runtime/JSProxy.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/JSProxy.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/JSProxy.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -28,7 +28,6 @@
#include "JSGlobalObject.h"
#include "JSCInlines.h"
-#include "PrototypeMapInlines.h"
namespace JSC {
@@ -53,7 +52,7 @@
setPrototypeDirect(vm, globalObject->getPrototypeDirect());
PrototypeMap& prototypeMap = vm.prototypeMap;
- if (!prototypeMap.isPrototype(this))
+ if (!mayBePrototype())
return;
// previousGlobalObject cannot be null because in order for this JSProxy to be used as a prototype
Modified: trunk/Source/_javascript_Core/runtime/MapIteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/MapIteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/MapIteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -37,7 +37,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", mapIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Map Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
Modified: trunk/Source/_javascript_Core/runtime/MapPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/MapPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/MapPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -60,7 +60,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, mapProtoFuncClear, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, mapProtoFuncDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
Modified: trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -56,7 +56,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, objectProtoFuncToString, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, objectProtoFuncToLocaleString, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
Added: trunk/Source/_javascript_Core/runtime/PrototypeKey.h (0 => 223027)
--- trunk/Source/_javascript_Core/runtime/PrototypeKey.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/PrototypeKey.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 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. ``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
+ * 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 <wtf/HashTable.h>
+
+namespace JSC {
+
+class PrototypeKey {
+public:
+ PrototypeKey() { }
+
+ PrototypeKey(JSObject* prototype, unsigned inlineCapacity, const ClassInfo* classInfo, JSGlobalObject* globalObject)
+ : m_prototype(prototype)
+ , m_inlineCapacity(inlineCapacity)
+ , m_classInfo(classInfo)
+ , m_globalObject(globalObject)
+ {
+ }
+
+ PrototypeKey(WTF::HashTableDeletedValueType)
+ : m_inlineCapacity(1)
+ {
+ }
+
+ JSObject* prototype() const { return m_prototype; }
+ unsigned inlineCapacity() const { return m_inlineCapacity; }
+ const ClassInfo* classInfo() const { return m_classInfo; }
+ JSGlobalObject* globalObject() const { return m_globalObject; }
+
+ bool operator==(const PrototypeKey& other) const
+ {
+ return m_prototype == other.m_prototype
+ && m_inlineCapacity == other.m_inlineCapacity
+ && m_classInfo == other.m_classInfo
+ && m_globalObject == other.m_globalObject;
+ }
+
+ bool operator!=(const PrototypeKey& other) const { return !(*this == other); }
+ explicit operator bool() const { return *this != PrototypeKey(); }
+ bool isHashTableDeletedValue() const { return *this == PrototypeKey(WTF::HashTableDeletedValue); }
+
+ unsigned hash() const
+ {
+ return WTF::IntHash<uintptr_t>::hash(bitwise_cast<uintptr_t>(m_prototype) ^ bitwise_cast<uintptr_t>(m_classInfo) ^ bitwise_cast<uintptr_t>(m_globalObject)) + m_inlineCapacity;
+ }
+
+private:
+ // WARNING: We require all of these default values to be zero. Otherwise, you'll need to add
+ // "static const bool emptyValueIsZero = false;" to the HashTraits at the bottom of this file.
+ JSObject* m_prototype { nullptr };
+ unsigned m_inlineCapacity { 0 };
+ const ClassInfo* m_classInfo { nullptr };
+ JSGlobalObject* m_globalObject { nullptr };
+};
+
+struct PrototypeKeyHash {
+ static unsigned hash(const PrototypeKey& key) { return key.hash(); }
+ static bool equal(const PrototypeKey& a, const PrototypeKey& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::PrototypeKey> {
+ typedef JSC::PrototypeKeyHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::PrototypeKey> : SimpleClassHashTraits<JSC::PrototypeKey> { };
+
+} // namespace WTF
+
Modified: trunk/Source/_javascript_Core/runtime/PrototypeMap.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/PrototypeMap.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/PrototypeMap.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,7 +29,6 @@
#include "IndexingType.h"
#include "JSGlobalObject.h"
#include "JSCInlines.h"
-#include "PrototypeMapInlines.h"
namespace JSC {
@@ -37,18 +36,18 @@
{
RELEASE_ASSERT(!!prototype); // We use nullptr inside the HashMap for prototype to mean poly proto, so user's of this API must provide non-null prototypes.
- auto key = std::make_tuple(makePolyProtoStructure ? nullptr : prototype, inlineCapacity, classInfo, globalObject);
+ auto key = PrototypeKey(makePolyProtoStructure ? nullptr : prototype, inlineCapacity, classInfo, globalObject);
if (Structure* structure = m_structures.get(key)) {
if (makePolyProtoStructure) {
- addPrototype(prototype);
+ prototype->didBecomePrototype();
RELEASE_ASSERT(structure->hasPolyProto());
} else
RELEASE_ASSERT(structure->hasMonoProto());
- ASSERT(isPrototype(prototype));
+ ASSERT(prototype->mayBePrototype());
return structure;
}
- addPrototype(prototype);
+ prototype->didBecomePrototype();
VM& vm = globalObject->vm();
Structure* structure;
@@ -81,8 +80,8 @@
void PrototypeMap::clearEmptyObjectStructureForPrototype(JSGlobalObject* globalObject, JSObject* object, unsigned inlineCapacity)
{
- m_structures.remove(std::make_tuple(object, inlineCapacity, JSFinalObject::info(), globalObject));
- m_structures.remove(std::make_tuple(nullptr, inlineCapacity, JSFinalObject::info(), globalObject));
+ m_structures.remove(PrototypeKey(object, inlineCapacity, JSFinalObject::info(), globalObject));
+ m_structures.remove(PrototypeKey(nullptr, inlineCapacity, JSFinalObject::info(), globalObject));
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/PrototypeMap.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/PrototypeMap.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/PrototypeMap.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
#include "IndexingType.h"
#include "JSTypeInfo.h"
+#include "PrototypeKey.h"
#include "WeakGCMap.h"
#include <wtf/TriState.h>
@@ -41,8 +42,7 @@
class PrototypeMap {
public:
explicit PrototypeMap(VM& vm)
- : m_prototypes(vm)
- , m_structures(vm)
+ : m_structures(vm)
{
}
@@ -49,15 +49,11 @@
JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSGlobalObject*, JSObject*, unsigned inlineCapacity, bool makePolyProtoStructure = false);
JS_EXPORT_PRIVATE Structure* emptyStructureForPrototypeFromBaseStructure(JSGlobalObject*, JSObject*, Structure*);
void clearEmptyObjectStructureForPrototype(JSGlobalObject*, JSObject*, unsigned inlineCapacity);
- ALWAYS_INLINE void addPrototype(JSObject*);
- ALWAYS_INLINE TriState isPrototype(JSObject*) const; // Returns a conservative estimate.
private:
Structure* createEmptyStructure(JSGlobalObject*, JSObject* prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity, bool makePolyProtoStructure);
- WeakGCMap<JSObject*, JSObject> m_prototypes;
- // FIXME: make the key a struct.
- using StructureMap = WeakGCMap<std::tuple<JSObject*, unsigned, const ClassInfo*, JSGlobalObject*>, Structure>;
+ using StructureMap = WeakGCMap<PrototypeKey, Structure>;
StructureMap m_structures;
};
Deleted: trunk/Source/_javascript_Core/runtime/PrototypeMapInlines.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/PrototypeMapInlines.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/PrototypeMapInlines.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2016 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. ``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
- * 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 "PrototypeMap.h"
-#include "WeakGCMapInlines.h"
-
-namespace JSC {
-
-ALWAYS_INLINE TriState PrototypeMap::isPrototype(JSObject* object) const
-{
- if (!m_prototypes.contains(object))
- return FalseTriState;
-
- // We know that 'object' was used as a prototype at one time, so be
- // conservative and say that it might still be so. (It would be expensive
- // to find out for sure, and we don't know of any cases where being precise
- // would improve performance.)
- return MixedTriState;
-}
-
-ALWAYS_INLINE void PrototypeMap::addPrototype(JSObject* object)
-{
- m_prototypes.set(object, object);
-
- // Note that this method makes the somewhat odd decision to not check if this
- // object currently has indexed accessors. We could do that check here, and if
- // indexed accessors were found, we could tell the global object to have a bad
- // time. But we avoid this, to allow the following to be always fast:
- //
- // 1) Create an object.
- // 2) Give it a setter or read-only property that happens to have a numeric name.
- // 3) Allocate objects that use this object as a prototype.
- //
- // This avoids anyone having a bad time. Even if the instance objects end up
- // having indexed storage, the creation of indexed storage leads to a prototype
- // chain walk that detects the presence of indexed setters and then does the
- // right thing. As a result, having a bad time only happens if you add an
- // indexed setter (or getter, or read-only field) to an object that is already
- // used as a prototype.
-}
-
-} // namespace JSC
-
Modified: trunk/Source/_javascript_Core/runtime/SetIteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/SetIteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/SetIteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -37,7 +37,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", setIteratorPrototypeNextCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Set Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
Modified: trunk/Source/_javascript_Core/runtime/SetPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/SetPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/SetPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -59,7 +59,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->add, setProtoFuncAdd, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, setProtoFuncClear, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
Modified: trunk/Source/_javascript_Core/runtime/StringIteratorPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/StringIteratorPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/StringIteratorPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -49,7 +49,7 @@
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "String Iterator"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/WeakGCMap.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/WeakGCMap.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMap.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -32,9 +32,15 @@
// 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 = typename DefaultHash<KeyArg>::Hash,
typename KeyTraitsArg = HashTraits<KeyArg>>
-class WeakGCMap {
+class WeakGCMap : public WeakGCMapBase {
WTF_MAKE_FAST_ALLOCATED;
typedef Weak<ValueArg> ValueType;
typedef HashMap<KeyArg, ValueType, HashArg, KeyTraitsArg> HashMapType;
@@ -94,7 +100,7 @@
inline bool contains(const KeyType& key) const;
- void pruneStaleEntries();
+ void pruneStaleEntries() override;
private:
HashMapType m_map;
Modified: trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h 2017-10-08 03:15:56 UTC (rev 223027)
@@ -35,9 +35,7 @@
inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::WeakGCMap(VM& vm)
: m_vm(vm)
{
- vm.heap.registerWeakGCMap(this, [this]() {
- pruneStaleEntries();
- });
+ vm.heap.registerWeakGCMap(this);
}
template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
Modified: trunk/Source/_javascript_Core/runtime/WeakMapPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/WeakMapPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/WeakMapPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -43,7 +43,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, protoFuncWeakMapDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, protoFuncWeakMapGet, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, JSWeakMapGetIntrinsic);
Modified: trunk/Source/_javascript_Core/runtime/WeakSetPrototype.cpp (223026 => 223027)
--- trunk/Source/_javascript_Core/runtime/WeakSetPrototype.cpp 2017-10-08 02:55:44 UTC (rev 223026)
+++ trunk/Source/_javascript_Core/runtime/WeakSetPrototype.cpp 2017-10-08 03:15:56 UTC (rev 223027)
@@ -42,7 +42,7 @@
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
- vm.prototypeMap.addPrototype(this);
+ didBecomePrototype();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, protoFuncWeakSetDelete, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, protoFuncWeakSetHas, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);