summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/saved-stacks/bug-1445973-quick.js
blob: e95315f71f9e00465f8f4dc97477e6309f74aa83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
// |jit-test| --no-baseline; skip-if: !('oomTest' in this)
//
// For background, see the comments for LiveSavedFrameCache in js/src/vm/Stack.h.
//
// The cache would like to assert that, assuming the cache hasn't been
// completely flushed due to a compartment mismatch, if a stack frame's
// hasCachedSavedFrame bit is set, then that frame does indeed have an entry in
// the cache.
//
// When LiveSavedFrameCache::find finds an entry whose frame address matches,
// but whose pc does not match, it removes that entry from the cache. Usually, a
// fresh entry for that frame will be pushed into the cache in short order as we
// rebuild the SavedFrame chain, but if the creation of the SavedFrame fails due
// to OOM, then we are left with no cache entry for that frame.
//
// The fix for 1445973 is simply to clear the frame's bit when we remove the
// cache entry for a pc mismatch. Previously the code neglected to do this, but
// usually got away with it because the cache would be re-populated. OOM fuzzing
// interrupted the code at the proper place and revealed the crash, but did so
// with a test that took 90s to run. This test runs in a fraction of a second.

function f() {
  // Ensure that we will try to allocate fresh SavedFrame objects.
  clearSavedFrames();

  // Ensure that all frames have their hasCachedSavedFrame bits set.
  saveStack();

  try {
    // Capture the stack again. The entry for this frame will be removed due to
    // a pc mismatch. The OOM must occur here, causing the cache not to be
    // repopulated.
    saveStack();
  } catch (e) { }

  // Capture the stack a third time. This will see that f's frame has its bit
  // set, even though it has no entry in the cache.
  saveStack();
}

// This ensures that there is a frame below f's in the same Activation, so that
// the assertion doesn't get skipped because the LiveSavedFrameCache is entirely
// empty, to handle caches flushed by compartment mismatches.
function g() { f(); }

// Call all the code once, to ensure that everything has been delazified. When
// different calls to g perform different amounts of allocation, oomTest's
// simple strategy for choosing which allocation should fail can neglect to hit
// the SavedFrame creation. This is also why we disable the baseline compiler in
// the test metaline.
g();

oomTest(g);