/* * Copyright (C) 2011-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. */ #ifndef DFGVariableAccessData_h #define DFGVariableAccessData_h #if ENABLE(DFG_JIT) #include "DFGCommon.h" #include "DFGDoubleFormatState.h" #include "DFGFlushFormat.h" #include "DFGFlushedAt.h" #include "DFGNodeFlags.h" #include "Operands.h" #include "SpeculatedType.h" #include "VirtualRegister.h" #include #include namespace JSC { namespace DFG { struct Node; enum DoubleBallot { VoteValue, VoteDouble }; class VariableAccessData : public UnionFind { public: VariableAccessData(); VariableAccessData(VirtualRegister local); VirtualRegister local() { ASSERT(m_local == find()->m_local); return m_local; } VirtualRegister& machineLocal() { ASSERT(find() == this); return m_machineLocal; } bool mergeIsProfitableToUnbox(bool isProfitableToUnbox) { return checkAndSet(m_isProfitableToUnbox, m_isProfitableToUnbox || isProfitableToUnbox); } bool isProfitableToUnbox() { return m_isProfitableToUnbox; } bool mergeShouldNeverUnbox(bool shouldNeverUnbox); // Returns true if it would be unsound to store the value in an unboxed fashion. // If this returns false, it simply means that it is sound to unbox; it doesn't // mean that we have actually done so. bool shouldNeverUnbox() { return m_shouldNeverUnbox; } // Returns true if we should be unboxing the value provided that the predictions // and double format vote say so. This may return false even if shouldNeverUnbox() // returns false, since this incorporates heuristics of profitability. bool shouldUnboxIfPossible() { return !shouldNeverUnbox() && isProfitableToUnbox(); } bool mergeStructureCheckHoistingFailed(bool failed) { return checkAndSet(m_structureCheckHoistingFailed, m_structureCheckHoistingFailed || failed); } bool mergeCheckArrayHoistingFailed(bool failed) { return checkAndSet(m_checkArrayHoistingFailed, m_checkArrayHoistingFailed || failed); } bool structureCheckHoistingFailed() { return m_structureCheckHoistingFailed; } bool checkArrayHoistingFailed() { return m_checkArrayHoistingFailed; } bool mergeIsLoadedFrom(bool isLoadedFrom) { return checkAndSet(m_isLoadedFrom, m_isLoadedFrom || isLoadedFrom); } void setIsLoadedFrom(bool isLoadedFrom) { m_isLoadedFrom = isLoadedFrom; } bool isLoadedFrom() { return m_isLoadedFrom; } bool predict(SpeculatedType prediction); SpeculatedType nonUnifiedPrediction() { return m_prediction; } SpeculatedType prediction() { return find()->m_prediction; } SpeculatedType argumentAwarePrediction() { return find()->m_argumentAwarePrediction; } bool mergeArgumentAwarePrediction(SpeculatedType prediction); void clearVotes() { ASSERT(find() == this); m_votes[0] = 0; m_votes[1] = 0; } void vote(unsigned ballot, float weight = 1) { ASSERT(ballot < 2); m_votes[ballot] += weight; } double voteRatio() { ASSERT(find() == this); return static_cast(m_votes[1]) / m_votes[0]; } bool shouldUseDoubleFormatAccordingToVote(); DoubleFormatState doubleFormatState() { return find()->m_doubleFormatState; } bool shouldUseDoubleFormat() { ASSERT(isRoot()); bool doubleState = m_doubleFormatState == UsingDoubleFormat; ASSERT(!(doubleState && shouldNeverUnbox())); return doubleState && isProfitableToUnbox(); } bool tallyVotesForShouldUseDoubleFormat(); bool mergeDoubleFormatState(DoubleFormatState); bool makePredictionForDoubleFormat(); NodeFlags flags() const { return m_flags; } bool mergeFlags(NodeFlags newFlags) { return checkAndSet(m_flags, m_flags | newFlags); } FlushFormat flushFormat(); bool couldRepresentInt52(); FlushedAt flushedAt() { return FlushedAt(flushFormat(), machineLocal()); } private: bool couldRepresentInt52Impl(); // This is slightly space-inefficient, since anything we're unified with // will have the same operand and should have the same prediction. But // putting them here simplifies the code, and we don't expect DFG space // usage for variable access nodes do be significant. VirtualRegister m_local; VirtualRegister m_machineLocal; SpeculatedType m_prediction; SpeculatedType m_argumentAwarePrediction; NodeFlags m_flags; bool m_shouldNeverUnbox; bool m_structureCheckHoistingFailed; bool m_checkArrayHoistingFailed; bool m_isProfitableToUnbox; bool m_isLoadedFrom; float m_votes[2]; // Used primarily for double voting but may be reused for other purposes. DoubleFormatState m_doubleFormatState; }; } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) #endif // DFGVariableAccessData_h