#ifndef B3ControlValue_h
#define B3ControlValue_h
#if ENABLE(B3_JIT)
#include "B3FrequentedBlock.h"
#include "B3SuccessorCollection.h"
#include "B3Value.h"
namespace JSC { namespace B3 {
class BasicBlock;
class JS_EXPORT_PRIVATE ControlValue : public Value {
public:
static bool accepts(Opcode opcode)
{
switch (opcode) {
case Jump:
case Branch:
case Return:
case Oops:
return true;
case Switch:
return true;
default:
return false;
}
}
typedef Vector<FrequentedBlock, 2> SuccessorList;
~ControlValue();
unsigned numSuccessors() const { return m_successors.size(); }
const FrequentedBlock& successor(unsigned index) const { return m_successors[index]; }
FrequentedBlock& successor(unsigned index) { return m_successors[index]; }
const SuccessorList& successors() const { return m_successors; }
SuccessorList& successors() { return m_successors; }
BasicBlock* successorBlock(unsigned index) const { return successor(index).block(); }
BasicBlock*& successorBlock(unsigned index) { return successor(index).block(); }
SuccessorCollection<BasicBlock, SuccessorList> successorBlocks()
{
return SuccessorCollection<BasicBlock, SuccessorList>(successors());
}
SuccessorCollection<const BasicBlock, const SuccessorList> successorBlocks() const
{
return SuccessorCollection<const BasicBlock, const SuccessorList>(successors());
}
bool replaceSuccessor(BasicBlock* from, BasicBlock* to);
const FrequentedBlock& taken() const
{
ASSERT(opcode() == Jump || opcode() == Branch);
return successor(0);
}
FrequentedBlock& taken()
{
ASSERT(opcode() == Jump || opcode() == Branch);
return successor(0);
}
const FrequentedBlock& notTaken() const
{
ASSERT(opcode() == Branch);
return successor(1);
}
FrequentedBlock& notTaken()
{
ASSERT(opcode() == Branch);
return successor(1);
}
void convertToJump(BasicBlock* destination);
void convertToOops();
protected:
void dumpMeta(CommaPrinter&, PrintStream&) const override;
Value* cloneImpl() const override;
template<typename... Arguments>
ControlValue(Opcode opcode, Type type, Origin origin, Arguments... arguments)
: Value(CheckedOpcode, opcode, type, origin, arguments...)
{
ASSERT(accepts(opcode));
}
SuccessorList m_successors;
private:
friend class Procedure;
ControlValue(Opcode opcode, Origin origin)
: Value(CheckedOpcode, opcode, Void, origin)
{
ASSERT(opcode == Oops);
}
ControlValue(Opcode opcode, Origin origin, Value* result)
: Value(CheckedOpcode, opcode, Void, origin, result)
{
ASSERT(opcode == Return);
}
ControlValue(Opcode opcode, Origin origin, const FrequentedBlock& target)
: Value(CheckedOpcode, opcode, Void, origin)
{
ASSERT(opcode == Jump);
m_successors.append(target);
}
ControlValue(
Opcode opcode, Origin origin, Value* predicate,
const FrequentedBlock& yes, const FrequentedBlock& no)
: Value(CheckedOpcode, opcode, Void, origin, predicate)
{
ASSERT(opcode == Branch);
m_successors.append(yes);
m_successors.append(no);
}
};
} }
#endif // ENABLE(B3_JIT)
#endif // B3ControlValue_h