Skip to content

Commit

Permalink
Reduce stack usage of ParseExpectKet when no array indices are used
Browse files Browse the repository at this point in the history
  • Loading branch information
dc42 committed Apr 16, 2024
1 parent 66f8afa commit e7cc658
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 26 deletions.
58 changes: 32 additions & 26 deletions src/GCodes/GCodeBuffer/ExpressionParser.cpp
Expand Up @@ -24,11 +24,12 @@ namespace StackUsage
{
// The following values are the number of bytes of stack space needed by the corresponding functions and functions they call,
// not counting other called functions that call CheckStack. They are obtained from file ExpressionParser.su generated by the compiler.
constexpr uint32_t ParseInternal = 80;
constexpr uint32_t ParseIdentifierExpression = 288;
constexpr uint32_t ParseInternal = 72;
constexpr uint32_t ParseIdentifierExpression = 296;
constexpr uint32_t GetObjectValueUsingTableNumber = 48;
constexpr uint32_t ReadArrayFromFile = 384;
constexpr uint32_t ParseGeneralArray = 360;
constexpr uint32_t ApplyObjectModelArrayIndex = 112;
}

// Read a character from the text file.
Expand Down Expand Up @@ -107,30 +108,8 @@ void ExpressionParser::ParseExpectKet(ExpressionValue& rslt, bool evaluate, char
switch (rslt.GetType())
{
case TypeCode::ObjectModelArray:
{
const ObjectModelArrayTableEntry *const entry = rslt.omVal->FindObjectModelArrayEntry(rslt.param & 0xFF);
if (entry == nullptr)
{
THROW_INTERNAL_ERROR;
}
ObjectExplorationContext context;
context.AddIndex(rslt.param >> 16);
ReadLocker lock(entry->lockPointer);
const size_t numElements = entry->GetNumElements(rslt.omVal, context);
if (indexValue < numElements)
{
context.AddIndex(indexValue);
rslt = entry->GetElement(rslt.omVal, context);
}
else if (evaluate)
{
throw GCodeException(&gb, indexCol, "array index out of range");
}
else
{
rslt.SetNull(nullptr);
}
}
CheckStack(StackUsage::ApplyObjectModelArrayIndex);
ApplyObjectModelArrayIndex(rslt, indexCol, indexValue, evaluate); // call out to separate function to reduce stack usage of this one from 128 to 32 bytes
break;

case TypeCode::HeapArray:
Expand Down Expand Up @@ -161,6 +140,33 @@ void ExpressionParser::ParseExpectKet(ExpressionValue& rslt, bool evaluate, char
}
}

// Handle an index after an object model array expression.
void ExpressionParser::ApplyObjectModelArrayIndex(ExpressionValue& rslt, int indexCol, uint32_t indexValue, bool evaluate) THROWS(GCodeException)
{
const ObjectModelArrayTableEntry *const entry = rslt.omVal->FindObjectModelArrayEntry(rslt.param & 0xFF);
if (entry == nullptr)
{
THROW_INTERNAL_ERROR;
}
ObjectExplorationContext context;
context.AddIndex(rslt.param >> 16);
ReadLocker lock(entry->lockPointer);
const size_t numElements = entry->GetNumElements(rslt.omVal, context);
if (indexValue < numElements)
{
context.AddIndex(indexValue);
rslt = entry->GetElement(rslt.omVal, context);
}
else if (evaluate)
{
throw GCodeException(&gb, indexCol, "array index out of range");
}
else
{
rslt.SetNull(nullptr);
}
}

// Evaluate an expression. Do not call this one recursively!
ExpressionValue ExpressionParser::Parse(bool evaluate) THROWS(GCodeException)
{
Expand Down
2 changes: 2 additions & 0 deletions src/GCodes/GCodeBuffer/ExpressionParser.h
Expand Up @@ -106,6 +106,8 @@ class ExpressionParser
void __attribute__((noinline)) ReadArrayFromFile(ExpressionValue& rslt, unsigned int offset, unsigned int length, char delimiter) const THROWS(GCodeException);
void ReadArrayElementFromFile(ExpressionValue& rslt, LineReader& reader, char delimiter) const THROWS(GCodeException);
void GetNextOperand(ExpressionValue& operand, bool evaluate) THROWS(GCodeException);
void __attribute__((noinline)) ApplyObjectModelArrayIndex(ExpressionValue& rslt, int indexCol, uint32_t indexValue, bool evaluate) THROWS(GCodeException);

static bool TypeHasNoLiterals(TypeCode t) noexcept;

int GetColumn() const noexcept;
Expand Down

0 comments on commit e7cc658

Please sign in to comment.