| // Copyright 2017 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 --expose-gc |
| |
| function Data() { |
| } |
| Data.prototype = { x: 1 }; |
| |
| function TriggerDeopt() { |
| Data.prototype = { x: 2 }; |
| } |
| |
| function TestDontSelfHealWithDeoptedCode(run_unoptimized, ClosureFactory) { |
| // Create some function closures which don't have |
| // optimized code. |
| var unoptimized_closure = ClosureFactory(); |
| if (run_unoptimized) { |
| unoptimized_closure(); |
| } |
| |
| // Run and optimize the code (do this in a separate function |
| // so that the closure doesn't leak in a dead register). |
| (() => { |
| var optimized_closure = ClosureFactory(); |
| // Use .call to avoid the CallIC retaining the JSFunction in the |
| // feedback vector via a weak map, which would mean it wouldn't be |
| // collected in the minor gc below. |
| optimized_closure.call(undefined); |
| %OptimizeFunctionOnNextCall(optimized_closure); |
| optimized_closure.call(undefined); |
| })(); |
| |
| // Optimize a dummy function, just so it gets linked into the |
| // Contexts optimized_functions list head, which is in the old |
| // space, and the link from to the optimized_closure's JSFunction |
| // moves to the inline link in dummy's JSFunction in the new space, |
| // otherwise optimized_closure's JSFunction will be retained by the |
| // old->new remember set. |
| (() => { |
| var dummy = function() { return 1; }; |
| %OptimizeFunctionOnNextCall(dummy); |
| dummy(); |
| })(); |
| |
| // GC the optimized closure with a minor GC - the optimized |
| // code will remain in the feedback vector. |
| gc(true); |
| |
| // Trigger deoptimization by changing the prototype of Data. This |
| // will mark the code for deopt, but since no live JSFunction has |
| // optimized code, we won't clear the feedback vector. |
| TriggerDeopt(); |
| |
| // Call pre-existing functions, these will try to self-heal with the |
| // optimized code in the feedback vector op, but should bail-out |
| // since the code is marked for deoptimization. |
| unoptimized_closure(); |
| } |
| |
| // Run with the unoptimized closure both uncomplied and compiled for the |
| // interpreter initially, to test self healing on both CompileLazy and |
| // the InterpreterEntryTrampoline respectively. |
| TestDontSelfHealWithDeoptedCode(false, |
| () => { return () => { return new Data() }}); |
| TestDontSelfHealWithDeoptedCode(true, |
| () => { return () => { return new Data() }}); |