/*
 * 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"

#if ENABLE(DFG_JIT)

#include "DFGBinarySwitch.h"

#include "Operations.h"

namespace JSC { namespace DFG {

BinarySwitch::BinarySwitch(GPRReg value, const Vector<int64_t>& cases, Type type)
    : m_value(value)
    , m_index(0)
    , m_caseIndex(UINT_MAX)
    , m_medianBias(0)
    , m_type(type)
{
    if (cases.isEmpty())
        return;
    
    for (unsigned i = 0; i < cases.size(); ++i)
        m_cases.append(Case(cases[i], i));
    std::sort(m_cases.begin(), m_cases.end());
    build(0, m_cases.size());
}

bool BinarySwitch::advance(MacroAssembler& jit)
{
    if (m_cases.isEmpty()) {
        m_fallThrough.append(jit.jump());
        return false;
    }
    
    if (m_index == m_branches.size()) {
        RELEASE_ASSERT(m_jumpStack.isEmpty());
        return false;
    }
    
    for (;;) {
        const BranchCode& code = m_branches[m_index++];
        switch (code.kind) {
        case NotEqualToFallThrough:
            switch (m_type) {
            case Int32:
                m_fallThrough.append(jit.branch32(
                    MacroAssembler::NotEqual, m_value,
                    MacroAssembler::Imm32(static_cast<int32_t>(m_cases[code.index].value))));
                break;
            case IntPtr:
                m_fallThrough.append(jit.branchPtr(
                    MacroAssembler::NotEqual, m_value,
                    MacroAssembler::ImmPtr(bitwise_cast<const void*>(static_cast<intptr_t>(m_cases[code.index].value)))));
                break;
            }
            break;
        case NotEqualToPush:
            switch (m_type) {
            case Int32:
                m_jumpStack.append(jit.branch32(
                    MacroAssembler::NotEqual, m_value,
                    MacroAssembler::Imm32(static_cast<int32_t>(m_cases[code.index].value))));
                break;
            case IntPtr:
                m_jumpStack.append(jit.branchPtr(
                    MacroAssembler::NotEqual, m_value,
                    MacroAssembler::ImmPtr(bitwise_cast<const void*>(static_cast<intptr_t>(m_cases[code.index].value)))));
                break;
            }
            break;
        case LessThanToPush:
            switch (m_type) {
            case Int32:
                m_jumpStack.append(jit.branch32(
                    MacroAssembler::LessThan, m_value,
                    MacroAssembler::Imm32(static_cast<int32_t>(m_cases[code.index].value))));
                break;
            case IntPtr:
                m_jumpStack.append(jit.branchPtr(
                    MacroAssembler::LessThan, m_value,
                    MacroAssembler::ImmPtr(bitwise_cast<const void*>(static_cast<intptr_t>(m_cases[code.index].value)))));
                break;
            }
            break;
        case Pop:
            m_jumpStack.takeLast().link(&jit);
            break;
        case ExecuteCase:
            m_caseIndex = code.index;
            return true;
        }
    }
}

void BinarySwitch::build(unsigned start, unsigned end)
{
    unsigned size = end - start;
    
    switch (size) {
    case 0: {
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
        
    case 1: {
        if (start
            && m_cases[start - 1].value == m_cases[start].value - 1
            && start + 1 < m_cases.size()
            && m_cases[start + 1].value == m_cases[start].value + 1) {
            m_branches.append(BranchCode(ExecuteCase, start));
            break;
        }
        
        m_branches.append(BranchCode(NotEqualToFallThrough, start));
        m_branches.append(BranchCode(ExecuteCase, start));
        break;
    }
        
    case 2: {
        if (m_cases[start].value + 1 == m_cases[start + 1].value
            && start
            && m_cases[start - 1].value == m_cases[start].value - 1
            && start + 2 < m_cases.size()
            && m_cases[start + 2].value == m_cases[start + 1].value + 1) {
            m_branches.append(BranchCode(NotEqualToPush, start));
            m_branches.append(BranchCode(ExecuteCase, start));
            m_branches.append(BranchCode(Pop));
            m_branches.append(BranchCode(ExecuteCase, start + 1));
            break;
        }
        
        unsigned firstCase = start;
        unsigned secondCase = start + 1;
        if (m_medianBias)
            std::swap(firstCase, secondCase);
        m_medianBias ^= 1;
        
        m_branches.append(BranchCode(NotEqualToPush, firstCase));
        m_branches.append(BranchCode(ExecuteCase, firstCase));
        m_branches.append(BranchCode(Pop));
        m_branches.append(BranchCode(NotEqualToFallThrough, secondCase));
        m_branches.append(BranchCode(ExecuteCase, secondCase));
        break;
    }
        
    default: {
        unsigned medianIndex = (start + end) / 2;
        if (!(size & 1)) {
            // Because end is exclusive, in the even case, this rounds up by
            // default. Hence median bias sometimes flips to subtracing one
            // in order to get round-down behavior.
            medianIndex -= m_medianBias;
            m_medianBias ^= 1;
        }
        
        RELEASE_ASSERT(medianIndex > start);
        RELEASE_ASSERT(medianIndex + 1 < end);
        
        m_branches.append(BranchCode(LessThanToPush, medianIndex));
        m_branches.append(BranchCode(NotEqualToPush, medianIndex));
        m_branches.append(BranchCode(ExecuteCase, medianIndex));
        
        m_branches.append(BranchCode(Pop));
        build(medianIndex + 1, end);
        
        m_branches.append(BranchCode(Pop));
        build(start, medianIndex);
        break;
    } }
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

