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

#include "JSCInlines.h"

namespace JSC {

template <size_t vectorSize>
static void getJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector<unsigned, vectorSize>& out)
{
    OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
    Instruction* current = instructionsBegin + bytecodeOffset;
    switch (opcodeID) {
    case op_jmp:
        out.append(bytecodeOffset + current[1].u.operand);
        break;
    case op_jtrue:
    case op_jfalse:
    case op_jeq_null:
    case op_jneq_null:
        out.append(bytecodeOffset + current[2].u.operand);
        break;
    case op_jneq_ptr:
    case op_jless:
    case op_jlesseq:
    case op_jgreater:
    case op_jgreatereq:
    case op_jnless:
    case op_jnlesseq:
    case op_jngreater:
    case op_jngreatereq:
    case op_save: // The jump of op_save is purely for calculating liveness.
        out.append(bytecodeOffset + current[3].u.operand);
        break;
    case op_switch_imm:
    case op_switch_char: {
        SimpleJumpTable& table = codeBlock->switchJumpTable(current[1].u.operand);
        for (unsigned i = table.branchOffsets.size(); i--;)
            out.append(bytecodeOffset + table.branchOffsets[i]);
        out.append(bytecodeOffset + current[2].u.operand);
        break;
    }
    case op_switch_string: {
        StringJumpTable& table = codeBlock->stringSwitchJumpTable(current[1].u.operand);
        StringJumpTable::StringOffsetTable::iterator iter = table.offsetTable.begin();
        StringJumpTable::StringOffsetTable::iterator end = table.offsetTable.end();
        for (; iter != end; ++iter)
            out.append(bytecodeOffset + iter->value.branchOffset);
        out.append(bytecodeOffset + current[2].u.operand);
        break;
    }
    case op_loop_hint:
        out.append(bytecodeOffset);
        break;
    default:
        break;
    }
}

void computePreciseJumpTargets(CodeBlock* codeBlock, Vector<unsigned, 32>& out)
{
    ASSERT(out.isEmpty());
    
    // We will derive a superset of the jump targets that the code block thinks it has.
    // So, if the code block claims there are none, then we are done.
    if (!codeBlock->numberOfJumpTargets())
        return;
    
    for (unsigned i = codeBlock->numberOfExceptionHandlers(); i--;) {
        out.append(codeBlock->exceptionHandler(i).target);
        out.append(codeBlock->exceptionHandler(i).start);
        out.append(codeBlock->exceptionHandler(i).end);
    }

    Interpreter* interpreter = codeBlock->vm()->interpreter;
    Instruction* instructionsBegin = codeBlock->instructions().begin();
    unsigned instructionCount = codeBlock->instructions().size();
    for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) {
        OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
        getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out);
        bytecodeOffset += opcodeLengths[opcodeID];
    }
    
    std::sort(out.begin(), out.end());
    
    // We will have duplicates, and we must remove them.
    unsigned toIndex = 0;
    unsigned fromIndex = 0;
    unsigned lastValue = UINT_MAX;
    while (fromIndex < out.size()) {
        unsigned value = out[fromIndex++];
        if (value == lastValue)
            continue;
        out[toIndex++] = value;
        lastValue = value;
    }
    out.resize(toIndex);
    out.shrinkToFit();
}

void findJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Vector<unsigned, 1>& out)
{
    Interpreter* interpreter = codeBlock->vm()->interpreter;
    Instruction* instructionsBegin = codeBlock->instructions().begin();
    getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out);
}

} // namespace JSC

