[JSC] InferredValue should not be a JSCell
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jun 2019 18:27:59 +0000 (18:27 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jun 2019 18:27:59 +0000 (18:27 +0000)
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.

* JavaScriptCore.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/JavaScriptCore/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/JavaScriptCore/runtime/InferredValueInlines.h.
(JSC::SymbolTable::finalizeUnconditionally):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246073 268f45cc-cd09-0410-ab3c-d52691b4dbfc

28 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/bytecode/ObjectAllocationProfileInlines.h
Source/JavaScriptCore/bytecode/Watchpoint.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp
Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h
Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/runtime/FunctionExecutable.cpp
Source/JavaScriptCore/runtime/FunctionExecutable.h
Source/JavaScriptCore/runtime/FunctionExecutableInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/InferredValue.cpp [deleted file]
Source/JavaScriptCore/runtime/InferredValue.h
Source/JavaScriptCore/runtime/InferredValueInlines.h
Source/JavaScriptCore/runtime/JSFunctionInlines.h
Source/JavaScriptCore/runtime/JSSymbolTableObject.h
Source/JavaScriptCore/runtime/SymbolTable.cpp
Source/JavaScriptCore/runtime/SymbolTable.h
Source/JavaScriptCore/runtime/SymbolTableInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h

index 40a5487..29d0cc0 100644 (file)
@@ -1,3 +1,109 @@
+2019-06-04  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [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.
+
+        * JavaScriptCore.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/JavaScriptCore/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/JavaScriptCore/runtime/InferredValueInlines.h.
+        (JSC::SymbolTable::finalizeUnconditionally):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
 2019-06-04  Tadeu Zagallo  <tzagallo@apple.com>
 
         Argument elimination should check for negative indices in GetByVal
index 7dc5545..6750a65 100644 (file)
                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, ); }; };
                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 */; };
                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>"; };
                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>"; };
                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>"; };
                                147341D71DC02F9900AA29BA /* FunctionExecutable.h */,
                                0FB4B52116B6278D003F696B /* FunctionExecutableDump.cpp */,
                                0FB4B52216B6278D003F696B /* FunctionExecutableDump.h */,
+                               E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */,
                                52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */,
                                52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */,
                                F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
                                0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
                                14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */,
                                14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */,
-                               0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
                                0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
                                0F4AE0421FE0D25400E20839 /* InferredValueInlines.h */,
                                E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
                                705B41AA1A6E501E00716757 /* SymbolPrototype.h */,
                                0F919D2715856770004A4E7D /* SymbolTable.cpp */,
                                14A396A60CD2933100B5B4FF /* SymbolTable.h */,
+                               E39BF39822A2288B00BD183E /* SymbolTableInlines.h */,
                                E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */,
                                BDB4B5E099CD4C1BB3C1CF05 /* TemplateObjectDescriptor.cpp */,
                                70ECA6041AFDBEA200449739 /* TemplateObjectDescriptor.h */,
                                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 */,
                                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 */,
index 3c7dd98..b8893ba 100644 (file)
@@ -784,7 +784,6 @@ runtime/HashMapImpl.cpp
 runtime/Identifier.cpp
 runtime/IndexingType.cpp
 runtime/IndirectEvalExecutable.cpp
-runtime/InferredValue.cpp
 runtime/InitializeThreading.cpp
 runtime/InspectorInstrumentationObject.cpp
 runtime/InternalFunction.cpp
index f11c4cc..1f7e83c 100644 (file)
@@ -63,7 +63,7 @@ ALWAYS_INLINE void ObjectAllocationProfileBase<Derived>::initializeProfile(VM& v
         if (Options::forcePolyProto())
             isPolyProto = true;
         else
-            isPolyProto = executable->ensurePolyProtoWatchpoint().hasBeenInvalidated() && executable->singletonFunctionHasBeenInvalidated();
+            isPolyProto = executable->ensurePolyProtoWatchpoint().hasBeenInvalidated() && executable->singleton().hasBeenInvalidated();
     }
 
     unsigned inlineCapacity = 0;
index ee8dd75..7bebc04 100644 (file)
@@ -161,10 +161,11 @@ private:
     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;
index 80c33f7..e82aa19 100644 (file)
@@ -2762,10 +2762,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         
     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;
             }
index bf9f55d..a69b01c 100644 (file)
@@ -321,10 +321,8 @@ private:
             // 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 @@ void ByteCodeParser::parseBlock(unsigned limit)
                 
                 // 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 @@ void ByteCodeParser::parseBlock(unsigned limit)
         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);
