/*
 * Copyright (C) 2014 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 "CPUCount.h"
#include "Interpreter.h"
#include <assert.h>
#include <cstddef>
#include <cstdlib>
#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <vector>

#include "mbmalloc.h"

#define UNUSED_PARAM(variable) (void)variable

Interpreter::Interpreter(const char* fileName, bool shouldFreeAllObjects, bool useThreadId)
    : m_shouldFreeAllObjects(shouldFreeAllObjects)
    , m_useThreadId(useThreadId)
    , m_currentThreadId(0)
    , m_ops(1024)
{
    m_fd = open(fileName, O_RDONLY);
    if (m_fd == -1) {
        fprintf(stderr, "Failed to open op file %s: ", fileName);
        perror("");
        exit(-1);
    }

    struct stat buf;
    fstat(m_fd, &buf);

    m_opCount = buf.st_size / sizeof(Op);
    assert(m_opCount * sizeof(Op) == static_cast<size_t>(buf.st_size));

    size_t maxSlot = 0;

    std::vector<Op> ops(1024);
    size_t remaining = m_opCount * sizeof(Op);
    while (remaining) {
        size_t bytes = std::min(remaining, ops.size() * sizeof(Op));
        remaining -= bytes;
        auto ret = read(m_fd, ops.data(), bytes);
        UNUSED_PARAM(ret);

        size_t opCount = bytes / sizeof(Op);
        for (size_t i = 0; i < opCount; ++i) {
            Op op = ops[i];
            if (op.slot > maxSlot)
                maxSlot = op.slot;
        }
    }

    m_objects.resize(maxSlot + 1);
}

Interpreter::~Interpreter()
{
    int result = close(m_fd);
    if (result == -1) {
        perror("Failed to close op file");
        exit(-1);
    }
}

void Interpreter::run()
{
    std::vector<Op> ops(1024);
    lseek(m_fd, 0, SEEK_SET);

    m_remaining = m_opCount * sizeof(Op);
    m_opsCursor = m_opsInBuffer = 0;
    doOnSameThread(0);

    for (auto thread : m_threads)
        thread->stop();

    for (auto thread : m_threads)
        delete thread;

    // A recording might not free all of its allocations.
    if (!m_shouldFreeAllObjects)
        return;

    for (size_t i = 0; i < m_objects.size(); ++i) {
        if (!m_objects[i].object)
            continue;
        mbfree(m_objects[i].object, m_objects[i].size);
        m_objects[i] = { 0, 0 };
    }
}

bool Interpreter::readOps()
{
    if (!m_remaining)
        return false;

    size_t bytes = std::min(m_remaining, m_ops.size() * sizeof(Op));
    m_remaining -= bytes;
    auto ret = read(m_fd, m_ops.data(), bytes);
    UNUSED_PARAM(ret);
    m_opsCursor = 0;
    m_opsInBuffer = bytes / sizeof(Op);
    
    if (!m_opsInBuffer)
        return false;

    return true;
}

void Interpreter::doOnSameThread(ThreadId runThreadId)
{
    while (true) {
        if ((m_opsCursor >= m_opsInBuffer) && (!readOps())) {
            if (runThreadId)
                switchToThread(0);
            return;
        }

        for (; m_opsCursor < m_opsInBuffer; ++m_opsCursor) {
            Op op = m_ops[m_opsCursor];
            ThreadId threadId = op.threadId;
            if (m_useThreadId && (runThreadId != threadId)) {
                switchToThread(threadId);
                break;
            }

            doMallocOp(op, m_currentThreadId);
        }
    }
}

void Interpreter::switchToThread(ThreadId threadId)
{
    if (m_currentThreadId == threadId)
        return;

    for (ThreadId threadIndex = static_cast<ThreadId>(m_threads.size());
         threadIndex < threadId; ++threadIndex)
        m_threads.push_back(new Thread(this, threadId));

    ThreadId currentThreadId = m_currentThreadId;

    if (threadId == 0) {
        std::unique_lock<std::mutex> lock(m_threadMutex);
        m_currentThreadId = threadId;
        m_shouldRun.notify_one();
    } else
        m_threads[threadId - 1]->switchTo();
    
    if (currentThreadId == 0) {
        std::unique_lock<std::mutex> lock(m_threadMutex);
        m_shouldRun.wait(lock, [this](){return m_currentThreadId == 0; });
    } else
        m_threads[currentThreadId - 1]->waitToRun();
}

void Interpreter::detailedReport()
{
    size_t totalInUse = 0;
    size_t smallInUse = 0;
    size_t mediumInUse = 0;
    size_t largeInUse = 0;
    size_t extraLargeInUse = 0;
    size_t memoryAllocated = 0;

    for (size_t i = 0; i < m_objects.size(); ++i) {
        if (!m_objects[i].object)
            continue;
        size_t objectSize = m_objects[i].size;
        memoryAllocated += objectSize;
        totalInUse++;

        if (objectSize <= 256)
            smallInUse++;
        else if (objectSize <= 1024)
            mediumInUse++;
        else if (objectSize <= 1032192)
            largeInUse++;
        else
            extraLargeInUse++;
    }

    std::cout << "0B-256B objects in use: " << smallInUse << std::endl;
    std::cout << "257B-1K objects in use: " << mediumInUse << std::endl;
    std::cout << "  1K-1M objects in use: " << largeInUse << std::endl;
    std::cout << "    1M+ objects in use: " << extraLargeInUse << std::endl;
    std::cout << "  Total objects in use: " << totalInUse << std::endl;
    std::cout << "Total allocated memory: " << memoryAllocated / 1024 << "kB" << std::endl;
}
static size_t compute2toPower(unsigned log2n)
{
    // Check for bad alignment log2 value and return a bad alignment.
    if (log2n > 64)
        return 0xff00;

    size_t result = 1;
    while (log2n--)
        result <<= 1;
    
    return result;
}

void Interpreter::doMallocOp(Op op, ThreadId)
{
    switch (op.opcode) {
        case op_malloc: {
            m_objects[op.slot] = { mbmalloc(op.size), op.size };
            assert(m_objects[op.slot].object);
            bzero(m_objects[op.slot].object, op.size);
            break;
        }
        case op_free: {
            if (!m_objects[op.slot].object)
                return;
            mbfree(m_objects[op.slot].object, m_objects[op.slot].size);
            m_objects[op.slot] = { 0, 0 };
            break;
        }
        case op_realloc: {
            if (!m_objects[op.slot].object)
                return;
            m_objects[op.slot] = { mbrealloc(m_objects[op.slot].object, m_objects[op.slot].size, op.size), op.size };
            break;
        }
        case op_align_malloc: {
            size_t alignment = compute2toPower(op.alignLog2);
            m_objects[op.slot] = { mbmemalign(alignment, op.size), op.size };
            assert(m_objects[op.slot].object);
            bzero(m_objects[op.slot].object, op.size);
            break;
        }
        default: {
            fprintf(stderr, "bad opcode: %d\n", op.opcode);
            abort();
            break;
        }
    }
}

Interpreter::Thread::Thread(Interpreter* myInterpreter, ThreadId threadId)
    : m_threadId(threadId)
    , m_myInterpreter(myInterpreter)
{
    m_thread = std::thread(&Thread::runThread, this);
}

void Interpreter::Thread::stop()
{
    m_myInterpreter->switchToThread(m_threadId);
}

Interpreter::Thread::~Thread()
{
    switchTo();
    m_thread.join();
}

void Interpreter::Thread::runThread()
{
    waitToRun();
    m_myInterpreter->doOnSameThread(m_threadId);
}

void Interpreter::Thread::waitToRun()
{
    std::unique_lock<std::mutex> lock(m_myInterpreter->m_threadMutex);
    m_shouldRun.wait(lock, [this](){return m_myInterpreter->m_currentThreadId == m_threadId; });
}

void Interpreter::Thread::switchTo()
{
    std::unique_lock<std::mutex> lock(m_myInterpreter->m_threadMutex);
    m_myInterpreter->m_currentThreadId = m_threadId;
    m_shouldRun.notify_one();
}
