Browse Source

Update gas.check helper function: Runtime pointer not needed

cl-refactor
Paweł Bylica 10 years ago
parent
commit
d2c82bf9c9
  1. 4
      evmjit/libevmjit/Compiler.cpp
  2. 42
      evmjit/libevmjit/GasMeter.cpp
  3. 2
      evmjit/libevmjit/RuntimeManager.h
  4. 6
      evmjit/libevmjit/Type.cpp
  5. 3
      evmjit/libevmjit/Type.h

4
evmjit/libevmjit/Compiler.cpp

@ -9,7 +9,6 @@
#include <llvm/IR/CFG.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/MDBuilder.h>
#include "preprocessor/llvm_includes_end.h"
#include "Instruction.h"
@ -162,8 +161,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
auto abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc);
auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm();
auto expectTrue = llvm::MDBuilder{m_builder.getContext()}.createBranchWeights(1, 0);
m_builder.CreateCondBr(normalFlow, firstBB, abortBB, expectTrue);
m_builder.CreateCondBr(normalFlow, firstBB, abortBB, Type::expectTrue);
for (auto basicBlockPairIt = m_basicBlocks.begin(); basicBlockPairIt != m_basicBlocks.end(); ++basicBlockPairIt)
{

42
evmjit/libevmjit/GasMeter.cpp

@ -82,34 +82,36 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager)
CompilerHelper(_builder),
m_runtimeManager(_runtimeManager)
{
auto module = getModule();
llvm::Type* gasCheckArgs[] = {Type::RuntimePtr, Type::Gas};
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, gasCheckArgs, false), llvm::Function::PrivateLinkage, "gas.check", module);
InsertPointGuard guard(m_builder);
llvm::Type* gasCheckArgs[] = {Type::Gas->getPointerTo(), Type::Gas, Type::BytePtr};
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, gasCheckArgs, false), llvm::Function::PrivateLinkage, "gas.check", getModule());
m_gasCheckFunc->setDoesNotThrow();
m_gasCheckFunc->setDoesNotCapture(1);
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc);
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc);
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc);
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc);
auto rt = &m_gasCheckFunc->getArgumentList().front();
rt->setName("rt");
auto cost = rt->getNextNode();
auto gasPtr = &m_gasCheckFunc->getArgumentList().front();
gasPtr->setName("gasPtr");
auto cost = gasPtr->getNextNode();
cost->setName("cost");
auto jmpBuf = cost->getNextNode();
jmpBuf->setName("jmpBuf");
InsertPointGuard guard(m_builder);
m_builder.SetInsertPoint(checkBB);
auto gas = m_runtimeManager.getGas();
gas = m_builder.CreateNSWSub(gas, cost, "gasUpdated");
auto isOutOfGas = m_builder.CreateICmpSLT(gas, m_builder.getInt64(0), "isOutOfGas"); // gas < 0, with gas == 0 we can still do 0 cost instructions
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB);
m_builder.SetInsertPoint(outOfGasBB);
m_runtimeManager.abort();
m_builder.CreateUnreachable();
auto gas = m_builder.CreateLoad(gasPtr, "gas");
auto gasUpdated = m_builder.CreateNSWSub(gas, cost, "gasUpdated");
auto gasOk = m_builder.CreateICmpSGE(gasUpdated, m_builder.getInt64(0), "gasOk"); // gas >= 0, with gas == 0 we can still do 0 cost instructions
m_builder.CreateCondBr(gasOk, updateBB, outOfGasBB, Type::expectTrue);
m_builder.SetInsertPoint(updateBB);
m_runtimeManager.setGas(gas);
m_builder.CreateStore(gasUpdated, gasPtr);
m_builder.CreateRetVoid();
m_builder.SetInsertPoint(outOfGasBB);
m_runtimeManager.abort(jmpBuf);
m_builder.CreateUnreachable();
}
void GasMeter::count(Instruction _inst)
@ -117,7 +119,7 @@ void GasMeter::count(Instruction _inst)
if (!m_checkCall)
{
// Create gas check call with mocked block cost at begining of current cost-block
m_checkCall = createCall(m_gasCheckFunc, {m_runtimeManager.getRuntimePtr(), llvm::UndefValue::get(Type::Gas)});
m_checkCall = createCall(m_gasCheckFunc, {m_runtimeManager.getGasPtr(), llvm::UndefValue::get(Type::Gas), m_runtimeManager.getJmpBuf()});
}
m_blockCost += getStepCost(_inst);
@ -134,7 +136,7 @@ void GasMeter::count(llvm::Value* _cost)
}
assert(_cost->getType() == Type::Gas);
createCall(m_gasCheckFunc, {m_runtimeManager.getRuntimePtr(), _cost});
createCall(m_gasCheckFunc, {m_runtimeManager.getGasPtr(), _cost, m_runtimeManager.getJmpBufExt()});
}
void GasMeter::countExp(llvm::Value* _exponent)

2
evmjit/libevmjit/RuntimeManager.h

@ -31,6 +31,7 @@ public:
llvm::Value* getCodeSize();
llvm::Value* getCallDataSize();
llvm::Value* getJmpBuf() { return m_jmpBuf; }
llvm::Value* getJmpBufExt();
void setGas(llvm::Value* _gas);
void registerReturnData(llvm::Value* _index, llvm::Value* _size);
@ -49,7 +50,6 @@ public:
private:
llvm::Value* getPtr(RuntimeData::Index _index);
void set(RuntimeData::Index _index, llvm::Value* _value);
llvm::Value* getJmpBufExt();
llvm::Function* m_longjmp = nullptr;
llvm::Value* const m_jmpBuf;

6
evmjit/libevmjit/Type.cpp

@ -1,4 +1,7 @@
#include "Type.h"
#include <llvm/IR/MDBuilder.h>
#include "RuntimeManager.h"
namespace dev
@ -23,6 +26,7 @@ llvm::PointerType* Type::EnvPtr;
llvm::PointerType* Type::RuntimeDataPtr;
llvm::PointerType* Type::RuntimePtr;
llvm::ConstantInt* Constant::gasMax;
llvm::MDNode* Type::expectTrue;
void Type::init(llvm::LLVMContext& _context)
{
@ -46,6 +50,8 @@ void Type::init(llvm::LLVMContext& _context)
RuntimePtr = RuntimeManager::getRuntimeType()->getPointerTo();
Constant::gasMax = llvm::ConstantInt::getSigned(Type::Gas, std::numeric_limits<int64_t>::max());
expectTrue = llvm::MDBuilder{_context}.createBranchWeights(1, 0);
}
}

3
evmjit/libevmjit/Type.h

@ -40,6 +40,9 @@ struct Type
static llvm::PointerType* RuntimeDataPtr;
static llvm::PointerType* RuntimePtr;
// TODO: Redesign static LLVM objects
static llvm::MDNode* expectTrue;
static void init(llvm::LLVMContext& _context);
};

Loading…
Cancel
Save