Skip to content

Commit

Permalink
Collects graph meta info during graph construction
Browse files Browse the repository at this point in the history
This information is very useful during type inference.
It may be gathered on-demand, but that would require
additional pass.

It is very cheap to collect meta info on the fly, so why not?

Issue: #17
  • Loading branch information
0x7CFE committed May 31, 2016
1 parent 3367adc commit 4d27f82
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 6 deletions.
25 changes: 24 additions & 1 deletion include/analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,10 @@ class ControlGraph {
: m_parsedMethod(parsedMethod), m_parsedBlock(0), m_lastNodeIndex(0) { }

ControlGraph(ParsedMethod* parsedMethod, ParsedBlock* parsedBlock)
: m_parsedMethod(parsedMethod), m_parsedBlock(parsedBlock), m_lastNodeIndex(0) { }
: m_parsedMethod(parsedMethod), m_parsedBlock(parsedBlock), m_lastNodeIndex(0)
{
m_metaInfo.isBlock = true;
}

ParsedMethod* getParsedMethod() const { return m_parsedMethod; }

Expand Down Expand Up @@ -462,8 +465,27 @@ class ControlGraph {
}

struct TMetaInfo {
bool isBlock;
bool hasBlockReturn;
bool hasLiteralBlocks;

bool hasLoops;
bool hasBackEdgeTau;

bool usesSelf;
bool usesSuper;

bool readsArguments;
bool readsFields;
bool writesFields;

bool hasPrimitive;

typedef std::set<std::size_t> TIndexSet;
TIndexSet readsTemporaries;
TIndexSet writesTemporaries;

TMetaInfo();
};

TMetaInfo& getMeta() { return m_metaInfo; }
Expand Down Expand Up @@ -492,6 +514,7 @@ template<> TauNode* ControlGraph::newNode<TauNode>();

template<> PushBlockNode* ControlNode::cast<PushBlockNode>();
template<> PushBlockNode* ControlGraph::newNode<PushBlockNode>();
template<> const PushBlockNode* ControlNode::cast<PushBlockNode>() const;

template<> BranchNode* ControlNode::cast<BranchNode>();
template<> const BranchNode* ControlNode::cast<BranchNode>() const;
Expand Down
46 changes: 41 additions & 5 deletions src/ControlGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ using namespace st;

static const bool traces_enabled = false;

ControlGraph::TMetaInfo::TMetaInfo() :
isBlock(false),
hasBlockReturn(false),
hasLiteralBlocks(false),
hasLoops(false),
hasBackEdgeTau(false),
usesSelf(false),
usesSuper(false),
readsArguments(false),
readsFields(false),
writesFields(false),
hasPrimitive(false)
{
}

bool NodeIndexCompare::operator() (const ControlNode* a, const ControlNode* b) const
{
return a->getIndex() < b->getIndex();
Expand Down Expand Up @@ -33,6 +48,10 @@ template<> PushBlockNode* ControlNode::cast<PushBlockNode>() {
return static_cast<PushBlockNode*>(this);
}

template<> const PushBlockNode* ControlNode::cast<PushBlockNode>() const {
return const_cast<ControlNode*>(this)->cast<PushBlockNode>();
}

template<> PushBlockNode* ControlGraph::newNode<PushBlockNode>() {
PushBlockNode* const node = new PushBlockNode(m_lastNodeIndex++);
m_nodes.push_back(node);
Expand Down Expand Up @@ -146,15 +165,24 @@ void GraphConstructor::processNode(InstructionNode* node)
m_currentDomain->setEntryPoint(node);

switch (instruction.getOpcode()) {
case opcode::pushConstant:
case opcode::pushLiteral:
case opcode::pushArgument:
case opcode::pushTemporary: // TODO Link with tau node
if (instruction.getArgument() == 0)
m_graph->getMeta().usesSelf = true;
m_graph->getMeta().readsArguments = true;

case opcode::pushInstance:
m_graph->getMeta().readsFields = true;

case opcode::pushTemporary:
m_graph->getMeta().readsTemporaries.insert(node->getInstruction().getArgument());
case opcode::pushConstant:
case opcode::pushLiteral:
m_currentDomain->pushValue(node);
break;

case opcode::pushBlock: {
m_graph->getMeta().hasLiteralBlocks = true;

const uint16_t blockEndOffset = node->getInstruction().getExtra();
ParsedMethod* const parsedMethod = m_graph->getParsedMethod();
ParsedBlock* const parsedBlock = parsedMethod->getParsedBlockByEndOffset(blockEndOffset);
Expand All @@ -163,8 +191,13 @@ void GraphConstructor::processNode(InstructionNode* node)
m_currentDomain->pushValue(node);
} break;

case opcode::assignTemporary: // TODO Link with tau node
case opcode::assignTemporary:
m_graph->getMeta().writesTemporaries.insert(node->getInstruction().getArgument());
m_currentDomain->requestArgument(0, node, true);
break;

case opcode::assignInstance:
m_graph->getMeta().writesFields = true;
m_currentDomain->requestArgument(0, node, true);
break;

Expand All @@ -191,6 +224,7 @@ void GraphConstructor::processNode(InstructionNode* node)
break;

case opcode::doPrimitive:
m_graph->getMeta().hasPrimitive = true;
processPrimitives(node);
m_currentDomain->pushValue(node);
break;
Expand All @@ -205,8 +239,9 @@ void GraphConstructor::processSpecials(InstructionNode* node)
const TSmalltalkInstruction& instruction = node->getInstruction();

switch (instruction.getArgument()) {
case special::stackReturn:
case special::blockReturn:
m_graph->getMeta().hasBlockReturn = true;
case special::stackReturn:
m_currentDomain->requestArgument(0, node);

case special::selfReturn:
Expand All @@ -215,6 +250,7 @@ void GraphConstructor::processSpecials(InstructionNode* node)
break;

case special::sendToSuper:
m_graph->getMeta().usesSuper = true;
m_currentDomain->requestArgument(0, node);
m_currentDomain->pushValue(node);
break;
Expand Down

0 comments on commit 4d27f82

Please sign in to comment.