/*
 * Copyright (C) 2014, 2015 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 "DFGVariableAccessData.h"

#if ENABLE(DFG_JIT)

namespace JSC { namespace DFG {

VariableAccessData::VariableAccessData()
    : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
    , m_prediction(SpecNone)
    , m_argumentAwarePrediction(SpecNone)
    , m_flags(0)
    , m_shouldNeverUnbox(false)
    , m_structureCheckHoistingFailed(false)
    , m_checkArrayHoistingFailed(false)
    , m_isProfitableToUnbox(false)
    , m_isLoadedFrom(false)
    , m_doubleFormatState(EmptyDoubleFormatState)
{
    clearVotes();
}

VariableAccessData::VariableAccessData(VirtualRegister local)
    : m_local(local)
    , m_prediction(SpecNone)
    , m_argumentAwarePrediction(SpecNone)
    , m_flags(0)
    , m_shouldNeverUnbox(false)
    , m_structureCheckHoistingFailed(false)
    , m_checkArrayHoistingFailed(false)
    , m_isProfitableToUnbox(false)
    , m_isLoadedFrom(false)
    , m_doubleFormatState(EmptyDoubleFormatState)
{
    clearVotes();
}

bool VariableAccessData::mergeShouldNeverUnbox(bool shouldNeverUnbox)
{
    bool newShouldNeverUnbox = m_shouldNeverUnbox | shouldNeverUnbox;
    if (newShouldNeverUnbox == m_shouldNeverUnbox)
        return false;
    m_shouldNeverUnbox = newShouldNeverUnbox;
    return true;
}

bool VariableAccessData::predict(SpeculatedType prediction)
{
    VariableAccessData* self = find();
    bool result = mergeSpeculation(self->m_prediction, prediction);
    if (result)
        mergeSpeculation(m_argumentAwarePrediction, m_prediction);
    return result;
}

bool VariableAccessData::mergeArgumentAwarePrediction(SpeculatedType prediction)
{
    return mergeSpeculation(find()->m_argumentAwarePrediction, prediction);
}

bool VariableAccessData::shouldUseDoubleFormatAccordingToVote()
{
    // We don't support this facility for arguments, yet.
    // FIXME: make this work for arguments.
    if (local().isArgument())
        return false;
        
    // If the variable is not a number prediction, then this doesn't
    // make any sense.
    if (!isFullNumberSpeculation(prediction())) {
        // FIXME: we may end up forcing a local in inlined argument position to be a double even
        // if it is sometimes not even numeric, since this never signals the fact that it doesn't
        // want doubles. https://bugs.webkit.org/show_bug.cgi?id=109511
        return false;
    }
        
    // If the variable is predicted to hold only doubles, then it's a
    // no-brainer: it should be formatted as a double.
    if (isDoubleSpeculation(prediction()))
        return true;
        
    // If the variable is known to be used as an integer, then be safe -
    // don't force it to be a double.
    if (flags() & NodeBytecodeUsesAsInt)
        return false;
        
    // If the variable has been voted to become a double, then make it a
    // double.
    if (voteRatio() >= Options::doubleVoteRatioForDoubleFormat())
        return true;
        
    return false;
}

bool VariableAccessData::tallyVotesForShouldUseDoubleFormat()
{
    ASSERT(isRoot());
        
    if (local().isArgument() || shouldNeverUnbox()
        || (flags() & NodeBytecodeUsesAsArrayIndex))
        return DFG::mergeDoubleFormatState(m_doubleFormatState, NotUsingDoubleFormat);
    
    if (m_doubleFormatState == CantUseDoubleFormat)
        return false;
        
    bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote();
    if (!newValueOfShouldUseDoubleFormat) {
        // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should
        // switch back to int, we instead ignore this and stick with double.
        return false;
    }
        
    if (m_doubleFormatState == UsingDoubleFormat)
        return false;
        
    return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat);
}

bool VariableAccessData::mergeDoubleFormatState(DoubleFormatState doubleFormatState)
{
    return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState);
}

bool VariableAccessData::makePredictionForDoubleFormat()
{
    ASSERT(isRoot());
    
    if (m_doubleFormatState != UsingDoubleFormat)
        return false;
    
    SpeculatedType type = m_prediction;
    if (type & ~SpecBytecodeNumber)
        type |= SpecDoublePureNaN;
    if (type & (SpecInt32Only | SpecInt52Any))
        type |= SpecAnyIntAsDouble;
    return checkAndSet(m_prediction, type);
}

bool VariableAccessData::couldRepresentInt52()
{
    if (shouldNeverUnbox())
        return false;
    
    return couldRepresentInt52Impl();
}

bool VariableAccessData::couldRepresentInt52Impl()
{
    // The hardware has to support it.
    if (!enableInt52())
        return false;
    
    // We punt for machine arguments.
    if (m_local.isArgument())
        return false;
    
    // The argument-aware prediction -- which merges all of an (inlined or machine)
    // argument's variable access datas' predictions -- must possibly be Int52Any.
    return isInt32OrInt52Speculation(argumentAwarePrediction());
}

FlushFormat VariableAccessData::flushFormat()
{
    ASSERT(find() == this);
    
    if (!shouldUnboxIfPossible())
        return FlushedJSValue;
    
    if (shouldUseDoubleFormat())
        return FlushedDouble;
    
    SpeculatedType prediction = argumentAwarePrediction();
    
    // This guard is here to protect the call to couldRepresentInt52(), which will return
    // true for !prediction.
    if (!prediction)
        return FlushedJSValue;
    
    if (isInt32Speculation(prediction))
        return FlushedInt32;
    
    if (couldRepresentInt52Impl())
        return FlushedInt52;
    
    if (isCellSpeculation(prediction))
        return FlushedCell;
    
    if (isBooleanSpeculation(prediction))
        return FlushedBoolean;
    
    return FlushedJSValue;
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

