mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 12:46:44 +00:00
Remove unnecessary jump dest map. Create jump table block on demand.
This commit is contained in:
parent
ed614c5d2a
commit
c21237f7b0
3 changed files with 34 additions and 36 deletions
|
|
@ -67,6 +67,9 @@ public:
|
||||||
ProgramCounter begin() { return m_beginInstIdx; }
|
ProgramCounter begin() { return m_beginInstIdx; }
|
||||||
ProgramCounter end() { return m_endInstIdx; }
|
ProgramCounter end() { return m_endInstIdx; }
|
||||||
|
|
||||||
|
bool isJumpDest() const { return m_isJumpDest; }
|
||||||
|
void markAsJumpDest() { m_isJumpDest = true; }
|
||||||
|
|
||||||
LocalStack& localStack() { return m_stack; }
|
LocalStack& localStack() { return m_stack; }
|
||||||
|
|
||||||
/// Optimization: propagates values between local stacks in basic blocks
|
/// Optimization: propagates values between local stacks in basic blocks
|
||||||
|
|
@ -109,6 +112,10 @@ private:
|
||||||
/// How many items higher is the current stack than the initial one.
|
/// How many items higher is the current stack than the initial one.
|
||||||
/// May be negative.
|
/// May be negative.
|
||||||
int m_tosOffset = 0;
|
int m_tosOffset = 0;
|
||||||
|
|
||||||
|
/// Is the basic block a valid jump destination.
|
||||||
|
/// JUMPDEST is the first instruction of the basic block.
|
||||||
|
bool m_isJumpDest = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,10 +95,27 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
|
||||||
|
|
||||||
m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc);
|
m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc);
|
||||||
m_badJumpBlock = std::unique_ptr<BasicBlock>(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder));
|
m_badJumpBlock = std::unique_ptr<BasicBlock>(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder));
|
||||||
m_jumpTableBlock = std::unique_ptr<BasicBlock>(new BasicBlock("JumpTableBlock", m_mainFunc, m_builder));
|
|
||||||
|
|
||||||
for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it)
|
for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it)
|
||||||
m_jumpDests[*it] = basicBlocks.find(*it)->second.llvm();
|
basicBlocks.find(*it)->second.markAsJumpDest();
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicBlock& Compiler::getJumpTableBlock()
|
||||||
|
{
|
||||||
|
if (!m_jumpTableBlock)
|
||||||
|
{
|
||||||
|
m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder));
|
||||||
|
InsertPointGuard g{m_builder};
|
||||||
|
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
||||||
|
auto dest = m_jumpTableBlock->localStack().pop();
|
||||||
|
auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm());
|
||||||
|
for (auto&& p : basicBlocks)
|
||||||
|
{
|
||||||
|
if (p.second.isJumpDest())
|
||||||
|
switchInstr->addCase(Constant::get(p.first), p.second.llvm());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *m_jumpTableBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::string const& _id)
|
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::string const& _id)
|
||||||
|
|
@ -144,21 +161,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::str
|
||||||
m_builder.SetInsertPoint(m_badJumpBlock->llvm());
|
m_builder.SetInsertPoint(m_badJumpBlock->llvm());
|
||||||
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
|
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
|
||||||
|
|
||||||
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
|
||||||
if (m_jumpDests.size() > 0)
|
|
||||||
{
|
|
||||||
auto dest = m_jumpTableBlock->localStack().pop();
|
|
||||||
auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(), m_jumpDests.size());
|
|
||||||
for (auto it = m_jumpDests.cbegin(); it != m_jumpDests.cend(); ++it)
|
|
||||||
{
|
|
||||||
auto& bb = *it;
|
|
||||||
auto dest = Constant::get(it->first);
|
|
||||||
switchInstr->addCase(dest, it->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_builder.CreateBr(m_badJumpBlock->llvm());
|
|
||||||
|
|
||||||
removeDeadBlocks();
|
removeDeadBlocks();
|
||||||
|
|
||||||
dumpCFGifRequired("blocks-init.dot");
|
dumpCFGifRequired("blocks-init.dot");
|
||||||
|
|
@ -552,16 +554,14 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
|
||||||
if (c.ult(_bytecode.size()))
|
if (c.ult(_bytecode.size()))
|
||||||
{
|
{
|
||||||
auto v = c.getZExtValue();
|
auto v = c.getZExtValue();
|
||||||
auto it = m_jumpDests.find(v);
|
auto it = basicBlocks.find(v);
|
||||||
if (it != m_jumpDests.end())
|
if (it != basicBlocks.end() && it->second.isJumpDest())
|
||||||
targetBlock = it->second;
|
targetBlock = it->second.llvm();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetBlock)
|
if (!targetBlock)
|
||||||
{
|
|
||||||
targetBlock = m_badJumpBlock->llvm();
|
targetBlock = m_badJumpBlock->llvm();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (inst == Instruction::JUMP)
|
if (inst == Instruction::JUMP)
|
||||||
{
|
{
|
||||||
|
|
@ -574,7 +574,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stack.push(target);
|
stack.push(target);
|
||||||
m_builder.CreateBr(m_jumpTableBlock->llvm());
|
m_builder.CreateBr(getJumpTableBlock().llvm());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // JUMPI
|
else // JUMPI
|
||||||
|
|
@ -594,7 +594,6 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
|
||||||
m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock);
|
m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -830,13 +829,6 @@ void Compiler::removeDeadBlocks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (sthErased);
|
while (sthErased);
|
||||||
|
|
||||||
// Remove jump table block if no predecessors
|
|
||||||
if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm()))
|
|
||||||
{
|
|
||||||
m_jumpTableBlock->llvm()->eraseFromParent();
|
|
||||||
m_jumpTableBlock.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::dumpCFGifRequired(std::string const& _dotfilePath)
|
void Compiler::dumpCFGifRequired(std::string const& _dotfilePath)
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ private:
|
||||||
|
|
||||||
void compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock);
|
void compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock);
|
||||||
|
|
||||||
|
BasicBlock& getJumpTableBlock();
|
||||||
|
|
||||||
void removeDeadBlocks();
|
void removeDeadBlocks();
|
||||||
|
|
||||||
/// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled.
|
/// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled.
|
||||||
|
|
@ -65,10 +67,7 @@ private:
|
||||||
llvm::IRBuilder<> m_builder;
|
llvm::IRBuilder<> m_builder;
|
||||||
|
|
||||||
/// Maps a program counter pc to a basic block that starts at pc (if any).
|
/// Maps a program counter pc to a basic block that starts at pc (if any).
|
||||||
std::map<ProgramCounter, BasicBlock> basicBlocks = {};
|
std::map<ProgramCounter, BasicBlock> basicBlocks;
|
||||||
|
|
||||||
/// Map of jump destinations
|
|
||||||
std::map<ProgramCounter, llvm::BasicBlock*> m_jumpDests = {};
|
|
||||||
|
|
||||||
/// Stop basic block - terminates execution with STOP code (0)
|
/// Stop basic block - terminates execution with STOP code (0)
|
||||||
llvm::BasicBlock* m_stopBB = nullptr;
|
llvm::BasicBlock* m_stopBB = nullptr;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue