| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --allow-natives-syntax --opt --no-always-opt |
| // Flags: --concurrent-recompilation --block-concurrent-recompilation |
| |
| function foo(x) { bar(x) } |
| function bar(x) { x.p } |
| |
| %PrepareFunctionForOptimization(foo); |
| %PrepareFunctionForOptimization(bar); |
| |
| // Create map transitions such that a's final map is not stable. |
| var dummy = []; |
| dummy.p = 0; |
| dummy.q = 0; |
| |
| var a = []; |
| a.p = 42; |
| |
| var b = []; |
| b.p = 42; |
| |
| // Warm-up. |
| foo(a); |
| foo(a); |
| |
| // Trigger optimization of bar but don't yet complete it. |
| %OptimizeFunctionOnNextCall(bar, "concurrent"); |
| foo(a); |
| %PrepareFunctionForOptimization(bar); |
| |
| // Change a's map from PACKED_SMI_ELEMENTS to PACKED_ELEMENTS and run bar in the |
| // interpreter (via foo) s.t. bar's load feedback changes accordingly. |
| a[0] = {}; |
| foo(a); |
| assertUnoptimized(bar, "no sync"); |
| |
| // Now finish the optimization of bar, which was based on the old |
| // PACKED_SMI_ELEMENTS feedback. |
| %UnblockConcurrentRecompilation(); |
| assertOptimized(bar); |
| // If we were to call the optimized bar now, it would deopt. |
| |
| // Instead we trigger optimization of foo, which will inline bar (this time |
| // based on the new PACKED_ELEMENTS map. |
| %OptimizeFunctionOnNextCall(foo); |
| foo(a); |
| assertOptimized(foo); |
| %PrepareFunctionForOptimization(foo); |
| assertOptimized(bar); |
| |
| // Now call the optimized foo on an object that has the old PACKED_SMI_ELEMENTS |
| // map. This will lead to an eager deopt of foo when the inlined bar sees that |
| // old map. |
| foo(b); |
| assertUnoptimized(foo); |
| assertOptimized(bar); |
| |
| // Now ensure there is no deopt-loop. There used to be a deopt-loop because, as |
| // a result of over-eager checkpoint elimination, we used to deopt into foo |
| // (right before the call to bar) rather than into bar (right before the load). |
| %OptimizeFunctionOnNextCall(foo); |
| foo(b); |
| assertOptimized(foo); |