/*
 * Copyright (C) 2012-2013, 2016 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 "ProfilerDatabase.h"

#include "CodeBlock.h"
#include "JSCInlines.h"
#include "JSONObject.h"
#include "ObjectConstructor.h"
#include <wtf/FilePrintStream.h>

namespace JSC { namespace Profiler {

static std::atomic<int> databaseCounter;

static Lock registrationLock;
static std::atomic<int> didRegisterAtExit;
static Database* firstDatabase;

Database::Database(VM& vm)
    : m_databaseID(++databaseCounter)
    , m_vm(vm)
    , m_shouldSaveAtExit(false)
    , m_nextRegisteredDatabase(nullptr)
{
}

Database::~Database()
{
    if (m_shouldSaveAtExit) {
        removeDatabaseFromAtExit();
        performAtExitSave();
    }
}

Bytecodes* Database::ensureBytecodesFor(CodeBlock* codeBlock)
{
    Locker locker { m_lock };
    return ensureBytecodesFor(locker, codeBlock);
}

Bytecodes* Database::ensureBytecodesFor(const AbstractLocker&, CodeBlock* codeBlock)
{
    codeBlock = codeBlock->baselineAlternative();
    
    HashMap<CodeBlock*, Bytecodes*>::iterator iter = m_bytecodesMap.find(codeBlock);
    if (iter != m_bytecodesMap.end())
        return iter->value;
    
    m_bytecodes.append(Bytecodes(m_bytecodes.size(), codeBlock));
    Bytecodes* result = &m_bytecodes.last();
    
    m_bytecodesMap.add(codeBlock, result);
    
    return result;
}

void Database::notifyDestruction(CodeBlock* codeBlock)
{
    Locker locker { m_lock };
    
    m_bytecodesMap.remove(codeBlock);
    m_compilationMap.remove(codeBlock);
}

void Database::addCompilation(CodeBlock* codeBlock, Ref<Compilation>&& compilation)
{
    Locker locker { m_lock };

    m_compilations.append(compilation.copyRef());
    m_compilationMap.set(codeBlock, WTFMove(compilation));
}

JSValue Database::toJS(JSGlobalObject* globalObject) const
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    JSObject* result = constructEmptyObject(globalObject);
    
    JSArray* bytecodes = constructEmptyArray(globalObject, nullptr);
    RETURN_IF_EXCEPTION(scope, { });
    for (unsigned i = 0; i < m_bytecodes.size(); ++i) {
        auto value = m_bytecodes[i].toJS(globalObject);
        RETURN_IF_EXCEPTION(scope, { });
        bytecodes->putDirectIndex(globalObject, i, value);
        RETURN_IF_EXCEPTION(scope, { });
    }
    result->putDirect(vm, vm.propertyNames->bytecodes, bytecodes);
    
    JSArray* compilations = constructEmptyArray(globalObject, nullptr);
    RETURN_IF_EXCEPTION(scope, { });
    for (unsigned i = 0; i < m_compilations.size(); ++i) {
        auto value = m_compilations[i]->toJS(globalObject);
        RETURN_IF_EXCEPTION(scope, { });
        compilations->putDirectIndex(globalObject, i, value);
        RETURN_IF_EXCEPTION(scope, { });
    }
    result->putDirect(vm, vm.propertyNames->compilations, compilations);
    
    JSArray* events = constructEmptyArray(globalObject, nullptr);
    RETURN_IF_EXCEPTION(scope, { });
    for (unsigned i = 0; i < m_events.size(); ++i) {
        auto value = m_events[i].toJS(globalObject);
        RETURN_IF_EXCEPTION(scope, { });
        events->putDirectIndex(globalObject, i, value);
        RETURN_IF_EXCEPTION(scope, { });
    }
    result->putDirect(vm, vm.propertyNames->events, events);
    
    return result;
}

String Database::toJSON() const
{
    auto scope = DECLARE_THROW_SCOPE(m_vm);
    JSGlobalObject* globalObject = JSGlobalObject::create(
        m_vm, JSGlobalObject::createStructure(m_vm, jsNull()));

    auto value = toJS(globalObject);
    RETURN_IF_EXCEPTION(scope, String());
    RELEASE_AND_RETURN(scope, JSONStringify(globalObject, value, 0));
}

bool Database::save(const char* filename) const
{
    auto scope = DECLARE_CATCH_SCOPE(m_vm);
    auto out = FilePrintStream::open(filename, "w");
    if (!out)
        return false;
    
    String data = toJSON();
    if (UNLIKELY(scope.exception())) {
        scope.clearException();
        return false;
    }
    out->print(data);
    return true;
}

void Database::registerToSaveAtExit(const char* filename)
{
    m_atExitSaveFilename = filename;
    
    if (m_shouldSaveAtExit)
        return;
    
    addDatabaseToAtExit();
    m_shouldSaveAtExit = true;
}

void Database::logEvent(CodeBlock* codeBlock, const char* summary, const CString& detail)
{
    Locker locker { m_lock };
    
    Bytecodes* bytecodes = ensureBytecodesFor(locker, codeBlock);
    Compilation* compilation = m_compilationMap.get(codeBlock);
    m_events.append(Event(WallTime::now(), bytecodes, compilation, summary, detail));
}

void Database::addDatabaseToAtExit()
{
    if (++didRegisterAtExit == 1)
        atexit(atExitCallback);
    
    Locker locker { registrationLock };
    m_nextRegisteredDatabase = firstDatabase;
    firstDatabase = this;
}

void Database::removeDatabaseFromAtExit()
{
    Locker locker { registrationLock };
    for (Database** current = &firstDatabase; *current; current = &(*current)->m_nextRegisteredDatabase) {
        if (*current != this)
            continue;
        *current = m_nextRegisteredDatabase;
        m_nextRegisteredDatabase = nullptr;
        m_shouldSaveAtExit = false;
        break;
    }
}

void Database::performAtExitSave() const
{
    JSLockHolder lock(m_vm);
    save(m_atExitSaveFilename.data());
}

Database* Database::removeFirstAtExitDatabase()
{
    Locker locker { registrationLock };
    Database* result = firstDatabase;
    if (result) {
        firstDatabase = result->m_nextRegisteredDatabase;
        result->m_nextRegisteredDatabase = nullptr;
        result->m_shouldSaveAtExit = false;
    }
    return result;
}

void Database::atExitCallback()
{
    while (Database* database = removeFirstAtExitDatabase())
        database->performAtExitSave();
}

} } // namespace JSC::Profiler

