Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/compiler/evm_frontend/evm_imported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,8 +662,7 @@ void evmExpandMemoryNoGas(zen::runtime::EVMInstance *Instance,
}

uint64_t evmGetReturnDataSize(zen::runtime::EVMInstance *Instance) {
const auto &ReturnData = Instance->getReturnData();
return ReturnData.size();
return Instance->getReturnDataSize();
}

template <size_t MaxTopics>
Expand Down
6 changes: 4 additions & 2 deletions src/compiler/evm_frontend/evm_mir_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4627,8 +4627,10 @@ void EVMMirBuilder::handleReturnDataCopy(Operand DestOffsetComponents,
}

typename EVMMirBuilder::Operand EVMMirBuilder::handleReturnDataSize() {
const auto &RuntimeFunctions = getRuntimeFunctionTable();
return callRuntimeFor<uint64_t>(RuntimeFunctions.GetReturnDataSize);
MInstruction *ReturnDataSize = getInstanceElement(
&Ctx.I64Type, zen::runtime::EVMInstance::getReturnDataSizeOffset());
ReturnDataSize = protectUnsafeValue(ReturnDataSize, &Ctx.I64Type);
return convertSingleInstrToU256Operand(ReturnDataSize);
}

bool EVMMirBuilder::hasMemoryCompileStats() const {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/evm_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void EVMInstance::resetForNewCall(evmc_revision NewRev) {
MemoryStack.clear();

// Reset output
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In resetForNewCall(), switching from ReturnData.clear() to clearReturnData() changes the buffer-retention behavior: clearReturnDataBuffer() will deallocate when capacity > ReturnDataReleaseThreshold (64KB). If callers frequently return large data, this can introduce repeated alloc/free churn across calls. If this is intentional, consider adding a short comment here documenting the memory/perf tradeoff; otherwise consider preserving the previous behavior (clear size without releasing capacity) while still resetting ReturnDataSize.

Suggested change
// Reset output
// Reset output.
// Note: clearReturnData() may release the underlying buffer when its
// capacity exceeds ReturnDataReleaseThreshold to cap peak memory usage,
// at the cost of possible alloc/free churn if large return data is common.

Copilot uses AI. Check for mistakes.
ReturnData.clear();
clearReturnData();
ExeResult = evmc::Result{EVMC_SUCCESS, 0, 0};

// Reset execution cache: clear() keeps allocated bucket arrays,
Expand Down
15 changes: 14 additions & 1 deletion src/runtime/evm_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,15 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
InstanceExecutionCache.clear();
}
void setReturnData(std::vector<uint8_t> Data) {
ReturnDataSize = Data.size();
ReturnData = std::move(Data);
}
void clearReturnData() { clearReturnDataBuffer(ReturnData); }
void clearReturnData() {
clearReturnDataBuffer(ReturnData);
ReturnDataSize = 0;
}
const std::vector<uint8_t> &getReturnData() const { return ReturnData; }
uint64_t getReturnDataSize() const { return ReturnDataSize; }
void setExeResult(evmc::Result Result) { ExeResult = std::move(Result); }
const evmc::Result &getExeResult() const { return ExeResult; }
void exit(int32_t ExitCode);
Expand Down Expand Up @@ -294,6 +299,13 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
return static_cast<int32_t>(offsetof(EVMInstance, MemorySize));
}

static constexpr int32_t getReturnDataSizeOffset() {
static_assert(offsetof(EVMInstance, ReturnDataSize) <=
std::numeric_limits<int32_t>::max(),
"EVMInstance offsets should fit in 32-bit signed range");
return static_cast<int32_t>(offsetof(EVMInstance, ReturnDataSize));
}

// Capacity for EVMStack: 1024 * 256 / 8 = 32768
static const size_t EVMStackCapacity = 32768;

Expand Down Expand Up @@ -380,6 +392,7 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
};
std::vector<MemoryFrame> MemoryStack;
std::vector<uint8_t> ReturnData;
uint64_t ReturnDataSize = 0;
evmc::Result ExeResult{EVMC_SUCCESS, 0, 0};

// Message stack for call hierarchy tracking
Expand Down
Loading