Title: [246073] trunk/Source/_javascript_Core
Revision
246073
Author
[email protected]
Date
2019-06-04 11:27:59 -0700 (Tue, 04 Jun 2019)

Log Message

[JSC] InferredValue should not be a JSCell
https://bugs.webkit.org/show_bug.cgi?id=198407

Reviewed by Filip Pizlo.

Allocating InferredValue as a JSCell is too costly in terms of memory. Gmail has 90000 FunctionExecutables. And each gets
InferredValue, which takes 32 bytes. So it takes 2.7 MB memory footprint.

In this patch, we introduce a new container InferredValue<>. Which is similar to WriteBarrier<> container, but it replaces
the existing InferredValue cells with one pointer size field. The implementation of InferredValue<> is similar to
InlineWatchpointSet. But we encode JSCell* too to the pointer data of InlineWatchpointSet. So sizeof(InferredValue<>) is one
pointer size while it keeps Watchpoint feature and JSCell holder feature.

InferredValue<> needs validation in GC finalize phase. So this patch also makes SymbolTable Iso-allocated.

* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecode/ObjectAllocationProfileInlines.h:
(JSC::ObjectAllocationProfileBase<Derived>::initializeProfile):
* bytecode/Watchpoint.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::get):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGClobbersExitState.cpp:
(JSC::DFG::clobbersExitState):
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::SymbolTableAdaptor::add):
(JSC::DFG::FunctionExecutableAdaptor::add):
(JSC::DFG::DesiredWatchpoints::addLazily):
(JSC::DFG::DesiredWatchpoints::reallyAdd):
(JSC::DFG::DesiredWatchpoints::areStillValid const):
(JSC::DFG::DesiredWatchpoints::dumpInContext const):
(JSC::DFG::InferredValueAdaptor::add): Deleted.
* dfg/DFGDesiredWatchpoints.h:
(JSC::DFG::SymbolTableAdaptor::hasBeenInvalidated):
(JSC::DFG::SymbolTableAdaptor::dumpInContext):
(JSC::DFG::FunctionExecutableAdaptor::hasBeenInvalidated):
(JSC::DFG::FunctionExecutableAdaptor::dumpInContext):
(JSC::DFG::DesiredWatchpoints::isWatched):
(JSC::DFG::InferredValueAdaptor::hasBeenInvalidated): Deleted.
(JSC::DFG::InferredValueAdaptor::dumpInContext): Deleted.
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewFunction):
(JSC::DFG::SpeculativeJIT::compileCreateActivation):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCreateActivation):
(JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
* heap/Heap.cpp:
(JSC::Heap::finalizeUnconditionalFinalizers):
* runtime/FunctionExecutable.cpp:
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::FunctionExecutable::finishCreation):
(JSC::FunctionExecutable::visitChildren):
* runtime/FunctionExecutable.h:
* runtime/FunctionExecutableInlines.h: Copied from Source/_javascript_Core/runtime/InferredValueInlines.h.
(JSC::FunctionExecutable::finalizeUnconditionally):
* runtime/InferredValue.cpp: Removed.
* runtime/InferredValue.h:
(JSC::InferredValue::inferredValue):
(JSC::InferredValue::InferredValue):
(JSC::InferredValue::~InferredValue):
(JSC::InferredValue::stateOnJSThread const):
(JSC::InferredValue::state const):
(JSC::InferredValue::hasBeenInvalidated const):
(JSC::InferredValue::isStillValid const):
(JSC::InferredValue::invalidate):
(JSC::InferredValue::isBeingWatched const):
(JSC::InferredValue::notifyWrite):
(JSC::InferredValue::isThin):
(JSC::InferredValue::isFat):
(JSC::InferredValue::decodeState):
(JSC::InferredValue::encodeState):
(JSC::InferredValue::isThin const):
(JSC::InferredValue::isFat const):
(JSC::InferredValue::fat):
(JSC::InferredValue::fat const):
(JSC::InferredValue::inflate):
(JSC::InferredValue<JSCellType>::InferredValueWatchpointSet::notifyWriteSlow):
(JSC::InferredValue<JSCellType>::notifyWriteSlow):
(JSC::InferredValue<JSCellType>::add):
(JSC::InferredValue<JSCellType>::inflateSlow):
(JSC::InferredValue<JSCellType>::freeFat):
* runtime/InferredValueInlines.h:
(JSC::InferredValue<JSCellType>::finalizeUnconditionally):
(JSC::InferredValue::finalizeUnconditionally): Deleted.
* runtime/JSFunctionInlines.h:
(JSC::JSFunction::createWithInvalidatedReallocationWatchpoint):
* runtime/JSSymbolTableObject.h:
(JSC::JSSymbolTableObject::setSymbolTable):
* runtime/SymbolTable.cpp:
(JSC::SymbolTable::finishCreation):
(JSC::SymbolTable::visitChildren):
* runtime/SymbolTable.h:
* runtime/SymbolTableInlines.h: Copied from Source/_javascript_Core/runtime/InferredValueInlines.h.
(JSC::SymbolTable::finalizeUnconditionally):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (246072 => 246073)


