Changeset 254349 in webkit for trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
- Timestamp:
- Jan 10, 2020, 10:49:51 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
r254252 r254349 1 1 /* 2 * Copyright (C) 2015-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2015-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 403 403 { 404 404 auto iter = m_pointers.find(node); 405 ASSERT(iter == m_pointers.end() || m_allocations.contains(iter->value));405 ASSERT(iter == m_pointers.end() || (!iter->value || m_allocations.contains(iter->value))); 406 406 return iter == m_pointers.end() ? nullptr : iter->value; 407 407 } … … 500 500 } 501 501 502 mergePointerSets(m_pointers, other.m_pointers, toEscape); 502 { 503 // This works because we won't collect all pointers until all of our predecessors 504 // merge their pointer sets with ours. That allows us to see the full state of the 505 // world during our fixpoint analysis. Once we have the full set of pointers, we 506 // only mark pointers to TOP, so we will eventually converge. 507 for (auto entry : other.m_pointers) { 508 auto addResult = m_pointers.add(entry.key, entry.value); 509 if (addResult.iterator->value != entry.value) { 510 if (addResult.iterator->value) { 511 toEscape.addVoid(addResult.iterator->value); 512 addResult.iterator->value = nullptr; 513 } 514 if (entry.value) 515 toEscape.addVoid(entry.value); 516 } 517 } 518 // This allows us to rule out pointers for graphs like this: 519 // bb#0 520 // branch #1, #2 521 // #1: 522 // x = pointer A 523 // jump #3 524 // #2: 525 // y = pointer B 526 // jump #3 527 // #3: 528 // ... 529 // 530 // When we merge state at #3, we'll very likely prune away the x and y pointer, 531 // since they're not live. But if they do happen to make it to this merge function, when 532 // #3 merges with #2 and #1, it'll eventually rule out x and y as not existing 533 // in the other, and therefore not existing in #3, which is the desired behavior. 534 // 535 // This also is necessary for a graph like this: 536 // #0 537 // o = {} 538 // o2 = {} 539 // jump #1 540 // 541 // #1 542 // o.f = o2 543 // effects() 544 // x = o.f 545 // escape(o) 546 // branch #2, #1 547 // 548 // #2 549 // x cannot be o2 here, it has to be TOP 550 // ... 551 // 552 // On the first fixpoint iteration, we might think that x is o2 at the head 553 // of #2. However, when we fixpoint our analysis, we determine that o gets 554 // escaped. This means that when we fixpoint, x will eventually not be a pointer. 555 // When we merge again here, we'll notice and mark o2 as escaped. 556 for (auto& entry : m_pointers) { 557 if (!other.m_pointers.contains(entry.key)) { 558 if (entry.value) { 559 toEscape.addVoid(entry.value); 560 entry.value = nullptr; 561 ASSERT(!m_pointers.find(entry.key)->value); 562 } 563 } 564 } 565 } 503 566 504 567 for (Node* identifier : toEscape) … … 535 598 // Pointers should point to an actual allocation 536 599 for (const auto& entry : m_pointers) { 537 ASSERT_UNUSED(entry, entry.value);538 ASSERT(m_allocations.contains(entry.value));600 if (entry.value) 601 ASSERT(m_allocations.contains(entry.value)); 539 602 } 540 603 … … 566 629 } 567 630 568 const HashMap<Node*, Node*>& pointers() const569 {570 return m_pointers;571 }572 573 631 void dump(PrintStream& out) const 574 632 { … … 577 635 out.print(" #", entry.key, ": ", entry.value, "\n"); 578 636 out.print(" Pointers:\n"); 579 for (const auto& entry : m_pointers) 580 out.print(" ", entry.key, " => #", entry.value, "\n"); 637 for (const auto& entry : m_pointers) { 638 out.print(" ", entry.key, " => #"); 639 if (entry.value) 640 out.print(entry.value, "\n"); 641 else 642 out.print("TOP\n"); 643 } 581 644 } 582 645 … … 672 735 { 673 736 NodeSet reachable; 674 for (const auto& entry : m_pointers) 675 reachable.addVoid(entry.value); 737 for (const auto& entry : m_pointers) { 738 if (entry.value) 739 reachable.addVoid(entry.value); 740 } 676 741 677 742 // Repeatedly mark as reachable allocations in fields of other … … 811 876 // a live allocation. 812 877 // 813 // This means we can accidental y leak non-dominating878 // This means we can accidentally leak non-dominating 814 879 // nodes into the successor. However, due to the 815 880 // non-dominance property, we are guaranteed that the … … 820 885 m_heap.pruneByLiveness(m_combinedLiveness.liveAtTail[block]); 821 886 822 for (BasicBlock* successorBlock : block->successors()) 887 for (BasicBlock* successorBlock : block->successors()) { 888 // FIXME: Maybe we should: 889 // 1. Store the liveness pruned heap as part of m_heapAtTail 890 // 2. Move this code above where we make block merge with 891 // its predecessors before walking the block forward. 892 // https://bugs.webkit.org/show_bug.cgi?id=206041 893 LocalHeap heap = m_heapAtHead[successorBlock]; 823 894 m_heapAtHead[successorBlock].merge(m_heap); 895 if (heap != m_heapAtHead[successorBlock]) 896 changed = true; 897 } 824 898 } 825 899 } while (changed);
Note:
See TracChangeset
for help on using the changeset viewer.