WebKit Bugzilla
Attachment 371109 Details for
Bug 198407
: [JSC] InferredValue should not be a JSCell
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198407-20190531235613.patch (text/plain), 66.90 KB, created by
Yusuke Suzuki
on 2019-05-31 23:56:14 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2019-05-31 23:56:14 PDT
Size:
66.90 KB
patch
obsolete
>Subversion Revision: 245981 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 2a775655d2c6f0ab030aebf499b211319c2f7089..28f1e808c03768ffddd1e5d3669920a271ca44ab 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,105 @@ >+2019-05-31 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] InferredValue should not be a JSCell >+ https://bugs.webkit.org/show_bug.cgi?id=198407 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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/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/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-05-31 Don Olmstead <don.olmstead@sony.com> > > [CMake] Add WebKit::WTF target >diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >index bda0c56cba220d6dbf3e462ef86d803576f78644..c84a1ee584285bf40d3caadc129f812be087cb45 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >@@ -1773,6 +1773,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, ); }; }; >@@ -1791,6 +1792,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 */; }; >@@ -3132,7 +3134,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>"; }; >@@ -4769,6 +4770,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>"; }; >@@ -4801,6 +4803,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>"; }; >@@ -6867,6 +6870,7 @@ > 147341D71DC02F9900AA29BA /* FunctionExecutable.h */, > 0FB4B52116B6278D003F696B /* FunctionExecutableDump.cpp */, > 0FB4B52216B6278D003F696B /* FunctionExecutableDump.h */, >+ E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */, > 52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */, > 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */, > F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */, >@@ -6904,7 +6908,6 @@ > 0FB7F38F15ED8E3800F167B2 /* IndexingType.h */, > 14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */, > 14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */, >- 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */, > 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */, > 0F4AE0421FE0D25400E20839 /* InferredValueInlines.h */, > E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */, >@@ -7312,6 +7315,7 @@ > 705B41AA1A6E501E00716757 /* SymbolPrototype.h */, > 0F919D2715856770004A4E7D /* SymbolTable.cpp */, > 14A396A60CD2933100B5B4FF /* SymbolTable.h */, >+ E39BF39822A2288B00BD183E /* SymbolTableInlines.h */, > E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */, > BDB4B5E099CD4C1BB3C1CF05 /* TemplateObjectDescriptor.cpp */, > 70ECA6041AFDBEA200449739 /* TemplateObjectDescriptor.h */, >@@ -9178,6 +9182,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 */, >@@ -9874,6 +9879,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 */, >diff --git a/Source/JavaScriptCore/Sources.txt b/Source/JavaScriptCore/Sources.txt >index 43d7ef475822a83afaf9a12e8cf9e11a9d7db87b..20a25589061ab3c90335d43c89abae0a089bae82 100644 >--- a/Source/JavaScriptCore/Sources.txt >+++ b/Source/JavaScriptCore/Sources.txt >@@ -783,7 +783,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 >diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h >index ee8dd75ea1e2d5d76e8ba905814f763c8905b7ba..7bebc0463a58ba85d820939202a0ea48e6485dc3 100644 >--- a/Source/JavaScriptCore/bytecode/Watchpoint.h >+++ b/Source/JavaScriptCore/bytecode/Watchpoint.h >@@ -161,10 +161,11 @@ class Watchpoint : public PackedRawSentinelNode<Watchpoint> { > 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; >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index ac28dcdbb3a20a9266c99a027e340a7e11a60b80..8e9cd36eb5da0bfe9f6acb4442b2fd78c239caf5 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -2741,10 +2741,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->singletonFunction()) { >+ m_graph.watchpoints().addLazily(executable); > setConstant(node, *m_graph.freeze(function)); > break; > } >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index 38023fce2d22564f46d451a016f4a0cf23e2bdb2..62e168cc5770677e33a6cab6060f05fd172bd2c9 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -321,10 +321,8 @@ class ByteCodeParser { > // 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->singletonFunction()) { >+ m_graph.watchpoints().addLazily(executable); > return weakJSConstant(function); > } > } >@@ -6275,11 +6273,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->singletonScope()) { >+ m_graph.watchpoints().addLazily(symbolTable); >+ set(bytecode.m_dst, weakJSConstant(scope)); > break; > } > } >@@ -6310,7 +6308,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); >diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h >index 72dbaab46134a35452f4b10fc364513303a087dc..2bc966300a94beef484324c237cdfddde40d4dd4 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobberize.h >+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h >@@ -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->isStillValid()) > write(Watchpoint_fire); > read(HeapObjectCount); > write(HeapObjectCount); >@@ -1567,7 +1567,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*>()->isStillValid()) > write(Watchpoint_fire); > read(HeapObjectCount); > write(HeapObjectCount); >diff --git a/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp b/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp >index fddd5187086d99c31861f64c9833f0db4719c603..147e12380b374ea5e96cd55196d26b55bf837998 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp >+++ b/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp >@@ -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*>()->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*>()->isStillValid(); > > default: > // For all other nodes, we just care about whether they write to something other than SideState. >diff --git a/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp b/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp >index 1ac86acf32743f3a6f7e01cb1c1c4b8b77ee4c85..c233f2ce0296d808f5bdbf6d7da16dc5e6d20aaf 100644 >--- a/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp >+++ b/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp >@@ -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->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->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"); > } >diff --git a/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h b/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h >index af7f14f2667ec14d5ea7f7cfe1349efc9b83f677..c61d386972be2e4d3384a548f985c67252a2ed80 100644 >--- a/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h >+++ b/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h >@@ -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,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->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->hasBeenInvalidated(); >+ } >+ static void dumpInContext(PrintStream& out, FunctionExecutable* executable, DumpContext*) >+ { >+ out.print(RawPointer(executable)); > } > }; > >@@ -154,7 +167,8 @@ class DesiredWatchpoints { > > 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 @@ class DesiredWatchpoints { > { > 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 @@ class DesiredWatchpoints { > 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; > }; >diff --git a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp >index 034533905b7ae32be963f07e2163681b42be7a91..eb345513e97c0fe677056a58753d996f2517d5b5 100644 >--- a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp >@@ -840,7 +840,7 @@ class ObjectAllocationSinkingPhase : public Phase { > 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 @@ class ObjectAllocationSinkingPhase : public Phase { > } > > case CreateActivation: { >- if (isStillValid(node->castOperand<SymbolTable*>()->singletonScope())) { >+ if (isStillValid(node->castOperand<SymbolTable*>())) { > m_heap.escape(node->child1().node()); > break; > } >@@ -2382,11 +2382,17 @@ class ObjectAllocationSinkingPhase : public Phase { > // 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; > } > >+ bool isStillValid(FunctionExecutable* value) >+ { >+ return m_validInferredValues.add(value, value->isStillValid()).iterator->value; >+ } >+ >+ > SSACalculator m_pointerSSA; > SSACalculator m_allocationSSA; > NodeSet m_sinkCandidates; >@@ -2397,7 +2403,7 @@ class ObjectAllocationSinkingPhase : public Phase { > 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; >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index d0410b35d39017f80db5905ed492d3e33868bc5c..ea5b81da6c2b2b8c1c7fcbb2a1fc5fcf39aead81 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -7152,7 +7152,7 @@ void SpeculativeJIT::compileNewFunction(Node* node) > > FunctionExecutable* executable = node->castOperand<FunctionExecutable*>(); > >- if (executable->singletonFunction()->isStillValid()) { >+ if (executable->isStillValid()) { > GPRFlushedCallResult result(this); > GPRReg resultGPR = result.gpr(); > >@@ -7369,7 +7369,7 @@ void SpeculativeJIT::compileCreateActivation(Node* node) > JSValue initializationValue = node->initializationValueForActivation(); > ASSERT(initializationValue == jsUndefined() || initializationValue == jsTDZValue()); > >- if (table->singletonScope()->isStillValid()) { >+ if (table->isStillValid()) { > GPRFlushedCallResult result(this); > GPRReg resultGPR = result.gpr(); > >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index 5e28a1a232b1771b5a8291234f476cfb31b28f95..825acc174646a4f72a5beea73f07e145baa78b1d 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -5419,7 +5419,7 @@ class LowerDFGToB3 { > 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->isStillValid()) { > LValue callResult = vmCall( > Int64, > m_out.operation(operationCreateActivationDirect), m_callFrame, weakStructure(structure), >@@ -5480,7 +5480,7 @@ class LowerDFGToB3 { > LValue scope = lowCell(m_node->child1()); > > FunctionExecutable* executable = m_node->castOperand<FunctionExecutable*>(); >- if (executable->singletonFunction()->isStillValid()) { >+ if (executable->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)) : >diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp >index eed26726fb2a347b0c0c10467b1bc044402953da..6663b4f0d39ebbef9d270de03d2b5fc5e33d6482 100644 >--- a/Source/JavaScriptCore/heap/Heap.cpp >+++ b/Source/JavaScriptCore/heap/Heap.cpp >@@ -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); >diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >index af3ab889a6b134b62a8a3e2f08d82973ab5c2dcc..439e209b0a5f8fb829b7919757488c415634273f 100644 >--- a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp >@@ -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()) { >diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.h b/Source/JavaScriptCore/runtime/FunctionExecutable.h >index 598803ce2afe08f5ecbb08268da466db4815ffa5..9f5a08cb4999434558e1d021bdec29a6aee9e6e6 100644 >--- a/Source/JavaScriptCore/runtime/FunctionExecutable.h >+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.h >@@ -248,36 +248,19 @@ class FunctionExecutable final : public ScriptExecutable { > > DECLARE_INFO; > >- InferredValue* singletonFunction() >+ JSFunction* singletonFunction() > { >- if (VM::canUseJIT()) >- return m_singletonFunction.get(); >- return nullptr; >+ return m_singletonFunction.inferredValue(); > } > >- 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_singletonFunction.notifyWrite(vm, this, function, reason); > } > > bool singletonFunctionHasBeenInvalidated() > { >- if (VM::canUseJIT()) >- return singletonFunction()->hasBeenInvalidated(); >- return m_singletonFunctionState == IsInvalidated; >+ return hasBeenInvalidated(); > } > > // Cached poly proto structure for the result of constructing this executable. >@@ -305,6 +288,14 @@ class FunctionExecutable final : public ScriptExecutable { > > TemplateObjectMap& ensureTemplateObjectMap(VM&); > >+ void finalizeUnconditionally(VM&); >+ >+ // Forwards some WatchpointSet methods. >+ WatchpointState state() const { return m_singletonFunction.state(); } >+ bool isStillValid() const { return m_singletonFunction.isStillValid(); } >+ bool hasBeenInvalidated() const { return m_singletonFunction.hasBeenInvalidated(); } >+ void add(Watchpoint* watchpoint) { m_singletonFunction.add(watchpoint); } >+ > private: > friend class ExecutableBase; > FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, Intrinsic); >@@ -342,10 +333,7 @@ class FunctionExecutable final : public ScriptExecutable { > WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; > WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall; > WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct; >- union { >- WriteBarrier<InferredValue> m_singletonFunction; >- WatchpointState m_singletonFunctionState; >- }; >+ InferredValue<JSFunction> m_singletonFunction; > Box<InlineWatchpointSet> m_polyProtoWatchpoint; > }; > >diff --git a/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h b/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h >new file mode 100644 >index 0000000000000000000000000000000000000000..e8dbbcb75a591fff7af9969db48957611e00012e >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h >@@ -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_singletonFunction.finalizeUnconditionally(vm); >+} >+ >+} // namespace JSC >+ >diff --git a/Source/JavaScriptCore/runtime/InferredValue.cpp b/Source/JavaScriptCore/runtime/InferredValue.cpp >deleted file mode 100644 >index c90f55d7baa5dadf7a251f3e44bff2bc3362c43d..0000000000000000000000000000000000000000 >--- a/Source/JavaScriptCore/runtime/InferredValue.cpp >+++ /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 >- >diff --git a/Source/JavaScriptCore/runtime/InferredValue.h b/Source/JavaScriptCore/runtime/InferredValue.h >index da63e018c34d980aa06ee14bc972a57a29f0b6b6..3299a3f94ea477ee09e2b5cee51834b727008eb0 100644 >--- a/Source/JavaScriptCore/runtime/InferredValue.h >+++ b/Source/JavaScriptCore/runtime/InferredValue.h >@@ -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,7 +25,6 @@ > > #pragma once > >-#include "IsoSubspace.h" > #include "JSCast.h" > #include "VM.h" > #include "Watchpoint.h" >@@ -33,35 +32,10 @@ > > 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); > 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 +47,259 @@ class InferredValue final : public JSCell { > // 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 >diff --git a/Source/JavaScriptCore/runtime/InferredValueInlines.h b/Source/JavaScriptCore/runtime/InferredValueInlines.h >index c143687e5ddb134b82aeff904d2d081528a316d5..633999f7037a2eb1ec7808e0c977464bf85e4bcd 100644 >--- a/Source/JavaScriptCore/runtime/InferredValueInlines.h >+++ b/Source/JavaScriptCore/runtime/InferredValueInlines.h >@@ -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 >- >diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h >index 5aa6d49f8a1a12b795cd4daddf6f7640cf0097d8..4cd4fa0756d8761b77bc329b765f2987df6bb1e7 100644 >--- a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h >+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h >@@ -66,8 +66,7 @@ class JSSymbolTableObject : public JSScope { > 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); > } > >diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp >index c93607e891447d6ace3d80c2e4e373f5685d726b..632c7367d8952a144f1a6dbb3c0333bb74a6adcc 100644 >--- a/Source/JavaScriptCore/runtime/SymbolTable.cpp >+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp >@@ -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); >diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h >index 3fd1c46e1adf7ceade4e16b11ba7c10000274fb0..993a40922eb7e12c6f2b6d51b84fae09d40a8a00 100644 >--- a/Source/JavaScriptCore/runtime/SymbolTable.h >+++ b/Source/JavaScriptCore/runtime/SymbolTable.h >@@ -345,7 +345,6 @@ struct SymbolTableEntry { > }; > > SymbolTableEntry& copySlow(const SymbolTableEntry&); >- JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&); > > bool isFat() const > { >@@ -450,6 +449,12 @@ class SymbolTable final : public JSCell { > 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,25 @@ class SymbolTable final : public JSCell { > CodeBlock* rareDataCodeBlock(); > void setRareDataCodeBlock(CodeBlock*); > >- InferredValue* singletonScope() { return m_singletonScope.get(); } >+ JSScope* singletonScope() { return m_singletonScope.inferredValue(); } >+ >+ void notifyCreation(VM& vm, JSScope* scope, const char* reason) >+ { >+ m_singletonScope.notifyWrite(vm, this, scope, reason); >+ } > > static void visitChildren(JSCell*, SlotVisitor&); > > DECLARE_EXPORT_INFO; > >+ // Forwards some WatchpointSet methods. >+ WatchpointState state() const { return m_singletonScope.state(); } >+ bool isStillValid() const { return m_singletonScope.isStillValid(); } >+ bool hasBeenInvalidated() const { return m_singletonScope.hasBeenInvalidated(); } >+ void add(Watchpoint* watchpoint) { m_singletonScope.add(watchpoint); } >+ >+ void finalizeUnconditionally(VM&); >+ > private: > JS_EXPORT_PRIVATE SymbolTable(VM&); > ~SymbolTable(); >@@ -717,7 +735,7 @@ class SymbolTable final : public JSCell { > std::unique_ptr<SymbolTableRareData> m_rareData; > > WriteBarrier<ScopedArgumentsTable> m_arguments; >- WriteBarrier<InferredValue> m_singletonScope; >+ InferredValue<JSScope> m_singletonScope; > > std::unique_ptr<LocalToEntryVec> m_localToEntry; > }; >diff --git a/Source/JavaScriptCore/runtime/SymbolTableInlines.h b/Source/JavaScriptCore/runtime/SymbolTableInlines.h >new file mode 100644 >index 0000000000000000000000000000000000000000..b6d5929fbd7abdd2f8d04c51797c259981edc8df >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/SymbolTableInlines.h >@@ -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_singletonScope.finalizeUnconditionally(vm); >+} >+ >+} // namespace JSC >+ >diff --git a/Source/JavaScriptCore/runtime/VM.cpp b/Source/JavaScriptCore/runtime/VM.cpp >index 2b06a3bed934c588df87fc9f859222d8670e4e50..45fa20269215afeb7fa896575d65479fd3e70b8b 100644 >--- a/Source/JavaScriptCore/runtime/VM.cpp >+++ b/Source/JavaScriptCore/runtime/VM.cpp >@@ -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) > >diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h >index 918827ffa88b626b208abf26c1be16e1db570563..11c87dfc74498f456e1f393a832625d260edefa1 100644 >--- a/Source/JavaScriptCore/runtime/VM.h >+++ b/Source/JavaScriptCore/runtime/VM.h >@@ -380,6 +380,7 @@ class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> { > IsoSubspace propertyTableSpace; > IsoSubspace structureRareDataSpace; > IsoSubspace structureSpace; >+ IsoSubspace symbolTableSpace; > > #define DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(name) \ > template<SubspaceAccess mode> \ >@@ -451,7 +452,6 @@ class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> { > }; > > SpaceAndSet codeBlockSpace; >- DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(inferredValueSpace) > > template<typename Func> > void forEachCodeBlockSpace(const Func& func) >@@ -527,7 +527,6 @@ class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> { > Strong<Structure> unlinkedFunctionCodeBlockStructure; > Strong<Structure> unlinkedModuleProgramCodeBlockStructure; > Strong<Structure> propertyTableStructure; >- Strong<Structure> inferredValueStructure; > Strong<Structure> functionRareDataStructure; > Strong<Structure> exceptionStructure; > Strong<Structure> promiseDeferredStructure;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198407
:
371109
|
371112
|
371128
|
371250