--- trunk/Source/_javascript_Core/ChangeLog	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-06-04 18:27:59 UTC (rev 246073)
@@ -1,3 +1,109 @@
+2019-06-04  Yusuke Suzuki  <[email protected]>
+
+        [JSC] InferredValue should not be a JSCell
+        https://bugs.webkit.org/show_bug.cgi?id=198407
+
+        Reviewed by Filip Pizlo.
+
+        Allocating InferredValue as a JSCell is too costly in terms of memory. Gmail has 90000 FunctionExecutables. And each gets
+        InferredValue, which takes 32 bytes. So it takes 2.7 MB memory footprint.
+
+        In this patch, we introduce a new container InferredValue<>. Which is similar to WriteBarrier<> container, but it replaces
+        the existing InferredValue cells with one pointer size field. The implementation of InferredValue<> is similar to
+        InlineWatchpointSet. But we encode JSCell* too to the pointer data of InlineWatchpointSet. So sizeof(InferredValue<>) is one
+        pointer size while it keeps Watchpoint feature and JSCell holder feature.
+
+        InferredValue<> needs validation in GC finalize phase. So this patch also makes SymbolTable Iso-allocated.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * bytecode/ObjectAllocationProfileInlines.h:
+        (JSC::ObjectAllocationProfileBase<Derived>::initializeProfile):
+        * bytecode/Watchpoint.h:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::get):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGClobbersExitState.cpp:
+        (JSC::DFG::clobbersExitState):
+        * dfg/DFGDesiredWatchpoints.cpp:
+        (JSC::DFG::SymbolTableAdaptor::add):
+        (JSC::DFG::FunctionExecutableAdaptor::add):
+        (JSC::DFG::DesiredWatchpoints::addLazily):
+        (JSC::DFG::DesiredWatchpoints::reallyAdd):
+        (JSC::DFG::DesiredWatchpoints::areStillValid const):
+        (JSC::DFG::DesiredWatchpoints::dumpInContext const):
+        (JSC::DFG::InferredValueAdaptor::add): Deleted.
+        * dfg/DFGDesiredWatchpoints.h:
+        (JSC::DFG::SymbolTableAdaptor::hasBeenInvalidated):
+        (JSC::DFG::SymbolTableAdaptor::dumpInContext):
+        (JSC::DFG::FunctionExecutableAdaptor::hasBeenInvalidated):
+        (JSC::DFG::FunctionExecutableAdaptor::dumpInContext):
+        (JSC::DFG::DesiredWatchpoints::isWatched):
+        (JSC::DFG::InferredValueAdaptor::hasBeenInvalidated): Deleted.
+        (JSC::DFG::InferredValueAdaptor::dumpInContext): Deleted.
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewFunction):
+        (JSC::DFG::SpeculativeJIT::compileCreateActivation):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateActivation):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewFunction):
+        * heap/Heap.cpp:
+        (JSC::Heap::finalizeUnconditionalFinalizers):
+        * runtime/FunctionExecutable.cpp:
+        (JSC::FunctionExecutable::FunctionExecutable):
+        (JSC::FunctionExecutable::finishCreation):
+        (JSC::FunctionExecutable::visitChildren):
+        * runtime/FunctionExecutable.h:
+        * runtime/FunctionExecutableInlines.h: Copied from Source/_javascript_Core/runtime/InferredValueInlines.h.
+        (JSC::FunctionExecutable::finalizeUnconditionally):
+        * runtime/InferredValue.cpp: Removed.
+        * runtime/InferredValue.h:
+        (JSC::InferredValue::inferredValue):
+        (JSC::InferredValue::InferredValue):
+        (JSC::InferredValue::~InferredValue):
+        (JSC::InferredValue::stateOnJSThread const):
+        (JSC::InferredValue::state const):
+        (JSC::InferredValue::hasBeenInvalidated const):
+        (JSC::InferredValue::isStillValid const):
+        (JSC::InferredValue::invalidate):
+        (JSC::InferredValue::isBeingWatched const):
+        (JSC::InferredValue::notifyWrite):
+        (JSC::InferredValue::isThin):
+        (JSC::InferredValue::isFat):
+        (JSC::InferredValue::decodeState):
+        (JSC::InferredValue::encodeState):
+        (JSC::InferredValue::isThin const):
+        (JSC::InferredValue::isFat const):
+        (JSC::InferredValue::fat):
+        (JSC::InferredValue::fat const):
+        (JSC::InferredValue::inflate):
+        (JSC::InferredValue<JSCellType>::InferredValueWatchpointSet::notifyWriteSlow):
+        (JSC::InferredValue<JSCellType>::notifyWriteSlow):
+        (JSC::InferredValue<JSCellType>::add):
+        (JSC::InferredValue<JSCellType>::inflateSlow):
+        (JSC::InferredValue<JSCellType>::freeFat):
+        * runtime/InferredValueInlines.h:
+        (JSC::InferredValue<JSCellType>::finalizeUnconditionally):
+        (JSC::InferredValue::finalizeUnconditionally): Deleted.
+        * runtime/JSFunctionInlines.h:
+        (JSC::JSFunction::createWithInvalidatedReallocationWatchpoint):
+        * runtime/JSSymbolTableObject.h:
+        (JSC::JSSymbolTableObject::setSymbolTable):
+        * runtime/SymbolTable.cpp:
+        (JSC::SymbolTable::finishCreation):
+        (JSC::SymbolTable::visitChildren):
+        * runtime/SymbolTable.h:
+        * runtime/SymbolTableInlines.h: Copied from Source/_javascript_Core/runtime/InferredValueInlines.h.
+        (JSC::SymbolTable::finalizeUnconditionally):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
 2019-06-04  Tadeu Zagallo  <[email protected]>
 
         Argument elimination should check for negative indices in GetByVal

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (246072 => 246073)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-06-04 18:27:59 UTC (rev 246073)
@@ -1774,6 +1774,7 @@
 		E33F50811B8429A400413856 /* JSInternalPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F507F1B8429A400413856 /* JSInternalPromise.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50831B8437A000413856 /* JSInternalPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */; };
+		E3400EC122A1CC7B009DED54 /* FunctionExecutableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */; };
 		E34E657520668EAA00FB81AC /* ParseHash.h in Headers */ = {isa = PBXBuildFile; fileRef = E34E657320668E8D00FB81AC /* ParseHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E34EDBF71DB5FFC900DC87A5 /* FrameTracers.h in Headers */ = {isa = PBXBuildFile; fileRef = E34EDBF61DB5FFC100DC87A5 /* FrameTracers.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E350708A1DC49BBF0089BCD6 /* DOMJITSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = E35070891DC49BB60089BCD6 /* DOMJITSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1792,6 +1793,7 @@
 		E38D999C221B78BB00D50474 /* JSNonDestructibleProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = E38D999A221B789F00D50474 /* JSNonDestructibleProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E39006212208BFC4001019CF /* SubspaceAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = E39006202208BFC3001019CF /* SubspaceAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */; };
+		E39BF39922A2288B00BD183E /* SymbolTableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39BF39822A2288B00BD183E /* SymbolTableInlines.h */; };
 		E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E39EEAF322812450008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */; };
@@ -3133,7 +3135,6 @@
 		0FF729A0166AD347000F5BA3 /* ProfilerOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOrigin.h; path = profiler/ProfilerOrigin.h; sourceTree = "<group>"; };
 		0FF729A1166AD347000F5BA3 /* ProfilerOriginStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerOriginStack.cpp; path = profiler/ProfilerOriginStack.cpp; sourceTree = "<group>"; };
 		0FF729A2166AD347000F5BA3 /* ProfilerOriginStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOriginStack.h; path = profiler/ProfilerOriginStack.h; sourceTree = "<group>"; };
-		0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredValue.cpp; sourceTree = "<group>"; };
 		0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredValue.h; sourceTree = "<group>"; };
 		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
 		0FF9CE711B9CD6D0004EDCA6 /* PolymorphicAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicAccess.cpp; sourceTree = "<group>"; };
@@ -4772,6 +4773,7 @@
 		E33F50831B8437A000413856 /* JSInternalPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalPromiseDeferred.h; sourceTree = "<group>"; };
 		E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalPromiseConstructor.lut.h; sourceTree = "<group>"; };
 		E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = InternalPromiseConstructor.js; sourceTree = "<group>"; };
+		E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FunctionExecutableInlines.h; sourceTree = "<group>"; };
 		E34E657320668E8D00FB81AC /* ParseHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseHash.h; sourceTree = "<group>"; };
 		E34E657420668E8E00FB81AC /* ParseHash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParseHash.cpp; sourceTree = "<group>"; };
 		E34EDBF61DB5FFC100DC87A5 /* FrameTracers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameTracers.h; sourceTree = "<group>"; };
@@ -4804,6 +4806,7 @@
 		E39006202208BFC3001019CF /* SubspaceAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubspaceAccess.h; sourceTree = "<group>"; };
 		E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakMapImplInlines.h; sourceTree = "<group>"; };
 		E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; };
+		E39BF39822A2288B00BD183E /* SymbolTableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolTableInlines.h; sourceTree = "<group>"; };
 		E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; };
 		E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; };
 		E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleRecord.h; sourceTree = "<group>"; };
@@ -6872,6 +6875,7 @@
 				147341D71DC02F9900AA29BA /* FunctionExecutable.h */,
 				0FB4B52116B6278D003F696B /* FunctionExecutableDump.cpp */,
 				0FB4B52216B6278D003F696B /* FunctionExecutableDump.h */,
