WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
passing some tests
blah.patch (text/plain), 82.48 KB, created by
Filip Pizlo
on 2013-12-25 15:39:15 PST
(
hide
)
Description:
passing some tests
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-12-25 15:39:15 PST
Size:
82.48 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 161036) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,72 @@ >+2013-12-25 Filip Pizlo <fpizlo@apple.com> >+ >+ DFG PhantomArguments shouldn't rely on a dead Phi graph >+ https://bugs.webkit.org/show_bug.cgi?id=126218 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This change dramatically rationalizes our handling of PhantomArguments (i.e. >+ speculative elision of arguments object allocation). >+ >+ It's now the case that if we decide that we can elide arguments allocation, we just >+ turn the arguments-creating node into a PhantomArguments and mark all locals that >+ it's stored to as being arguments aliases. Being an arguments alias and being a >+ PhantomArguments means basically the same thing: in DFG execution you have the empty >+ value, on OSR exit an arguments object is allocated in your place, and all operations >+ that use the value now just refer directly to the actual arguments in the call frame >+ header (or the arguments we know that we passed to the call, in case of inlining). >+ >+ This means that we no longer have arguments simplification creating a dead Phi graph >+ that then has to be interpreted by the OSR exit logic. That sort of never made any >+ sense. >+ >+ This means that PhantomArguments now has a clear story in SSA: basically SSA just >+ gets rid of the "locals" but everything else is the same. >+ >+ Finally, this means that we can more easily get rid of forward exiting. As I was >+ working on the code to get rid of forward exiting, I realized that I'd have to >+ carefully preserve the special meanings of MovHint and SetLocal in the case of >+ PhantomArguments. It was really bizarre: even the semantics of MovHint were tied to >+ our specific treatment of PhantomArguments. After this change this is no longer the >+ case. >+ >+ One of the really cool things about this change is that arguments reification now >+ just becomes a special kind of FlushFormat. This further unifies things: it means >+ that a MovHint(PhantomArguments) and a SetLocal(PhantomArguments) both have the same >+ meaning, since both of them dictate that the way we recover the local on exit is by >+ reifying arguments. Previously, the SetLocal(PhantomArguments) case needed some >+ special handling to accomplish this. >+ >+ A downside of this approach is that we will now emit code to store the empty value >+ into aliased arguments variables, and we will even emit code to load that empty value >+ as well. As far as I can tell this doesn't cost anything, since PhantomArguments are >+ most profitable in cases where it allows us to simplify control flow and kill the >+ arguments locals entirely. Of course, this isn't an issue in SSA form since SSA form >+ also eliminates the locals. >+ >+ * dfg/DFGArgumentsSimplificationPhase.cpp: >+ (JSC::DFG::ArgumentsSimplificationPhase::run): >+ (JSC::DFG::ArgumentsSimplificationPhase::detypeArgumentsReferencingPhantomChild): >+ * dfg/DFGFlushFormat.cpp: >+ (WTF::printInternal): >+ * dfg/DFGFlushFormat.h: >+ (JSC::DFG::resultFor): >+ (JSC::DFG::useKindFor): >+ (JSC::DFG::dataFormatFor): >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileCurrentBlock): >+ * dfg/DFGSpeculativeJIT32_64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGValueSource.h: >+ (JSC::DFG::ValueSource::ValueSource): >+ (JSC::DFG::ValueSource::forFlushFormat): >+ * dfg/DFGVariableAccessData.h: >+ (JSC::DFG::VariableAccessData::flushFormat): >+ * ftl/FTLLowerDFGToLLVM.cpp: >+ (JSC::FTL::LowerDFGToLLVM::buildExitArguments): >+ > 2013-12-23 Oliver Hunt <oliver@apple.com> > > Refactor PutPropertySlot to be aware of custom properties >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -195,10 +195,10 @@ bool AbstractInterpreter<AbstractStateTy > break; > } > >- case MovHint: >- case MovHintAndCheck: { >- // Don't need to do anything. A MovHint is effectively a promise that the SetLocal >- // was dead. >+ case MovHint: { >+ // Don't need to do anything. A MovHint only informs us about what would have happened >+ // in bytecode, but this code is just concerned with what is actually happening during >+ // DFG execution. > break; > } > >Index: Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp (working copy) >@@ -395,16 +395,6 @@ public: > || unmodifiedArgumentsRegister(m_graph.argumentsRegisterFor(node->codeOrigin)) == variableAccessData->local()) > break; > >- ASSERT(!variableAccessData->isCaptured()); >- >- // If this is a store into a VariableAccessData* that is marked as >- // arguments aliasing for an InlineCallFrame* that does not create >- // arguments, then flag the VariableAccessData as being an >- // arguments-aliased. This'll let the OSR exit machinery do the right >- // things. Note also that the SetLocal should become dead as soon as >- // we replace all uses of this variable with GetMyArgumentsLength and >- // GetMyArgumentByVal. >- ASSERT(m_argumentsAliasing.find(variableAccessData)->value.isValid()); > if (variableAccessData->mergeIsArgumentsAlias(true)) { > changed = true; > >@@ -420,22 +410,6 @@ public: > break; > } > >- case PhantomLocal: { >- VariableAccessData* variableAccessData = node->variableAccessData(); >- >- if (variableAccessData->isCaptured() >- || !m_argumentsAliasing.find(variableAccessData)->value.isValid() >- || m_createsArguments.contains(node->codeOrigin.inlineCallFrame)) >- break; >- >- // Turn PhantomLocals into just GetLocals. This will preserve the threading >- // of the local through to this point, but will allow it to die, causing >- // only OSR to know about it. >- >- node->setOpAndDefaultFlags(GetLocal); >- break; >- } >- > case Flush: { > VariableAccessData* variableAccessData = node->variableAccessData(); > >@@ -459,7 +433,7 @@ public: > // 2) The Phantom may keep the CreateArguments node alive, which is > // precisely what we don't want. > for (unsigned i = 0; i < AdjacencyList::Size; ++i) >- removeArgumentsReferencingPhantomChild(node, i); >+ detypeArgumentsReferencingPhantomChild(node, i); > break; > } > >@@ -470,7 +444,6 @@ public: > if (!isOKToOptimize(node->child1().node())) > break; > node->convertToPhantom(); >- node->children.setChild1(Edge()); > break; > } > >@@ -488,8 +461,11 @@ public: > if (!isOKToOptimize(node->child1().node())) > break; > >- node->children.child1() = node->children.child2(); >- node->children.child2() = Edge(); >+ insertionSet.insertNode( >+ indexInBlock, SpecNone, Phantom, node->codeOrigin, node->child1()); >+ >+ node->child1() = node->child2(); >+ node->child2() = Edge(); > node->setOpAndDefaultFlags(GetMyArgumentByVal); > changed = true; > --indexInBlock; // Force reconsideration of this op now that it's a GetMyArgumentByVal. >@@ -503,7 +479,10 @@ public: > if (!isOKToOptimize(node->child1().node())) > break; > >- node->children.child1() = Edge(); >+ insertionSet.insertNode( >+ indexInBlock, SpecNone, Phantom, node->codeOrigin, node->child1()); >+ >+ node->child1() = Edge(); > node->setOpAndDefaultFlags(GetMyArgumentsLength); > changed = true; > --indexInBlock; // Force reconsideration of this op noew that it's a GetMyArgumentsLength. >@@ -580,8 +559,7 @@ public: > indexInBlock, SpecNone, CheckArgumentsNotCreated, > codeOrigin); > insertionSet.insertNode( >- indexInBlock, SpecNone, Phantom, codeOrigin, >- children); >+ indexInBlock, SpecNone, Phantom, codeOrigin, children); > > changed = true; > break; >@@ -591,8 +569,7 @@ public: > if (m_createsArguments.contains(node->codeOrigin.inlineCallFrame)) > continue; > >- node->setOpAndDefaultFlags(Phantom); >- node->children.reset(); >+ node->convertToPhantom(); > break; > } > >@@ -627,6 +604,19 @@ public: > insertionSet.execute(block); > } > >+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { >+ BasicBlock* block = m_graph.block(blockIndex); >+ if (!block) >+ continue; >+ for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { >+ Node* node = block->at(indexInBlock); >+ if (node->op() != Phantom) >+ continue; >+ for (unsigned i = 0; i < AdjacencyList::Size; ++i) >+ detypeArgumentsReferencingPhantomChild(node, i); >+ } >+ } >+ > if (changed) { > m_graph.dethread(); > m_graph.m_form = LoadStore; >@@ -764,35 +754,23 @@ private: > return false; > } > >- void removeArgumentsReferencingPhantomChild(Node* node, unsigned edgeIndex) >+ void detypeArgumentsReferencingPhantomChild(Node* node, unsigned edgeIndex) > { > Edge edge = node->children.child(edgeIndex); > if (!edge) > return; > > switch (edge->op()) { >- case Phi: // Arises if we had CSE on a GetLocal of the arguments register. >- case GetLocal: // Arises if we had CSE on an arguments access to a variable aliased to the arguments. >- case SetLocal: { // Arises if we had CSE on a GetLocal of the arguments register. >+ case GetLocal: { > VariableAccessData* variableAccessData = edge->variableAccessData(); >- bool isDeadArgumentsRegister = >- variableAccessData->local() == >- m_graph.uncheckedArgumentsRegisterFor(edge->codeOrigin) >- && !m_createsArguments.contains(edge->codeOrigin.inlineCallFrame); >- bool isAliasedArgumentsRegister = >- !variableAccessData->isCaptured() >- && m_argumentsAliasing.find(variableAccessData)->value.isValid() >- && !m_createsArguments.contains(edge->codeOrigin.inlineCallFrame); >- if (!isDeadArgumentsRegister && !isAliasedArgumentsRegister) >+ if (!variableAccessData->isArgumentsAlias()) > break; >- node->children.removeEdge(edgeIndex); >+ node->children.child(edgeIndex).setUseKind(UntypedUse); > break; > } > >- case CreateArguments: { // Arises if we CSE two GetLocals to the arguments register and then CSE the second use of the GetLocal to the first. >- if (m_createsArguments.contains(edge->codeOrigin.inlineCallFrame)) >- break; >- node->children.removeEdge(edgeIndex); >+ case PhantomArguments: { >+ node->children.child(edgeIndex).setUseKind(UntypedUse); > break; > } > >Index: Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h (working copy) >@@ -63,13 +63,13 @@ public: > case Array::Int32: > case Array::Double: > case Array::Contiguous: >- m_badPropertyJump = jit->backwardSpeculationCheck(Uncountable, JSValueRegs(), 0); >+ m_badPropertyJump = jit->speculationCheck(Uncountable, JSValueRegs(), 0); > break; > default: > break; > } > } >- m_badIndexingTypeJump = jit->backwardSpeculationCheck(BadIndexingType, JSValueSource::unboxedCell(m_baseGPR), 0); >+ m_badIndexingTypeJump = jit->speculationCheck(BadIndexingType, JSValueSource::unboxedCell(m_baseGPR), 0); > } > > protected: >Index: Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (working copy) >@@ -187,6 +187,9 @@ private: > break; > } > >+ case MovHint: >+ break; >+ > case BitAnd: > case BitOr: > case BitXor: >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -232,15 +232,19 @@ private: > return getDirect(m_inlineStackTop->remapOperand(operand)); > } > >- enum SetMode { NormalSet, SetOnEntry }; >+ enum SetMode { NormalSet, ImmediateSet }; > Node* setDirect(VirtualRegister operand, Node* value, SetMode setMode = NormalSet) > { >- // Is this an argument? >- if (operand.isArgument()) >- return setArgument(operand, value, setMode); >- >- // Must be a local. >- return setLocal(operand, value, setMode); >+ addToGraph(MovHint, OpInfo(operand.offset()), value); >+ >+ DelayedSetLocal delayed = DelayedSetLocal(operand, value); >+ >+ if (setMode == NormalSet) { >+ m_setLocalQueue.append(delayed); >+ return 0; >+ } >+ >+ return delayed.execute(this, setMode); > } > > Node* set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet) >@@ -1121,6 +1125,27 @@ private: > }; > > InlineStackEntry* m_inlineStackTop; >+ >+ struct DelayedSetLocal { >+ VirtualRegister m_operand; >+ Node* m_value; >+ >+ DelayedSetLocal() { } >+ DelayedSetLocal(VirtualRegister operand, Node* value) >+ : m_operand(operand) >+ , m_value(value) >+ { >+ } >+ >+ Node* execute(ByteCodeParser* parser, SetMode setMode = NormalSet) >+ { >+ if (m_operand.isArgument()) >+ return parser->setArgument(m_operand, m_value, setMode); >+ return parser->setLocal(m_operand, m_value, setMode); >+ } >+ }; >+ >+ Vector<DelayedSetLocal, 2> m_setLocalQueue; > > // Have we built operand maps? We initialize them lazily, and only when doing > // inlining. >@@ -1325,9 +1350,9 @@ bool ByteCodeParser::handleInlining(Node > == callLinkStatus.isClosureCall()); > if (callLinkStatus.isClosureCall()) { > VariableAccessData* calleeVariable = >- set(VirtualRegister(JSStack::Callee), callTargetNode)->variableAccessData(); >+ set(VirtualRegister(JSStack::Callee), callTargetNode, ImmediateSet)->variableAccessData(); > VariableAccessData* scopeVariable = >- set(VirtualRegister(JSStack::ScopeChain), addToGraph(GetScope, callTargetNode))->variableAccessData(); >+ set(VirtualRegister(JSStack::ScopeChain), addToGraph(GetScope, callTargetNode), ImmediateSet)->variableAccessData(); > > calleeVariable->mergeShouldNeverUnbox(true); > scopeVariable->mergeShouldNeverUnbox(true); >@@ -1872,6 +1897,10 @@ bool ByteCodeParser::parseBlock(unsigned > } > > while (true) { >+ for (unsigned i = 0; i < m_setLocalQueue.size(); ++i) >+ m_setLocalQueue[i].execute(this); >+ m_setLocalQueue.resize(0); >+ > // Don't extend over jump destinations. > if (m_currentIndex == limit) { > // Ordinarily we want to plant a jump. But refuse to do this if the block is >@@ -1903,7 +1932,7 @@ bool ByteCodeParser::parseBlock(unsigned > case op_enter: > // Initialize all locals to undefined. > for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i) >- set(virtualRegisterForLocal(i), constantUndefined(), SetOnEntry); >+ set(virtualRegisterForLocal(i), constantUndefined(), ImmediateSet); > NEXT_OPCODE(op_enter); > > case op_touch_entry: >@@ -2908,7 +2937,7 @@ bool ByteCodeParser::parseBlock(unsigned > flushArgumentsAndCapturedVariables(); > if (inlineCallFrame()) { > ASSERT(m_inlineStackTop->m_returnValue.isValid()); >- setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand))); >+ setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)), ImmediateSet); > m_inlineStackTop->m_didReturn = true; > if (m_inlineStackTop->m_unlinkedBlocks.isEmpty()) { > // If we're returning from the first block, then we're done parsing. >Index: Source/JavaScriptCore/dfg/DFGClobberize.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGClobberize.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGClobberize.h (working copy) >@@ -131,7 +131,6 @@ void clobberize(Graph& graph, Node* node > case DoubleAsInt32: > return; > >- case MovHintAndCheck: > case MovHint: > case ZombieHint: > case Upsilon: >Index: Source/JavaScriptCore/dfg/DFGCommon.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCommon.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGCommon.h (working copy) >@@ -182,8 +182,6 @@ enum RefCountState { > > enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation }; > >-enum SpeculationDirection { ForwardSpeculation, BackwardSpeculation }; >- > enum ProofStatus { NeedsCheck, IsProved }; > > inline bool isProved(ProofStatus proofStatus) >Index: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (working copy) >@@ -110,12 +110,8 @@ private: > m_interpreter.execute(indexInBlock); // Catch the fact that we may filter on cell. > AdjacencyList children = node->children; > children.removeEdge(0); >- if (!!children.child1()) { >- Node phantom(Phantom, node->codeOrigin, children); >- if (node->flags() & NodeExitsForward) >- phantom.mergeFlags(NodeExitsForward); >- m_insertionSet.insertNode(indexInBlock, SpecNone, phantom); >- } >+ if (!!children.child1()) >+ m_insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node->codeOrigin, children); > node->children.setChild2(Edge()); > node->children.setChild3(Edge()); > node->convertToStructureTransitionWatchpoint(structure); >Index: Source/JavaScriptCore/dfg/DFGDCEPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (working copy) >@@ -113,8 +113,12 @@ public: > for (unsigned i = depthFirst.size(); i--;) > fixupBlock(depthFirst[i]); > } else { >+ RELEASE_ASSERT(m_graph.m_form == ThreadedCPS); >+ > for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) > fixupBlock(m_graph.block(blockIndex)); >+ >+ cleanVariables(m_graph.m_arguments); > } > > m_graph.m_refCountState = ExactRefCount; >@@ -159,37 +163,23 @@ private: > continue; > > switch (node->op()) { >- case SetLocal: > case MovHint: { >- ASSERT((node->op() == SetLocal) == (m_graph.m_form == ThreadedCPS)); >- if (node->child1().willNotHaveCheck()) { >- // Consider the possibility that UInt32ToNumber is dead but its >- // child isn't; if so then we should MovHint the child. >- if (!node->child1()->shouldGenerate() >- && permitsOSRBackwardRewiring(node->child1()->op())) >- node->child1() = node->child1()->child1(); >- >- if (!node->child1()->shouldGenerate()) { >- node->setOpAndDefaultFlags(ZombieHint); >- node->child1() = Edge(); >- break; >- } >- node->setOpAndDefaultFlags(MovHint); >+ ASSERT(node->child1().useKind() == UntypedUse); >+ if (!node->child1()->shouldGenerate()) { >+ node->setOpAndDefaultFlags(ZombieHint); >+ node->child1() = Edge(); > break; > } >- node->setOpAndDefaultFlags(MovHintAndCheck); >- node->setRefCount(1); >+ node->setOpAndDefaultFlags(MovHint); > break; > } >- >- case GetLocal: >- case SetArgument: { >- if (m_graph.m_form == ThreadedCPS) { >- // Leave them as not shouldGenerate. >- break; >- } >+ >+ case ZombieHint: { >+ // Currently we assume that DCE runs only once. >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; > } >- >+ > default: { > if (node->flags() & NodeHasVarArgs) { > for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) { >@@ -215,6 +205,22 @@ private: > } > > m_insertionSet.execute(block); >+ >+ switch (m_graph.m_form) { >+ case SSA: >+ return; >+ >+ case ThreadedCPS: { >+ cleanVariables(block->variablesAtHead); >+ cleanVariables(block->variablesAtTail); >+ return; >+ } >+ >+ case LoadStore: >+ RELEASE_ASSERT_NOT_REACHED(); >+ return; >+ } >+ RELEASE_ASSERT_NOT_REACHED(); > } > > void eliminateIrrelevantPhantomChildren(Node* node) >@@ -228,6 +234,19 @@ private: > } > } > >+ template<typename VariablesVectorType> >+ void cleanVariables(VariablesVectorType& variables) >+ { >+ for (unsigned i = variables.size(); i--;) { >+ Node* node = variables[i]; >+ if (!node) >+ continue; >+ if (node->op() != Phantom && node->shouldGenerate()) >+ continue; >+ variables[i] = 0; >+ } >+ } >+ > Vector<Node*, 128> m_worklist; > InsertionSet m_insertionSet; > }; >Index: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (working copy) >@@ -907,9 +907,6 @@ private: > case GetIndexedPropertyStorage: > case GetTypedArrayByteOffset: > case LastNodeType: >- case MovHint: >- case MovHintAndCheck: >- case ZombieHint: > case CheckTierUpInLoop: > case CheckTierUpAtReturn: > case CheckTierUpAndOSREnter: >@@ -1005,6 +1002,8 @@ private: > case StoreBarrierWithNullCheck: > case FunctionReentryWatchpoint: > case TypedArrayWatchpoint: >+ case MovHint: >+ case ZombieHint: > break; > #else > default: >@@ -1478,7 +1477,7 @@ private: > { > if (isDouble(useKind)) { > if (edge->shouldSpeculateInt32ForArithmetic()) { >- injectInt32ToDoubleNode(edge, useKind, m_currentNode->speculationDirection()); >+ injectInt32ToDoubleNode(edge, useKind); > return; > } > >@@ -1491,7 +1490,6 @@ private: > Node* result = m_insertionSet.insertNode( > m_indexInBlock, SpecInt52AsDouble, Int52ToDouble, > m_currentNode->codeOrigin, Edge(edge.node(), NumberUse)); >- result->setSpeculationDirection(m_currentNode->speculationDirection()); > edge = Edge(result, useKind); > return; > } >@@ -1545,7 +1543,6 @@ private: > Node* result = m_insertionSet.insertNode( > m_indexInBlock, SpecInt52, Int52ToValue, > m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse)); >- result->setSpeculationDirection(m_currentNode->speculationDirection()); > edge = Edge(result, useKind); > return; > } >@@ -1587,13 +1584,11 @@ private: > edge = newEdge; > } > >- void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation) >+ void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse) > { > Node* result = m_insertionSet.insertNode( > m_indexInBlock, SpecInt52AsDouble, Int32ToDouble, > m_currentNode->codeOrigin, Edge(edge.node(), NumberUse)); >- if (direction == ForwardSpeculation) >- result->mergeFlags(NodeExitsForward); > > edge = Edge(result, useKind); > } >Index: Source/JavaScriptCore/dfg/DFGFlushFormat.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlushFormat.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGFlushFormat.cpp (working copy) >@@ -56,6 +56,9 @@ void printInternal(PrintStream& out, Flu > case FlushedJSValue: > out.print("FlushedJSValue"); > return; >+ case FlushedArguments: >+ out.print("FlushedArguments"); >+ return; > case ConflictingFlush: > out.print("ConflictingFlush"); > return; >Index: Source/JavaScriptCore/dfg/DFGFlushFormat.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFlushFormat.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGFlushFormat.h (working copy) >@@ -46,6 +46,7 @@ enum FlushFormat { > FlushedCell, > FlushedBoolean, > FlushedJSValue, >+ FlushedArguments, > ConflictingFlush > }; > >@@ -56,6 +57,7 @@ inline NodeFlags resultFor(FlushFormat f > case FlushedJSValue: > case FlushedCell: > case ConflictingFlush: >+ case FlushedArguments: > return NodeResultJS; > case FlushedInt32: > return NodeResultInt32; >@@ -76,6 +78,7 @@ inline UseKind useKindFor(FlushFormat fo > case DeadFlush: > case FlushedJSValue: > case ConflictingFlush: >+ case FlushedArguments: > return UntypedUse; > case FlushedCell: > return CellUse; >@@ -110,6 +113,8 @@ inline DataFormat dataFormatFor(FlushFor > return DataFormatCell; > case FlushedBoolean: > return DataFormatBoolean; >+ case FlushedArguments: >+ return DataFormatArguments; > } > RELEASE_ASSERT_NOT_REACHED(); > return DataFormatDead; >Index: Source/JavaScriptCore/dfg/DFGLICMPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGLICMPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGLICMPhase.cpp (working copy) >@@ -128,7 +128,6 @@ public: > // time and preserve some kind of sanity, if we hoist something that must exit. > // > // Also, we need to remember to: >- // - Clear NodeExitsForward for any nodes we hoisted. > // - Update the state-at-tail with the node we hoisted, so future hoist candidates > // know about any type checks we hoisted. > // >@@ -230,8 +229,6 @@ private: > > data.preHeader->insertBeforeLast(node); > node->misc.owner = data.preHeader; >- NodeFlags didExitForward = node->flags() & NodeExitsForward; >- node->clearFlags(NodeExitsForward); > node->codeOriginForExitTarget = data.preHeader->last()->codeOriginForExitTarget; > > // Modify the states at the end of the preHeader of the loop we hoisted to, >@@ -256,7 +253,6 @@ private: > RELEASE_ASSERT(!(node->flags() & NodeHasVarArgs)); > > nodeRef = m_graph.addNode(SpecNone, Phantom, node->codeOrigin, node->children); >- nodeRef->mergeFlags(didExitForward); > > return true; > } >Index: Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp (working copy) >@@ -38,15 +38,13 @@ MinifiedNode MinifiedNode::fromNode(Node > MinifiedNode result; > result.m_id = MinifiedID(node); > result.m_op = node->op(); >- if (hasChild(node->op())) >- result.m_childOrInfo = MinifiedID(node->child1().node()).m_id; >- else if (hasConstantNumber(node->op())) >- result.m_childOrInfo = node->constantNumber(); >+ if (hasConstantNumber(node->op())) >+ result.m_info = node->constantNumber(); > else if (hasWeakConstant(node->op())) >- result.m_childOrInfo = bitwise_cast<uintptr_t>(node->weakConstant()); >+ result.m_info = bitwise_cast<uintptr_t>(node->weakConstant()); > else { > ASSERT(node->op() == PhantomArguments); >- result.m_childOrInfo = 0; >+ result.m_info = 0; > } > return result; > } >Index: Source/JavaScriptCore/dfg/DFGMinifiedNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGMinifiedNode.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGMinifiedNode.h (working copy) >@@ -43,16 +43,9 @@ inline bool belongsInMinifiedGraph(NodeT > switch (type) { > case JSConstant: > case WeakJSConstant: >- case ValueToInt32: >- case Int32ToDouble: >- case UInt32ToNumber: >- case DoubleAsInt32: > case PhantomArguments: >- case Int52ToValue: >- case Int52ToDouble: > return true; > default: >- ASSERT(!permitsOSRBackwardRewiring(type) && !permitsOSRForwardRewiring(type)); > return false; > } > } >@@ -66,14 +59,6 @@ public: > MinifiedID id() const { return m_id; } > NodeType op() const { return m_op; } > >- bool hasChild1() const { return hasChild(m_op); } >- >- MinifiedID child1() const >- { >- ASSERT(hasChild(m_op)); >- return MinifiedID::fromBits(m_childOrInfo); >- } >- > bool hasConstant() const { return hasConstantNumber() || hasWeakConstant(); } > > bool hasConstantNumber() const { return hasConstantNumber(m_op); } >@@ -81,7 +66,7 @@ public: > unsigned constantNumber() const > { > ASSERT(hasConstantNumber(m_op)); >- return m_childOrInfo; >+ return m_info; > } > > bool hasWeakConstant() const { return hasWeakConstant(m_op); } >@@ -89,7 +74,7 @@ public: > JSCell* weakConstant() const > { > ASSERT(hasWeakConstant(m_op)); >- return bitwise_cast<JSCell*>(m_childOrInfo); >+ return bitwise_cast<JSCell*>(m_info); > } > > static MinifiedID getID(MinifiedNode* node) { return node->id(); } >@@ -99,20 +84,6 @@ public: > } > > private: >- static bool hasChild(NodeType type) >- { >- switch (type) { >- case ValueToInt32: >- case Int32ToDouble: >- case UInt32ToNumber: >- case DoubleAsInt32: >- case Int52ToDouble: >- case Int52ToValue: >- return true; >- default: >- return false; >- } >- } > static bool hasConstantNumber(NodeType type) > { > return type == JSConstant; >@@ -123,7 +94,7 @@ private: > } > > MinifiedID m_id; >- uintptr_t m_childOrInfo; // Nodes in the minified graph have only one child each. >+ uintptr_t m_info; > NodeType m_op; > }; > >Index: Source/JavaScriptCore/dfg/DFGNode.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGNode.cpp (working copy) >@@ -46,9 +46,6 @@ bool Node::hasVariableAccessData(Graph& > case GetLocal: > case GetArgument: > case SetLocal: >- case MovHint: >- case MovHintAndCheck: >- case ZombieHint: > case SetArgument: > case Flush: > case PhantomLocal: >Index: Source/JavaScriptCore/dfg/DFGNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGNode.h (working copy) >@@ -274,42 +274,24 @@ struct Node { > return filterFlags(~flags); > } > >- SpeculationDirection speculationDirection() >- { >- if (flags() & NodeExitsForward) >- return ForwardSpeculation; >- return BackwardSpeculation; >- } >- >- void setSpeculationDirection(SpeculationDirection direction) >- { >- switch (direction) { >- case ForwardSpeculation: >- mergeFlags(NodeExitsForward); >- return; >- case BackwardSpeculation: >- clearFlags(NodeExitsForward); >- return; >- } >- RELEASE_ASSERT_NOT_REACHED(); >- } >- > void setOpAndDefaultFlags(NodeType op) > { > m_op = op; > m_flags = defaultFlags(op); > } > >+ // FIXME: Get rid of this. > void setOpAndDefaultNonExitFlags(NodeType op) > { > ASSERT(!(m_flags & NodeHasVarArgs)); > setOpAndDefaultNonExitFlagsUnchecked(op); > } > >+ // FIXME: Get rid of this. > void setOpAndDefaultNonExitFlagsUnchecked(NodeType op) > { > m_op = op; >- m_flags = (defaultFlags(op) & ~NodeExitsForward) | (m_flags & NodeExitsForward); >+ m_flags = defaultFlags(op); > } > > void convertToPhantom() >@@ -531,9 +513,7 @@ struct Node { > bool containsMovHint() > { > switch (op()) { >- case SetLocal: > case MovHint: >- case MovHintAndCheck: > case ZombieHint: > return true; > default: >@@ -567,6 +547,8 @@ struct Node { > switch (op()) { > case GetLocalUnlinked: > case ExtractOSREntryLocal: >+ case MovHint: >+ case ZombieHint: > return true; > default: > return false; >@@ -1190,11 +1172,6 @@ struct Node { > case SetLocal: > case MovHint: > case ZombieHint: >- case MovHintAndCheck: >- case Int32ToDouble: >- case ValueToInt32: >- case UInt32ToNumber: >- case DoubleAsInt32: > case PhantomArguments: > return true; > case Phantom: >Index: Source/JavaScriptCore/dfg/DFGNodeFlags.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeFlags.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGNodeFlags.cpp (working copy) >@@ -96,9 +96,6 @@ void dumpNodeFlags(PrintStream& actualOu > if (!(flags & NodeDoesNotExit)) > out.print(comma, "CanExit"); > >- if (flags & NodeExitsForward) >- out.print(comma, "NodeExitsForward"); >- > CString string = out.toCString(); > if (!string.length()) > actualOut.print("<empty>"); >Index: Source/JavaScriptCore/dfg/DFGNodeFlags.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeFlags.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGNodeFlags.h (working copy) >@@ -68,9 +68,7 @@ namespace JSC { namespace DFG { > > #define NodeRelevantToOSR 0x4000 > >-#define NodeExitsForward 0x8000 >- >-#define NodeIsStaticConstant 0x10000 // Used only by the parser, to determine if a constant arose statically and hence could be folded at parse-time. >+#define NodeIsStaticConstant 0x8000 // Used only by the parser, to determine if a constant arose statically and hence could be folded at parse-time. > > typedef uint32_t NodeFlags; > >Index: Source/JavaScriptCore/dfg/DFGNodeType.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeType.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGNodeType.h (working copy) >@@ -57,8 +57,7 @@ namespace JSC { namespace DFG { > /* Any two nodes that are part of the same Phi graph will share the same */\ > /* VariableAccessData, and thus will share predictions. */\ > macro(GetLocal, NodeResultJS) \ >- macro(SetLocal, NodeExitsForward) \ >- macro(MovHintAndCheck, NodeMustGenerate | NodeExitsForward) \ >+ macro(SetLocal, 0) \ > macro(MovHint, NodeDoesNotExit) \ > macro(ZombieHint, NodeDoesNotExit) \ > macro(GetArgument, NodeResultJS | NodeMustGenerate) \ >@@ -318,80 +317,6 @@ inline NodeFlags defaultFlags(NodeType o > } > } > >-inline bool permitsOSRBackwardRewiring(NodeType op) >-{ >- switch (op) { >- case Identity: >- RELEASE_ASSERT_NOT_REACHED(); >- return true; >- case UInt32ToNumber: >- case Int52ToValue: >- case Int52ToDouble: >- // These are the only node where we do: >- // >- // b: UInt32ToNumber(@a) >- // c: SetLocal(@b) >- // >- // and then also have some uses of @a without Phantom'ing @b. >- return true; >- default: >- return false; >- } >-} >- >-// Returns the priority with which we should select the given node for forward >-// rewiring. Higher is better. Zero means that the node is not useful for rewiring. >-// By convention, we use 100 to mean that the node is totally equivalent to its >-// input with no information loss. >-inline unsigned forwardRewiringSelectionScore(NodeType op) >-{ >- switch (op) { >- case Identity: >- // We shouldn't see these by the time we get to OSR even though it clearly >- // is a perfect identity function. >- RELEASE_ASSERT_NOT_REACHED(); >- return 100; >- >- case DoubleAsInt32: >- // This speculates that the incoming double is convertible to an int32. So >- // its result is totally equivalent. >- return 100; >- >- case Int32ToDouble: >- // This converts an int32 to a double, but that loses a bit of information. >- // OTOH it's still an equivalent number. >- return 75; >- >- case UInt32ToNumber: >- // It's completely fine to use this for OSR exit, since the uint32 isn't >- // actually representable in bytecode. >- return 100; >- >- case ValueToInt32: >- // This loses information. Only use it if there are no better alternatives. >- return 25; >- >- case Int52ToValue: >- // Loses no information. It just boxes the value, which is what OSR wants >- // to do anyway. >- return 100; >- >- case Int52ToDouble: >- // This is like Int32ToDouble; we can use it because it gives a semantically >- // equivalent value but that value may be an int32 in a double, so we'd >- // rather not if we can avoid it. >- return 75; >- >- default: >- return 0; >- } >-} >- >-inline bool permitsOSRForwardRewiring(NodeType op) >-{ >- return forwardRewiringSelectionScore(op) > 0; >-} >- > } } // namespace JSC::DFG > > #endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (working copy) >@@ -103,10 +103,8 @@ public: > break; > } > >- case MovHint: >- case MovHintAndCheck: { >- VariableAccessData* variable = node->variableAccessData(); >- availability.operand(variable->local()) = >+ case MovHint: { >+ availability.operand(node->unlinkedLocal()) = > Availability(node->child1().node()); > break; > } >Index: Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp (working copy) >@@ -104,17 +104,9 @@ public: > m_graph, variable->prediction(), ExtractOSREntryLocal, codeOrigin, > OpInfo(variable->local().offset())); > >- // Create a MovHint. We can't use MovHint's directly at this stage of >- // compilation, so we cook one up by creating a new VariableAccessData >- // that isn't unified with any of the others. This ensures that this >- // SetLocal will turn into a MovHint and will not have any type checks. >- m_graph.m_variableAccessData.append( >- VariableAccessData(variable->local(), variable->isCaptured())); >- VariableAccessData* newVariable = &m_graph.m_variableAccessData.last(); >- Node* setLocal = newRoot->appendNode( >- m_graph, SpecNone, SetLocal, codeOrigin, OpInfo(newVariable), >+ newRoot->appendNode( >+ m_graph, SpecNone, MovHint, codeOrigin, OpInfo(variable->local().offset()), > Edge(locals[local])); >- setLocal->setSpeculationDirection(BackwardSpeculation); > } > for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) { > Node* previousHead = target->variablesAtHead.local(local); >@@ -122,9 +114,8 @@ public: > continue; > VariableAccessData* variable = previousHead->variableAccessData(); > Node* node = locals[local]; >- Node* setLocal = newRoot->appendNode( >+ newRoot->appendNode( > m_graph, SpecNone, SetLocal, codeOrigin, OpInfo(variable), Edge(node)); >- setLocal->setSpeculationDirection(BackwardSpeculation); > } > > newRoot->appendNode( >Index: Source/JavaScriptCore/dfg/DFGOSRExit.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExit.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGOSRExit.cpp (working copy) >@@ -68,26 +68,6 @@ void OSRExit::correctJump(LinkBuffer& li > m_patchableCodeOffset = linkBuffer.offsetOf(label); > } > >-void OSRExit::convertToForward(BasicBlock* block, Node* currentNode, unsigned nodeIndex, const ValueRecovery& valueRecovery) >-{ >- Node* node; >- Node* lastMovHint; >- if (!doSearchForForwardConversion(block, currentNode, nodeIndex, !!valueRecovery, node, lastMovHint)) >- return; >- >- ASSERT(node->codeOrigin != currentNode->codeOrigin); >- >- m_codeOrigin = node->codeOrigin; >- >- if (!valueRecovery) >- return; >- >- ASSERT(lastMovHint); >- ASSERT(lastMovHint->child1() == currentNode); >- m_valueRecoveryOverride = adoptRef( >- new ValueRecoveryOverride(lastMovHint->local(), valueRecovery)); >-} >- > } } // namespace JSC::DFG > > #endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGOSRExit.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExit.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGOSRExit.h (working copy) >@@ -101,8 +101,6 @@ struct OSRExit : public OSRExitBase { > MacroAssembler::Jump getPatchableCodeOffsetAsJump() const; > CodeLocationJump codeLocationForRepatch(CodeBlock*) const; > void correctJump(LinkBuffer&); >- >- void convertToForward(BasicBlock*, Node*, unsigned nodeIndex, const ValueRecovery&); > > unsigned m_streamIndex; > >Index: Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (working copy) >@@ -46,45 +46,6 @@ bool OSRExitBase::considerAddingAsFreque > FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind)); > } > >-bool OSRExitBase::doSearchForForwardConversion( >- BasicBlock* block, Node* currentNode, unsigned nodeIndex, bool hasValueRecovery, >- Node*& node, Node*& lastMovHint) >-{ >- // Check that either the current node is a SetLocal, or the preceding node was a >- // SetLocal with the same code origin, or that we've provided a valueRecovery. >- if (!ASSERT_DISABLED >- && !hasValueRecovery >- && !currentNode->containsMovHint()) { >- Node* setLocal = block->at(nodeIndex - 1); >- ASSERT_UNUSED(setLocal, setLocal->containsMovHint()); >- ASSERT_UNUSED(setLocal, setLocal->codeOriginForExitTarget == currentNode->codeOriginForExitTarget); >- } >- >- // Find the first node for the next bytecode instruction. Also track the last mov hint >- // on this node. >- unsigned indexInBlock = nodeIndex + 1; >- node = 0; >- lastMovHint = 0; >- for (;;) { >- if (indexInBlock == block->size()) { >- // This is an inline return. Give up and do a backwards speculation. This is safe >- // because an inline return has its own bytecode index and it's always safe to >- // reexecute that bytecode. >- ASSERT(node->op() == Jump); >- return false; >- } >- node = block->at(indexInBlock); >- if (node->containsMovHint() && node->child1() == currentNode) >- lastMovHint = node; >- if (node->codeOriginForExitTarget != currentNode->codeOriginForExitTarget) >- break; >- indexInBlock++; >- } >- >- ASSERT(node->codeOriginForExitTarget != currentNode->codeOriginForExitTarget); >- return true; >-} >- > } } // namespace JSC::DFG > > #endif // ENABLE(DFG_JIT) >Index: Source/JavaScriptCore/dfg/DFGOSRExitBase.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitBase.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGOSRExitBase.h (working copy) >@@ -64,11 +64,6 @@ struct OSRExitBase { > return false; > return considerAddingAsFrequentExitSiteSlow(profiledCodeBlock); > } >- >- // Returns true if the forward conversion is really needed. >- bool doSearchForForwardConversion( >- BasicBlock*, Node* currentNode, unsigned nodeIndex, bool hasValueRecovery, >- Node*& nextBCNode, Node*& lastMovHint); > > private: > bool considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock); >Index: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (working copy) >@@ -504,9 +504,6 @@ private: > case CheckArray: > case Arrayify: > case ArrayifyToStructure: >- case MovHint: >- case MovHintAndCheck: >- case ZombieHint: > case CheckTierUpInLoop: > case CheckTierUpAtReturn: > case CheckTierUpAndOSREnter: >@@ -585,6 +582,8 @@ private: > case FunctionReentryWatchpoint: > case TypedArrayWatchpoint: > case ConstantStoragePointer: >+ case MovHint: >+ case ZombieHint: > break; > > // This gets ignored because it already has a prediction. >Index: Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (working copy) >@@ -186,8 +186,8 @@ public: > // the value was already on the stack. > } else { > m_insertionSet.insertNode( >- 0, SpecNone, MovHint, CodeOrigin(), OpInfo(variable), >- Edge(node)); >+ 0, SpecNone, MovHint, CodeOrigin(), >+ OpInfo(variable->local().offset()), Edge(node)); > } > } > } >@@ -269,7 +269,7 @@ public: > // - GetLocal over uncaptured variables die and get replaced with references > // to the node specified by variablesAtHead. > // - SetLocal gets NodeMustGenerate if it's flushed, or turns into a >- // MovHint otherwise. >+ // Phantom otherwise. > // - Flush loses its children but remains, because we want to know when a > // flushed SetLocal's value is no longer needed. This also makes it simpler > // to reason about the format of a local, since we can just do a backwards >@@ -308,7 +308,7 @@ public: > if (variable->isCaptured() || m_flushedLocalOps.contains(node)) > node->mergeFlags(NodeMustGenerate); > else >- node->setOpAndDefaultFlags(MovHint); >+ node->convertToPhantom(); > node->misc.replacement = node->child1().node(); // Only for Upsilons. > break; > } >Index: Source/JavaScriptCore/dfg/DFGSafeToExecute.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSafeToExecute.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGSafeToExecute.h (working copy) >@@ -118,7 +118,6 @@ bool safeToExecute(AbstractStateType& st > case GetCallee: > case GetLocal: > case SetLocal: >- case MovHintAndCheck: > case MovHint: > case ZombieHint: > case GetArgument: >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (working copy) >@@ -1920,11 +1920,6 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >- case MovHintAndCheck: { >- compileMovHintAndCheck(node); >- break; >- } >- > case MovHint: > case ZombieHint: { > RELEASE_ASSERT_NOT_REACHED(); >@@ -1932,12 +1927,6 @@ void SpeculativeJIT::compile(Node* node) > } > > case SetLocal: { >- // SetLocal doubles as a hint as to where a node will be stored and >- // as a speculation point. So before we speculate make sure that we >- // know where the child of this node needs to go in the virtual >- // stack. >- compileMovHint(node); >- > switch (node->variableAccessData()->flushFormat()) { > case FlushedDouble: { > SpeculateDoubleOperand value(this, node->child1()); >@@ -1988,15 +1977,6 @@ void SpeculativeJIT::compile(Node* node) > m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal())); > m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->machineLocal())); > noResult(node); >- recordSetLocal(DataFormatJS); >- >- // If we're storing an arguments object that has been optimized away, >- // our variable event stream for OSR exit now reflects the optimized >- // value (JSValue()). On the slow path, we want an arguments object >- // instead. We add an additional move hint to show OSR exit that it >- // needs to reconstruct the arguments object. >- if (node->child1()->op() == PhantomArguments) >- compileMovHint(node); > break; > } > >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -2236,11 +2236,6 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >- case MovHintAndCheck: { >- compileMovHintAndCheck(node); >- break; >- } >- > case MovHint: > case ZombieHint: { > RELEASE_ASSERT_NOT_REACHED(); >@@ -2248,12 +2243,6 @@ void SpeculativeJIT::compile(Node* node) > } > > case SetLocal: { >- // SetLocal doubles as a hint as to where a node will be stored and >- // as a speculation point. So before we speculate make sure that we >- // know where the child of this node needs to go in the virtual >- // stack. >- compileMovHint(node); >- > switch (node->variableAccessData()->flushFormat()) { > case FlushedDouble: { > SpeculateDoubleOperand value(this, node->child1()); >@@ -2299,20 +2288,12 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >- case FlushedJSValue: { >+ case FlushedJSValue: >+ case FlushedArguments: { > JSValueOperand value(this, node->child1()); > m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal())); > noResult(node); >- > recordSetLocal(DataFormatJS); >- >- // If we're storing an arguments object that has been optimized away, >- // our variable event stream for OSR exit now reflects the optimized >- // value (JSValue()). On the slow path, we want an arguments object >- // instead. We add an additional move hint to show OSR exit that it >- // needs to reconstruct the arguments object. >- if (node->child1()->op() == PhantomArguments) >- compileMovHint(node); > break; > } > >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (working copy) >@@ -106,7 +106,7 @@ void SpeculativeJIT::emitAllocateJSArray > structure, numElements))); > } > >-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail) >+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail) > { > if (!m_compileOkay) > return; >@@ -115,7 +115,7 @@ void SpeculativeJIT::backwardSpeculation > m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size())); > } > >-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail) >+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail) > { > if (!m_compileOkay) > return; >@@ -124,22 +124,7 @@ void SpeculativeJIT::backwardSpeculation > m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size())); > } > >-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail) >-{ >- if (!m_compileOkay) >- return; >- backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail); >- if (m_speculationDirection == ForwardSpeculation) >- convertLastOSRExitToForward(); >-} >- >-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) >-{ >- ASSERT(m_isCheckingArgumentTypes || m_canExit); >- speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail); >-} >- >-OSRExitJumpPlaceholder SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node) >+OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node) > { > if (!m_compileOkay) > return OSRExitJumpPlaceholder(); >@@ -150,19 +135,16 @@ OSRExitJumpPlaceholder SpeculativeJIT::b > return OSRExitJumpPlaceholder(index); > } > >-OSRExitJumpPlaceholder SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse) >+OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse) > { > ASSERT(m_isCheckingArgumentTypes || m_canExit); >- return backwardSpeculationCheck(kind, jsValueSource, nodeUse.node()); >+ return speculationCheck(kind, jsValueSource, nodeUse.node()); > } > >-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail) >+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) > { >- if (!m_compileOkay) >- return; >- backwardSpeculationCheck(kind, jsValueSource, node, jumpsToFail); >- if (m_speculationDirection == ForwardSpeculation) >- convertLastOSRExitToForward(); >+ ASSERT(m_isCheckingArgumentTypes || m_canExit); >+ speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail); > } > > void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail) >@@ -171,7 +153,7 @@ void SpeculativeJIT::speculationCheck(Ex > speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail); > } > >-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) >+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) > { > if (!m_compileOkay) > return; >@@ -181,24 +163,10 @@ void SpeculativeJIT::backwardSpeculation > m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size(), recoveryIndex)); > } > >-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) >+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) > { > ASSERT(m_isCheckingArgumentTypes || m_canExit); >- backwardSpeculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery); >-} >- >-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) >-{ >- if (!m_compileOkay) >- return; >- backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail, recovery); >- if (m_speculationDirection == ForwardSpeculation) >- convertLastOSRExitToForward(); >-} >- >-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) >-{ >- speculationCheck(kind, jsValueSource, edge.node(), jumpToFail, recovery); >+ speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery); > } > > void SpeculativeJIT::emitInvalidationPoint(Node* node) >@@ -206,7 +174,6 @@ void SpeculativeJIT::emitInvalidationPoi > if (!m_compileOkay) > return; > ASSERT(m_canExit); >- ASSERT(m_speculationDirection == BackwardSpeculation); > OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList()); > m_jit.jitCode()->appendOSRExit(OSRExit( > UncountableInvalidation, JSValueSource(), >@@ -217,26 +184,6 @@ void SpeculativeJIT::emitInvalidationPoi > noResult(node); > } > >-void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery& valueRecovery) >-{ >- m_jit.jitCode()->lastOSRExit().convertToForward( >- m_block, m_currentNode, m_indexInBlock, valueRecovery); >-} >- >-void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) >-{ >- ASSERT(m_isCheckingArgumentTypes || m_canExit); >- backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail); >- convertLastOSRExitToForward(valueRecovery); >-} >- >-void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery) >-{ >- ASSERT(m_isCheckingArgumentTypes || m_canExit); >- backwardSpeculationCheck(kind, jsValueSource, node, jumpsToFail); >- convertLastOSRExitToForward(valueRecovery); >-} >- > void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node) > { > ASSERT(m_isCheckingArgumentTypes || m_canExit); >@@ -252,24 +199,11 @@ void SpeculativeJIT::terminateSpeculativ > terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node()); > } > >-void SpeculativeJIT::backwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail) >+void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail) > { > ASSERT(needsTypeCheck(edge, typesPassedThrough)); > m_interpreter.filter(edge, typesPassedThrough); >- backwardSpeculationCheck(BadType, source, edge.node(), jumpToFail); >-} >- >-void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail) >-{ >- backwardTypeCheck(source, edge, typesPassedThrough, jumpToFail); >- if (m_speculationDirection == ForwardSpeculation) >- convertLastOSRExitToForward(); >-} >- >-void SpeculativeJIT::forwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) >-{ >- backwardTypeCheck(source, edge, typesPassedThrough, jumpToFail); >- convertLastOSRExitToForward(valueRecovery); >+ speculationCheck(BadType, source, edge.node(), jumpToFail); > } > > RegisterSet SpeculativeJIT::usedRegisters() >@@ -1380,14 +1314,7 @@ void SpeculativeJIT::compileMovHint(Node > Node* child = node->child1().node(); > noticeOSRBirth(child); > >- m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->local())); >-} >- >-void SpeculativeJIT::compileMovHintAndCheck(Node* node) >-{ >- compileMovHint(node); >- speculate(node, node->child1()); >- noResult(node); >+ m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->unlinkedLocal())); > } > > void SpeculativeJIT::bail() >@@ -1436,9 +1363,7 @@ void SpeculativeJIT::compileCurrentBlock > > VariableAccessData* variable = node->variableAccessData(); > DataFormat format; >- if (variable->isArgumentsAlias()) >- format = DataFormatArguments; >- else if (!node->refCount()) >+ if (!node->refCount()) > continue; // No need to record dead SetLocal's. > else > format = dataFormatFor(variable->flushFormat()); >@@ -1484,7 +1409,7 @@ void SpeculativeJIT::compileCurrentBlock > break; > > case ZombieHint: { >- recordSetLocal(DataFormatDead); >+ recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead); > break; > } > >@@ -1503,8 +1428,6 @@ void SpeculativeJIT::compileCurrentBlock > dataLog("\n"); > } > >- m_speculationDirection = (m_currentNode->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation; >- > compile(m_currentNode); > > #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) >@@ -1542,18 +1465,19 @@ void SpeculativeJIT::checkArgumentTypes( > { > ASSERT(!m_currentNode); > m_isCheckingArgumentTypes = true; >- m_speculationDirection = BackwardSpeculation; > m_codeOriginForExitTarget = CodeOrigin(0); > m_codeOriginForExitProfile = CodeOrigin(0); > > for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) { > Node* node = m_jit.graph().m_arguments[i]; >- ASSERT(node->op() == SetArgument); >- if (!node->shouldGenerate()) { >+ if (!node) { > // The argument is dead. We don't do any checks for such arguments. > continue; > } > >+ ASSERT(node->op() == SetArgument); >+ ASSERT(node->shouldGenerate()); >+ > VariableAccessData* variableAccessData = node->variableAccessData(); > FlushFormat format = variableAccessData->flushFormat(); > >@@ -2169,16 +2093,9 @@ void SpeculativeJIT::compileInt32ToDoubl > MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); > > if (needsTypeCheck(node->child1(), SpecFullNumber)) { >- if (node->flags() & NodeExitsForward) { >- forwardTypeCheck( >- JSValueRegs(op1GPR), node->child1(), SpecFullNumber, >- m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister), >- ValueRecovery::inGPR(op1GPR, DataFormatJS)); >- } else { >- backwardTypeCheck( >- JSValueRegs(op1GPR), node->child1(), SpecFullNumber, >- m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); >- } >+ typeCheck( >+ JSValueRegs(op1GPR), node->child1(), SpecFullNumber, >+ m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); > } > > m_jit.move(op1GPR, tempGPR); >@@ -2200,16 +2117,9 @@ void SpeculativeJIT::compileInt32ToDoubl > MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); > > if (needsTypeCheck(node->child1(), SpecFullNumber)) { >- if (node->flags() & NodeExitsForward) { >- forwardTypeCheck( >- JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, >- m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)), >- ValueRecovery::inPair(op1TagGPR, op1PayloadGPR)); >- } else { >- backwardTypeCheck( >- JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, >- m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); >- } >+ typeCheck( >+ JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, >+ m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); > } > > unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR); >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (working copy) >@@ -2143,43 +2143,28 @@ public: > JITCompiler::Jump convertToDouble(JSValueOperand&, FPRReg result); > #endif > >- // Add a backward speculation check. >- void backwardSpeculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail); >- void backwardSpeculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail); >- >- // Add a speculation check without additional recovery. >+ // Add a speculation check. > void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail); >- void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail); >- // Add a speculation check without additional recovery, and with a promise to supply a jump later. >- OSRExitJumpPlaceholder backwardSpeculationCheck(ExitKind, JSValueSource, Node*); >- OSRExitJumpPlaceholder backwardSpeculationCheck(ExitKind, JSValueSource, Edge); >- // Add a set of speculation checks without additional recovery. > void speculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail); >+ >+ // Add a speculation check without additional recovery, and with a promise to supply a jump later. >+ OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Node*); >+ OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Edge); >+ void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail); > void speculationCheck(ExitKind, JSValueSource, Edge, const MacroAssembler::JumpList& jumpsToFail); > // Add a speculation check with additional recovery. >- void backwardSpeculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); >- void backwardSpeculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); >+ void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); >+ void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); > > void emitInvalidationPoint(Node*); > >- // It is generally a good idea to not use this directly. >- void convertLastOSRExitToForward(const ValueRecovery& = ValueRecovery()); >- >- // Note: not specifying the valueRecovery argument (leaving it as ValueRecovery()) implies >- // that you've ensured that there exists a MovHint prior to your use of forwardSpeculationCheck(). >- void forwardSpeculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const ValueRecovery& = ValueRecovery()); >- void forwardSpeculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& = ValueRecovery()); >- void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); >- void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&); > // Called when we statically determine that a speculation will fail. > void terminateSpeculativeExecution(ExitKind, JSValueRegs, Node*); > void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge); > > // Helpers for performing type checks on an edge stored in the given registers. > bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_interpreter.needsTypeCheck(edge, typesPassedThrough); } >- void backwardTypeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail); > void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail); >- void forwardTypeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery&); > > void speculateInt32(Edge); > void speculateMachineInt(Edge); >@@ -2252,7 +2237,6 @@ public: > // The current node being generated. > BasicBlock* m_block; > Node* m_currentNode; >- SpeculationDirection m_speculationDirection; > bool m_canExit; > unsigned m_indexInBlock; > // Virtual and physical register maps. >Index: Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (working copy) >@@ -163,33 +163,22 @@ public: > if (!iter->value.m_structure && !iter->value.m_arrayModeIsValid) > break; > >- // First insert a dead SetLocal to tell OSR that the child's value should >- // be dropped into this bytecode variable if the CheckStructure decides >- // to exit. >- > CodeOrigin codeOrigin = node->codeOrigin; > Edge child1 = node->child1(); > >- insertionSet.insertNode( >- indexInBlock, SpecNone, SetLocal, codeOrigin, OpInfo(variable), child1); >- >- // Use NodeExitsForward to indicate that we should exit to the next >- // bytecode instruction rather than reexecuting the current one. >- Node* newNode = 0; > if (iter->value.m_structure) { >- newNode = insertionSet.insertNode( >+ insertionSet.insertNode( > indexInBlock, SpecNone, CheckStructure, codeOrigin, > OpInfo(m_graph.addStructureSet(iter->value.m_structure)), > Edge(child1.node(), CellUse)); > } else if (iter->value.m_arrayModeIsValid) { > ASSERT(iter->value.m_arrayModeHoistingOkay); >- newNode = insertionSet.insertNode( >+ insertionSet.insertNode( > indexInBlock, SpecNone, CheckArray, codeOrigin, > OpInfo(iter->value.m_arrayMode.asWord()), > Edge(child1.node(), CellUse)); > } else > RELEASE_ASSERT_NOT_REACHED(); >- newNode->mergeFlags(NodeExitsForward); > changed = true; > break; > } >@@ -228,9 +217,6 @@ private: > switch (node->op()) { > case CheckStructure: > case StructureTransitionWatchpoint: { >- // We currently rely on the fact that we're the only ones who would >- // insert these nodes with NodeExitsForward. >- RELEASE_ASSERT(!(node->flags() & NodeExitsForward)); > Node* child = node->child1().node(); > if (child->op() != GetLocal) > break; >@@ -329,9 +315,6 @@ private: > Node* node = block->at(indexInBlock); > switch (node->op()) { > case CheckArray: { >- // We currently rely on the fact that we're the only ones who would >- // insert these nodes with NodeExitsForward. >- RELEASE_ASSERT(!(node->flags() & NodeExitsForward)); > Node* child = node->child1().node(); > if (child->op() != GetLocal) > break; >Index: Source/JavaScriptCore/dfg/DFGValidate.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGValidate.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGValidate.cpp (working copy) >@@ -245,10 +245,7 @@ private: > edge->op() == SetLocal > || edge->op() == SetArgument > || edge->op() == Flush >- || edge->op() == Phi >- || edge->op() == ZombieHint >- || edge->op() == MovHint >- || edge->op() == MovHintAndCheck); >+ || edge->op() == Phi); > > if (phisInThisBlock.contains(edge.node())) > continue; >@@ -257,9 +254,6 @@ private: > VALIDATE( > (node, edge), > edge->op() == SetLocal >- || edge->op() == ZombieHint >- || edge->op() == MovHint >- || edge->op() == MovHintAndCheck > || edge->op() == SetArgument > || edge->op() == Flush); > >@@ -292,9 +286,6 @@ private: > VALIDATE( > (local, block->predecessors[k], prevNode), > prevNode->op() == SetLocal >- || prevNode->op() == MovHint >- || prevNode->op() == MovHintAndCheck >- || prevNode->op() == ZombieHint > || prevNode->op() == SetArgument > || prevNode->op() == Phi); > if (prevNode == edge.node()) { >Index: Source/JavaScriptCore/dfg/DFGValueSource.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGValueSource.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGValueSource.h (working copy) >@@ -122,7 +122,7 @@ public: > explicit ValueSource(ValueSourceKind valueSourceKind) > : m_kind(valueSourceKind) > { >- ASSERT(kind() == ArgumentsSource || kind() == SourceIsDead); >+ ASSERT(kind() == ArgumentsSource || kind() == SourceIsDead || kind() == ArgumentsSource); > } > > explicit ValueSource(MinifiedID id) >@@ -159,6 +159,8 @@ public: > return ValueSource(CellInJSStack, where); > case FlushedBoolean: > return ValueSource(BooleanInJSStack, where); >+ case FlushedArguments: >+ return ValueSource(ArgumentsSource); > } > RELEASE_ASSERT_NOT_REACHED(); > return ValueSource(); >Index: Source/JavaScriptCore/dfg/DFGVariableAccessData.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGVariableAccessData.h (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGVariableAccessData.h (working copy) >@@ -328,6 +328,9 @@ public: > { > ASSERT(find() == this); > >+ if (isArgumentsAlias()) >+ return FlushedArguments; >+ > if (!shouldUnboxIfPossible()) > return FlushedJSValue; > >Index: Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (revision 161036) >+++ Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (working copy) >@@ -192,70 +192,8 @@ void VariableEventStream::reconstruct( > > MinifiedGenerationInfo info = generationInfos.get(source.id()); > if (info.format == DataFormatNone) { >- // Try to see if there is an alternate node that would contain the value we want. >- // >- // Backward rewiring refers to: >- // >- // a: Something(...) >- // b: Id(@a) // some identity function >- // c: SetLocal(@b) >- // >- // Where we find @b being dead, but @a is still alive. >- // >- // Forward rewiring refers to: >- // >- // a: Something(...) >- // b: SetLocal(@a) >- // c: Id(@a) // some identity function >- // >- // Where we find @a being dead, but @b is still alive. >- >- bool found = false; >- >- if (node && permitsOSRBackwardRewiring(node->op())) { >- MinifiedID id = node->child1(); >- if (tryToSetConstantRecovery(valueRecoveries[i], codeBlock, graph.at(id))) >- continue; >- info = generationInfos.get(id); >- if (info.format != DataFormatNone) >- found = true; >- } >- >- if (!found) { >- MinifiedID bestID; >- unsigned bestScore = 0; >- >- HashMap<MinifiedID, MinifiedGenerationInfo>::iterator iter = generationInfos.begin(); >- HashMap<MinifiedID, MinifiedGenerationInfo>::iterator end = generationInfos.end(); >- for (; iter != end; ++iter) { >- MinifiedID id = iter->key; >- node = graph.at(id); >- if (!node) >- continue; >- if (!node->hasChild1()) >- continue; >- if (node->child1() != source.id()) >- continue; >- if (iter->value.format == DataFormatNone) >- continue; >- unsigned myScore = forwardRewiringSelectionScore(node->op()); >- if (myScore <= bestScore) >- continue; >- bestID = id; >- bestScore = myScore; >- } >- >- if (!!bestID) { >- info = generationInfos.get(bestID); >- ASSERT(info.format != DataFormatNone); >- found = true; >- } >- } >- >- if (!found) { >- valueRecoveries[i] = ValueRecovery::constant(jsUndefined()); >- continue; >- } >+ valueRecoveries[i] = ValueRecovery::constant(jsUndefined()); >+ continue; > } > > ASSERT(info.format != DataFormatNone); >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (revision 161036) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -4209,6 +4209,12 @@ private: > case FlushedDouble: > exit.m_values[i] = ExitValue::inJSStackAsDouble(flush.virtualRegister()); > break; >+ >+ case FlushedArguments: >+ // FIXME: implement PhantomArguments. >+ // https://bugs.webkit.org/show_bug.cgi?id=113986 >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; > } > } >
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 125531
:
219944
|
219968
|
219974
|
219998
|
220006
|
220009
|
220011
|
220033
|
220074
|
220080