/ tools / HeapVerifier.h
HeapVerifier.h
  1  /*
  2   * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  3   *
  4   * Redistribution and use in source and binary forms, with or without
  5   * modification, are permitted provided that the following conditions
  6   * are met:
  7   * 1. Redistributions of source code must retain the above copyright
  8   *    notice, this list of conditions and the following disclaimer.
  9   * 2. Redistributions in binary form must reproduce the above copyright
 10   *    notice, this list of conditions and the following disclaimer in the
 11   *    documentation and/or other materials provided with the distribution.
 12   *
 13   * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 24   */
 25  
 26  #pragma once
 27  
 28  #include "CellList.h"
 29  #include "Heap.h"
 30  #include <wtf/MonotonicTime.h>
 31  #include <wtf/ScopedLambda.h>
 32  #include <wtf/UniqueArray.h>
 33  
 34  namespace JSC {
 35  
 36  class JSCell;
 37  class MarkedBlock;
 38  
 39  class HeapVerifier {
 40      WTF_MAKE_FAST_ALLOCATED;
 41  public:
 42      enum class Phase {
 43          BeforeGC,
 44          BeforeMarking,
 45          AfterMarking,
 46          AfterGC
 47      };
 48  
 49      HeapVerifier(Heap*, unsigned numberOfGCCyclesToRecord);
 50  
 51      void startGC();
 52      void endGC();
 53  
 54      void gatherLiveCells(Phase);
 55      void trimDeadCells();
 56      void verify(Phase);
 57  
 58      static const char* phaseName(Phase);
 59      
 60      // Scans all previously recorded CellLists and checks if the specified
 61      // cell was in any of those lists.
 62      JS_EXPORT_PRIVATE static void checkIfRecorded(uintptr_t maybeCell);
 63  
 64      // Returns false if anything is found to be inconsistent/incorrect about the specified cell.
 65      JS_EXPORT_PRIVATE static bool validateCell(HeapCell*, VM* expectedVM = nullptr);
 66  
 67  private:
 68      struct GCCycle {
 69          WTF_MAKE_STRUCT_FAST_ALLOCATED;
 70  
 71          GCCycle()
 72              : before("Before Marking")
 73              , after("After Marking")
 74          {
 75          }
 76  
 77          void reset()
 78          {
 79              before.reset();
 80              after.reset();
 81          }
 82  
 83          CollectionScope scope;
 84          MonotonicTime timestamp;
 85          CellList before;
 86          CellList after;
 87      };
 88  
 89      void incrementCycle() { m_currentCycle = (m_currentCycle + 1) % m_numberOfCycles; }
 90      GCCycle& currentCycle() { return m_cycles[m_currentCycle]; }
 91      GCCycle& cycleForIndex(int cycleIndex)
 92      {
 93          ASSERT(cycleIndex <= 0 && cycleIndex > -m_numberOfCycles);
 94          cycleIndex += m_currentCycle;
 95          if (cycleIndex < 0)
 96              cycleIndex += m_numberOfCycles;
 97          ASSERT(cycleIndex < m_numberOfCycles);
 98          return m_cycles[cycleIndex];
 99      }
100  
101      CellList* cellListForGathering(Phase);
102      bool verifyCellList(Phase, CellList&);
103      static bool validateJSCell(VM* expectedVM, JSCell*, CellProfile*, CellList*, const ScopedLambda<void()>& printHeaderIfNeeded, const char* prefix = "");
104  
105      void printVerificationHeader();
106  
107      void checkIfRecorded(HeapCell* maybeHeapCell);
108      void reportCell(CellProfile&, int cycleIndex, HeapVerifier::GCCycle&, CellList&, const char* prefix = nullptr);
109  
110      Heap* m_heap;
111      int m_currentCycle;
112      int m_numberOfCycles;
113      bool m_didPrintLogs { false };
114      UniqueArray<GCCycle> m_cycles;
115  };
116  
117  } // namespace JSC