+				E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */,
 				52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */,
 				52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */,
 				F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
@@ -6909,7 +6913,6 @@
 				0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
 				14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */,
 				14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */,
-				0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
 				0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
 				0F4AE0421FE0D25400E20839 /* InferredValueInlines.h */,
 				E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
@@ -7317,6 +7320,7 @@
 				705B41AA1A6E501E00716757 /* SymbolPrototype.h */,
 				0F919D2715856770004A4E7D /* SymbolTable.cpp */,
 				14A396A60CD2933100B5B4FF /* SymbolTable.h */,
+				E39BF39822A2288B00BD183E /* SymbolTableInlines.h */,
 				E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */,
 				BDB4B5E099CD4C1BB3C1CF05 /* TemplateObjectDescriptor.cpp */,
 				70ECA6041AFDBEA200449739 /* TemplateObjectDescriptor.h */,
@@ -9184,6 +9188,7 @@
 				BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */,
 				147341D81DC02F9900AA29BA /* FunctionExecutable.h in Headers */,
 				0FF0F1A016B72A1A005DF95B /* FunctionExecutableDump.h in Headers */,
+				E3400EC122A1CC7B009DED54 /* FunctionExecutableInlines.h in Headers */,
 				52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */,
 				FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */,
 				BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */,
@@ -9880,6 +9885,7 @@
 				705B41B21A6E501E00716757 /* SymbolPrototype.h in Headers */,
 				996B73281BDA08EF00331B84 /* SymbolPrototype.lut.h in Headers */,
 				BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */,
+				E39BF39922A2288B00BD183E /* SymbolTableInlines.h in Headers */,
 				E31179AA2288386100514B2C /* SymbolTableOrScopeDepth.h in Headers */,
 				0FD79A2D1EBBBDBB00DA88D3 /* Synchronousness.h in Headers */,
 				0F1FB38F1E173A6700A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (246072 => 246073)


--- trunk/Source/_javascript_Core/Sources.txt	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-06-04 18:27:59 UTC (rev 246073)
@@ -784,7 +784,6 @@
 runtime/Identifier.cpp
 runtime/IndexingType.cpp
 runtime/IndirectEvalExecutable.cpp
-runtime/InferredValue.cpp
 runtime/InitializeThreading.cpp
 runtime/InspectorInstrumentationObject.cpp
 runtime/InternalFunction.cpp

Modified: trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfileInlines.h (246072 => 246073)


--- trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfileInlines.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfileInlines.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -63,7 +63,7 @@
         if (Options::forcePolyProto())
             isPolyProto = true;
         else
-            isPolyProto = executable->ensurePolyProtoWatchpoint().hasBeenInvalidated() && executable->singletonFunctionHasBeenInvalidated();
+            isPolyProto = executable->ensurePolyProtoWatchpoint().hasBeenInvalidated() && executable->singleton().hasBeenInvalidated();
     }
 
     unsigned inlineCapacity = 0;

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.h (246072 => 246073)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -161,10 +161,11 @@
     Type m_type;
 };
 
