mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2025-02-17 02:18:14 +00:00
230 lines
6.4 KiB
C++
230 lines
6.4 KiB
C++
/*
|
|
* 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)
|