/*
 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "HeapVerifier.h"

#include "CodeBlockInlines.h"
#include "HeapIterationScope.h"
#include "JSCInlines.h"
#include "JSObject.h"
#include "MarkedSpaceInlines.h"
#include "VMInspector.h"
#include "ValueProfile.h"
#include <wtf/ProcessID.h>

namespace JSC {

HeapVerifier::HeapVerifier(Heap* heap, unsigned numberOfGCCyclesToRecord)
    : m_heap(heap)
    , m_currentCycle(0)
    , m_numberOfCycles(numberOfGCCyclesToRecord)
{
    RELEASE_ASSERT(m_numberOfCycles > 0);
    m_cycles = makeUniqueArray<GCCycle>(m_numberOfCycles);
}

const char* HeapVerifier::phaseName(HeapVerifier::Phase phase)
{
    switch (phase) {
    case Phase::BeforeGC:
        return "BeforeGC";
    case Phase::BeforeMarking:
        return "BeforeMarking";
    case Phase::AfterMarking:
        return "AfterMarking";
    case Phase::AfterGC:
        return "AfterGC";
    }
    RELEASE_ASSERT_NOT_REACHED();
    return nullptr; // Silencing a compiler warning.
}

void HeapVerifier::startGC()
{
    Heap* heap = m_heap;
    incrementCycle();
    currentCycle().reset();
    currentCycle().scope = *heap->collectionScope();
    currentCycle().timestamp = MonotonicTime::now();
    ASSERT(!m_didPrintLogs);
}

void HeapVerifier::endGC()
{
    if (m_didPrintLogs) {
        dataLog("END ");
        printVerificationHeader();
        dataLog("\n\n");
        m_didPrintLogs = false;
    }
}

void HeapVerifier::gatherLiveCells(HeapVerifier::Phase phase)
{
    Heap* heap = m_heap;
    CellList& list = *cellListForGathering(phase);

    list.reset();
    heap->m_objectSpace.forEachLiveCell([&list] (HeapCell* cell, HeapCell::Kind kind) {
        list.add({ cell, kind, CellProfile::Live });
        return IterationStatus::Continue;
    });
}

CellList* HeapVerifier::cellListForGathering(HeapVerifier::Phase phase)
{
    switch (phase) {
    case Phase::BeforeMarking:
        return &currentCycle().before;
    case Phase::AfterMarking:
        return &currentCycle().after;
    case Phase::BeforeGC:
    case Phase::AfterGC:
        // We should not be gathering live cells during these phases.
        break;
    }
    RELEASE_ASSERT_NOT_REACHED();
    return nullptr; // Silencing a compiler warning.
}

static void trimDeadCellsFromList(CellList& knownLiveSet, CellList& list)
{
    if (!list.size())
        return;

    for (auto& cellProfile : list.cells()) {
        if (cellProfile.isDead())
            continue; // Don't "resurrect" known dead cells.
        if (!knownLiveSet.find(cellProfile.cell())) {
            cellProfile.setIsDead();
            continue;
        }
        cellProfile.setIsLive();
    }
}

void HeapVerifier::trimDeadCells()
{
    CellList& knownLiveSet = currentCycle().after;

    trimDeadCellsFromList(knownLiveSet, currentCycle().before);

    for (int i = -1; i > -m_numberOfCycles; i--) {
        trimDeadCellsFromList(knownLiveSet, cycleForIndex(i).before);
        trimDeadCellsFromList(knownLiveSet, cycleForIndex(i).after);
    }
}

void HeapVerifier::printVerificationHeader()
{
    RELEASE_ASSERT(m_heap->collectionScope());
    CollectionScope scope = currentCycle().scope;
    MonotonicTime gcCycleTimestamp = currentCycle().timestamp;
    dataLog("Verifying heap in [p", getCurrentProcessID(), ", ", Thread::current(), "] vm ",
        RawPointer(m_heap->vm()), " on ", scope, " GC @ ", gcCycleTimestamp, "\n");
}

bool HeapVerifier::verifyCellList(Phase phase, CellList& list)
{
    VM& vm = *m_heap->vm();
    auto& liveCells = list.cells();

    bool listNamePrinted = false;
    auto printHeaderIfNeeded = scopedLambda<void()>([&] () {
        if (listNamePrinted)
            return;
        
        printVerificationHeader();
        dataLog(" @ phase ", phaseName(phase), ": FAILED in cell list '", list.name(), "' (size ", liveCells.size(), ")\n");
        listNamePrinted = true;
        m_didPrintLogs = true;
    });
    
    bool success = true;
    for (size_t i = 0; i < liveCells.size(); i++) {
        CellProfile& profile = liveCells[i];
        if (!profile.isLive())
            continue;

        if (!profile.isJSCell())
            continue;

        JSCell* cell = profile.jsCell();
        success |= validateJSCell(&vm, cell, &profile, &list, printHeaderIfNeeded, "  ");
    }

    return success;
}

bool HeapVerifier::validateCell(HeapCell* cell, VM* expectedVM)
{
    auto printNothing = scopedLambda<void()>([] () { });

    if (cell->isZapped()) {
        dataLog("    cell ", RawPointer(cell), " is ZAPPED\n");
        return false;
    }

    if (!isJSCellKind(cell->cellKind()))
        return true; // Nothing more to validate.

    JSCell* jsCell = static_cast<JSCell*>(cell);
    return validateJSCell(expectedVM, jsCell, nullptr, nullptr, printNothing);
}

bool HeapVerifier::validateJSCell(VM* expectedVM, JSCell* cell, CellProfile* profile, CellList* list, const ScopedLambda<void()>& printHeaderIfNeeded, const char* prefix)
{
    auto printHeaderAndCell = [cell, profile, &printHeaderIfNeeded, prefix] () {
        printHeaderIfNeeded();
        dataLog(prefix, "cell ", RawPointer(cell));
        if (profile)
            dataLog(" [", profile->className(), "]");
    };

    // 1. Validate the cell.

    if (cell->isZapped()) {
        printHeaderAndCell();
        dataLog(" is zapped\n");
        return false;
    }

    StructureID structureID = cell->structureID();
    if (!structureID) {
        printHeaderAndCell();
        dataLog(" has NULL structureID\n");
        return false;
    }

    if (expectedVM) {
        VM& vm = *expectedVM;

        VM* cellVM = cell->vm();
        if (cellVM != expectedVM) {
            printHeaderAndCell();
            dataLog(" is from a different VM: expected:", RawPointer(expectedVM), " actual:", RawPointer(cellVM), "\n");
            return false;
        }

        // 2. Validate the cell's structure

        Structure* structure = vm.getStructure(structureID);
        if (!structure) {
            printHeaderAndCell();
#if USE(JSVALUE64)
            uint32_t structureIDAsUint32 = structureID;
#else
            uint32_t structureIDAsUint32 = reinterpret_cast<uint32_t>(structureID);
#endif
            dataLog(" with structureID ", structureIDAsUint32, " maps to a NULL Structure pointer\n");
            return false;
        }

        if (structure->isZapped()) {
            printHeaderAndCell();
            dataLog(" has ZAPPED structure ", RawPointer(structure), "\n");
            return false;
        }

        if (!structure->structureID()) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " whose structureID is NULL\n");
            return false;
        }

        VM* structureVM = structure->vm();
        if (structureVM != expectedVM) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " from a different VM: expected:", RawPointer(expectedVM), " actual:", RawPointer(structureVM), "\n");
            return false;
        }

        if (list) {
            auto* structureProfile = list->find(structure);
            if (!structureProfile) {
                printHeaderAndCell();
                dataLog(" has structure ", RawPointer(structure), " NOT found in the live cell list\n");
                return false;
            }

            if (!structureProfile->isLive()) {
                printHeaderAndCell();
                dataLog(" has DEAD structure ", RawPointer(structure), "\n");
                return false;
            }
        }

        StructureID structureStructureID = structure->structureID();
        if (!structureStructureID) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " with a NULL structureID\n");
            return false;
        }

        // 3. Validate the cell's structure's structure.
        
        Structure* structureStructure = vm.getStructure(structureID);
        if (!structureStructure) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " whose structure is NULL\n");
            return false;
        }
        
        if (structureStructure->isZapped()) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " whose structure ", RawPointer(structureStructure), " is ZAPPED\n");
            return false;
        }
        
        if (!structureStructure->structureID()) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " whose structure ", RawPointer(structureStructure), " has a NULL structureID\n");
            return false;
        }
        
        VM* structureStructureVM = structureStructure->vm();
        if (structureStructureVM != expectedVM) {
            printHeaderAndCell();
            dataLog(" has structure ", RawPointer(structure), " whose structure ", RawPointer(structureStructure), " is from a different VM: expected:", RawPointer(expectedVM), " actual:", RawPointer(structureStructureVM), "\n");
            return false;
        }
        
        if (list) {
            auto* structureStructureProfile = list->find(structureStructure);
            if (!structureStructureProfile) {
                printHeaderAndCell();
                dataLog(" has structure ", RawPointer(structure), " whose structure ", RawPointer(structureStructure), " is NOT found in the live cell list\n");
                return false;
            }
            
            if (!structureStructureProfile->isLive()) {
                printHeaderAndCell();
                dataLog(" has structure ", RawPointer(structure), " whose structure ", RawPointer(structureStructure), " is DEAD\n");
                return false;
            }
        }
        
        CodeBlock* codeBlock = jsDynamicCast<CodeBlock*>(vm, cell);
        if (UNLIKELY(codeBlock)) {
            bool success = true;
            codeBlock->forEachValueProfile([&](ValueProfile& valueProfile, bool) {
                for (unsigned i = 0; i < ValueProfile::totalNumberOfBuckets; ++i) {
                    JSValue value = JSValue::decode(valueProfile.m_buckets[i]);
                    if (!value)
                        continue;
                    if (!value.isCell())
                        continue;
                    JSCell* valueCell = value.asCell();
                    if (valueCell->isZapped()) {
                        printHeaderIfNeeded();
                        dataLog(prefix, "CodeBlock ", RawPointer(codeBlock), " has ZAPPED ValueProfile cell ", RawPointer(valueCell), "\n");
                        success = false;
                        continue;
                    }
                }
            });
            if (!success)
                return false;
        }
    }

    return true;
}

void HeapVerifier::verify(HeapVerifier::Phase phase)
{
    if (phase == Phase::AfterGC) {
        bool verified = verifyCellList(phase, currentCycle().after);
        RELEASE_ASSERT(verified);
    }
}

void HeapVerifier::reportCell(CellProfile& profile, int cycleIndex, HeapVerifier::GCCycle& cycle, CellList& list, const char* prefix)
{
    HeapCell* cell = profile.cell();
    VM* vm = m_heap->vm();

    if (prefix)
        dataLog(prefix);

    dataLog("FOUND");
    if (profile.isLive())
        dataLog(" LIVE");
    else if (profile.isDead())
        dataLog(" DEAD");

    if (!profile.isJSCell())
        dataLog(" HeapCell ");
    else
        dataLog(" JSCell ");
    dataLog(RawPointer(cell));

    if (profile.className())
        dataLog(" [", profile.className(), "]");

    if (profile.isLive() && profile.isJSCell()) {
        JSCell* jsCell = profile.jsCell();
        Structure* structure = jsCell->structure(*vm);
        dataLog(" structure:", RawPointer(structure));
        if (jsCell->isObject()) {
            JSObject* obj = static_cast<JSObject*>(cell);
            Butterfly* butterfly = obj->butterfly();
            void* butterflyBase = butterfly->base(structure);
            
            dataLog(" butterfly:", RawPointer(butterfly), " (base:", RawPointer(butterflyBase), ")");
        }
    }

    dataLog(" in ", cycle.scope, " GC[", cycleIndex, "] in '", list.name(), "' list in VM ",
        RawPointer(vm), " recorded at time ", profile.timestamp(), "\n");
    if (profile.stackTrace())
        dataLog(*profile.stackTrace());
}

void HeapVerifier::checkIfRecorded(HeapCell* cell)
{
    bool found = false;
    const char* const prefix = "  ";
    static const bool verbose = true;

    for (int cycleIndex = 0; cycleIndex > -m_numberOfCycles; cycleIndex--) {
        GCCycle& cycle = cycleForIndex(cycleIndex);
        CellList* lists[] = { &cycle.before, &cycle.after };

        if (verbose)
            dataLog("Checking ", cycle.scope, " GC<", cycle.timestamp, ">, cycle [", cycleIndex, "]:\n");
        
        const char* resultPrefix = "    ";
        for (auto* list : lists) {
            if (verbose)
                dataLog(prefix, "Cycle [", cycleIndex, "] '", list->name(), "' list: ");

            CellProfile* profile = list->find(cell);
            if (profile) {
                reportCell(*profile, cycleIndex, cycle, *list, resultPrefix);
                found = true;
            } else if (verbose)
                dataLog(resultPrefix, "cell NOT found\n");
        }
    }

    if (!found)
        dataLog(prefix, "cell ", RawPointer(cell), " NOT FOUND\n");
}

// The following are slower but more robust versions of the corresponding functions of the same name.
// These robust versions are designed so that we can call them interactively from a C++ debugger
// to query if a candidate is recorded cell.

void HeapVerifier::checkIfRecorded(uintptr_t candidateCell)
{
    HeapCell* candidateHeapCell = reinterpret_cast<HeapCell*>(candidateCell);
    
    VMInspector& inspector = VMInspector::instance();
    auto expectedLocker = inspector.lock(Seconds(2));
    if (!expectedLocker) {
        ASSERT(expectedLocker.error() == VMInspector::Error::TimedOut);
        dataLog("ERROR: Timed out while waiting to iterate VMs.");
        return;
    }

    auto& locker = expectedLocker.value();
    inspector.iterate(locker, [&] (VM& vm) {
        if (!vm.heap.m_verifier)
            return VMInspector::FunctorStatus::Continue;
        
        auto* verifier = vm.heap.m_verifier.get();
        dataLog("Search for cell ", RawPointer(candidateHeapCell), " in VM ", RawPointer(&vm), ":\n");
        verifier->checkIfRecorded(candidateHeapCell);
        return VMInspector::FunctorStatus::Continue;
    });
}

} // namespace JSC
