mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
Count additional gas cost for memory copies. Some GasMeter improvments.
This commit is contained in:
parent
077cf7be5d
commit
76d30b8f9f
4 changed files with 43 additions and 17 deletions
|
|
@ -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<uint64_t>(inst) - static_cast<uint64_t>(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)
|
||||
{
|
||||
auto cost = m_builder.CreateNUWMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(c_memoryGas)), "memcost");
|
||||
m_builder.CreateCall(m_gasCheckFunc, cost);
|
||||
static_assert(c_memoryGas == 1, "Memory gas cost has changed. Update GasMeter.");
|
||||
count(_additionalMemoryInWords);
|
||||
}
|
||||
|
||||
void GasMeter::countCopy(llvm::Value* _copyWords)
|
||||
{
|
||||
static_assert(c_copyGas == 1, "Copy gas cost has changed. Update GasMeter.");
|
||||
count(_copyWords);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue