From 76d30b8f9f0f0e8b1b4786e8438c6eb105be2da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 16 Dec 2014 19:52:02 +0100 Subject: [PATCH] Count additional gas cost for memory copies. Some GasMeter improvments. --- libevmjit/GasMeter.cpp | 37 ++++++++++++++++++++++++------------- libevmjit/GasMeter.h | 8 +++++++- libevmjit/Memory.cpp | 10 ++++++++-- libevmjit/Memory.h | 5 ++++- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index e2f45621b..0f67045a3 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -43,11 +43,16 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure { switch (inst) { + default: // Assumes instruction code is valid + return 1; + case Instruction::STOP: case Instruction::SUICIDE: case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore() return 0; + case Instruction::EXP: return c_expGas; + case Instruction::SLOAD: return c_sloadGas; case Instruction::SHA3: return c_sha3Gas; @@ -68,9 +73,6 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure auto numTopics = static_cast(inst) - static_cast(Instruction::LOG0); return c_logGas + numTopics * c_logTopicGas; } - - default: // Assumes instruction code is valid - return 1; } } @@ -144,6 +146,11 @@ void GasMeter::count(Instruction _inst) commitCostBlock(); } +void GasMeter::count(llvm::Value* _cost) +{ + createCall(m_gasCheckFunc, _cost); +} + void GasMeter::countExp(llvm::Value* _exponent) { // Additional cost is 1 per significant byte of exponent @@ -156,7 +163,7 @@ void GasMeter::countExp(llvm::Value* _exponent) auto lz = m_builder.CreateCall2(ctlz, _exponent, m_builder.getInt1(false)); auto sigBits = m_builder.CreateSub(Constant::get(256), lz); auto sigBytes = m_builder.CreateUDiv(m_builder.CreateAdd(sigBits, Constant::get(7)), Constant::get(8)); - createCall(m_gasCheckFunc, sigBytes); + count(sigBytes); } void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValue) @@ -172,15 +179,15 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu auto isDelete = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDelete"); auto cost = m_builder.CreateSelect(isInsert, Constant::get(c_sstoreSetGas), Constant::get(c_sstoreResetGas), "cost"); cost = m_builder.CreateSelect(isDelete, Constant::get(0), cost, "cost"); - createCall(m_gasCheckFunc, cost); + count(cost); } void GasMeter::countLogData(llvm::Value* _dataLength) { assert(m_checkCall); assert(m_blockCost > 0); // LOGn instruction is already counted - auto cost = m_builder.CreateMul(_dataLength, Constant::get(c_logDataGas), "logdata_cost"); - commitCostBlock(cost); + static_assert(c_logDataGas == 1, "Log data gas cost has changed. Update GasMeter."); + commitCostBlock(_dataLength); // TODO: commit is not necessary } void GasMeter::giveBack(llvm::Value* _gas) @@ -207,17 +214,21 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) m_blockCost = 0; if (_additionalCost) - { - m_builder.CreateCall(m_gasCheckFunc, _additionalCost); - } + count(_additionalCost); } assert(m_blockCost == 0); } -void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords) +void GasMeter::countMemory(llvm::Value* _additionalMemoryInWords) +{ + static_assert(c_memoryGas == 1, "Memory gas cost has changed. Update GasMeter."); + count(_additionalMemoryInWords); +} + +void GasMeter::countCopy(llvm::Value* _copyWords) { - auto cost = m_builder.CreateNUWMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); - m_builder.CreateCall(m_gasCheckFunc, cost); + static_assert(c_copyGas == 1, "Copy gas cost has changed. Update GasMeter."); + count(_copyWords); } } diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 2346bc714..2d8fb3044 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -20,6 +20,9 @@ public: /// Count step cost of instruction void count(Instruction _inst); + /// Count additional cost + void count(llvm::Value* _cost); + /// Calculate & count gas cost for SSTORE instruction void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue); @@ -37,7 +40,10 @@ public: void giveBack(llvm::Value* _gas); /// Generate code that checks the cost of additional memory used by program - void checkMemory(llvm::Value* _additionalMemoryInWords); + void countMemory(llvm::Value* _additionalMemoryInWords); + + /// Count addional gas cost for memory copy + void countCopy(llvm::Value* _copyWords); private: /// Cumulative gas cost of a block of instructions diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index d87c76035..18d53e63e 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -24,7 +24,8 @@ namespace jit { Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): - RuntimeHelper(_runtimeManager) + RuntimeHelper(_runtimeManager), + m_gasMeter(_gasMeter) { auto module = getModule(); llvm::Type* argTypes[] = {Type::Word, Type::Word}; @@ -88,7 +89,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _ sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq"); auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words"); // size is always 32*k auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords"); - _gasMeter.checkMemory(newWords); + _gasMeter.countMemory(newWords); // Resize m_builder.CreateStore(sizeRequired, m_size); auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData"); @@ -186,6 +187,11 @@ void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* require(_destMemIdx, _reqBytes); + // Additional copy cost + // TODO: This round ups to 32 happens in many places + auto copyWords = m_builder.CreateUDiv(m_builder.CreateAdd(_reqBytes, Constant::get(31)), Constant::get(32)); + m_gasMeter.countCopy(copyWords); + auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx"); auto memPtr = getData(); diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index 8d33fbc4f..3ccc54285 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -8,11 +8,12 @@ namespace eth { namespace jit { +class GasMeter; class Memory : public RuntimeHelper { public: - Memory(RuntimeManager& _runtimeManager, class GasMeter& _gasMeter); + Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -27,6 +28,8 @@ public: void require(llvm::Value* _offset, llvm::Value* _size); private: + GasMeter& m_gasMeter; + llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager);