regress-718891.js 2.42 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// 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 };

11 12
function TriggerDeopt() {
  Data.prototype = { x: 2 };
13 14
}

15 16 17 18 19 20 21 22
function TestDontSelfHealWithDeoptedCode(run_unoptimized, ClosureFactory) {
  // Create some function closures which don't have
  // optimized code.
  var unoptimized_closure = ClosureFactory();
  if (run_unoptimized) {
    unoptimized_closure();
  }

23
  // Run and optimize the code (do this in a separate function
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
  // 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() }});