⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 246420 in webkit


Ignore:
Timestamp:
Jun 13, 2019, 7:30:42 PM (7 years ago)
Author:
Kocsen Chung
Message:

Apply patch. rdar://problem/51656844

Location:
branches/safari-607-branch
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-607-branch/JSTests/ChangeLog

    r246379 r246420  
     12019-06-13  Kocsen Chung  <kocsen_chung@apple.com>
     2
     3        Apply patch. rdar://problem/51656844
     4
     5    2019-06-13  Tadeu Zagallo  <tzagallo@apple.com>
     6
     7            Argument elimination should check transitive dependents for interference
     8            https://bugs.webkit.org/show_bug.cgi?id=198520
     9            <rdar://problem/50863343>
     10
     11            Reviewed by Filip Pizlo.
     12
     13            * stress/argument-elimination-inline-rest-past-kill.js: Added.
     14            (f2):
     15            (f3):
     16
    1172019-06-12  Null  <null@apple.com>
    218
  • branches/safari-607-branch/Source/JavaScriptCore/ChangeLog

    r246380 r246420  
     12019-06-13  Kocsen Chung  <kocsen_chung@apple.com>
     2
     3        Apply patch. rdar://problem/51656844
     4
     5    2019-06-13  Tadeu Zagallo  <tzagallo@apple.com>
     6
     7            Argument elimination should check transitive dependents for interference
     8            https://bugs.webkit.org/show_bug.cgi?id=198520
     9            <rdar://problem/50863343>
     10
     11            Reviewed by Filip Pizlo.
     12
     13            Consider the following program:
     14
     15                a: CreateRest
     16                -->
     17                    b: CreateRest
     18                <--
     19                c: Spread(@a)
     20                d: Spread(@b)
     21                e: NewArrayWithSpread(@a, @b)
     22                f: KillStack(locX)
     23                g: LoadVarargs(@e)
     24
     25            Suppose @b reads locX, then we cannot transform @e to PhantomNewArraySpread, since that would
     26            move the stack access from @b into @g, and that stack location is no longer valid at that point.
     27
     28            We fix that by computing a set of all inline call frames that any argument elimination candidate
     29            depends on and checking each of them for interference in `eliminateCandidatesThatInterfere`.
     30
     31            * dfg/DFGArgumentsEliminationPhase.cpp:
     32
    1332019-06-12  Null  <null@apple.com>
    234
  • branches/safari-607-branch/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp

    r246379 r246420  
    503503        }
    504504       
     505        using InlineCallFrames = HashSet<InlineCallFrame*, WTF::DefaultHash<InlineCallFrame*>::Hash, WTF::NullableHashTraits<InlineCallFrame*>>;
     506        using InlineCallFramesForCanditates = HashMap<Node*, InlineCallFrames>;
     507        InlineCallFramesForCanditates inlineCallFramesForCandidate;
     508        auto forEachDependentNode = recursableLambda([&](auto self, Node* node, const auto& functor) -> void {
     509            functor(node);
     510
     511            if (node->op() == Spread) {
     512                self(node->child1().node(), functor);
     513                return;
     514            }
     515
     516            if (node->op() == NewArrayWithSpread) {
     517                BitVector* bitVector = node->bitVector();
     518                for (unsigned i = node->numChildren(); i--; ) {
     519                    if (bitVector->get(i))
     520                        self(m_graph.varArgChild(node, i).node(), functor);
     521                }
     522                return;
     523            }
     524        });
     525        for (Node* candidate : m_candidates) {
     526            auto& set = inlineCallFramesForCandidate.add(candidate, InlineCallFrames()).iterator->value;
     527            forEachDependentNode(candidate, [&](Node* dependent) {
     528                set.add(dependent->origin.semantic.inlineCallFrame);
     529            });
     530        }
     531
    505532        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
    506533            // Stop if we've already removed all candidates.
     
    525552                        return;
    526553                   
    527                     // Check if this block has any clobbers that affect this candidate. This is a fairly
    528                     // fast check.
    529                     bool isClobberedByBlock = false;
    530                     Operands<bool>& clobberedByThisBlock = clobberedByBlock[block];
    531                    
    532                     if (InlineCallFrame* inlineCallFrame = candidate->origin.semantic.inlineCallFrame) {
    533                         if (inlineCallFrame->isVarargs()) {
    534                             isClobberedByBlock |= clobberedByThisBlock.operand(
    535                                 inlineCallFrame->stackOffset + CallFrameSlot::argumentCount);
    536                         }
     554                    for (InlineCallFrame* inlineCallFrame : inlineCallFramesForCandidate.get(candidate)) {
     555                        // Check if this block has any clobbers that affect this candidate. This is a fairly
     556                        // fast check.
     557                        bool isClobberedByBlock = false;
     558                        Operands<bool>& clobberedByThisBlock = clobberedByBlock[block];
    537559                       
    538                         if (!isClobberedByBlock || inlineCallFrame->isClosureCall) {
    539                             isClobberedByBlock |= clobberedByThisBlock.operand(
    540                                 inlineCallFrame->stackOffset + CallFrameSlot::callee);
    541                         }
    542                        
    543                         if (!isClobberedByBlock) {
    544                             for (unsigned i = 0; i < inlineCallFrame->argumentCountIncludingThis - 1; ++i) {
    545                                 VirtualRegister reg =
    546                                     VirtualRegister(inlineCallFrame->stackOffset) +
    547                                     CallFrame::argumentOffset(i);
    548                                 if (clobberedByThisBlock.operand(reg)) {
     560                        if (inlineCallFrame) {
     561                            if (inlineCallFrame->isVarargs()) {
     562                                isClobberedByBlock |= clobberedByThisBlock.operand(
     563                                    inlineCallFrame->stackOffset + CallFrameSlot::argumentCount);
     564                            }
     565
     566                            if (!isClobberedByBlock || inlineCallFrame->isClosureCall) {
     567                                isClobberedByBlock |= clobberedByThisBlock.operand(
     568                                    inlineCallFrame->stackOffset + CallFrameSlot::callee);
     569                            }
     570
     571                            if (!isClobberedByBlock) {
     572                                for (unsigned i = 0; i < inlineCallFrame->argumentCountIncludingThis - 1; ++i) {
     573                                    VirtualRegister reg =
     574                                        VirtualRegister(inlineCallFrame->stackOffset) +
     575                                        CallFrame::argumentOffset(i);
     576                                    if (clobberedByThisBlock.operand(reg)) {
     577                                        isClobberedByBlock = true;
     578                                        break;
     579                                    }
     580                                }
     581                            }
     582                        } else {
     583                            // We don't include the ArgumentCount or Callee in this case because we can be
     584                            // damn sure that this won't be clobbered.
     585                            for (unsigned i = 1; i < static_cast<unsigned>(codeBlock()->numParameters()); ++i) {
     586                                if (clobberedByThisBlock.argument(i)) {
    549587                                    isClobberedByBlock = true;
    550588                                    break;
     
    552590                            }
    553591                        }
    554                     } else {
    555                         // We don't include the ArgumentCount or Callee in this case because we can be
    556                         // damn sure that this won't be clobbered.
    557                         for (unsigned i = 1; i < static_cast<unsigned>(codeBlock()->numParameters()); ++i) {
    558                             if (clobberedByThisBlock.argument(i)) {
    559                                 isClobberedByBlock = true;
    560                                 break;
    561                             }
    562                         }
    563                     }
    564                    
    565                     if (!isClobberedByBlock)
    566                         return;
    567                    
    568                     // Check if we can immediately eliminate this candidate. If the block has a clobber
    569                     // for this arguments allocation, and we'd have to examine every node in the block,
    570                     // then we can just eliminate the candidate.
    571                     if (nodeIndex == block->size() && candidate->owner != block) {
    572                         if (DFGArgumentsEliminationPhaseInternal::verbose)
    573                             dataLog("eliminating candidate: ", candidate, " because it is clobbered by: ", block->at(nodeIndex), "\n");
    574                         transitivelyRemoveCandidate(candidate);
    575                         return;
    576                     }
    577                    
    578                     // This loop considers all nodes up to the nodeIndex, excluding the nodeIndex.
    579                     while (nodeIndex--) {
    580                         Node* node = block->at(nodeIndex);
    581                         if (node == candidate)
    582                             break;
    583592                       
    584                         bool found = false;
    585                         clobberize(
    586                             m_graph, node, NoOpClobberize(),
    587                             [&] (AbstractHeap heap) {
    588                                 if (heap.kind() == Stack && !heap.payload().isTop()) {
    589                                     if (argumentsInvolveStackSlot(candidate, VirtualRegister(heap.payload().value32())))
    590                                         found = true;
    591                                     return;
    592                                 }
    593                                 if (heap.overlaps(Stack))
    594                                     found = true;
    595                             },
    596                             NoOpClobberize());
     593                        if (!isClobberedByBlock)
     594                            continue;
    597595                       
    598                         if (found) {
     596                        // Check if we can immediately eliminate this candidate. If the block has a clobber
     597                        // for this arguments allocation, and we'd have to examine every node in the block,
     598                        // then we can just eliminate the candidate.
     599                        if (nodeIndex == block->size() && candidate->owner != block) {
    599600                            if (DFGArgumentsEliminationPhaseInternal::verbose)
    600                                 dataLog("eliminating candidate: ", candidate, " because it is clobbered by ", block->at(nodeIndex), "\n");
     601                                dataLog("eliminating candidate: ", candidate, " because it is clobbered by: ", block->at(nodeIndex), "\n");
    601602                            transitivelyRemoveCandidate(candidate);
    602603                            return;
     604                        }
     605
     606                        // This loop considers all nodes up to the nodeIndex, excluding the nodeIndex.
     607                        while (nodeIndex--) {
     608                            Node* node = block->at(nodeIndex);
     609                            if (node == candidate)
     610                                break;
     611
     612                            bool found = false;
     613                            clobberize(
     614                                m_graph, node, NoOpClobberize(),
     615                                [&] (AbstractHeap heap) {
     616                                    if (heap.kind() == Stack && !heap.payload().isTop()) {
     617                                        if (argumentsInvolveStackSlot(inlineCallFrame, VirtualRegister(heap.payload().value32())))
     618                                            found = true;
     619                                        return;
     620                                    }
     621                                    if (heap.overlaps(Stack))
     622                                        found = true;
     623                                },
     624                                NoOpClobberize());
     625
     626                            if (found) {
     627                                if (DFGArgumentsEliminationPhaseInternal::verbose)
     628                                    dataLog("eliminating candidate: ", candidate, " because it is clobbered by ", block->at(nodeIndex), "\n");
     629                                transitivelyRemoveCandidate(candidate);
     630                                return;
     631                            }
    603632                        }
    604633                    }
Note: See TracChangeset for help on using the changeset viewer.