WebKit Bugzilla
Attachment 339662 Details for
Bug 185287
: DFG AI should have O(1) clobbering
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
the patch
blah.patch (text/plain), 114.76 KB, created by
Filip Pizlo
on 2018-05-05 18:09:01 PDT
(
hide
)
Description:
the patch
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2018-05-05 18:09:01 PDT
Size:
114.76 KB
patch
obsolete
>Index: JSTests/ChangeLog >=================================================================== >--- JSTests/ChangeLog (revision 231396) >+++ JSTests/ChangeLog (working copy) >@@ -1,3 +1,14 @@ >+2018-05-05 Filip Pizlo <fpizlo@apple.com> >+ >+ DFG AI should have O(1) clobbering >+ https://bugs.webkit.org/show_bug.cgi?id=185287 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/simple-ai-effect.js: Added. >+ (bar): >+ (foo): >+ > 2018-05-04 Keith Miller <keith_miller@apple.com> > > isCacheableArrayLength should return true for undecided arrays >Index: JSTests/stress/simple-ai-effect.js >=================================================================== >--- JSTests/stress/simple-ai-effect.js (nonexistent) >+++ JSTests/stress/simple-ai-effect.js (working copy) >@@ -0,0 +1,39 @@ >+var doEffect = false; >+var didEffect = false; >+ >+function bar(o, p) >+{ >+ if (doEffect) { >+ delete p.g; >+ p.__defineGetter__("g", () => { >+ didEffect = true; >+ return 42; >+ }); >+ } >+} >+ >+noInline(bar); >+ >+function foo(o, p) { >+ var result = o.f + p.g; >+ bar(o, p); >+ return result + o.f + p.g; >+} >+ >+noInline(foo); >+ >+var o = {g: 1}; >+o.h = 2; >+ >+for (var i = 0; i < 10000; ++i) { >+ var result = foo({f: 1}, {g: 3}); >+ if (result != 8) >+ throw "Error: bad result in loop: " + result; >+} >+ >+doEffect = true; >+var result = foo({f: 1}, {g: 3}); >+if (result != 47) >+ throw "Error: bad result at end: " + result; >+if (!didEffect) >+ throw "Error: did not do effect"; >Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 231338) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,91 @@ >+2018-05-05 Filip Pizlo <fpizlo@apple.com> >+ >+ DFG AI should have O(1) clobbering >+ https://bugs.webkit.org/show_bug.cgi?id=185287 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This fixes an old scalability probem in AI. Previously, if we did clobberWorld(), then we >+ would traverse all of the state available to the AI at that time and clobber it. >+ >+ This changes clobberWorld() to be O(1). It just does some math to a clobber epoch. >+ >+ This is a ~1% speed-up for compile times. >+ >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * Sources.txt: >+ * dfg/DFGAbstractInterpreter.h: >+ (JSC::DFG::AbstractInterpreter::forNode): >+ (JSC::DFG::AbstractInterpreter::setForNode): >+ (JSC::DFG::AbstractInterpreter::clearForNode): >+ (JSC::DFG::AbstractInterpreter::variables): Deleted. >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberWorld): >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::forAllValues): >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberStructures): >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects): >+ * dfg/DFGAbstractValue.cpp: >+ (JSC::DFG::AbstractValue::fastForwardToSlow): >+ * dfg/DFGAbstractValue.h: >+ (JSC::DFG::AbstractValue::fastForwardTo): >+ (JSC::DFG::AbstractValue::clobberStructuresFor): Deleted. >+ (JSC::DFG::AbstractValue::observeInvalidationPoint): Deleted. >+ (JSC::DFG::AbstractValue::observeInvalidationPointFor): Deleted. >+ * dfg/DFGAbstractValueClobberEpoch.cpp: Added. >+ (JSC::DFG::AbstractValueClobberEpoch::dump const): >+ * dfg/DFGAbstractValueClobberEpoch.h: Added. >+ (JSC::DFG::AbstractValueClobberEpoch::AbstractValueClobberEpoch): >+ (JSC::DFG::AbstractValueClobberEpoch::first): >+ (JSC::DFG::AbstractValueClobberEpoch::clobber): >+ (JSC::DFG::AbstractValueClobberEpoch::observeInvalidationPoint): >+ (JSC::DFG::AbstractValueClobberEpoch::operator== const): >+ (JSC::DFG::AbstractValueClobberEpoch::operator!= const): >+ (JSC::DFG::AbstractValueClobberEpoch::structureClobberState const): >+ (JSC::DFG::AbstractValueClobberEpoch::clobberEpoch const): >+ * dfg/DFGAtTailAbstractState.h: >+ (JSC::DFG::AtTailAbstractState::setForNode): >+ (JSC::DFG::AtTailAbstractState::clearForNode): >+ (JSC::DFG::AtTailAbstractState::numberOfArguments const): >+ (JSC::DFG::AtTailAbstractState::numberOfLocals const): >+ (JSC::DFG::AtTailAbstractState::operand): >+ (JSC::DFG::AtTailAbstractState::local): >+ (JSC::DFG::AtTailAbstractState::argument): >+ (JSC::DFG::AtTailAbstractState::clobberStructures): >+ (JSC::DFG::AtTailAbstractState::observeInvalidationPoint): >+ (JSC::DFG::AtTailAbstractState::variables): Deleted. >+ * dfg/DFGCFAPhase.cpp: >+ (JSC::DFG::CFAPhase::performBlockCFA): >+ * dfg/DFGConstantFoldingPhase.cpp: >+ (JSC::DFG::ConstantFoldingPhase::foldConstants): >+ * dfg/DFGFlowMap.h: >+ (JSC::DFG::FlowMap::at): >+ (JSC::DFG::FlowMap::atShadow): >+ (JSC::DFG::FlowMap::at const): >+ (JSC::DFG::FlowMap::atShadow const): >+ * dfg/DFGInPlaceAbstractState.cpp: >+ (JSC::DFG::InPlaceAbstractState::beginBasicBlock): >+ (JSC::DFG::InPlaceAbstractState::endBasicBlock): >+ * dfg/DFGInPlaceAbstractState.h: >+ (JSC::DFG::InPlaceAbstractState::forNode): >+ (JSC::DFG::InPlaceAbstractState::setForNode): >+ (JSC::DFG::InPlaceAbstractState::clearForNode): >+ (JSC::DFG::InPlaceAbstractState::variablesForDebugging): >+ (JSC::DFG::InPlaceAbstractState::numberOfArguments const): >+ (JSC::DFG::InPlaceAbstractState::numberOfLocals const): >+ (JSC::DFG::InPlaceAbstractState::operand): >+ (JSC::DFG::InPlaceAbstractState::local): >+ (JSC::DFG::InPlaceAbstractState::argument): >+ (JSC::DFG::InPlaceAbstractState::variableAt): >+ (JSC::DFG::InPlaceAbstractState::clobberStructures): >+ (JSC::DFG::InPlaceAbstractState::observeInvalidationPoint): >+ (JSC::DFG::InPlaceAbstractState::fastForward): >+ (JSC::DFG::InPlaceAbstractState::variables): Deleted. >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * ftl/FTLLowerDFGToB3.cpp: >+ (JSC::FTL::DFG::LowerDFGToB3::compileGetStack): >+ > 2018-05-03 Filip Pizlo <fpizlo@apple.com> > > Make it easy to log compile times for all optimizing tiers >Index: Source/JavaScriptCore/Sources.txt >=================================================================== >--- Source/JavaScriptCore/Sources.txt (revision 231338) >+++ Source/JavaScriptCore/Sources.txt (working copy) >@@ -274,6 +274,7 @@ debugger/DebuggerScope.cpp > dfg/DFGAbstractHeap.cpp > dfg/DFGAbstractInterpreterClobberState.cpp > dfg/DFGAbstractValue.cpp >+dfg/DFGAbstractValueClobberEpoch.cpp > dfg/DFGAdaptiveInferredPropertyValueWatchpoint.cpp > dfg/DFGAdaptiveStructureWatchpoint.cpp > dfg/DFGArgumentsEliminationPhase.cpp >Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 231338) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -319,6 +319,7 @@ > 0F4D8C781FCA3CFA001D32AC /* SimpleMarkingConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4D8C771FCA3CF3001D32AC /* SimpleMarkingConstraint.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F4DE1CF1C4C1B54004D6C11 /* AirFixObviousSpills.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4DE1CD1C4C1B54004D6C11 /* AirFixObviousSpills.h */; }; > 0F4F11E8209BCDAB00709654 /* CompilerTimingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F11E6209BCDA100709654 /* CompilerTimingScope.h */; }; >+ 0F4F11EB209D426600709654 /* DFGAbstractValueClobberEpoch.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F11EA209D426300709654 /* DFGAbstractValueClobberEpoch.h */; }; > 0F4F29E018B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F29DE18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h */; }; > 0F4F82881E2FFDE00075184C /* JSSegmentedVariableObjectHeapCellType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F82861E2FFDDB0075184C /* JSSegmentedVariableObjectHeapCellType.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F4F828C1E31B9760075184C /* StochasticSpaceTimeMutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4F828A1E31B9710075184C /* StochasticSpaceTimeMutatorScheduler.h */; }; >@@ -2310,6 +2311,8 @@ > 0F4DE1D01C4D764B004D6C11 /* B3OriginDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3OriginDump.cpp; path = b3/B3OriginDump.cpp; sourceTree = "<group>"; }; > 0F4F11E6209BCDA100709654 /* CompilerTimingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompilerTimingScope.h; sourceTree = "<group>"; }; > 0F4F11E7209BCDA100709654 /* CompilerTimingScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompilerTimingScope.cpp; sourceTree = "<group>"; }; >+ 0F4F11E9209D426300709654 /* DFGAbstractValueClobberEpoch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractValueClobberEpoch.cpp; path = dfg/DFGAbstractValueClobberEpoch.cpp; sourceTree = "<group>"; }; >+ 0F4F11EA209D426300709654 /* DFGAbstractValueClobberEpoch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValueClobberEpoch.h; path = dfg/DFGAbstractValueClobberEpoch.h; sourceTree = "<group>"; }; > 0F4F29DD18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStaticExecutionCountEstimationPhase.cpp; path = dfg/DFGStaticExecutionCountEstimationPhase.cpp; sourceTree = "<group>"; }; > 0F4F29DE18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStaticExecutionCountEstimationPhase.h; path = dfg/DFGStaticExecutionCountEstimationPhase.h; sourceTree = "<group>"; }; > 0F4F82851E2FFDDB0075184C /* JSSegmentedVariableObjectHeapCellType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSegmentedVariableObjectHeapCellType.cpp; sourceTree = "<group>"; }; >@@ -7114,6 +7117,8 @@ > A704D8FF17A0BAA8006BA554 /* DFGAbstractInterpreterInlines.h */, > 0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */, > 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */, >+ 0F4F11E9209D426300709654 /* DFGAbstractValueClobberEpoch.cpp */, >+ 0F4F11EA209D426300709654 /* DFGAbstractValueClobberEpoch.h */, > 0FD3E3FF1B618AAF00C80E1E /* DFGAdaptiveInferredPropertyValueWatchpoint.cpp */, > 0FD3E4001B618AAF00C80E1E /* DFGAdaptiveInferredPropertyValueWatchpoint.h */, > 0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */, >@@ -9040,6 +9045,7 @@ > A513E5C2185BFACC007E95AD /* JSInjectedScriptHostPrototype.h in Headers */, > 0F2B66F817B6B5AB00A7AE3F /* JSInt16Array.h in Headers */, > 0F2B66F917B6B5AB00A7AE3F /* JSInt32Array.h in Headers */, >+ 0F4F11EB209D426600709654 /* DFGAbstractValueClobberEpoch.h in Headers */, > 0F2B66F717B6B5AB00A7AE3F /* JSInt8Array.h in Headers */, > A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */, > E33F50811B8429A400413856 /* JSInternalPromise.h in Headers */, >Index: Source/JavaScriptCore/bytecode/Operands.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Operands.h (revision 231338) >+++ Source/JavaScriptCore/bytecode/Operands.h (working copy) >@@ -245,7 +245,7 @@ public: > > private: > // The first m_numArguments of m_values are arguments, the rest are locals. >- Vector<T, 24> m_values; >+ Vector<T, 24, UnsafeVectorOverflow> m_values; > unsigned m_numArguments; > }; > >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -41,19 +41,80 @@ public: > AbstractInterpreter(Graph&, AbstractStateType&); > ~AbstractInterpreter(); > >- AbstractValue& forNode(NodeFlowProjection node) >+ ALWAYS_INLINE AbstractValue& forNode(NodeFlowProjection node) > { > return m_state.forNode(node); > } > >- AbstractValue& forNode(Edge edge) >+ ALWAYS_INLINE AbstractValue& forNode(Edge edge) > { > return forNode(edge.node()); > } > >- Operands<AbstractValue>& variables() >+ ALWAYS_INLINE void clearForNode(NodeFlowProjection node) > { >- return m_state.variables(); >+ m_state.clearForNode(node); >+ } >+ >+ ALWAYS_INLINE void clearForNode(Edge edge) >+ { >+ clearForNode(edge.node()); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ m_state.setForNode(node, std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setForNode(Edge edge, Arguments&&... arguments) >+ { >+ setForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setTypeForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ m_state.setTypeForNode(node, std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setTypeForNode(Edge edge, Arguments&&... arguments) >+ { >+ setTypeForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setNonCellTypeForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ m_state.setNonCellTypeForNode(node, std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setNonCellTypeForNode(Edge edge, Arguments&&... arguments) >+ { >+ setNonCellTypeForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ ALWAYS_INLINE void makeBytecodeTopForNode(NodeFlowProjection node) >+ { >+ m_state.makeBytecodeTopForNode(node); >+ } >+ >+ ALWAYS_INLINE void makeBytecodeTopForNode(Edge edge) >+ { >+ makeBytecodeTopForNode(edge.node()); >+ } >+ >+ ALWAYS_INLINE void makeHeapTopForNode(NodeFlowProjection node) >+ { >+ m_state.makeHeapTopForNode(node); >+ } >+ >+ ALWAYS_INLINE void makeHeapTopForNode(Edge edge) >+ { >+ makeHeapTopForNode(edge.node()); > } > > bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough) >@@ -149,13 +210,13 @@ public: > PhiChildren* phiChildren() { return m_phiChildren.get(); } > > private: >- void clobberWorld(const CodeOrigin&, unsigned indexInBlock); >+ void clobberWorld(); > void didFoldClobberWorld(); > > template<typename Functor> > void forAllValues(unsigned indexInBlock, Functor&); > >- void clobberStructures(unsigned indexInBlock); >+ void clobberStructures(); > void didFoldClobberStructures(); > > void observeTransition(unsigned indexInBlock, RegisteredStructure from, RegisteredStructure to); >@@ -190,7 +251,7 @@ private: > > void verifyEdge(Node*, Edge); > void verifyEdges(Node*); >- void executeDoubleUnaryOpEffects(Node*, unsigned clobberLimit, double(*equivalentFunction)(double)); >+ void executeDoubleUnaryOpEffects(Node*, double(*equivalentFunction)(double)); > > CodeBlock* m_codeBlock; > Graph& m_graph; >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -227,7 +227,7 @@ bool AbstractInterpreter<AbstractStateTy > case LazyJSValue::SingleCharacterString: > case LazyJSValue::KnownStringImpl: > case LazyJSValue::NewStringImpl: >- forNode(node).setType(m_graph, SpecString); >+ setTypeForNode(node, SpecString); > break; > } > break; >@@ -235,7 +235,7 @@ bool AbstractInterpreter<AbstractStateTy > > case IdentityWithProfile: > case Identity: { >- forNode(node) = forNode(node->child1()); >+ setForNode(node, forNode(node->child1())); > if (forNode(node).value()) > m_state.setFoundConstants(true); > break; >@@ -243,39 +243,39 @@ bool AbstractInterpreter<AbstractStateTy > > case ExtractCatchLocal: > case ExtractOSREntryLocal: { >- forNode(node).makeBytecodeTop(); >+ makeBytecodeTopForNode(node); > break; > } > > case GetLocal: { > VariableAccessData* variableAccessData = node->variableAccessData(); >- AbstractValue value = m_state.variables().operand(variableAccessData->local().offset()); >+ AbstractValue value = m_state.operand(variableAccessData->local().offset()); > // The value in the local should already be checked. > DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat()))); > if (value.value()) > m_state.setFoundConstants(true); >- forNode(node) = value; >+ setForNode(node, value); > break; > } > > case GetStack: { > StackAccessData* data = node->stackAccessData(); >- AbstractValue value = m_state.variables().operand(data->local); >+ AbstractValue value = m_state.operand(data->local); > // The value in the local should already be checked. > DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format))); > if (value.value()) > m_state.setFoundConstants(true); >- forNode(node) = value; >+ setForNode(node, value); > break; > } > > case SetLocal: { >- m_state.variables().operand(node->local()) = forNode(node->child1()); >+ m_state.operand(node->local()) = forNode(node->child1()); > break; > } > > case PutStack: { >- m_state.variables().operand(node->stackAccessData()->local) = forNode(node->child1()); >+ m_state.operand(node->stackAccessData()->local) = forNode(node->child1()); > break; > } > >@@ -296,20 +296,20 @@ bool AbstractInterpreter<AbstractStateTy > // Assert that the state of arguments has been set. SetArgument means that someone set > // the argument values out-of-band, and currently this always means setting to a > // non-clear value. >- ASSERT(!m_state.variables().operand(node->local()).isClear()); >+ ASSERT(!m_state.operand(node->local()).isClear()); > break; > > case InitializeEntrypointArguments: { > unsigned entrypointIndex = node->entrypointIndex(); > const Vector<FlushFormat>& argumentFormats = m_graph.m_argumentFormats[entrypointIndex]; > for (unsigned argument = 0; argument < argumentFormats.size(); ++argument) { >- AbstractValue& value = m_state.variables().argument(argument); >+ AbstractValue& value = m_state.argument(argument); > switch (argumentFormats[argument]) { > case FlushedInt32: >- value.setType(SpecInt32Only); >+ value.setNonCellType(SpecInt32Only); > break; > case FlushedBoolean: >- value.setType(SpecBoolean); >+ value.setNonCellType(SpecBoolean); > break; > case FlushedCell: > value.setType(m_graph, SpecCell); >@@ -332,7 +332,7 @@ bool AbstractInterpreter<AbstractStateTy > // https://bugs.webkit.org/show_bug.cgi?id=143071 > switch (node->op()) { > case LoadVarargs: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > case ForwardVarargs: > break; >@@ -341,9 +341,9 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > LoadVarargsData* data = node->loadVarargsData(); >- m_state.variables().operand(data->count).setType(SpecInt32Only); >+ m_state.operand(data->count).setNonCellType(SpecInt32Only); > for (unsigned i = data->limit - 1; i--;) >- m_state.variables().operand(data->start.offset() + i).makeHeapTop(); >+ m_state.operand(data->start.offset() + i).makeHeapTop(); > break; > } > >@@ -354,8 +354,8 @@ bool AbstractInterpreter<AbstractStateTy > case BitLShift: > case BitURShift: { > if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) { >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecInt32Only); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -393,11 +393,11 @@ bool AbstractInterpreter<AbstractStateTy > if (node->op() == BitAnd > && (isBoolInt32Speculation(forNode(node->child1()).m_type) || > isBoolInt32Speculation(forNode(node->child2()).m_type))) { >- forNode(node).setType(SpecBoolInt32); >+ setNonCellTypeForNode(node, SpecBoolInt32); > break; > } > >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -410,7 +410,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsNumber(static_cast<uint32_t>(machineInt))); > break; > } >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > break; > } > if (child && child.isInt32()) { >@@ -418,7 +418,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsNumber(value)); > break; > } >- forNode(node).setType(SpecAnyIntAsDouble); >+ setNonCellTypeForNode(node, SpecAnyIntAsDouble); > break; > } > if (child && child.isInt32()) { >@@ -428,7 +428,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -462,7 +462,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -487,11 +487,11 @@ bool AbstractInterpreter<AbstractStateTy > } > > if (isBooleanSpeculation(forNode(node->child1()).m_type)) { >- forNode(node).setType(SpecBoolInt32); >+ setNonCellTypeForNode(node, SpecBoolInt32); > break; > } > >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -525,7 +525,7 @@ bool AbstractInterpreter<AbstractStateTy > default: > RELEASE_ASSERT_NOT_REACHED(); > } >- forNode(node).setType(type); >+ setNonCellTypeForNode(node, type); > forNode(node).fixTypeForRepresentation(m_graph, node); > break; > } >@@ -537,7 +537,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > break; > } > >@@ -548,20 +548,20 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN); >+ setTypeForNode(node, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN); > forNode(node).fixTypeForRepresentation(m_graph, node); > break; > } > > case ValueAdd: { > ASSERT(node->binaryUseKind() == UntypedUse); >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber); >+ clobberWorld(); >+ setTypeForNode(node, SpecString | SpecBytecodeNumber); > break; > } > > case StrCat: { >- forNode(node).setType(m_graph, SpecString); >+ setTypeForNode(node, SpecString); > break; > } > >@@ -581,7 +581,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Int52RepUse: > if (left && right && left.isAnyInt() && right.isAnyInt()) { >@@ -591,14 +591,14 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { > setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber())); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleSum( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; >@@ -611,8 +611,8 @@ bool AbstractInterpreter<AbstractStateTy > > case AtomicsIsLockFree: { > if (node->child1().useKind() != Int32Use) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolInt32); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolInt32); > break; > } > >@@ -636,10 +636,10 @@ bool AbstractInterpreter<AbstractStateTy > case KnownInt32Use: > break; > default: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -674,16 +674,16 @@ bool AbstractInterpreter<AbstractStateTy > m_state.setFoundConstants(true); > if (numberOfRemovedChildren == numberOfChildren) { > // Propagate the last child. This is the way taken in the constant folding phase. >- forNode(node) = forNode(node->children.child(numberOfChildren - 1)); >+ setForNode(node, forNode(node->children.child(numberOfChildren - 1))); > break; > } > if ((numberOfRemovedChildren + 1) == numberOfChildren) { > ASSERT(nonEmptyIndex); >- forNode(node) = forNode(node->children.child(nonEmptyIndex.value())); >+ setForNode(node, forNode(node->children.child(nonEmptyIndex.value()))); > break; > } > } >- forNode(node).set(m_graph, m_vm.stringStructure.get()); >+ setForNode(node, m_vm.stringStructure.get()); > break; > } > >@@ -703,7 +703,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Int52RepUse: > if (left && right && left.isAnyInt() && right.isAnyInt()) { >@@ -713,20 +713,20 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { > setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber())); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleDifference( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; > case UntypedUse: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > default: > RELEASE_ASSERT_NOT_REACHED(); >@@ -755,7 +755,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Int52RepUse: > if (child && child.isAnyInt()) { >@@ -770,21 +770,21 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > break; > case DoubleRepUse: > if (child && child.isNumber()) { > setConstant(node, jsDoubleNumber(-child.asNumber())); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleNegation( > forNode(node->child1()).m_type)); > break; > default: > DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind()); >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > } > break; >@@ -809,7 +809,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Int52RepUse: > if (left && right && left.isAnyInt() && right.isAnyInt()) { >@@ -822,20 +822,20 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { > setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber())); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleProduct( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; > case UntypedUse: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > default: > RELEASE_ASSERT_NOT_REACHED(); >@@ -861,20 +861,20 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { > setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber())); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleQuotient( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; > case UntypedUse: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > default: > RELEASE_ASSERT_NOT_REACHED(); >@@ -900,14 +900,14 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { > setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber()))); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleBinaryOp( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; >@@ -927,7 +927,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32()))); > break; > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { >@@ -936,7 +936,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b))); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleMinMax( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; >@@ -956,7 +956,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32()))); > break; > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case DoubleRepUse: > if (left && right && left.isNumber() && right.isNumber()) { >@@ -965,7 +965,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b))); > break; > } >- forNode(node).setType( >+ setNonCellTypeForNode(node, > typeOfDoubleMinMax( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; >@@ -987,19 +987,19 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case DoubleRepUse: > if (std::optional<double> number = child.toNumberFromPrimitive()) { > setConstant(node, jsDoubleNumber(fabs(*number))); > break; > } >- forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type)); >+ setNonCellTypeForNode(node, typeOfDoubleAbs(forNode(node->child1()).m_type)); > break; > default: > DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind()); >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecFullNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecFullNumber); > break; > } > break; >@@ -1019,12 +1019,12 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type)); >+ setNonCellTypeForNode(node, typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; > } > > case ArithRandom: { >- forNode(node).setType(m_graph, SpecDoubleReal); >+ setNonCellTypeForNode(node, SpecDoubleReal); > break; > } > >@@ -1073,27 +1073,27 @@ bool AbstractInterpreter<AbstractStateTy > } > if (node->child1().useKind() == DoubleRepUse) { > if (producesInteger(node->arithRoundingMode())) >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > else if (node->child1().useKind() == DoubleRepUse) >- forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type)); >+ setNonCellTypeForNode(node, typeOfDoubleRounding(forNode(node->child1()).m_type)); > } else { > DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind()); >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecFullNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecFullNumber); > } > break; > } > > case ArithSqrt: >- executeDoubleUnaryOpEffects(node, clobberLimit, sqrt); >+ executeDoubleUnaryOpEffects(node, sqrt); > break; > > case ArithFRound: >- executeDoubleUnaryOpEffects(node, clobberLimit, [](double value) -> double { return static_cast<float>(value); }); >+ executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); }); > break; > > case ArithUnary: >- executeDoubleUnaryOpEffects(node, clobberLimit, arithUnaryFunction(node->arithUnaryType())); >+ executeDoubleUnaryOpEffects(node, arithUnaryFunction(node->arithUnaryType())); > break; > > case LogicalNot: { >@@ -1105,7 +1105,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsBoolean(true)); > break; > default: >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > break; >@@ -1122,7 +1122,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -1139,51 +1139,51 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > } > > case StringSlice: { >- forNode(node).setType(m_graph, SpecString); >+ setTypeForNode(node, SpecString); > break; > } > > case ToLowerCase: { >- forNode(node).setType(m_graph, SpecString); >+ setTypeForNode(node, SpecString); > break; > } > > case LoadKeyFromMapBucket: > case LoadValueFromMapBucket: > case ExtractValueFromWeakMapGet: >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > > case GetMapBucket: > case GetMapBucketHead: > if (node->child1().useKind() == MapObjectUse) >- forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get()); >+ setForNode(node, m_vm.hashMapBucketMapStructure.get()); > else { > ASSERT(node->child1().useKind() == SetObjectUse); >- forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get()); >+ setForNode(node, m_vm.hashMapBucketSetStructure.get()); > } > break; > > case GetMapBucketNext: > if (node->bucketOwnerType() == BucketOwnerType::Map) >- forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get()); >+ setForNode(node, m_vm.hashMapBucketMapStructure.get()); > else { > ASSERT(node->bucketOwnerType() == BucketOwnerType::Set); >- forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get()); >+ setForNode(node, m_vm.hashMapBucketSetStructure.get()); > } > break; > > case SetAdd: >- forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get()); >+ setForNode(node, m_vm.hashMapBucketSetStructure.get()); > break; > > case MapSet: >- forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get()); >+ setForNode(node, m_vm.hashMapBucketMapStructure.get()); > break; > > case WeakSetAdd: >@@ -1191,7 +1191,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case WeakMapGet: >- forNode(node).makeBytecodeTop(); >+ makeBytecodeTopForNode(node); > break; > > case IsEmpty: >@@ -1441,7 +1441,7 @@ bool AbstractInterpreter<AbstractStateTy > if (constantWasSet) > break; > >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > >@@ -1491,7 +1491,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- forNode(node).setType(m_graph, SpecStringIdent); >+ setTypeForNode(node, SpecStringIdent); > break; > } > >@@ -1532,7 +1532,7 @@ bool AbstractInterpreter<AbstractStateTy > } > break; > } >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > >@@ -1668,8 +1668,8 @@ bool AbstractInterpreter<AbstractStateTy > } > > if (isClobbering) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolean); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > >@@ -1706,7 +1706,7 @@ bool AbstractInterpreter<AbstractStateTy > > if (isNonStringCellConstant(left) || isNonStringCellConstant(right)) { > m_state.setFoundConstants(true); >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > } >@@ -1737,7 +1737,7 @@ bool AbstractInterpreter<AbstractStateTy > } > } > >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > >@@ -1749,12 +1749,12 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > > case StringCharCodeAt: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > > case StringFromCharCode: >@@ -1762,17 +1762,17 @@ bool AbstractInterpreter<AbstractStateTy > case Int32Use: > break; > case UntypedUse: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > default: > DFG_CRASH(m_graph, node, "Bad use kind"); > break; > } >- forNode(node).setType(m_graph, SpecString); >+ setTypeForNode(node, SpecString); > break; > > case StringCharAt: >- forNode(node).set(m_graph, m_vm.stringStructure.get()); >+ setForNode(node, m_vm.stringStructure.get()); > break; > > case GetByVal: >@@ -1786,7 +1786,7 @@ bool AbstractInterpreter<AbstractStateTy > case AtomicsSub: > case AtomicsXor: { > if (node->op() != GetByVal) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > switch (node->arrayMode().type()) { > case Array::SelectUsingPredictions: > case Array::Unprofiled: >@@ -1802,12 +1802,12 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsUndefined()); > break; > } >- forNode(node).setType(SpecOther); >+ setNonCellTypeForNode(node, SpecOther); > break; > } > case Array::Generic: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > case Array::String: > if (node->arrayMode().isOutOfBounds()) { >@@ -1821,71 +1821,71 @@ bool AbstractInterpreter<AbstractStateTy > // implies an in-bounds access). None of this feels like it's worth it, > // so we're going with TOP for now. The same thing applies to > // clobbering the world. >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > } else >- forNode(node).set(m_graph, m_vm.stringStructure.get()); >+ setForNode(node, m_vm.stringStructure.get()); > break; > case Array::DirectArguments: > case Array::ScopedArguments: > if (node->arrayMode().isOutOfBounds()) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > case Array::Int32: > if (node->arrayMode().isOutOfBounds()) { >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > } else >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Double: > if (node->arrayMode().isOutOfBounds()) { >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > } else if (node->arrayMode().isSaneChain()) >- forNode(node).setType(SpecBytecodeDouble); >+ setNonCellTypeForNode(node, SpecBytecodeDouble); > else >- forNode(node).setType(SpecDoubleReal); >+ setNonCellTypeForNode(node, SpecDoubleReal); > break; > case Array::Contiguous: > case Array::ArrayStorage: > case Array::SlowPutArrayStorage: > if (node->arrayMode().isOutOfBounds()) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > case Array::Int8Array: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Int16Array: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Int32Array: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Uint8Array: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Uint8ClampedArray: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Uint16Array: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > case Array::Uint32Array: > if (node->shouldSpeculateInt32()) >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > else if (enableInt52() && node->shouldSpeculateAnyInt()) >- forNode(node).setType(SpecAnyInt); >+ setNonCellTypeForNode(node, SpecAnyInt); > else >- forNode(node).setType(SpecAnyIntAsDouble); >+ setNonCellTypeForNode(node, SpecAnyIntAsDouble); > break; > case Array::Float32Array: >- forNode(node).setType(SpecFullDouble); >+ setNonCellTypeForNode(node, SpecFullDouble); > break; > case Array::Float64Array: >- forNode(node).setType(SpecFullDouble); >+ setNonCellTypeForNode(node, SpecFullDouble); > break; > default: > RELEASE_ASSERT_NOT_REACHED(); >@@ -1902,24 +1902,24 @@ bool AbstractInterpreter<AbstractStateTy > m_state.setIsValid(false); > break; > case Array::Generic: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > case Array::Int32: > if (node->arrayMode().isOutOfBounds()) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > case Array::Double: > if (node->arrayMode().isOutOfBounds()) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > case Array::Contiguous: > case Array::ArrayStorage: > if (node->arrayMode().isOutOfBounds()) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > case Array::SlowPutArrayStorage: > if (node->arrayMode().mayStoreToHole()) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > default: > break; >@@ -1928,8 +1928,8 @@ bool AbstractInterpreter<AbstractStateTy > } > > case ArrayPush: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > > case ArraySlice: { >@@ -1942,18 +1942,18 @@ bool AbstractInterpreter<AbstractStateTy > structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous))); > structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble))); > >- forNode(node).set(m_graph, structureSet); >+ setForNode(node, structureSet); > break; > } > > case ArrayIndexOf: { >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > > case ArrayPop: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > > case GetMyArgumentByVal: >@@ -1972,14 +1972,14 @@ bool AbstractInterpreter<AbstractStateTy > if (argumentIndexChecked.safeGet(argumentIndex) != CheckedState::DidOverflow) { > if (inlineCallFrame) { > if (argumentIndex < inlineCallFrame->argumentCountIncludingThis - 1) { >- forNode(node) = m_state.variables().operand( >- virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset); >+ setForNode(node, m_state.operand( >+ virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset)); > m_state.setFoundConstants(true); > break; > } > } else { >- if (argumentIndex < m_state.variables().numberOfArguments() - 1) { >- forNode(node) = m_state.variables().argument(argumentIndex + 1); >+ if (argumentIndex < m_state.numberOfArguments() - 1) { >+ setForNode(node, m_state.argument(argumentIndex + 1)); > m_state.setFoundConstants(true); > break; > } >@@ -1993,7 +1993,7 @@ bool AbstractInterpreter<AbstractStateTy > AbstractValue result; > for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->argumentCountIncludingThis; ++i) { > result.merge( >- m_state.variables().operand( >+ m_state.operand( > virtualRegisterForArgument(i) + inlineCallFrame->stackOffset)); > } > >@@ -2003,11 +2003,11 @@ bool AbstractInterpreter<AbstractStateTy > if (result.value()) > m_state.setFoundConstants(true); > >- forNode(node) = result; >+ setForNode(node, result); > break; > } > >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > } > >@@ -2016,7 +2016,7 @@ bool AbstractInterpreter<AbstractStateTy > if (node->op() == RegExpExec) { > // Even if we've proven known input types as RegExpObject and String, > // accessing lastIndex is effectful if it's a global regexp. >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > } > > if (JSValue globalObjectValue = forNode(node->child1()).m_value) { >@@ -2026,31 +2026,31 @@ bool AbstractInterpreter<AbstractStateTy > RegisteredStructureSet structureSet; > structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayStructure())); > structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayWithGroupsStructure())); >- forNode(node).set(m_graph, structureSet); >+ setForNode(node, structureSet); > forNode(node).merge(SpecOther); > break; > } > } > } >- forNode(node).setType(m_graph, SpecOther | SpecArray); >+ setTypeForNode(node, SpecOther | SpecArray); > break; > > case RegExpTest: > // Even if we've proven known input types as RegExpObject and String, > // accessing lastIndex is effectful if it's a global regexp. >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolean); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > > case RegExpMatchFast: > ASSERT(node->child2().useKind() == RegExpObjectUse); > ASSERT(node->child3().useKind() == StringUse); >- forNode(node).setType(m_graph, SpecOther | SpecArray); >+ setTypeForNode(node, SpecOther | SpecArray); > break; > > case RegExpMatchFastGlobal: > ASSERT(node->child2().useKind() == StringUse); >- forNode(node).setType(m_graph, SpecOther | SpecArray); >+ setTypeForNode(node, SpecOther | SpecArray); > break; > > case StringReplace: >@@ -2060,8 +2060,8 @@ bool AbstractInterpreter<AbstractStateTy > && node->child3().useKind() == StringUse) { > // This doesn't clobber the world. It just reads and writes regexp state. > } else >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).set(m_graph, m_vm.stringStructure.get()); >+ clobberWorld(); >+ setForNode(node, m_vm.stringStructure.get()); > break; > > case Jump: >@@ -2105,7 +2105,7 @@ bool AbstractInterpreter<AbstractStateTy > case DirectTailCall: > case TailCallVarargs: > case TailCallForwardVarargs: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > m_state.setIsValid(false); > break; > >@@ -2122,13 +2122,13 @@ bool AbstractInterpreter<AbstractStateTy > if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt))) { > m_state.setFoundConstants(true); > didFoldClobberWorld(); >- forNode(node) = forNode(node->child1()); >+ setForNode(node, forNode(node->child1())); > break; > } > >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > >- forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject); >+ setTypeForNode(node, SpecHeapTop & ~SpecObject); > break; > } > >@@ -2145,12 +2145,12 @@ bool AbstractInterpreter<AbstractStateTy > if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) { > m_state.setFoundConstants(true); > didFoldClobberWorld(); >- forNode(node) = forNode(node->child1()); >+ setForNode(node, forNode(node->child1())); > break; > } > >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > } > >@@ -2172,13 +2172,13 @@ bool AbstractInterpreter<AbstractStateTy > break; > case CellUse: > case UntypedUse: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > default: > RELEASE_ASSERT_NOT_REACHED(); > break; > } >- forNode(node).set(m_graph, m_vm.stringStructure.get()); >+ setForNode(node, m_vm.stringStructure.get()); > break; > } > >@@ -2189,29 +2189,28 @@ bool AbstractInterpreter<AbstractStateTy > if (2 <= radix && radix <= 36) { > m_state.setFoundConstants(true); > didFoldClobberWorld(); >- forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); >+ setForNode(node, m_graph.m_vm.stringStructure.get()); > break; > } > } >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); >+ clobberWorld(); >+ setForNode(node, m_graph.m_vm.stringStructure.get()); > break; > } > > case NumberToStringWithValidRadixConstant: { >- forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); >+ setForNode(node, m_graph.m_vm.stringStructure.get()); > break; > } > > case NewStringObject: { > ASSERT(node->structure()->classInfo() == StringObject::info()); >- forNode(node).set(m_graph, node->structure()); >+ setForNode(node, node->structure()); > break; > } > > case NewArray: >- forNode(node).set( >- m_graph, >+ setForNode(node, > m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())); > break; > >@@ -2220,12 +2219,10 @@ bool AbstractInterpreter<AbstractStateTy > // We've compiled assuming we're not having a bad time, so to be consistent > // with StructureRegisterationPhase we must say we produce an original array > // allocation structure. >- forNode(node).set( >- m_graph, >+ setForNode(node, > m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous)); > } else { >- forNode(node).set( >- m_graph, >+ setForNode(node, > m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous)); > } > >@@ -2238,24 +2235,23 @@ bool AbstractInterpreter<AbstractStateTy > break; > default: > if (!m_graph.canDoFastSpread(node, forNode(node->child1()))) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > else > didFoldClobberWorld(); > break; > } > >- forNode(node).set( >- m_graph, m_vm.fixedArrayStructure.get()); >+ setForNode(node, >+ m_vm.fixedArrayStructure.get()); > break; > > case NewArrayBuffer: >- forNode(node).set( >- m_graph, >+ setForNode(node, > m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())); > break; > > case NewArrayWithSize: >- forNode(node).setType(m_graph, SpecArray); >+ setTypeForNode(node, SpecArray); > break; > > case NewTypedArray: >@@ -2263,20 +2259,19 @@ bool AbstractInterpreter<AbstractStateTy > case Int32Use: > break; > case UntypedUse: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > default: > RELEASE_ASSERT_NOT_REACHED(); > break; > } >- forNode(node).set( >- m_graph, >+ setForNode(node, > m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently( > node->typedArrayType())); > break; > > case NewRegexp: >- forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure()); >+ setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure()); > break; > > case ToThis: { >@@ -2325,21 +2320,21 @@ bool AbstractInterpreter<AbstractStateTy > m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet()); > m_state.setFoundConstants(true); > didFoldClobberWorld(); >- forNode(node).set(m_graph, structure); >+ setForNode(node, structure); > break; > } > } > } > } > } >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecFinalObject); >+ clobberWorld(); >+ setTypeForNode(node, SpecFinalObject); > break; > } > > case NewObject: > ASSERT(!!node->structure().get()); >- forNode(node).set(m_graph, node->structure()); >+ setForNode(node, node->structure()); > break; > > case ToObject: >@@ -2356,8 +2351,8 @@ bool AbstractInterpreter<AbstractStateTy > } > > if (node->op() == ToObject) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecObject); >+ clobberWorld(); >+ setTypeForNode(node, SpecObject); > break; > } > >@@ -2382,56 +2377,56 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case MaterializeNewObject: { >- forNode(node).set(m_graph, node->structureSet()); >+ setForNode(node, node->structureSet()); > break; > } > > case PushWithScope: > // We don't use the more precise withScopeStructure() here because it is a LazyProperty and may not yet be allocated. >- forNode(node).setType(m_graph, SpecObjectOther); >+ setTypeForNode(node, SpecObjectOther); > break; > > case CreateActivation: > case MaterializeCreateActivation: >- forNode(node).set( >- m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure()); >+ setForNode(node, >+ m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure()); > break; > > case CreateDirectArguments: >- forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure()); >+ setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure()); > break; > > case CreateScopedArguments: >- forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()); >+ setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure()); > break; > > case CreateClonedArguments: > if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) { >- forNode(node).setType(m_graph, SpecObject); >+ setTypeForNode(node, SpecObject); > break; > } >- forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure()); >+ setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure()); > break; > > case NewGeneratorFunction: >- forNode(node).set( >- m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure()); >+ setForNode(node, >+ m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure()); > break; > > case NewAsyncGeneratorFunction: >- forNode(node).set( >- m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->asyncGeneratorFunctionStructure()); >+ setForNode(node, >+ m_codeBlock->globalObjectFor(node->origin.semantic)->asyncGeneratorFunctionStructure()); > break; > > case NewAsyncFunction: >- forNode(node).set( >- m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure()); >+ setForNode(node, >+ m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure()); > break; > > case NewFunction: { > JSGlobalObject* globalObject = m_codeBlock->globalObjectFor(node->origin.semantic); > Structure* structure = JSFunction::selectStructureForNewFuncExp(globalObject, node->castOperand<FunctionExecutable*>()); >- forNode(node).set(m_graph, structure); >+ setForNode(node, structure); > break; > } > >@@ -2445,11 +2440,11 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(m_graph, SpecFunction); >+ setTypeForNode(node, SpecFunction); > break; > > case GetArgumentCountIncludingThis: >- forNode(node).setType(SpecInt32Only); >+ setTypeForNode(node, SpecInt32Only); > break; > > case SetCallee: >@@ -2457,7 +2452,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case GetRestLength: >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > > case GetGetter: { >@@ -2470,7 +2465,7 @@ bool AbstractInterpreter<AbstractStateTy > } > } > >- forNode(node).setType(m_graph, SpecObject); >+ setTypeForNode(node, SpecObject); > break; > } > >@@ -2484,7 +2479,7 @@ bool AbstractInterpreter<AbstractStateTy > } > } > >- forNode(node).setType(m_graph, SpecObject); >+ setTypeForNode(node, SpecObject); > break; > } > >@@ -2495,7 +2490,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(m_graph, SpecObjectOther); >+ setTypeForNode(node, SpecObjectOther); > break; > > case SkipScope: { >@@ -2504,7 +2499,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next()))); > break; > } >- forNode(node).setType(m_graph, SpecObjectOther); >+ setTypeForNode(node, SpecObjectOther); > break; > } > >@@ -2531,12 +2526,12 @@ bool AbstractInterpreter<AbstractStateTy > } > } > >- forNode(node).setType(m_graph, SpecObjectOther); >+ setTypeForNode(node, SpecObjectOther); > break; > } > > case GetGlobalThis: { >- forNode(node).setType(m_graph, SpecObject); >+ setTypeForNode(node, SpecObject); > break; > } > >@@ -2545,14 +2540,14 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, *m_graph.freeze(value)); > break; > } >- forNode(node).makeBytecodeTop(); >+ makeBytecodeTopForNode(node); > break; > > case PutClosureVar: > break; > > case GetRegExpObjectLastIndex: >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > > case SetRegExpObjectLastIndex: >@@ -2560,20 +2555,20 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case GetFromArguments: >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > > case PutToArguments: > break; > > case GetArgument: >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > > case TryGetById: > // FIXME: This should constant fold at least as well as the normal GetById case. > // https://bugs.webkit.org/show_bug.cgi?id=156422 >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > > case GetByIdDirect: >@@ -2605,15 +2600,15 @@ bool AbstractInterpreter<AbstractStateTy > } > } > >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > } > > case GetByValWithThis: > case GetByIdWithThis: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > > case GetArrayLength: { >@@ -2623,12 +2618,12 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsNumber(view->length())); > break; > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > > case GetVectorLength: { >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -2636,8 +2631,8 @@ bool AbstractInterpreter<AbstractStateTy > case DeleteByVal: { > // FIXME: This could decide if the delete will be successful based on the set of structures that > // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611 >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolean); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > >@@ -2747,7 +2742,7 @@ bool AbstractInterpreter<AbstractStateTy > // nobody would currently benefit from having that information. But it's a bug nonetheless. > if (node->op() == NukeStructureAndSetButterfly) > didFoldClobberStructures(); >- forNode(node).clear(); // The result is not a JS value. >+ clearForNode(node); // The result is not a JS value. > break; > case CheckSubClass: { > JSValue constant = forNode(node->child1()).value(); >@@ -2771,18 +2766,18 @@ bool AbstractInterpreter<AbstractStateTy > CallDOMGetterData* callDOMGetterData = node->callDOMGetterData(); > DOMJIT::CallDOMGetterSnippet* snippet = callDOMGetterData->snippet; > if (!snippet || snippet->effect.writes) >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > if (callDOMGetterData->domJIT) >- forNode(node).setType(m_graph, callDOMGetterData->domJIT->resultType()); >+ setTypeForNode(node, callDOMGetterData->domJIT->resultType()); > else >- forNode(node).makeBytecodeTop(); >+ makeBytecodeTopForNode(node); > break; > } > case CallDOM: { > const DOMJIT::Signature* signature = node->signature(); > if (signature->effect.writes) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, signature->result); >+ clobberWorld(); >+ setTypeForNode(node, signature->result); > break; > } > case CheckArray: { >@@ -2851,7 +2846,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > ASSERT(node->arrayMode().conversion() == Array::Convert); >- clobberStructures(clobberLimit); >+ clobberStructures(); > filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering()); > break; > } >@@ -2859,7 +2854,7 @@ bool AbstractInterpreter<AbstractStateTy > AbstractValue& value = forNode(node->child1()); > if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure()))) > m_state.setFoundConstants(true); >- clobberStructures(clobberLimit); >+ clobberStructures(); > > // We have a bunch of options of how to express the abstract set at this point. Let set S > // be the set of structures that the value had before clobbering and assume that all of >@@ -2888,7 +2883,7 @@ bool AbstractInterpreter<AbstractStateTy > // Note that it's tempting to simply say that the resulting value is BOTTOM because of > // the contradiction. That would be wrong, since we haven't hit an invalidation point, > // yet. >- value.set(m_graph, node->structure()); >+ forNode(node->child1()).set(m_graph, node->structure()); > break; > } > case GetIndexedPropertyStorage: { >@@ -2896,11 +2891,11 @@ bool AbstractInterpreter<AbstractStateTy > forNode(node->child1()).m_value, node->arrayMode()); > if (view) > m_state.setFoundConstants(true); >- forNode(node).clear(); >+ clearForNode(node); > break; > } > case ConstantStoragePointer: { >- forNode(node).clear(); >+ clearForNode(node); > break; > } > >@@ -2910,7 +2905,7 @@ bool AbstractInterpreter<AbstractStateTy > setConstant(node, jsNumber(view->byteOffset())); > break; > } >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > >@@ -2958,10 +2953,10 @@ bool AbstractInterpreter<AbstractStateTy > case FinalObjectUse: > break; > default: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > } >- forNode(node).setType(m_graph, SpecObject | SpecOther); >+ setTypeForNode(node, SpecObject | SpecOther); > break; > } > >@@ -2987,7 +2982,7 @@ bool AbstractInterpreter<AbstractStateTy > if (value.isClear()) > m_state.setIsValid(false); > >- forNode(node) = value; >+ setForNode(node, value); > if (value.m_value) > m_state.setFoundConstants(true); > break; >@@ -3001,7 +2996,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure()); >+ setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure()); > break; > } > >@@ -3058,7 +3053,7 @@ bool AbstractInterpreter<AbstractStateTy > if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction) > m_state.setIsValid(false); > >- forNode(node) = result; >+ setForNode(node, result); > break; > } > >@@ -3108,7 +3103,7 @@ bool AbstractInterpreter<AbstractStateTy > observeTransitions(clobberLimit, transitions); > if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction) > m_state.setIsValid(false); >- forNode(node->child2()) = resultingValue; >+ setForNode(node->child2(), resultingValue); > if (!!originalValue && !resultingValue) > m_state.setIsValid(false); > break; >@@ -3123,7 +3118,7 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > } >- forNode(node).setType(m_graph, SpecCellOther); >+ setTypeForNode(node, SpecCellOther); > break; > } > >@@ -3219,13 +3214,13 @@ bool AbstractInterpreter<AbstractStateTy > } > } > >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > } > > case PutByValWithThis: > case PutByIdWithThis: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > > case PutGetterById: >@@ -3233,41 +3228,41 @@ bool AbstractInterpreter<AbstractStateTy > case PutGetterSetterById: > case PutGetterByVal: > case PutSetterByVal: { >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > } > > case DefineDataProperty: > case DefineAccessorProperty: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > > case In: { > // FIXME: We can determine when the property definitely exists based on abstract > // value information. >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolean); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > > case HasOwnProperty: { >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolean); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > > case GetEnumerableLength: { >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > case HasGenericProperty: { >- forNode(node).setType(SpecBoolean); >- clobberWorld(node->origin.semantic, clobberLimit); >+ setNonCellTypeForNode(node, SpecBoolean); >+ clobberWorld(); > break; > } > case HasStructureProperty: { >- forNode(node).setType(SpecBoolean); >- clobberWorld(node->origin.semantic, clobberLimit); >+ setNonCellTypeForNode(node, SpecBoolean); >+ clobberWorld(); > break; > } > case HasIndexedProperty: { >@@ -3280,61 +3275,61 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > default: { >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > } > } >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > } > case GetDirectPname: { >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > } > case GetPropertyEnumerator: { >- forNode(node).setType(m_graph, SpecCell); >- clobberWorld(node->origin.semantic, clobberLimit); >+ setTypeForNode(node, SpecCell); >+ clobberWorld(); > break; > } > case GetEnumeratorStructurePname: { >- forNode(node).setType(m_graph, SpecString | SpecOther); >+ setTypeForNode(node, SpecString | SpecOther); > break; > } > case GetEnumeratorGenericPname: { >- forNode(node).setType(m_graph, SpecString | SpecOther); >+ setTypeForNode(node, SpecString | SpecOther); > break; > } > case ToIndexString: { >- forNode(node).setType(m_graph, SpecString); >+ setTypeForNode(node, SpecString); > break; > } > > case GetGlobalVar: >- forNode(node).makeHeapTop(); >+ makeHeapTopForNode(node); > break; > > case GetGlobalLexicalVariable: >- forNode(node).makeBytecodeTop(); >+ makeBytecodeTopForNode(node); > break; > > case GetDynamicVar: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeBytecodeTop(); >+ clobberWorld(); >+ makeBytecodeTopForNode(node); > break; > > case PutDynamicVar: >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > > case ResolveScope: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecObject); >+ clobberWorld(); >+ setTypeForNode(node, SpecObject); > break; > > case ResolveScopeForHoistingFuncDeclInEval: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeBytecodeTop(); >+ clobberWorld(); >+ makeBytecodeTopForNode(node); > break; > > case PutGlobalVariable: >@@ -3342,22 +3337,22 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case OverridesHasInstance: >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > > case InstanceOf: > // Sadly, we don't propagate the fact that we've done InstanceOf >- forNode(node).setType(SpecBoolean); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > > case InstanceOfCustom: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(SpecBoolean); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBoolean); > break; > > case Phi: > RELEASE_ASSERT(m_graph.m_form == SSA); >- forNode(node) = forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow)); >+ setForNode(node, forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow))); > // The state of this node would have already been decided, but it may have become a > // constant, in which case we'd like to know. > if (forNode(node).m_value) >@@ -3368,7 +3363,7 @@ bool AbstractInterpreter<AbstractStateTy > NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow); > if (shadow.isStillValid()) { > m_state.createValueForNode(shadow); >- forNode(shadow) = forNode(node->child1()); >+ setForNode(shadow, forNode(node->child1())); > } > break; > } >@@ -3390,8 +3385,8 @@ bool AbstractInterpreter<AbstractStateTy > case DirectCall: > case DirectConstruct: > case DirectTailCallInlinedCaller: >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).makeHeapTop(); >+ clobberWorld(); >+ makeHeapTopForNode(node); > break; > > case ForceOSRExit: >@@ -3400,15 +3395,15 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case InvalidationPoint: >- forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor); > m_state.setStructureClobberState(StructuresAreWatched); >+ m_state.observeInvalidationPoint(); > break; > > case CPUIntrinsic: > if (node->intrinsic() == CPURdtscIntrinsic) >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > else >- forNode(node).setType(SpecOther); >+ setNonCellTypeForNode(node, SpecOther); > break; > > case CheckTraps: >@@ -3441,26 +3436,25 @@ bool AbstractInterpreter<AbstractStateTy > m_state.setFoundConstants(true); > if (node->child1().useKind() == UntypedUse) > didFoldClobberWorld(); >- forNode(node).setType(SpecInt32Only); >+ setNonCellTypeForNode(node, SpecInt32Only); > break; > } > } > > if (node->child1().useKind() == UntypedUse) >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecBytecodeNumber); >+ clobberWorld(); >+ setNonCellTypeForNode(node, SpecBytecodeNumber); > break; > } > > case CreateRest: > if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) { > // This means we're already having a bad time. >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(m_graph, SpecArray); >+ clobberWorld(); >+ setTypeForNode(node, SpecArray); > break; > } >- forNode(node).set( >- m_graph, >+ setForNode(node, > m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure()); > break; > >@@ -3477,7 +3471,7 @@ bool AbstractInterpreter<AbstractStateTy > } > > case SetFunctionName: { >- clobberWorld(node->origin.semantic, clobberLimit); >+ clobberWorld(); > break; > } > >@@ -3537,10 +3531,9 @@ bool AbstractInterpreter<AbstractStateTy > } > > template<typename AbstractStateType> >-void AbstractInterpreter<AbstractStateType>::clobberWorld( >- const CodeOrigin&, unsigned clobberLimit) >+void AbstractInterpreter<AbstractStateType>::clobberWorld() > { >- clobberStructures(clobberLimit); >+ clobberStructures(); > } > > template<typename AbstractStateType> >@@ -3572,16 +3565,16 @@ void AbstractInterpreter<AbstractStateTy > functor(forNode(node)); > } > } >- for (size_t i = m_state.variables().numberOfArguments(); i--;) >- functor(m_state.variables().argument(i)); >- for (size_t i = m_state.variables().numberOfLocals(); i--;) >- functor(m_state.variables().local(i)); >+ for (size_t i = m_state.numberOfArguments(); i--;) >+ functor(m_state.argument(i)); >+ for (size_t i = m_state.numberOfLocals(); i--;) >+ functor(m_state.local(i)); > } > > template<typename AbstractStateType> >-void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit) >+void AbstractInterpreter<AbstractStateType>::clobberStructures() > { >- forAllValues(clobberLimit, AbstractValue::clobberStructuresFor); >+ m_state.clobberStructures(); > m_state.mergeClobberState(AbstractInterpreterClobberState::ClobberedStructures); > m_state.setStructureClobberState(StructuresAreClobbered); > } >@@ -3716,7 +3709,7 @@ FiltrationResult AbstractInterpreter<Abs > } > > template<typename AbstractStateType> >-void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, unsigned clobberLimit, double(*equivalentFunction)(double)) >+void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double)) > { > JSValue child = forNode(node->child1()).value(); > if (std::optional<double> number = child.toNumberFromPrimitive()) { >@@ -3729,8 +3722,8 @@ void AbstractInterpreter<AbstractStateTy > if (node->child1().useKind() == DoubleRepUse) > type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type); > else >- clobberWorld(node->origin.semantic, clobberLimit); >- forNode(node).setType(type); >+ clobberWorld(); >+ setNonCellTypeForNode(node, type); > } > > } } // namespace JSC::DFG >Index: Source/JavaScriptCore/dfg/DFGAbstractValue.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGAbstractValue.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -133,16 +133,16 @@ void AbstractValue::set(Graph& graph, co > clear(); > return; > case InferredType::Boolean: >- setType(SpecBoolean); >+ setNonCellType(SpecBoolean); > return; > case InferredType::Other: >- setType(SpecOther); >+ setNonCellType(SpecOther); > return; > case InferredType::Int32: >- setType(SpecInt32Only); >+ setNonCellType(SpecInt32Only); > return; > case InferredType::Number: >- setType(SpecBytecodeNumber); >+ setNonCellType(SpecBytecodeNumber); > return; > case InferredType::String: > set(graph, graph.m_vm.stringStructure.get()); >@@ -556,6 +556,7 @@ void AbstractValue::dumpInContext(PrintS > } > if (!!m_value) > out.print(", ", inContext(m_value, context)); >+ out.print(", ", m_effectEpoch); > out.print(")"); > } > >@@ -574,6 +575,20 @@ void AbstractValue::ensureCanInitializeW > } > #endif > >+void AbstractValue::fastForwardToSlow(AbstractValueClobberEpoch newEpoch) >+{ >+ ASSERT(newEpoch != m_effectEpoch); >+ >+ if (newEpoch.clobberEpoch() != m_effectEpoch.clobberEpoch()) >+ clobberStructures(); >+ if (newEpoch.structureClobberState() == StructuresAreWatched) >+ m_structure.observeInvalidationPoint(); >+ >+ m_effectEpoch = newEpoch; >+ >+ checkConsistency(); >+} >+ > } } // namespace JSC::DFG > > #endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGAbstractValue.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractValue.h (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGAbstractValue.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2011-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -28,6 +28,7 @@ > #if ENABLE(DFG_JIT) > > #include "ArrayProfile.h" >+#include "DFGAbstractValueClobberEpoch.h" > #include "DFGFiltrationResult.h" > #include "DFGFrozenValue.h" > #include "DFGNodeFlags.h" >@@ -103,20 +104,17 @@ struct AbstractValue { > checkConsistency(); > } > >- static void clobberStructuresFor(AbstractValue& value) >+ ALWAYS_INLINE void fastForwardTo(AbstractValueClobberEpoch newEpoch) > { >- value.clobberStructures(); >- } >- >- void observeInvalidationPoint() >- { >- m_structure.observeInvalidationPoint(); >- checkConsistency(); >- } >- >- static void observeInvalidationPointFor(AbstractValue& value) >- { >- value.observeInvalidationPoint(); >+ if (newEpoch == m_effectEpoch) >+ return; >+ >+ if (!(m_type & SpecCell)) { >+ m_effectEpoch = newEpoch; >+ return; >+ } >+ >+ fastForwardToSlow(newEpoch); > } > > void observeTransition(RegisteredStructure from, RegisteredStructure to) >@@ -206,6 +204,16 @@ struct AbstractValue { > return result; > } > >+ void set(Graph&, const AbstractValue& other) >+ { >+ *this = other; >+ } >+ >+ void set(Graph&, AbstractValue&& other) >+ { >+ *this = WTFMove(other); >+ } >+ > void set(Graph&, const FrozenValue&, StructureClobberState); > void set(Graph&, Structure*); > void set(Graph&, RegisteredStructure); >@@ -215,7 +223,7 @@ struct AbstractValue { > void setType(Graph&, SpeculatedType); > > // As above, but only valid for non-cell types. >- void setType(SpeculatedType type) >+ ALWAYS_INLINE void setNonCellType(SpeculatedType type) > { > RELEASE_ASSERT(!(type & SpecCell)); > m_structure.clear(); >@@ -397,6 +405,10 @@ struct AbstractValue { > // effect that makes non-obvious changes to the heap. > ArrayModes m_arrayModes; > >+ // The epoch. >+ // FIXME: Explain this. (OOPS!!) >+ AbstractValueClobberEpoch m_effectEpoch; >+ > // This is a proven constraint on the possible values that this value can > // have now or any time in the future, unless it is reassigned. Note that this > // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value) >@@ -455,6 +467,8 @@ private: > checkConsistency(); > } > >+ void fastForwardToSlow(AbstractValueClobberEpoch); >+ > void filterValueByType(); > void filterArrayModesByType(); > >Index: Source/JavaScriptCore/dfg/DFGAbstractValueClobberEpoch.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractValueClobberEpoch.cpp (nonexistent) >+++ Source/JavaScriptCore/dfg/DFGAbstractValueClobberEpoch.cpp (working copy) >@@ -0,0 +1,41 @@ >+/* >+ * Copyright (C) 2018 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 "DFGAbstractValueClobberEpoch.h" >+ >+#if ENABLE(DFG_JIT) >+ >+namespace JSC { namespace DFG { >+ >+void AbstractValueClobberEpoch::dump(PrintStream& out) const >+{ >+ out.print(clobberEpoch(), ":", structureClobberState()); >+} >+ >+} } // namespae JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >+ >Index: Source/JavaScriptCore/dfg/DFGAbstractValueClobberEpoch.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractValueClobberEpoch.h (nonexistent) >+++ Source/JavaScriptCore/dfg/DFGAbstractValueClobberEpoch.h (working copy) >@@ -0,0 +1,99 @@ >+/* >+ * Copyright (C) 2018 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 >+ >+#if ENABLE(DFG_JIT) >+ >+#include "DFGEpoch.h" >+#include "DFGStructureClobberState.h" >+#include <wtf/PrintStream.h> >+ >+namespace JSC { namespace DFG { >+ >+class AbstractValueClobberEpoch { >+public: >+ AbstractValueClobberEpoch() >+ { >+ } >+ >+ static AbstractValueClobberEpoch first(StructureClobberState clobberState) >+ { >+ AbstractValueClobberEpoch result; >+ result.m_value = Epoch::first().toUnsigned() << epochShift; >+ switch (clobberState) { >+ case StructuresAreWatched: >+ result.m_value |= watchedFlag; >+ break; >+ case StructuresAreClobbered: >+ break; >+ } >+ return result; >+ } >+ >+ void clobber() >+ { >+ m_value += step; >+ m_value &= ~watchedFlag; >+ } >+ >+ void observeInvalidationPoint() >+ { >+ m_value |= watchedFlag; >+ } >+ >+ bool operator==(const AbstractValueClobberEpoch& other) const >+ { >+ return m_value == other.m_value; >+ } >+ >+ bool operator!=(const AbstractValueClobberEpoch& other) const >+ { >+ return !(*this == other); >+ } >+ >+ StructureClobberState structureClobberState() const >+ { >+ return m_value & watchedFlag ? StructuresAreWatched : StructuresAreClobbered; >+ } >+ >+ Epoch clobberEpoch() const >+ { >+ return Epoch::fromUnsigned(m_value >> epochShift); >+ } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ static constexpr unsigned step = 2; >+ static constexpr unsigned watchedFlag = 1; >+ static constexpr unsigned epochShift = 1; >+ >+ unsigned m_value { 0 }; >+}; >+ >+} } // namespace JSC::DFG >+ >+#endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h (working copy) >@@ -52,7 +52,89 @@ public: > void createValueForNode(NodeFlowProjection); > AbstractValue& forNode(NodeFlowProjection); > AbstractValue& forNode(Edge edge) { return forNode(edge.node()); } >- Operands<AbstractValue>& variables() { return m_block->valuesAtTail; } >+ >+ ALWAYS_INLINE void clearForNode(NodeFlowProjection node) >+ { >+ forNode(node).clear(); >+ } >+ >+ ALWAYS_INLINE void clearForNode(Edge edge) >+ { >+ clearForNode(edge.node()); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ forNode(node).set(m_graph, std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setForNode(Edge edge, Arguments&&... arguments) >+ { >+ setForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setTypeForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ forNode(node).setType(m_graph, std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setTypeForNode(Edge edge, Arguments&&... arguments) >+ { >+ setTypeForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setNonCellTypeForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ forNode(node).setNonCellType(std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setNonCellTypeForNode(Edge edge, Arguments&&... arguments) >+ { >+ setNonCellTypeForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ ALWAYS_INLINE void makeBytecodeTopForNode(NodeFlowProjection node) >+ { >+ forNode(node).makeBytecodeTop(); >+ } >+ >+ ALWAYS_INLINE void makeBytecodeTopForNode(Edge edge) >+ { >+ makeBytecodeTopForNode(edge.node()); >+ } >+ >+ ALWAYS_INLINE void makeHeapTopForNode(NodeFlowProjection node) >+ { >+ forNode(node).makeHeapTop(); >+ } >+ >+ ALWAYS_INLINE void makeHeapTopForNode(Edge edge) >+ { >+ makeHeapTopForNode(edge.node()); >+ } >+ >+ unsigned numberOfArguments() const { return m_block->valuesAtTail.numberOfArguments(); } >+ unsigned numberOfLocals() const { return m_block->valuesAtTail.numberOfLocals(); } >+ AbstractValue& operand(int operand) { return m_block->valuesAtTail.operand(operand); } >+ AbstractValue& operand(VirtualRegister operand) { return m_block->valuesAtTail.operand(operand); } >+ AbstractValue& local(size_t index) { return m_block->valuesAtTail.local(index); } >+ AbstractValue& argument(size_t index) { return m_block->valuesAtTail.argument(index); } >+ >+ void clobberStructures() >+ { >+ UNREACHABLE_FOR_PLATFORM(); >+ } >+ >+ void observeInvalidationPoint() >+ { >+ UNREACHABLE_FOR_PLATFORM(); >+ } > > BasicBlock* block() const { return m_block; } > >Index: Source/JavaScriptCore/dfg/DFGCFAPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (working copy) >@@ -171,7 +171,7 @@ private: > if (!safeToExecute(m_state, m_graph, node)) > dataLog("(UNSAFE) "); > >- dataLog(m_state.variables(), " ", m_interpreter); >+ dataLog(m_state.variablesForDebugging(), " ", m_interpreter); > > dataLogF("\n"); > } >Index: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (working copy) >@@ -378,7 +378,7 @@ private: > if (index >= inlineCallFrame->argumentCountIncludingThis - 1) > break; > } else { >- if (index >= m_state.variables().numberOfArguments() - 1) >+ if (index >= m_state.numberOfArguments() - 1) > break; > } > >Index: Source/JavaScriptCore/dfg/DFGFlowMap.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlowMap.h (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGFlowMap.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2016 Apple Inc. All Rights Reserved. >+ * Copyright (C) 2016-2018 Apple Inc. All Rights Reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -55,27 +55,27 @@ public: > > Graph& graph() const { return m_graph; } > >- T& at(unsigned nodeIndex) >+ ALWAYS_INLINE T& at(unsigned nodeIndex) > { > return m_map[nodeIndex]; > } > >- T& at(Node* node) >+ ALWAYS_INLINE T& at(Node* node) > { > return at(node->index()); > } > >- T& atShadow(unsigned nodeIndex) >+ ALWAYS_INLINE T& atShadow(unsigned nodeIndex) > { > return m_shadowMap[nodeIndex]; > } > >- T& atShadow(Node* node) >+ ALWAYS_INLINE T& atShadow(Node* node) > { > return atShadow(node->index()); > } > >- T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind) >+ ALWAYS_INLINE T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind) > { > switch (kind) { > case NodeFlowProjection::Primary: >@@ -87,23 +87,23 @@ public: > return *bitwise_cast<T*>(nullptr); > } > >- T& at(Node* node, NodeFlowProjection::Kind kind) >+ ALWAYS_INLINE T& at(Node* node, NodeFlowProjection::Kind kind) > { > return at(node->index(), kind); > } > >- T& at(NodeFlowProjection projection) >+ ALWAYS_INLINE T& at(NodeFlowProjection projection) > { > return at(projection.node(), projection.kind()); > } > >- const T& at(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->at(nodeIndex); } >- const T& at(Node* node) const { return const_cast<FlowMap*>(this)->at(node); } >- const T& atShadow(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->atShadow(nodeIndex); } >- const T& atShadow(Node* node) const { return const_cast<FlowMap*>(this)->atShadow(node); } >- const T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(nodeIndex, kind); } >- const T& at(Node* node, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(node, kind); } >- const T& at(NodeFlowProjection projection) const { return const_cast<FlowMap*>(this)->at(projection); } >+ ALWAYS_INLINE const T& at(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->at(nodeIndex); } >+ ALWAYS_INLINE const T& at(Node* node) const { return const_cast<FlowMap*>(this)->at(node); } >+ ALWAYS_INLINE const T& atShadow(unsigned nodeIndex) const { return const_cast<FlowMap*>(this)->atShadow(nodeIndex); } >+ ALWAYS_INLINE const T& atShadow(Node* node) const { return const_cast<FlowMap*>(this)->atShadow(node); } >+ ALWAYS_INLINE const T& at(unsigned nodeIndex, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(nodeIndex, kind); } >+ ALWAYS_INLINE const T& at(Node* node, NodeFlowProjection::Kind kind) const { return const_cast<FlowMap*>(this)->at(node, kind); } >+ ALWAYS_INLINE const T& at(NodeFlowProjection projection) const { return const_cast<FlowMap*>(this)->at(projection); } > > private: > Graph& m_graph; >Index: Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013-2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -60,20 +60,32 @@ void InPlaceAbstractState::beginBasicBlo > ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals()); > > m_abstractValues.resize(); >+ >+ AbstractValueClobberEpoch epoch = AbstractValueClobberEpoch::first(basicBlock->cfaStructureClobberStateAtHead); >+ m_effectEpoch = epoch; > > for (size_t i = 0; i < basicBlock->size(); i++) { > NodeFlowProjection::forEach( > basicBlock->at(i), [&] (NodeFlowProjection nodeProjection) { >- forNode(nodeProjection).clear(); >+ AbstractValue& value = m_abstractValues.at(nodeProjection); >+ value.clear(); >+ value.m_effectEpoch = epoch; > }); > } > >- m_variables = basicBlock->valuesAtHead; >+ for (size_t i = m_variables.size(); i--;) { >+ AbstractValue& value = m_variables[i]; >+ value = basicBlock->valuesAtHead[i]; >+ value.m_effectEpoch = epoch; >+ } > > if (m_graph.m_form == SSA) { > for (NodeAbstractValuePair& entry : basicBlock->ssa->valuesAtHead) { >- if (entry.node.isStillValid()) >- forNode(entry.node) = entry.value; >+ if (entry.node.isStillValid()) { >+ AbstractValue& value = m_abstractValues.at(entry.node); >+ value = entry.value; >+ value.m_effectEpoch = epoch; >+ } > } > } > basicBlock->cfaShouldRevisit = false; >@@ -123,10 +135,10 @@ void InPlaceAbstractState::initialize() > > switch (format) { > case FlushedInt32: >- entrypoint->valuesAtHead.argument(i).setType(SpecInt32Only); >+ entrypoint->valuesAtHead.argument(i).setNonCellType(SpecInt32Only); > break; > case FlushedBoolean: >- entrypoint->valuesAtHead.argument(i).setType(SpecBoolean); >+ entrypoint->valuesAtHead.argument(i).setNonCellType(SpecBoolean); > break; > case FlushedCell: > entrypoint->valuesAtHead.argument(i).setType(m_graph, SpecCellCheck); >@@ -201,19 +213,19 @@ bool InPlaceAbstractState::endBasicBlock > case ThreadedCPS: { > for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) { > AbstractValue& destination = block->valuesAtTail.argument(argument); >- mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument)); >+ mergeStateAtTail(destination, this->argument(argument), block->variablesAtTail.argument(argument)); > } > > for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) { > AbstractValue& destination = block->valuesAtTail.local(local); >- mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local)); >+ mergeStateAtTail(destination, this->local(local), block->variablesAtTail.local(local)); > } > break; > } > > case SSA: { > for (size_t i = 0; i < block->valuesAtTail.size(); ++i) >- block->valuesAtTail[i].merge(m_variables[i]); >+ block->valuesAtTail[i].merge(variableAt(i)); > > for (NodeAbstractValuePair& valueAtTail : block->ssa->valuesAtTail) { > AbstractValue& valueAtNode = forNode(valueAtTail.node); >Index: Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h (working copy) >@@ -47,21 +47,104 @@ public: > > void createValueForNode(NodeFlowProjection) { } > >- AbstractValue& forNode(NodeFlowProjection node) >+ ALWAYS_INLINE AbstractValue& forNode(NodeFlowProjection node) > { >- return m_abstractValues.at(node); >+ return fastForward(m_abstractValues.at(node)); > } > >- AbstractValue& forNode(Edge edge) >+ ALWAYS_INLINE AbstractValue& forNode(Edge edge) > { > return forNode(edge.node()); > } > >- Operands<AbstractValue>& variables() >+ ALWAYS_INLINE void clearForNode(NodeFlowProjection node) > { >- return m_variables; >+ AbstractValue& value = m_abstractValues.at(node); >+ value.clear(); >+ value.m_effectEpoch = m_effectEpoch; > } > >+ ALWAYS_INLINE void clearForNode(Edge edge) >+ { >+ clearForNode(edge.node()); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ AbstractValue& value = m_abstractValues.at(node); >+ value.set(m_graph, std::forward<Arguments>(arguments)...); >+ value.m_effectEpoch = m_effectEpoch; >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setForNode(Edge edge, Arguments&&... arguments) >+ { >+ setForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setTypeForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ AbstractValue& value = m_abstractValues.at(node); >+ value.setType(m_graph, std::forward<Arguments>(arguments)...); >+ value.m_effectEpoch = m_effectEpoch; >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setTypeForNode(Edge edge, Arguments&&... arguments) >+ { >+ setTypeForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setNonCellTypeForNode(NodeFlowProjection node, Arguments&&... arguments) >+ { >+ AbstractValue& value = m_abstractValues.at(node); >+ value.setNonCellType(std::forward<Arguments>(arguments)...); >+ value.m_effectEpoch = m_effectEpoch; >+ } >+ >+ template<typename... Arguments> >+ ALWAYS_INLINE void setNonCellTypeForNode(Edge edge, Arguments&&... arguments) >+ { >+ setNonCellTypeForNode(edge.node(), std::forward<Arguments>(arguments)...); >+ } >+ >+ ALWAYS_INLINE void makeBytecodeTopForNode(NodeFlowProjection node) >+ { >+ AbstractValue& value = m_abstractValues.at(node); >+ value.makeBytecodeTop(); >+ value.m_effectEpoch = m_effectEpoch; >+ } >+ >+ ALWAYS_INLINE void makeBytecodeTopForNode(Edge edge) >+ { >+ makeBytecodeTopForNode(edge.node()); >+ } >+ >+ ALWAYS_INLINE void makeHeapTopForNode(NodeFlowProjection node) >+ { >+ AbstractValue& value = m_abstractValues.at(node); >+ value.makeHeapTop(); >+ value.m_effectEpoch = m_effectEpoch; >+ } >+ >+ ALWAYS_INLINE void makeHeapTopForNode(Edge edge) >+ { >+ makeHeapTopForNode(edge.node()); >+ } >+ >+ Operands<AbstractValue>& variablesForDebugging() { return m_variables; } >+ >+ unsigned numberOfArguments() const { return m_variables.numberOfArguments(); } >+ unsigned numberOfLocals() const { return m_variables.numberOfLocals(); } >+ AbstractValue& operand(int operand) { return fastForward(m_variables.operand(operand)); } >+ AbstractValue& operand(VirtualRegister operand) { return fastForward(m_variables.operand(operand)); } >+ AbstractValue& local(size_t index) { return fastForward(m_variables.local(index)); } >+ AbstractValue& argument(size_t index) { return fastForward(m_variables.argument(index)); } >+ AbstractValue& variableAt(size_t index) { return fastForward(m_variables[index]); } >+ > // Call this before beginning CFA to initialize the abstract values of > // arguments, and to indicate which blocks should be listed for CFA > // execution. >@@ -119,6 +202,10 @@ public: > // MergeToSuccessors. > bool mergeToSuccessors(BasicBlock*); > >+ void clobberStructures() { m_effectEpoch.clobber(); } >+ >+ void observeInvalidationPoint() { m_effectEpoch.observeInvalidationPoint(); } >+ > // Methods intended to be called from AbstractInterpreter. > void setClobberState(AbstractInterpreterClobberState state) { m_clobberState = state; } > void mergeClobberState(AbstractInterpreterClobberState state) { m_clobberState = mergeClobberStates(m_clobberState, state); } >@@ -139,6 +226,12 @@ public: > } > > private: >+ ALWAYS_INLINE AbstractValue& fastForward(AbstractValue& value) >+ { >+ value.fastForwardTo(m_effectEpoch); >+ return value; >+ } >+ > void mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node*); > > static bool mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, Node* destinationNode, Node* sourceNode); >@@ -154,6 +247,7 @@ private: > bool m_isValid; > AbstractInterpreterClobberState m_clobberState; > StructureClobberState m_structureClobberState; >+ AbstractValueClobberEpoch m_effectEpoch; > > BranchDirection m_branchDirection; // This is only set for blocks that end in Branch and that execute to completion (i.e. m_isValid == true). > }; >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 231338) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -1932,7 +1932,7 @@ void SpeculativeJIT::compile(Node* node) > } > > case GetLocal: { >- AbstractValue& value = m_state.variables().operand(node->local()); >+ AbstractValue& value = m_state.operand(node->local()); > > // If the CFA is tracking this variable and it found that the variable > // cannot have been assigned, then don't attempt to proceed. >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (revision 231338) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (working copy) >@@ -1685,7 +1685,7 @@ private: > void compileGetStack() > { > StackAccessData* data = m_node->stackAccessData(); >- AbstractValue& value = m_state.variables().operand(data->local); >+ AbstractValue& value = m_state.operand(data->local); > > DFG_ASSERT(m_graph, m_node, isConcrete(data->format), data->format); > DFG_ASSERT(m_graph, m_node, data->format != FlushedDouble, data->format); // This just happens to not arise for GetStacks, right now. It would be trivial to support.
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 185287
:
339509
|
339620
|
339623
|
339650
|
339661
|
339662
|
339663
|
339687