mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
perf: Dispatch hasInvalidAmount on type tag instead of dynamic_cast
hasInvalidAmount runs on the per-transaction invariant-checking path (ValidAmounts::finalize) and at preflight, walking every field of every modified entry. The previous implementation tried a dynamic_cast chain (STAmount, STObject, STArray) on each field, so every scalar non-amount field paid three failed RTTI casts. Dispatch on the serialized type tag via getSType() and a switch instead. The object-like tags all denote STObject subclasses (STLedgerEntry, STTx), so the downcast is sound; safeDowncast keeps a dynamic_cast validity assert in debug builds while compiling to static_cast in release.
This commit is contained in:
@@ -1250,16 +1250,30 @@ hasInvalidAmount(STBase const& field, int depth, beast::Journal j)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto const amount = dynamic_cast<STAmount const*>(&field))
|
||||
return !isLegalMPT(*amount) || !isLegalNet(*amount);
|
||||
// Dispatch on the serialized type tag rather than RTTI: this is on the invariant-checking path
|
||||
// and a dynamic_cast chain over every field of every modified entry is measurably expensive.
|
||||
// The object-like tags below all denote STObject subclasses (STLedgerEntry, STTx), so the
|
||||
// downcast is sound; nested fields are only ever plain STI_OBJECT / STI_ARRAY containers.
|
||||
// safeDowncast keeps a dynamic_cast validity assert in debug builds while compiling to
|
||||
// static_cast in release.
|
||||
switch (field.getSType())
|
||||
{
|
||||
case STI_AMOUNT: {
|
||||
auto const& amount = safeDowncast<STAmount const&>(field);
|
||||
return !isLegalMPT(amount) || !isLegalNet(amount);
|
||||
}
|
||||
|
||||
if (auto const object = dynamic_cast<STObject const*>(&field))
|
||||
return hasInvalidAmount(*object, depth + 1, j);
|
||||
case STI_OBJECT:
|
||||
case STI_LEDGERENTRY:
|
||||
case STI_TRANSACTION:
|
||||
return hasInvalidAmount(safeDowncast<STObject const&>(field), depth + 1, j);
|
||||
|
||||
if (auto const array = dynamic_cast<STArray const*>(&field))
|
||||
return hasInvalidAmount(*array, depth + 1, j);
|
||||
case STI_ARRAY:
|
||||
return hasInvalidAmount(safeDowncast<STArray const&>(field), depth + 1, j);
|
||||
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
Reference in New Issue
Block a user