/*
 * Copyright (C) 2012 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 "CodeProfile.h"

#include "CodeBlock.h"
#include "CodeProfiling.h"
#include "LinkBuffer.h"
#include "ProfileTreeNode.h"
#include <wtf/text/WTFString.h>

#if OS(DARWIN)
#include <cxxabi.h>
#include <dlfcn.h>
#include <execinfo.h>
#endif

namespace JSC {

// Map from CodeType enum to a corresponding name.
const char* CodeProfile::s_codeTypeNames[CodeProfile::NumberOfCodeTypes] = {
    "[[EngineCode]]",
    "[[GlobalThunk]]",
    "[[RegExpCode]]",
    "[[DFGJIT]]",
    "[[BaselineOnly]]",
    "[[BaselineProfile]]",
    "[[BaselineOSR]]",
    "[[EngineFrame]]"
};

// Helper function, find the symbol name for a pc in JSC.
static const char* symbolName(void* address)
{
#if OS(DARWIN)
    Dl_info info;
    if (!dladdr(address, &info) || !info.dli_sname)
        return "<unknown>";

    const char* mangledName = info.dli_sname;
    const char* cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0);
    return cxaDemangled ? cxaDemangled : mangledName;
#else
    UNUSED_PARAM(address);
    return "<unknown>";
#endif
}

// Helper function, truncate traces to prune the output & make very verbose mode a little more readable.
static bool truncateTrace(const char* symbolName)
{
    return !strcmp(symbolName, "JSC::BytecodeGenerator::generate()")
        || !strcmp(symbolName, "JSC::Parser<JSC::Lexer<unsigned char>>::parseInner()")
        || !strcmp(symbolName, "WTF::fastMalloc(unsigned long)")
        || !strcmp(symbolName, "WTF::calculateUTCOffset()")
        || !strcmp(symbolName, "JSC::DFG::ByteCodeParser::parseCodeBlock()");
        
}

// Each trace consists of a sequence of zero or more 'EngineFrame' entries,
// followed by a sample in JIT code, or one or more 'EngineFrame' entries,
// followed by a 'EngineCode' terminator.
void CodeProfile::sample(void* pc, void** framePointer)
{
    // Disallow traces containing only a 'EngineCode' terminator, without any 'EngineFrame' frames.
    if (!framePointer)
        return;

    while (framePointer) {
        CodeType type;

#if ENABLE(JIT)
        // Determine if this sample fell in JIT code, and if so, from which JIT & why.
        void* ownerUID = CodeProfiling::getOwnerUIDForPC(pc);

        if (!ownerUID)
            type = EngineFrame;
        else if (ownerUID == GLOBAL_THUNK_ID)
            type = GlobalThunk;
        else if (ownerUID == REGEXP_CODE_ID)
            type = RegExpCode;
        else {
            CodeBlock* codeBlock = static_cast<CodeBlock*>(ownerUID);
            if (codeBlock->jitType() == JITCode::DFGJIT)
                type = DFGJIT;
            else if (!canCompile(codeBlock->capabilityLevelState()))
                type = BaselineOnly;
            else if (codeBlock->replacement())
                type = BaselineOSR;
            else
                type = BaselineProfile;
        }
#else
        type = EngineFrame;
#endif

        // A sample in JIT code terminates the trace.
        m_samples.append(CodeRecord(pc, type));
        if (type != EngineFrame)
            return;

#if OS(DARWIN) && CPU(X86_64)
        // Walk up the stack.
        pc = framePointer[1];
        framePointer = reinterpret_cast<void**>(*framePointer);
#elif OS(LINUX) && CPU(X86)
        // Don't unwind the stack as some dependent third party libraries
        // may be compiled with -fomit-frame-pointer.
        framePointer = 0;
#else
        // This platform is not yet supported!
        RELEASE_ASSERT_NOT_REACHED();
#endif
    }

    // If we get here, we walked the entire stack without finding any frames of JIT code.
    m_samples.append(CodeRecord(0, EngineCode));
}

void CodeProfile::report()
{
    dataLogF("<CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber);

    // How many frames of C-code to print - 0, if not verbose, 1 if verbose, up to 1024 if very verbose.
    unsigned recursionLimit = CodeProfiling::beVeryVerbose() ? 1024 : CodeProfiling::beVerbose();

    ProfileTreeNode profile;

    // Walk through the sample buffer.
    size_t trace = 0;
    while (trace < m_samples.size()) {

        // All traces are zero or more 'EngineFrame's, followed by a non-'EngineFrame'.
        // Scan to find the last sample in the trace.
        size_t lastInTrace = trace;
        while (m_samples[lastInTrace].type == EngineFrame)
            ++lastInTrace;

        // We use the last sample type to look up a name (used as a bucket in the profiler).
        ProfileTreeNode* callbacks = profile.sampleChild(s_codeTypeNames[m_samples[lastInTrace].type]);

        // If there are any samples in C-code, add up to recursionLimit of them into the profile tree.
        size_t lastEngineFrame = lastInTrace;
        for (unsigned count = 0; lastEngineFrame > trace && count < recursionLimit; ++count) {
            --lastEngineFrame;
            ASSERT(m_samples[lastEngineFrame].type == EngineFrame);
            const char* name = symbolName(m_samples[lastEngineFrame].pc);
            callbacks = callbacks->sampleChild(name);
            if (truncateTrace(name))
                break;
        }

        // Move on to the next trace.
        trace = lastInTrace + 1;
        ASSERT(trace <= m_samples.size());
    }

    // Output the profile tree.
    dataLogF("Total samples: %lld\n", static_cast<long long>(profile.childCount()));
    profile.dump();
    
    for (size_t i = 0 ; i < m_children.size(); ++i)
        m_children[i]->report();

    dataLogF("</CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber);
}

}
