Changeset 246420 in webkit
- Timestamp:
- Jun 13, 2019, 7:30:42 PM (7 years ago)
- Location:
- branches/safari-607-branch
- Files:
-
- 1 added
- 3 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/argument-elimination-inline-rest-past-kill.js (added)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-607-branch/JSTests/ChangeLog
r246379 r246420 1 2019-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 1 17 2019-06-12 Null <null@apple.com> 2 18 -
branches/safari-607-branch/Source/JavaScriptCore/ChangeLog
r246380 r246420 1 2019-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 1 33 2019-06-12 Null <null@apple.com> 2 34 -
branches/safari-607-branch/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp
r246379 r246420 503 503 } 504 504 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 505 532 for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { 506 533 // Stop if we've already removed all candidates. … … 525 552 return; 526 553 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]; 537 559 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)) { 549 587 isClobberedByBlock = true; 550 588 break; … … 552 590 } 553 591 } 554 } else {555 // We don't include the ArgumentCount or Callee in this case because we can be556 // 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 clobber569 // 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;583 592 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; 597 595 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) { 599 600 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"); 601 602 transitivelyRemoveCandidate(candidate); 602 603 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 } 603 632 } 604 633 }
Note:
See TracChangeset
for help on using the changeset viewer.