index c56d3ed..81033e9 100644 (file)
@@ -514,7 +514,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
 
     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 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     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);
index fddd518..aeb009b 100644 (file)
@@ -87,14 +87,14 @@ bool clobbersExitState(Graph& graph, Node* node)
 
     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:
     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.
index 1ac86ac..4a63e0e 100644 (file)
@@ -48,11 +48,18 @@ void ArrayBufferViewWatchpointAdaptor::add(
     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(
@@ -82,9 +89,14 @@ void DesiredWatchpoints::addLazily(InlineWatchpointSet& set)
     m_inlineSets.addLazily(&set);
 }
 
-void DesiredWatchpoints::addLazily(InferredValue* inferredValue)
+void DesiredWatchpoints::addLazily(SymbolTable* symbolTable)
+{
+    m_symbolTables.addLazily(symbolTable);
+}
+
+void DesiredWatchpoints::addLazily(FunctionExecutable* executable)
 {
-    m_inferredValues.addLazily(inferredValue);
+    m_functionExecutables.addLazily(executable);
 }
 
 void DesiredWatchpoints::addLazily(JSArrayBufferView* view)
@@ -109,7 +121,8 @@ void DesiredWatchpoints::reallyAdd(CodeBlock* codeBlock, CommonData& commonData)
 {
     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 @@ bool DesiredWatchpoints::areStillValid() const
 {
     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 @@ void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) c
     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");
 }
index af7f14f..e1c9ea8 100644 (file)
 #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,15 +56,27 @@ struct SetPointerAdaptor {
     }
 };
 
-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));
     }
 };
 
@@ -154,7 +167,8 @@ public:
     
     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,9 +189,13 @@ public:
     {
         return m_inlineSets.isWatched(&set);
     }
-    bool isWatched(InferredValue* inferredValue)
+    bool isWatched(SymbolTable* symbolTable)
+    {
+        return m_symbolTables.isWatched(symbolTable);
+    }
+    bool isWatched(FunctionExecutable* executable)
     {
-        return m_inferredValues.isWatched(inferredValue);
+        return m_functionExecutables.isWatched(executable);
     }
     bool isWatched(JSArrayBufferView* view)
     {
@@ -193,7 +211,8 @@ public:
 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;
 };
index 0345339..80b9eef 100644 (file)
@@ -840,7 +840,7 @@ private:
         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 @@ private:
         }
 
         case CreateActivation: {
-            if (isStillValid(node->castOperand<SymbolTable*>()->singletonScope())) {
+            if (isStillValid(node->castOperand<SymbolTable*>())) {
                 m_heap.escape(node->child1().node());
                 break;
             }
@@ -2382,11 +2382,17 @@ private:
     // 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 @@ private:
     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;
index e5538f1..7b96ec0 100644 (file)
@@ -7193,7 +7193,7 @@ void SpeculativeJIT::compileNewFunction(Node* node)
 
     FunctionExecutable* executable = node->castOperand<FunctionExecutable*>();
 
-    if (executable->singletonFunction()->isStillValid()) {
+    if (executable->singleton().isStillValid()) {
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
         
@@ -7410,7 +7410,7 @@ void SpeculativeJIT::compileCreateActivation(Node* node)
     JSValue initializationValue = node->initializationValueForActivation();
     ASSERT(initializationValue == jsUndefined() || initializationValue == jsTDZValue());
     
-    if (table->singletonScope()->isStillValid()) {
+    if (table->singleton().isStillValid()) {
         GPRFlushedCallResult result(this);
         GPRReg resultGPR = result.gpr();
 
index 873ae3b..d72af41 100644 (file)
@@ -5441,7 +5441,7 @@ private:
         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 @@ private:
         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)) :
index eed2672..6663b4f 100644 (file)
@@ -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::finalizeMarkedUnconditionalFinalizers(CellSet& cellSet)
 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);
index af3ab88..439e209 100644 (file)
@@ -48,18 +48,12 @@ FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, Unlinke
 {
     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)
 {
     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 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     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()) {
index 598803c..5a019b7 100644 (file)
@@ -248,36 +248,14 @@ public:
 
     DECLARE_INFO;
 
-    InferredValue* singletonFunction()
+    InferredValue<JSFunction>& singleton()
     {
-        if (VM::canUseJIT())
-            return m_singletonFunction.get();
-        return nullptr;
-    }
-
-    void notifyCreation(VM& vm, JSValue value, 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;
-        }
+        return m_singleton;
     }
 
-    bool singletonFunctionHasBeenInvalidated()
+    void notifyCreation(VM& vm, JSFunction* function, const char* reason)
     {
-        if (VM::canUseJIT())
-            return singletonFunction()->hasBeenInvalidated();
-        return m_singletonFunctionState == IsInvalidated;
+        m_singleton.notifyWrite(vm, this, function, reason);
     }
 
     // Cached poly proto structure for the result of constructing this executable.
@@ -305,6 +283,8 @@ public:
 
     TemplateObjectMap& ensureTemplateObjectMap(VM&);
 
+    void finalizeUnconditionally(VM&);
+
 private:
     friend class ExecutableBase;
     FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic);
@@ -342,10 +322,7 @@ private:
     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;
 };
 
diff --git a/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h b/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h
new file mode 100644 (file)
index 0000000..45299c3
--- /dev/null
@@ -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
+
diff --git a/Source/JavaScriptCore/runtime/InferredValue.cpp b/Source/JavaScriptCore/runtime/InferredValue.cpp
deleted file mode 100644 (file)
index c90f55d..0000000
+++ /dev/null
@@ -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
-
index da63e01..c2c9d61 100644 (file)
@@ -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
 
 #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 @@ public:
     //    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 = m_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))
+    {
+        ASSERT(inferredValue() == nullptr);
+    }
+
+    ~InferredValue()
     {
-        if (LIKELY(m_set.stateOnJSThread() == IsInvalidated))
+        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 = m_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 = m_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);
+    }
+    
+    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);
     }
     
