mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +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)
|
switch (inst)
|
||||||
{
|
{
|
||||||
|
default: // Assumes instruction code is valid
|
||||||
|
return 1;
|
||||||
|
|
||||||
case Instruction::STOP:
|
case Instruction::STOP:
|
||||||
case Instruction::SUICIDE:
|
case Instruction::SUICIDE:
|
||||||
case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore()
|
case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore()
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case Instruction::EXP: return c_expGas;
|
||||||
|
|
||||||
case Instruction::SLOAD: return c_sloadGas;
|
case Instruction::SLOAD: return c_sloadGas;
|
||||||
|
|
||||||
case Instruction::SHA3: return c_sha3Gas;
|
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);
|
auto numTopics = static_cast<uint64_t>(inst) - static_cast<uint64_t>(Instruction::LOG0);
|
||||||
return c_logGas + numTopics * c_logTopicGas;
|
return c_logGas + numTopics * c_logTopicGas;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // Assumes instruction code is valid
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,6 +146,11 @@ void GasMeter::count(Instruction _inst)
|
||||||
commitCostBlock();
|
commitCostBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GasMeter::count(llvm::Value* _cost)
|
||||||
|
{
|
||||||
|
createCall(m_gasCheckFunc, _cost);
|
||||||
|
}
|
||||||
|
|
||||||
void GasMeter::countExp(llvm::Value* _exponent)
|
void GasMeter::countExp(llvm::Value* _exponent)
|
||||||
{
|
{
|
||||||
// Additional cost is 1 per significant byte of 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 lz = m_builder.CreateCall2(ctlz, _exponent, m_builder.getInt1(false));
|
||||||
auto sigBits = m_builder.CreateSub(Constant::get(256), lz);
|
auto sigBits = m_builder.CreateSub(Constant::get(256), lz);
|
||||||
auto sigBytes = m_builder.CreateUDiv(m_builder.CreateAdd(sigBits, Constant::get(7)), Constant::get(8));
|
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)
|
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 isDelete = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDelete");
|
||||||
auto cost = m_builder.CreateSelect(isInsert, Constant::get(c_sstoreSetGas), Constant::get(c_sstoreResetGas), "cost");
|
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");
|
cost = m_builder.CreateSelect(isDelete, Constant::get(0), cost, "cost");
|
||||||
createCall(m_gasCheckFunc, cost);
|
count(cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GasMeter::countLogData(llvm::Value* _dataLength)
|
void GasMeter::countLogData(llvm::Value* _dataLength)
|
||||||
{
|
{
|
||||||
assert(m_checkCall);
|
assert(m_checkCall);
|
||||||
assert(m_blockCost > 0); // LOGn instruction is already counted
|
assert(m_blockCost > 0); // LOGn instruction is already counted
|
||||||
auto cost = m_builder.CreateMul(_dataLength, Constant::get(c_logDataGas), "logdata_cost");
|
static_assert(c_logDataGas == 1, "Log data gas cost has changed. Update GasMeter.");
|
||||||
commitCostBlock(cost);
|
commitCostBlock(_dataLength); // TODO: commit is not necessary
|
||||||
}
|
}
|
||||||
|
|
||||||
void GasMeter::giveBack(llvm::Value* _gas)
|
void GasMeter::giveBack(llvm::Value* _gas)
|
||||||
|
|
@ -207,17 +214,21 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost)
|
||||||
m_blockCost = 0;
|
m_blockCost = 0;
|
||||||
|
|
||||||
if (_additionalCost)
|
if (_additionalCost)
|
||||||
{
|
count(_additionalCost);
|
||||||
m_builder.CreateCall(m_gasCheckFunc, _additionalCost);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
assert(m_blockCost == 0);
|
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");
|
static_assert(c_memoryGas == 1, "Memory gas cost has changed. Update GasMeter.");
|
||||||
m_builder.CreateCall(m_gasCheckFunc, cost);
|
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
|
/// Count step cost of instruction
|
||||||
void count(Instruction _inst);
|
void count(Instruction _inst);
|
||||||
|
|
||||||
|
/// Count additional cost
|
||||||
|
void count(llvm::Value* _cost);
|
||||||
|
|
||||||
/// Calculate & count gas cost for SSTORE instruction
|
/// Calculate & count gas cost for SSTORE instruction
|
||||||
void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue);
|
void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue);
|
||||||
|
|
||||||
|
|
@ -37,7 +40,10 @@ public:
|
||||||
void giveBack(llvm::Value* _gas);
|
void giveBack(llvm::Value* _gas);
|
||||||
|
|
||||||
/// Generate code that checks the cost of additional memory used by program
|
/// 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:
|
private:
|
||||||
/// Cumulative gas cost of a block of instructions
|
/// Cumulative gas cost of a block of instructions
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ namespace jit
|
||||||
{
|
{
|
||||||
|
|
||||||
Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
|
Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
|
||||||
RuntimeHelper(_runtimeManager)
|
RuntimeHelper(_runtimeManager),
|
||||||
|
m_gasMeter(_gasMeter)
|
||||||
{
|
{
|
||||||
auto module = getModule();
|
auto module = getModule();
|
||||||
llvm::Type* argTypes[] = {Type::Word, Type::Word};
|
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");
|
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 words = m_builder.CreateUDiv(currSize, Constant::get(32), "words"); // size is always 32*k
|
||||||
auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
|
auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
|
||||||
_gasMeter.checkMemory(newWords);
|
_gasMeter.countMemory(newWords);
|
||||||
// Resize
|
// Resize
|
||||||
m_builder.CreateStore(sizeRequired, m_size);
|
m_builder.CreateStore(sizeRequired, m_size);
|
||||||
auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData");
|
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);
|
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 srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx");
|
||||||
|
|
||||||
auto memPtr = getData();
|
auto memPtr = getData();
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@ namespace eth
|
||||||
{
|
{
|
||||||
namespace jit
|
namespace jit
|
||||||
{
|
{
|
||||||
|
class GasMeter;
|
||||||
|
|
||||||
class Memory : public RuntimeHelper
|
class Memory : public RuntimeHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Memory(RuntimeManager& _runtimeManager, class GasMeter& _gasMeter);
|
Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter);
|
||||||
|
|
||||||
llvm::Value* loadWord(llvm::Value* _addr);
|
llvm::Value* loadWord(llvm::Value* _addr);
|
||||||
void storeWord(llvm::Value* _addr, llvm::Value* _word);
|
void storeWord(llvm::Value* _addr, llvm::Value* _word);
|
||||||
|
|
@ -27,6 +28,8 @@ public:
|
||||||
void require(llvm::Value* _offset, llvm::Value* _size);
|
void require(llvm::Value* _offset, llvm::Value* _size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GasMeter& m_gasMeter;
|
||||||
|
|
||||||
llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter);
|
llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter);
|
||||||
llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
|
llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue