JSTests:
Object allocation sinking is missing PutHint for allocations unreachable in the graph
https://bugs.webkit.org/show_bug.cgi?id=203799
<rdar://problem/56852162>

Reviewed by Saam Barati.

* stress/allocation-sinking-puthint-control-flow-2.js: Added.
(f.handler.construct):
(f):

Source/JavaScriptCore:
Object allocation sinking is missing PutHint for sunken allocations
https://bugs.webkit.org/show_bug.cgi?id=203799
<rdar://problem/56852162>

Reviewed by Saam Barati.

Consider the following graph:

    Block #0:
      1: PhantomCreateActivation()
      2: PhantomNewFunction()
      PutHint(@2, @1, FunctionActivationPLoc)
      Branch(#1, #2)

    Block #1:
      3: MaterializeCreateActivation()
      PutHint(@2, @3, FunctionActivationPLoc)
      Upsilon(@3, ^5)
      Jump(#3)

    Block #2:
      4: MaterializeCreateActivation()
      PutHint(@2, @4, FunctionActivationPLoc)
      Upsilon(@4, ^5)
      Jump(#3)

    Block #3:
      5: Phi()
      ExitOK()

On Block #3, we need to emit a PutHint after the Phi, since we might exit after it. However,
object allocation sinking skipped this Phi because it was checking whether the base of the
location that caused us to create this Phi (@2) was live, but it's dead in the graph (there
are no pointers to it).  The issue is that, even though there are no pointers to the base, the
location `PromotedHeapLocation(@2, FunctionActivationPLoc)` is still live, so we should PutHint
to it. We fix it by checking for liveness of the location rather than its base.

* dfg/DFGObjectAllocationSinkingPhase.cpp:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254725 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog
index 8f4f3a9..7f91d14 100644
--- a/JSTests/ChangeLog
+++ b/JSTests/ChangeLog
@@ -1,3 +1,15 @@
+2020-01-16  Tadeu Zagallo  <tzagallo@apple.com>
+
+        Object allocation sinking is missing PutHint for allocations unreachable in the graph
+        https://bugs.webkit.org/show_bug.cgi?id=203799
+        <rdar://problem/56852162>
+
+        Reviewed by Saam Barati.
+
+        * stress/allocation-sinking-puthint-control-flow-2.js: Added.
+        (f.handler.construct):
+        (f):
+
 2020-01-16  Robin Morisset  <rmorisset@apple.com>
 
         Teach the bytecode that arithmetic operations can return bigints
diff --git a/JSTests/stress/allocation-sinking-puthint-control-flow-2.js b/JSTests/stress/allocation-sinking-puthint-control-flow-2.js
new file mode 100644
index 0000000..473de06
--- /dev/null
+++ b/JSTests/stress/allocation-sinking-puthint-control-flow-2.js
@@ -0,0 +1,16 @@
+//@ runDefault("--useConcurrentJIT=0", "--jitPolicyScale=0")
+
+function f() {
+    var x = {};
+    x = 0;
+    var handler = {
+        construct: function () {
+            x;
+        }
+    };
+    for (let i = 0; i < 1; i++)
+        (function () { i });
+    new Proxy(function() { }, handler);
+}
+f();
+f();
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index ba38171..4418dc0 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,44 @@
+2020-01-16  Tadeu Zagallo  <tzagallo@apple.com>
+
+        Object allocation sinking is missing PutHint for sunken allocations
+        https://bugs.webkit.org/show_bug.cgi?id=203799
+        <rdar://problem/56852162>
+
+        Reviewed by Saam Barati.
+
+        Consider the following graph:
+
+            Block #0:
+              1: PhantomCreateActivation()
+              2: PhantomNewFunction()
+              PutHint(@2, @1, FunctionActivationPLoc)
+              Branch(#1, #2)
+
+            Block #1:
+              3: MaterializeCreateActivation()
+              PutHint(@2, @3, FunctionActivationPLoc)
+              Upsilon(@3, ^5)
+              Jump(#3)
+
+            Block #2:
+              4: MaterializeCreateActivation()
+              PutHint(@2, @4, FunctionActivationPLoc)
+              Upsilon(@4, ^5)
+              Jump(#3)
+
+            Block #3:
+              5: Phi()
+              ExitOK()
+
+        On Block #3, we need to emit a PutHint after the Phi, since we might exit after it. However,
+        object allocation sinking skipped this Phi because it was checking whether the base of the
+        location that caused us to create this Phi (@2) was live, but it's dead in the graph (there
+        are no pointers to it).  The issue is that, even though there are no pointers to the base, the
+        location `PromotedHeapLocation(@2, FunctionActivationPLoc)` is still live, so we should PutHint
+        to it. We fix it by checking for liveness of the location rather than its base.
+
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+
 2020-01-16  Robin Morisset  <rmorisset@apple.com>
 
         Try to simplify the template deduction used by callOperation in DFGSpeculativeJIT
diff --git a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
index e25b68a..2e62e29 100644
--- a/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
@@ -409,8 +409,10 @@
     Node* follow(PromotedHeapLocation location) const
     {
         const Allocation& base = m_allocations.find(location.base())->value;
-        auto iter = base.fields().find(location.descriptor());
+        if (base.isEscapedAllocation())
+            return nullptr;
 
+        auto iter = base.fields().find(location.descriptor());
         if (iter == base.fields().end())
             return nullptr;
 
@@ -1946,7 +1948,7 @@
                     availabilityCalculator.m_availability, identifier, phiDef->value());
 
                 for (PromotedHeapLocation location : hintsForPhi[variable->index()]) {
-                    if (m_heap.onlyLocalAllocation(location.base())) {
+                    if (m_heap.onlyLocalAllocation(location)) {
                         m_insertionSet.insert(0,
                             location.createHint(m_graph, block->at(0)->origin.withInvalidExit(), phiDef->value()));
                         m_localMapping.set(location, phiDef->value());