|  | /* | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #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 <wtf/UnionFind.h> | 
|  |  | 
|  | namespace JSC { namespace DFG { | 
|  |  | 
|  | struct Node; | 
|  |  | 
|  | enum DoubleBallot { VoteValue, VoteDouble }; | 
|  |  | 
|  | class VariableAccessData : public UnionFind<VariableAccessData> { | 
|  | WTF_MAKE_FAST_ALLOCATED; | 
|  | WTF_MAKE_NONCOPYABLE(VariableAccessData); | 
|  | public: | 
|  | VariableAccessData(); | 
|  | VariableAccessData(Operand); | 
|  |  | 
|  | Operand operand() | 
|  | { | 
|  | ASSERT(m_operand == find()->m_operand); | 
|  | return m_operand; | 
|  | } | 
|  |  | 
|  | 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<double>(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. | 
|  |  | 
|  | SpeculatedType m_prediction; | 
|  | SpeculatedType m_argumentAwarePrediction; | 
|  | Operand m_operand; | 
|  | VirtualRegister m_machineLocal; | 
|  | 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) |