-enum WatchpointState {
-    ClearWatchpoint,
-    IsWatched,
-    IsInvalidated
+// Make sure that the state can be represented in 2 bits.
+enum WatchpointState : uint8_t {
+    ClearWatchpoint = 0,
+    IsWatched = 1,
+    IsInvalidated = 2
 };
 
 class InlineWatchpointSet;

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -2762,10 +2762,8 @@
         
     case GetCallee:
         if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {
-            InferredValue* singleton = executable->singletonFunction();
-            if (JSValue value = singleton->inferredValue()) {
-                m_graph.watchpoints().addLazily(singleton);
-                JSFunction* function = jsCast<JSFunction*>(value);
+            if (JSFunction* function = executable->singleton().inferredValue()) {
+                m_graph.watchpoints().addLazily(executable);
                 setConstant(node, *m_graph.freeze(function));
                 break;
             }

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -321,10 +321,8 @@
             // that we don't have such watchpoint-based folding for inlined uses of Callee, since in that
             // case if the function is a singleton then we already know it.
             if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(*m_vm, m_codeBlock->ownerExecutable())) {
-                InferredValue* singleton = executable->singletonFunction();
-                if (JSValue value = singleton->inferredValue()) {
-                    m_graph.watchpoints().addLazily(singleton);
-                    JSFunction* function = jsCast<JSFunction*>(value);
+                if (JSFunction* function = executable->singleton().inferredValue()) {
+                    m_graph.watchpoints().addLazily(executable);
                     return weakJSConstant(function);
                 }
             }
@@ -6276,11 +6274,11 @@
                 
                 // We have various forms of constant folding here. This is necessary to avoid
                 // spurious recompiles in dead-but-foldable code.
+
                 if (symbolTable) {
-                    InferredValue* singleton = symbolTable->singletonScope();
-                    if (JSValue value = singleton->inferredValue()) {
-                        m_graph.watchpoints().addLazily(singleton);
-                        set(bytecode.m_dst, weakJSConstant(value));
+                    if (JSScope* scope = symbolTable->singleton().inferredValue()) {
+                        m_graph.watchpoints().addLazily(symbolTable);
+                        set(bytecode.m_dst, weakJSConstant(scope));
                         break;
                     }
                 }
@@ -6311,7 +6309,6 @@
         case op_resolve_scope_for_hoisting_func_decl_in_eval: {
             auto bytecode = currentInstruction->as<OpResolveScopeForHoistingFuncDeclInEval>();
             unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[bytecode.m_property];
-
             set(bytecode.m_dst, addToGraph(ResolveScopeForHoistingFuncDeclInEval, OpInfo(identifierNumber), get(bytecode.m_scope)));
 
             NEXT_OPCODE(op_resolve_scope_for_hoisting_func_decl_in_eval);

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -514,7 +514,7 @@
 
     case CreateActivation: {
         SymbolTable* table = node->castOperand<SymbolTable*>();
-        if (table->singletonScope()->isStillValid())
+        if (table->singleton().isStillValid())
             write(Watchpoint_fire);
         read(HeapObjectCount);
         write(HeapObjectCount);
@@ -1568,7 +1568,7 @@
     case NewGeneratorFunction:
     case NewAsyncGeneratorFunction:
     case NewAsyncFunction:
-        if (node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid())
+        if (node->castOperand<FunctionExecutable*>()->singleton().isStillValid())
             write(Watchpoint_fire);
         read(HeapObjectCount);
         write(HeapObjectCount);

Modified: trunk/Source/_javascript_Core/dfg/DFGClobbersExitState.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGClobbersExitState.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGClobbersExitState.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -87,7 +87,7 @@
 
     case CreateActivation:
         // Like above, but with the activation allocation caveat.
-        return node->castOperand<SymbolTable*>()->singletonScope()->isStillValid();
+        return node->castOperand<SymbolTable*>()->singleton().isStillValid();
 
     case NewFunction:
     case NewGeneratorFunction:
@@ -94,7 +94,7 @@
     case NewAsyncGeneratorFunction:
     case NewAsyncFunction:
         // Like above, but with the JSFunction allocation caveat.
-        return node->castOperand<FunctionExecutable*>()->singletonFunction()->isStillValid();
+        return node->castOperand<FunctionExecutable*>()->singleton().isStillValid();
 
     default:
         // For all other nodes, we just care about whether they write to something other than SideState.

Modified: trunk/Source/_javascript_Core/dfg/DFGDesiredWatchpoints.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGDesiredWatchpoints.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGDesiredWatchpoints.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -48,13 +48,20 @@
     vm.heap.addReference(neuteringWatchpoint, view->possiblySharedBuffer());
 }
 
-void InferredValueAdaptor::add(
-    CodeBlock* codeBlock, InferredValue* inferredValue, CommonData& common)
+void SymbolTableAdaptor::add(
+    CodeBlock* codeBlock, SymbolTable* symbolTable, CommonData& common)
 {
-    codeBlock->addConstant(inferredValue); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
-    inferredValue->add(common.watchpoints.add(codeBlock));
+    codeBlock->addConstant(symbolTable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
+    symbolTable->singleton().add(common.watchpoints.add(codeBlock));
 }
 
+void FunctionExecutableAdaptor::add(
+    CodeBlock* codeBlock, FunctionExecutable* executable, CommonData& common)
+{
+    codeBlock->addConstant(executable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
+    executable->singleton().add(common.watchpoints.add(codeBlock));
+}
+
 void AdaptiveStructureWatchpointAdaptor::add(
     CodeBlock* codeBlock, const ObjectPropertyCondition& key, CommonData& common)
 {
@@ -82,11 +89,16 @@
     m_inlineSets.addLazily(&set);
 }
 
-void DesiredWatchpoints::addLazily(InferredValue* inferredValue)
+void DesiredWatchpoints::addLazily(SymbolTable* symbolTable)
 {
-    m_inferredValues.addLazily(inferredValue);
+    m_symbolTables.addLazily(symbolTable);
 }
 
+void DesiredWatchpoints::addLazily(FunctionExecutable* executable)
+{
+    m_functionExecutables.addLazily(executable);
+}
+
 void DesiredWatchpoints::addLazily(JSArrayBufferView* view)
 {
     m_bufferViews.addLazily(view);
@@ -109,7 +121,8 @@
 {
     m_sets.reallyAdd(codeBlock, commonData);
     m_inlineSets.reallyAdd(codeBlock, commonData);
-    m_inferredValues.reallyAdd(codeBlock, commonData);
+    m_symbolTables.reallyAdd(codeBlock, commonData);
+    m_functionExecutables.reallyAdd(codeBlock, commonData);
     m_bufferViews.reallyAdd(codeBlock, commonData);
     m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
 }
@@ -118,7 +131,8 @@
 {
     return m_sets.areStillValid()
         && m_inlineSets.areStillValid()
-        && m_inferredValues.areStillValid()
+        && m_symbolTables.areStillValid()
+        && m_functionExecutables.areStillValid()
         && m_bufferViews.areStillValid()
         && m_adaptiveStructureSets.areStillValid();
 }
@@ -128,7 +142,8 @@
     out.print("Desired watchpoints:\n");
     out.print("    Watchpoint sets: ", inContext(m_sets, context), "\n");
     out.print("    Inline watchpoint sets: ", inContext(m_inlineSets, context), "\n");
-    out.print("    Inferred values: ", inContext(m_inferredValues, context), "\n");
+    out.print("    SymbolTables: ", inContext(m_symbolTables, context), "\n");
+    out.print("    FunctionExecutables: ", inContext(m_functionExecutables, context), "\n");
     out.print("    Buffer views: ", inContext(m_bufferViews, context), "\n");
     out.print("    Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGDesiredWatchpoints.h (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGDesiredWatchpoints.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGDesiredWatchpoints.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -28,9 +28,10 @@
 #if ENABLE(DFG_JIT)
 
 #include "DFGCommonData.h"
-#include "InferredValue.h"
+#include "FunctionExecutable.h"
 #include "JSArrayBufferView.h"
 #include "ObjectPropertyCondition.h"
+#include "SymbolTable.h"
 #include "Watchpoint.h"
 #include <wtf/CommaPrinter.h>
 #include <wtf/HashSet.h>
@@ -55,18 +56,30 @@
     }
 };
 
-struct InferredValueAdaptor {
-    static void add(CodeBlock*, InferredValue*, CommonData&);
-    static bool hasBeenInvalidated(InferredValue* inferredValue)
+struct SymbolTableAdaptor {
+    static void add(CodeBlock*, SymbolTable*, CommonData&);
+    static bool hasBeenInvalidated(SymbolTable* symbolTable)
     {
-        return inferredValue->hasBeenInvalidated();
+        return symbolTable->singleton().hasBeenInvalidated();
     }
-    static void dumpInContext(PrintStream& out, InferredValue* inferredValue, DumpContext*)
+    static void dumpInContext(PrintStream& out, SymbolTable* symbolTable, DumpContext*)
     {
-        out.print(RawPointer(inferredValue));
+        out.print(RawPointer(symbolTable));
     }
 };
 
+struct FunctionExecutableAdaptor {
+    static void add(CodeBlock*, FunctionExecutable*, CommonData&);
+    static bool hasBeenInvalidated(FunctionExecutable* executable)
+    {
+        return executable->singleton().hasBeenInvalidated();
+    }
+    static void dumpInContext(PrintStream& out, FunctionExecutable* executable, DumpContext*)
+    {
+        out.print(RawPointer(executable));
+    }
+};
+
 struct ArrayBufferViewWatchpointAdaptor {
     static void add(CodeBlock*, JSArrayBufferView*, CommonData&);
     static bool hasBeenInvalidated(JSArrayBufferView* view)
@@ -154,7 +167,8 @@
     
     void addLazily(WatchpointSet*);
     void addLazily(InlineWatchpointSet&);
-    void addLazily(InferredValue*);
+    void addLazily(SymbolTable*);
+    void addLazily(FunctionExecutable*);
     void addLazily(JSArrayBufferView*);
     
     // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
@@ -175,10 +189,14 @@
     {
         return m_inlineSets.isWatched(&set);
     }
-    bool isWatched(InferredValue* inferredValue)
+    bool isWatched(SymbolTable* symbolTable)
     {
-        return m_inferredValues.isWatched(inferredValue);
+        return m_symbolTables.isWatched(symbolTable);
     }
+    bool isWatched(FunctionExecutable* executable)
+    {
+        return m_functionExecutables.isWatched(executable);
+    }
     bool isWatched(JSArrayBufferView* view)
     {
         return m_bufferViews.isWatched(view);
@@ -193,7 +211,8 @@
 private:
     GenericDesiredWatchpoints<WatchpointSet*> m_sets;
     GenericDesiredWatchpoints<InlineWatchpointSet*> m_inlineSets;
-    GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues;
+    GenericDesiredWatchpoints<SymbolTable*, SymbolTableAdaptor> m_symbolTables;
+    GenericDesiredWatchpoints<FunctionExecutable*, FunctionExecutableAdaptor> m_functionExecutables;
     GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
     GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets;
 };

Modified: trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGObjectAllocationSinkingPhase.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -840,7 +840,7 @@
         case NewGeneratorFunction:
         case NewAsyncGeneratorFunction:
         case NewAsyncFunction: {
-            if (isStillValid(node->castOperand<FunctionExecutable*>()->singletonFunction())) {
+            if (isStillValid(node->castOperand<FunctionExecutable*>())) {
                 m_heap.escape(node->child1().node());
                 break;
             }
@@ -868,7 +868,7 @@
         }
 
         case CreateActivation: {
-            if (isStillValid(node->castOperand<SymbolTable*>()->singletonScope())) {
+            if (isStillValid(node->castOperand<SymbolTable*>())) {
                 m_heap.escape(node->child1().node());
                 break;
             }
@@ -2382,11 +2382,17 @@
     // different answers. It turns out that this analysis works OK regardless of what this
     // returns but breaks badly if this changes its mind for any particular InferredValue. This
     // method protects us from that.
-    bool isStillValid(InferredValue* value)
+    bool isStillValid(SymbolTable* value)
     {
-        return m_validInferredValues.add(value, value->isStillValid()).iterator->value;
+        return m_validInferredValues.add(value, value->singleton().isStillValid()).iterator->value;
     }
 
+    bool isStillValid(FunctionExecutable* value)
+    {
+        return m_validInferredValues.add(value, value->singleton().isStillValid()).iterator->value;
+    }
+
+
     SSACalculator m_pointerSSA;
     SSACalculator m_allocationSSA;
     NodeSet m_sinkCandidates;
@@ -2397,7 +2403,7 @@
     InsertionSet m_insertionSet;
     CombinedLiveness m_combinedLiveness;
 
-    HashMap<InferredValue*, bool> m_validInferredValues;
+    HashMap<JSCell*, bool> m_validInferredValues;
 
     HashMap<Node*, Node*> m_materializationToEscapee;
     HashMap<Node*, Vector<Node*>> m_materializationSiteToMaterializations;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -7193,7 +7193,7 @@
 
     FunctionExecutable* executable = node->castOperand<FunctionExecutable*>();
 
-    if (executable->singletonFunction()->isStillValid()) {
+    if (executable->singleton().isStillValid()) {
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
         
@@ -7410,7 +7410,7 @@
     JSValue initializationValue = node->initializationValueForActivation();
     ASSERT(initializationValue == jsUndefined() || initializationValue == jsTDZValue());
     
-    if (table->singletonScope()->isStillValid()) {
+    if (table->singleton().isStillValid()) {
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
 

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -5441,7 +5441,7 @@
         RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure());
         JSValue initializationValue = m_node->initializationValueForActivation();
         ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue());
-        if (table->singletonScope()->isStillValid()) {
+        if (table->singleton().isStillValid()) {
             LValue callResult = vmCall(
                 Int64,
                 m_out.operation(operationCreateActivationDirect), m_callFrame, weakStructure(structure),
@@ -5502,7 +5502,7 @@
         LValue scope = lowCell(m_node->child1());
         
         FunctionExecutable* executable = m_node->castOperand<FunctionExecutable*>();
-        if (executable->singletonFunction()->isStillValid()) {
+        if (executable->singleton().isStillValid()) {
             LValue callResult =
                 isGeneratorFunction ? vmCall(Int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) :
                 isAsyncFunction ? vmCall(Int64, m_out.operation(operationNewAsyncFunction), m_callFrame, scope, weakPointer(executable)) :

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -31,6 +31,7 @@
 #include "EdenGCActivityCallback.h"
 #include "Exception.h"
 #include "FullGCActivityCallback.h"
+#include "FunctionExecutableInlines.h"
 #include "GCActivityCallback.h"
 #include "GCIncomingRefCountedSetInlines.h"
 #include "GCSegmentedArrayInlines.h"
@@ -67,6 +68,7 @@
 #include "SubspaceInlines.h"
 #include "SuperSampler.h"
 #include "SweepingScope.h"
+#include "SymbolTableInlines.h"
 #include "SynchronousStopTheWorldMutatorScheduler.h"
 #include "TypeProfiler.h"
 #include "TypeProfilerLog.h"
@@ -596,8 +598,8 @@
 void Heap::finalizeUnconditionalFinalizers()
 {
     vm()->builtinExecutables()->finalizeUnconditionally();
-    if (vm()->m_inferredValueSpace)
-        finalizeMarkedUnconditionalFinalizers<InferredValue>(vm()->m_inferredValueSpace->space);
+    finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(vm()->functionExecutableSpace.space);
+    finalizeMarkedUnconditionalFinalizers<SymbolTable>(vm()->symbolTableSpace);
     vm()->forEachCodeBlockSpace(
         [&] (auto& space) {
             this->finalizeMarkedUnconditionalFinalizers<CodeBlock>(space.set);

Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -48,10 +48,6 @@
 {
     RELEASE_ASSERT(!source.isNull());
     ASSERT(source.length());
-    if (VM::canUseJIT())
-        new (&m_singletonFunction) WriteBarrier<InferredValue>();
-    else
-        m_singletonFunctionState = ClearWatchpoint;
 }
 
 void FunctionExecutable::finishCreation(VM& vm, ScriptExecutable* topLevelExecutable)
@@ -58,8 +54,6 @@
 {
     Base::finishCreation(vm);
     m_topLevelExecutable.set(vm, this, topLevelExecutable ? topLevelExecutable : this);
-    if (VM::canUseJIT())
-        m_singletonFunction.set(vm, this, InferredValue::create(vm));
 }
 
 void FunctionExecutable::destroy(JSCell* cell)
@@ -90,8 +84,6 @@
     visitor.append(thisObject->m_codeBlockForCall);
     visitor.append(thisObject->m_codeBlockForConstruct);
     visitor.append(thisObject->m_unlinkedExecutable);
-    if (VM::canUseJIT())
-        visitor.append(thisObject->m_singletonFunction);
     if (RareData* rareData = thisObject->m_rareData.get()) {
         visitor.append(rareData->m_cachedPolyProtoStructure);
         if (TemplateObjectMap* map = rareData->m_templateObjectMap.get()) {

Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -248,38 +248,16 @@
 
     DECLARE_INFO;
 
-    InferredValue* singletonFunction()
+    InferredValue<JSFunction>& singleton()
     {
-        if (VM::canUseJIT())
-            return m_singletonFunction.get();
-        return nullptr;
+        return m_singleton;
     }
 
-    void notifyCreation(VM& vm, JSValue value, const char* reason)
+    void notifyCreation(VM& vm, JSFunction* function, const char* reason)
     {
-        if (VM::canUseJIT()) {
-            singletonFunction()->notifyWrite(vm, value, reason);
-            return;
-        }
-        switch (m_singletonFunctionState) {
-        case ClearWatchpoint:
-            m_singletonFunctionState = IsWatched;
-            return;
-        case IsWatched:
-            m_singletonFunctionState = IsInvalidated;
-            return;
-        case IsInvalidated:
-            return;
-        }
+        m_singleton.notifyWrite(vm, this, function, reason);
     }
 
-    bool singletonFunctionHasBeenInvalidated()
-    {
-        if (VM::canUseJIT())
-            return singletonFunction()->hasBeenInvalidated();
-        return m_singletonFunctionState == IsInvalidated;
-    }
-
     // Cached poly proto structure for the result of constructing this executable.
     Structure* cachedPolyProtoStructure()
     {
@@ -305,6 +283,8 @@
 
     TemplateObjectMap& ensureTemplateObjectMap(VM&);
 
+    void finalizeUnconditionally(VM&);
+
 private:
     friend class ExecutableBase;
     FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic);
@@ -342,10 +322,7 @@
     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
     WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall;
     WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct;
-    union {
-        WriteBarrier<InferredValue> m_singletonFunction;
-        WatchpointState m_singletonFunctionState;
-    };
+    InferredValue<JSFunction> m_singleton;
     Box<InlineWatchpointSet> m_polyProtoWatchpoint;
 };
 

Copied: trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h (from rev 246072, trunk/Source/_javascript_Core/runtime/InferredValueInlines.h) (0 => 246073)


--- trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutableInlines.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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 "FunctionExecutable.h"
+#include "InferredValueInlines.h"
+
+namespace JSC {
+
+inline void FunctionExecutable::finalizeUnconditionally(VM& vm)
+{
+    m_singleton.finalizeUnconditionally(vm);
+}
+
+} // namespace JSC
+

Deleted: trunk/Source/_javascript_Core/runtime/InferredValue.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/InferredValue.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/InferredValue.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2015-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. 
- */
-
-#include "config.h"
-#include "InferredValue.h"
-
-#include "IsoCellSetInlines.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-const ClassInfo InferredValue::s_info = { "InferredValue", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(InferredValue) };
-
-InferredValue* InferredValue::create(VM& vm)
-{
-    ASSERT(VM::canUseJIT());
-    InferredValue* result = new (NotNull, allocateCell<InferredValue>(vm.heap)) InferredValue(vm);
-    result->finishCreation(vm);
-    return result;
-}
-
-void InferredValue::destroy(JSCell* cell)
-{
-    InferredValue* inferredValue = static_cast<InferredValue*>(cell);
-    inferredValue->InferredValue::~InferredValue();
-}
-
-Structure* InferredValue::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
-{
-    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
-}
-
-void InferredValue::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
-    InferredValue* inferredValue = jsCast<InferredValue*>(cell);
-    Base::visitChildren(cell, visitor);
-
-    JSValue value = inferredValue->m_value.get();
-    if (!value)
-        return;
-    if (!value.isCell())
-        return;
-    
-    VM::SpaceAndSet::setFor(*inferredValue->subspace()).add(inferredValue);
-}
-
-InferredValue::InferredValue(VM& vm)
-    : Base(vm, vm.inferredValueStructure.get())
-    , m_set(ClearWatchpoint)
-{
-}
-
-InferredValue::~InferredValue()
-{
-}
-
-void InferredValue::notifyWriteSlow(VM& vm, JSValue value, const FireDetail& detail)
-{
-    ASSERT(!!value);
-    switch (m_set.state()) {
-    case ClearWatchpoint:
-        m_value.set(vm, this, value);
-        m_set.startWatching();
-        return;
-        
-    case IsWatched:
-        ASSERT(!!m_value);
-        if (m_value.get() == value)
-            return;
-        invalidate(vm, detail);
-        return;
-        
-    case IsInvalidated:
-        ASSERT_NOT_REACHED();
-        return;
-    }
-    
-    ASSERT_NOT_REACHED();
-}
-
-void InferredValue::notifyWriteSlow(VM& vm, JSValue value, const char* reason)
-{
-    notifyWriteSlow(vm, value, StringFireDetail(reason));
-}
-
-} // namespace JSC
-

Modified: trunk/Source/_javascript_Core/runtime/InferredValue.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/InferredValue.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/InferredValue.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,43 +25,19 @@
 
 #pragma once
 
-#include "IsoSubspace.h"
 #include "JSCast.h"
 #include "VM.h"
 #include "Watchpoint.h"
 #include "WriteBarrier.h"
+#include <wtf/Nonmovable.h>
 
 namespace JSC {
 
-// Allocate one of these if you'd like to infer a constant value. Writes to the value should use
-// notifyWrite(). So long as exactly one value had ever been written and invalidate() has never been
-// called, and you register a watchpoint, you can rely on the inferredValue() being the one true
-// value.
-//
-// Commonly used for inferring singletons - in that case each allocation does notifyWrite(). But you
-// can use it for other things as well.
-
-class InferredValue final : public JSCell {
+template<typename JSCellType>
+class InferredValue {
+    WTF_MAKE_NONCOPYABLE(InferredValue);
+    WTF_MAKE_NONMOVABLE(InferredValue);
 public:
-    typedef JSCell Base;
-    
-    template<typename CellType, SubspaceAccess mode>
-    static IsoSubspace* subspaceFor(VM& vm)
-    {
-        return vm.inferredValueSpace<mode>();
-    }
-
-    static InferredValue* create(VM&);
-    
-    static const bool needsDestruction = true;
-    static void destroy(JSCell*);
-    
-    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
-    
-    static void visitChildren(JSCell*, SlotVisitor&);
-    
-    DECLARE_INFO;
-    
     // For the purpose of deciding whether or not to watch this variable, you only need
     // to inspect inferredValue(). If this returns something other than the empty
     // value, then it means that at all future safepoints, this watchpoint set will be
@@ -73,51 +49,259 @@
     //    IsInvalidated: in this case the variable's value may be anything but you'll
     //        either notice that it's invalidated and not install the watchpoint, or
     //        you will have been notified that the watchpoint was fired.
-    JSValue inferredValue() { return m_value.get(); }
+    JSCellType* inferredValue()
+    {
+        uintptr_t data = ""
+        if (isFat(data))
+            return fat(data)->inferredValue();
+        return bitwise_cast<JSCellType*>(data & ValueMask);
+    }
 
-    // Forwards some WatchpointSet methods.
-    WatchpointState state() const { return m_set.state(); }
-    bool isStillValid() const { return m_set.isStillValid(); }
-    bool hasBeenInvalidated() const { return m_set.hasBeenInvalidated(); }
-    void add(Watchpoint* watchpoint) { m_set.add(watchpoint); }
-    
-    void notifyWrite(VM& vm, JSValue value, const FireDetail& detail)
+    explicit InferredValue()
+        : m_data(encodeState(ClearWatchpoint))
     {
-        if (LIKELY(m_set.stateOnJSThread() == IsInvalidated))
+        ASSERT(inferredValue() == nullptr);
+    }
+
+    ~InferredValue()
+    {
+        if (isThin())
             return;
-        notifyWriteSlow(vm, value, detail);
+        freeFat();
     }
+
+    // Fast way of getting the state, which only works from the main thread.
+    WatchpointState stateOnJSThread() const
+    {
+        uintptr_t data = ""
+        if (isFat(data))
+            return fat(data)->stateOnJSThread();
+        return decodeState(data);
+    }
+
+    // It is safe to call this from another thread. It may return a prior state,
+    // but that should be fine since you should only perform actions based on the
+    // state if you also add a watchpoint.
+    WatchpointState state() const
+    {
+        WTF::loadLoadFence();
+        uintptr_t data = ""
+        WTF::loadLoadFence();
+        if (isFat(data))
+            return fat(data)->state();
+        return decodeState(data);
+    }
+
+    // It is safe to call this from another thread. It may return false
+    // even if the set actually had been invalidated, but that ought to happen
+    // only in the case of races, and should be rare.
+    bool hasBeenInvalidated() const
+    {
+        return state() == IsInvalidated;
+    }
     
-    void notifyWrite(VM& vm, JSValue value, const char* reason)
+    // Like hasBeenInvalidated(), may be called from another thread.
+    bool isStillValid() const
     {
-        if (LIKELY(m_set.stateOnJSThread() == IsInvalidated))
-            return;
-        notifyWriteSlow(vm, value, reason);
+        return !hasBeenInvalidated();
     }
     
+    void add(Watchpoint*);
+    
     void invalidate(VM& vm, const FireDetail& detail)
     {
-        m_value.clear();
-        m_set.invalidate(vm, detail);
+        if (isFat())
+            fat()->invalidate(vm, detail);
+        else
+            m_data = encodeState(IsInvalidated);
     }
     
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+    bool isBeingWatched() const
+    {
+        if (isFat())
+            return fat()->isBeingWatched();
+        return false;
+    }
+
+    void notifyWrite(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail)
+    {
+        if (LIKELY(stateOnJSThread() == IsInvalidated))
+            return;
+        notifyWriteSlow(vm, owner, value, detail);
+    }
     
+    void notifyWrite(VM& vm, JSCell* owner, JSCellType* value, const char* reason)
+    {
+        if (LIKELY(stateOnJSThread() == IsInvalidated))
+            return;
+        notifyWriteSlow(vm, owner, value, reason);
+    }
+    
     void finalizeUnconditionally(VM&);
-    
+
 private:
-    InferredValue(VM&);
-    ~InferredValue();
+    class InferredValueWatchpointSet final : public WatchpointSet {
+    public:
+        InferredValueWatchpointSet(WatchpointState state, JSCellType* value)
+            : WatchpointSet(state)
+            , m_value(value)
+        {
+        }
+
+        JSCellType* inferredValue() const { return m_value; }
+
+        void invalidate(VM& vm, const FireDetail& detail)
+        {
+            m_value = nullptr;
+            WatchpointSet::invalidate(vm, detail);
+        }
+
+        void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const FireDetail&);
+
+    private:
+        JSCellType* m_value;
+    };
+
+    static constexpr uintptr_t IsThinFlag        = 1;
+    static constexpr uintptr_t StateMask         = 6;
+    static constexpr uintptr_t StateShift        = 1;
+    static constexpr uintptr_t ValueMask         = ~static_cast<uintptr_t>(IsThinFlag | StateMask);
     
-    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&);
-    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const char* reason);
+    static bool isThin(uintptr_t data) { return data & IsThinFlag; }
+    static bool isFat(uintptr_t data) { return !isThin(data); }
     
-    InlineWatchpointSet m_set;
-    WriteBarrier<Unknown> m_value;
+    static WatchpointState decodeState(uintptr_t data)
+    {
+        ASSERT(isThin(data));
+        return static_cast<WatchpointState>((data & StateMask) >> StateShift);
+    }
+    
+    static uintptr_t encodeState(WatchpointState state)
+    {
+        return (static_cast<uintptr_t>(state) << StateShift) | IsThinFlag;
+    }
+    
+    bool isThin() const { return isThin(m_data); }
+    bool isFat() const { return isFat(m_data); };
+    
+    static InferredValueWatchpointSet* fat(uintptr_t data)
+    {
+        return bitwise_cast<InferredValueWatchpointSet*>(data);
+    }
+    
+    InferredValueWatchpointSet* fat()
+    {
+        ASSERT(isFat());
+        return fat(m_data);
+    }
+    
+    const InferredValueWatchpointSet* fat() const
+    {
+        ASSERT(isFat());
+        return fat(m_data);
+    }
+    
+    InferredValueWatchpointSet* inflate()
+    {
+        if (LIKELY(isFat()))
+            return fat();
+        return inflateSlow();
+    }
+
+    InferredValueWatchpointSet* inflateSlow();
+    void freeFat();
+
+    void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const FireDetail&);
+    void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const char* reason);
+    
+    uintptr_t m_data;
 };
 
-// FIXME: We could have an InlineInferredValue, which only allocates the InferredValue object when
-// a notifyWrite() transitions us towards watching, and then clears the reference (allowing the object
-// to die) when we get invalidated.
+template<typename JSCellType>
+void InferredValue<JSCellType>::InferredValueWatchpointSet::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail)
+{
+    switch (state()) {
+    case ClearWatchpoint:
+        m_value = value;
+        vm.heap.writeBarrier(owner, value);
+        startWatching();
+        return;
 
+    case IsWatched:
+        ASSERT(!!m_value);
+        if (m_value == value)
+            return;
+        invalidate(vm, detail);
+        return;
+
+    case IsInvalidated:
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
+template<typename JSCellType>
+void InferredValue<JSCellType>::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail)
+{
+    uintptr_t data = ""
+    if (isFat(data)) {
+        fat(data)->notifyWriteSlow(vm, owner, value, detail);
+        return;
+    }
+
+    switch (state()) {
+    case ClearWatchpoint:
+        ASSERT(decodeState(m_data) != IsInvalidated);
+        m_data = (bitwise_cast<uintptr_t>(value) & ValueMask) | encodeState(IsWatched);
+        vm.heap.writeBarrier(owner, value);
+        return;
+
+    case IsWatched:
+        ASSERT(!!inferredValue());
+        if (inferredValue() == value)
+            return;
+        invalidate(vm, detail);
+        return;
+
+    case IsInvalidated:
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
+template<typename JSCellType>
+void InferredValue<JSCellType>::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const char* reason)
+{
+    notifyWriteSlow(vm, owner, value, StringFireDetail(reason));
+}
+
+template<typename JSCellType>
+void InferredValue<JSCellType>::add(Watchpoint* watchpoint)
+{
+    inflate()->add(watchpoint);
+}
+
+template<typename JSCellType>
+auto InferredValue<JSCellType>::inflateSlow() -> InferredValueWatchpointSet*
+{
+    ASSERT(isThin());
+    ASSERT(!isCompilationThread());
+    uintptr_t data = ""
+    InferredValueWatchpointSet* fat = adoptRef(new InferredValueWatchpointSet(decodeState(m_data), bitwise_cast<JSCellType*>(data & ValueMask))).leakRef();
+    WTF::storeStoreFence();
+    m_data = bitwise_cast<uintptr_t>(fat);
+    return fat;
+}
+
+template<typename JSCellType>
+void InferredValue<JSCellType>::freeFat()
+{
+    ASSERT(isFat());
+    fat()->deref();
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/InferredValueInlines.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/InferredValueInlines.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/InferredValueInlines.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -20,7 +20,7 @@
  * 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. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #pragma once
@@ -29,19 +29,17 @@
 
 namespace JSC {
 
-void InferredValue::finalizeUnconditionally(VM& vm)
+template<typename JSCellType>
+void InferredValue<JSCellType>::finalizeUnconditionally(VM& vm)
 {
-    JSValue value = m_value.get();
-    
-    if (value && value.isCell()) {
-        if (vm.heap.isMarked(value.asCell()))
+    JSCellType* value = inferredValue();
+
+    if (value) {
+        if (vm.heap.isMarked(value))
             return;
-        
+
         invalidate(vm, StringFireDetail("InferredValue clean-up during GC"));
     }
-    
-    VM::SpaceAndSet::setFor(*subspace()).remove(this);
 }
 
 } // namespace JSC
-

Modified: trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/JSFunctionInlines.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -34,7 +34,7 @@
 inline JSFunction* JSFunction::createWithInvalidatedReallocationWatchpoint(
     VM& vm, FunctionExecutable* executable, JSScope* scope)
 {
-    ASSERT(executable->singletonFunctionHasBeenInvalidated());
+    ASSERT(executable->singleton().hasBeenInvalidated());
     return createImpl(vm, executable, scope, selectStructureForNewFuncExp(scope->globalObject(vm), executable));
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSSymbolTableObject.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/JSSymbolTableObject.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/JSSymbolTableObject.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -66,8 +66,7 @@
     void setSymbolTable(VM& vm, SymbolTable* symbolTable)
     {
         ASSERT(!m_symbolTable);
-        if (auto* singletonScope = symbolTable->singletonScope())
-            singletonScope->notifyWrite(vm, this, "Allocated a scope");
+        symbolTable->notifyCreation(vm, this, "Allocated a scope");
         m_symbolTable.set(vm, this, symbolTable);
     }
     

Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/SymbolTable.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -90,8 +90,6 @@
 void SymbolTable::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
-    if (VM::canUseJIT())
-        m_singletonScope.set(vm, this, InferredValue::create(vm));
 }
 
 void SymbolTable::visitChildren(JSCell* thisCell, SlotVisitor& visitor)
@@ -100,7 +98,6 @@
     Base::visitChildren(thisSymbolTable, visitor);
 
     visitor.append(thisSymbolTable->m_arguments);
-    visitor.append(thisSymbolTable->m_singletonScope);
     
     if (thisSymbolTable->m_rareData)
         visitor.append(thisSymbolTable->m_rareData->m_codeBlock);

Modified: trunk/Source/_javascript_Core/runtime/SymbolTable.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/SymbolTable.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/SymbolTable.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -345,7 +345,6 @@
     };
     
     SymbolTableEntry& copySlow(const SymbolTableEntry&);
-    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&);
     
     bool isFat() const
     {
@@ -450,6 +449,12 @@
     typedef HashMap<VarOffset, RefPtr<UniquedStringImpl>> OffsetToVariableMap;
     typedef Vector<SymbolTableEntry*> LocalToEntryVec;
 
+    template<typename CellType, SubspaceAccess>
+    static IsoSubspace* subspaceFor(VM& vm)
+    {
+        return &vm.symbolTableSpace;
+    }
+
     static SymbolTable* create(VM& vm)
     {
         SymbolTable* symbolTable = new (NotNull, allocateCell<SymbolTable>(vm.heap)) SymbolTable(vm);
@@ -687,12 +692,19 @@
     CodeBlock* rareDataCodeBlock();
     void setRareDataCodeBlock(CodeBlock*);
     
-    InferredValue* singletonScope() { return m_singletonScope.get(); }
+    InferredValue<JSScope>& singleton() { return m_singleton; }
 
+    void notifyCreation(VM& vm, JSScope* scope, const char* reason)
+    {
+        m_singleton.notifyWrite(vm, this, scope, reason);
+    }
+
     static void visitChildren(JSCell*, SlotVisitor&);
 
     DECLARE_EXPORT_INFO;
 
+    void finalizeUnconditionally(VM&);
+
 private:
     JS_EXPORT_PRIVATE SymbolTable(VM&);
     ~SymbolTable();
@@ -717,7 +729,7 @@
     std::unique_ptr<SymbolTableRareData> m_rareData;
 
     WriteBarrier<ScopedArgumentsTable> m_arguments;
-    WriteBarrier<InferredValue> m_singletonScope;
+    InferredValue<JSScope> m_singleton;
     
     std::unique_ptr<LocalToEntryVec> m_localToEntry;
 };

Copied: trunk/Source/_javascript_Core/runtime/SymbolTableInlines.h (from rev 246072, trunk/Source/_javascript_Core/runtime/InferredValueInlines.h) (0 => 246073)


--- trunk/Source/_javascript_Core/runtime/SymbolTableInlines.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/SymbolTableInlines.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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 "InferredValueInlines.h"
+#include "SymbolTable.h"
+
+namespace JSC {
+
+inline void SymbolTable::finalizeUnconditionally(VM& vm)
+{
+    m_singleton.finalizeUnconditionally(vm);
+}
+
+} // namespace JSC
+

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2019-06-04 18:27:59 UTC (rev 246073)
@@ -64,7 +64,6 @@
 #include "Identifier.h"
 #include "IncrementalSweeper.h"
 #include "IndirectEvalExecutable.h"
-#include "InferredValue.h"
 #include "Interpreter.h"
 #include "IntlCollatorConstructor.h"
 #include "IntlDateTimeFormatConstructor.h"
@@ -286,6 +285,7 @@
     , propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable)
     , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData)
     , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure)
+    , symbolTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), SymbolTable)
     , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace)
     , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace)
     , codeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), CodeBlock)
@@ -378,8 +378,6 @@
     unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
     unlinkedModuleProgramCodeBlockStructure.set(*this, UnlinkedModuleProgramCodeBlock::createStructure(*this, 0, jsNull()));
     propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
-    if (VM::canUseJIT())
-        inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));
     functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
     exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
     promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
@@ -1277,7 +1275,6 @@
         return &m_##name->space; \
     }
 
-DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(inferredValueSpace, destructibleCellHeapCellType.get(), InferredValue)
 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType.get(), EvalExecutable)
 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType.get(), ModuleProgramExecutable)
 

Modified: trunk/Source/_javascript_Core/runtime/VM.h (246072 => 246073)


--- trunk/Source/_javascript_Core/runtime/VM.h	2019-06-04 17:59:51 UTC (rev 246072)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2019-06-04 18:27:59 UTC (rev 246073)
@@ -380,6 +380,7 @@
     IsoSubspace propertyTableSpace;
     IsoSubspace structureRareDataSpace;
     IsoSubspace structureSpace;
+    IsoSubspace symbolTableSpace;
 
 #define DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(name) \
     template<SubspaceAccess mode> \
@@ -451,7 +452,6 @@
     };
     
     SpaceAndSet codeBlockSpace;
-    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(inferredValueSpace)
 
     template<typename Func>
     void forEachCodeBlockSpace(const Func& func)
@@ -527,7 +527,6 @@
     Strong<Structure> unlinkedFunctionCodeBlockStructure;
     Strong<Structure> unlinkedModuleProgramCodeBlockStructure;
     Strong<Structure> propertyTableStructure;
-    Strong<Structure> inferredValueStructure;
     Strong<Structure> functionRareDataStructure;
     Strong<Structure> exceptionStructure;
     Strong<Structure> promiseDeferredStructure;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to