WebKit Bugzilla
Attachment 339620 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]
more
blah.patch (text/plain), 39.41 KB, created by
Filip Pizlo
on 2018-05-04 18:50:14 PDT
(
hide
)
Description:
more
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2018-05-04 18:50:14 PDT
Size:
39.41 KB
patch
obsolete
>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/dfg/DFGAbstractInterpreter.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (revision 231337) >+++ 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,21 +41,38 @@ 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() >+ template<typename ValueType> >+ ALWAYS_INLINE void setForNode(NodeFlowProjection node, ValueType&& value) > { >- return m_state.variables(); >+ m_state.setForNode(node, std::forward<ValueType>(value)); > } > >+ template<typename ValueType> >+ ALWAYS_INLINE void setForNode(Edge edge, ValueType&& value) >+ { >+ setForNode(edge.node(), std::forward<ValueType>(value)); >+ } >+ >+ ALWAYS_INLINE void clearForNode(NodeFlowProjection node) >+ { >+ m_state.clearForNode(node); >+ } >+ >+ ALWAYS_INLINE void clearForNode(Edge edge) >+ { >+ clearForNode(edge.node()); >+ } >+ > bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough) > { > return !forNode(node).isType(typesPassedThrough); >@@ -149,13 +166,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); >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 231337) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -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; >@@ -249,33 +249,33 @@ bool AbstractInterpreter<AbstractStateTy > > 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,14 +296,14 @@ 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); >@@ -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).setType(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; > } > >@@ -674,12 +674,12 @@ 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; > } > } >@@ -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,7 +2003,7 @@ bool AbstractInterpreter<AbstractStateTy > if (result.value()) > m_state.setFoundConstants(true); > >- forNode(node) = result; >+ setForNode(node, result); > break; > } > >@@ -2122,7 +2122,7 @@ 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; > } > >@@ -2145,7 +2145,7 @@ 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; > } > >@@ -2747,7 +2747,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(); >@@ -2888,7 +2888,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 +2896,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; > } > >@@ -2987,7 +2987,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; >@@ -3058,7 +3058,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 +3108,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; >@@ -3357,7 +3357,7 @@ bool AbstractInterpreter<AbstractStateTy > > 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 +3368,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; > } >@@ -3400,8 +3400,8 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case InvalidationPoint: >- forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor); > m_state.setStructureClobberState(StructuresAreWatched); >+ m_state.observeInvalidationPoint(); > break; > > case CPUIntrinsic: >@@ -3537,10 +3537,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 +3571,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); > } >Index: Source/JavaScriptCore/dfg/DFGAbstractValue.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractValue.cpp (revision 231337) >+++ 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 >@@ -574,6 +574,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 231337) >+++ 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,10 @@ 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) >+ fastForwardToSlow(newEpoch); > } > > void observeTransition(RegisteredStructure from, RegisteredStructure to) >@@ -397,6 +388,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 +450,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 231337) >+++ Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h (working copy) >@@ -52,7 +52,45 @@ public: > void createValueForNode(NodeFlowProjection); > AbstractValue& forNode(NodeFlowProjection); > AbstractValue& forNode(Edge edge) { return forNode(edge.node()); } >- Operands<AbstractValue>& variables() { return m_block->valuesAtTail; } >+ >+ template<typename ValueType> >+ ALWAYS_INLINE void setForNode(NodeFlowProjection node, ValueType&& value) >+ { >+ forNode(node) = std::forward<ValueType>(value); >+ } >+ >+ template<typename ValueType> >+ ALWAYS_INLINE void setForNode(Edge edge, ValueType&& value) >+ { >+ setForNode(edge.node(), std::forward<ValueType>(value)); >+ } >+ >+ ALWAYS_INLINE void clearForNode(NodeFlowProjection node) >+ { >+ forNode(node).clear(); >+ } >+ >+ ALWAYS_INLINE void clearForNode(Edge edge) >+ { >+ clearForNode(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/DFGFlowMap.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlowMap.h (revision 231337) >+++ 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 231337) >+++ 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,22 @@ void InPlaceAbstractState::beginBasicBlo > ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals()); > > m_abstractValues.resize(); >+ m_effectEpoch = AbstractValueClobberEpoch::first(basicBlock->cfaStructureClobberStateAtHead); > > for (size_t i = 0; i < basicBlock->size(); i++) { > NodeFlowProjection::forEach( > basicBlock->at(i), [&] (NodeFlowProjection nodeProjection) { >- forNode(nodeProjection).clear(); >+ clearForNode(nodeProjection); > }); > } > >- m_variables = basicBlock->valuesAtHead; >+ for (size_t i = m_variables.size(); i--;) >+ variableAt(i) = basicBlock->valuesAtHead[i]; > > if (m_graph.m_form == SSA) { > for (NodeAbstractValuePair& entry : basicBlock->ssa->valuesAtHead) { > if (entry.node.isStillValid()) >- forNode(entry.node) = entry.value; >+ setForNode(entry.node, entry.value); > } > } > basicBlock->cfaShouldRevisit = false; >@@ -201,19 +203,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, 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, 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 231337) >+++ Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h (working copy) >@@ -47,21 +47,46 @@ 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() >+ template<typename ValueType> >+ ALWAYS_INLINE void setForNode(NodeFlowProjection node, ValueType&& value) > { >- return m_variables; >+ m_abstractValues.at(node) = std::forward<ValueType>(value); > } > >+ template<typename ValueType> >+ ALWAYS_INLINE void setForNode(Edge edge, ValueType&& value) >+ { >+ setForNode(edge.node(), std::forward<ValueType>(value)); >+ } >+ >+ ALWAYS_INLINE void clearForNode(NodeFlowProjection node) >+ { >+ m_abstractValues.at(node).clear(); >+ } >+ >+ ALWAYS_INLINE void clearForNode(Edge edge) >+ { >+ clearForNode(edge.node()); >+ } >+ >+ unsigned numberOfArguments() const { return m_variables.numberOfArguments(); } >+ unsigend 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 +144,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 +168,12 @@ public: > } > > private: >+ 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 +189,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). > };
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