Title: [223027] trunk/Source/_javascript_Core
Revision
223027
Author
[email protected]
Date
2017-10-07 20:15:56 -0700 (Sat, 07 Oct 2017)

Log Message

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):

Modified Paths

Added Paths

Removed Paths

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);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to