-    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+    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); }
+    
+    static WatchpointState decodeState(uintptr_t data)
+    {
+        ASSERT(isThin(data));
+        return static_cast<WatchpointState>((data & StateMask) >> StateShift);
+    }
     
-    InlineWatchpointSet m_set;
-    WriteBarrier<Unknown> m_value;
+    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 = m_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 = m_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
index c143687..633999f 100644 (file)
@@ -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
 
 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
-
index 189021a..0fe78d5 100644 (file)
@@ -34,7 +34,7 @@ namespace JSC {
 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));
 }
 
index 5aa6d49..4cd4fa0 100644 (file)
@@ -66,8 +66,7 @@ protected:
     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);
     }
     
index c93607e..632c736 100644 (file)
@@ -90,8 +90,6 @@ SymbolTable::~SymbolTable() { }
 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 @@ void SymbolTable::visitChildren(JSCell* thisCell, SlotVisitor& visitor)
     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);
index 3fd1c46..8b74a20 100644 (file)
@@ -345,7 +345,6 @@ private:
     };
     
     SymbolTableEntry& copySlow(const SymbolTableEntry&);
-    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&);
     
     bool isFat() const
     {
@@ -450,6 +449,12 @@ public:
     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 @@ public:
     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 @@ private:
     std::unique_ptr<SymbolTableRareData> m_rareData;
 
     WriteBarrier<ScopedArgumentsTable> m_arguments;
-    WriteBarrier<InferredValue> m_singletonScope;
+    InferredValue<JSScope> m_singleton;
     
     std::unique_ptr<LocalToEntryVec> m_localToEntry;
 };
diff --git a/Source/JavaScriptCore/runtime/SymbolTableInlines.h b/Source/JavaScriptCore/runtime/SymbolTableInlines.h
new file mode 100644 (file)
index 0000000..834ef80
--- /dev/null
@@ -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
+
index 2b06a3b..45fa202 100644 (file)
@@ -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 @@ VM::VM(VMType vmType, HeapType heapType)
     , 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 @@ VM::VM(VMType vmType, HeapType heapType)
     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 @@ DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHea
         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)
 
index 918827f..11c87df 100644 (file)
@@ -380,6 +380,7 @@ public:
     IsoSubspace propertyTableSpace;
     IsoSubspace structureRareDataSpace;
     IsoSubspace structureSpace;
+    IsoSubspace symbolTableSpace;
 
 #define DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(name) \
     template<SubspaceAccess mode> \
@@ -451,7 +452,6 @@ public:
     };
     
     SpaceAndSet codeBlockSpace;
-    DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(inferredValueSpace)
 
     template<typename Func>
     void forEachCodeBlockSpace(const Func& func)
@@ -527,7 +527,6 @@ public:
     Strong<Structure> unlinkedFunctionCodeBlockStructure;
     Strong<Structure> unlinkedModuleProgramCodeBlockStructure;
     Strong<Structure> propertyTableStructure;
-    Strong<Structure> inferredValueStructure;
     Strong<Structure> functionRareDataStructure;
     Strong<Structure> exceptionStructure;
     Strong<Structure> promiseDeferredStructure;