diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index eaf9f50cd..06c5e30ed 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -9,7 +9,7 @@ namespace Poincare { class FunctionNode : public SymbolNode { public: // TreeNode - size_t size() const override { return sizeof(FunctionNode); } + size_t size() const override; int numberOfChildren() const override { return 1; } //TODO allow any number of children? Needs templating #if POINCARE_TREE_LOG virtual void logNodeName(std::ostream & stream) const override { diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 26cbef4d1..7632daadb 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -8,6 +8,15 @@ namespace Poincare { /* TODO: should we keep the size of SymbolNode as a member to speed up TreePool * scan? */ +/* Symbol Node contains an empty member variable "m_name", which is used to get + * the string that follows. This means that a SymbolNode's size is sizeo + * (SymbolNode) + strlen(string). + * + * Seen by TreePool: |SymbolNode | + * SymbolNode layout: |ExpressionNode|m_name| | + * Memory content: |ExpressionNode|S |y|m|b|o|l|N|a|m|e|0| + * */ + class SymbolNode final : public ExpressionNode { friend class Store; public: @@ -54,11 +63,11 @@ public: bool isPi() const { return isSymbolChar(Ion::Charset::SmallPi); } bool isExponential() const { return isSymbolChar(Ion::Charset::Exponential); } bool isIComplex() const { return isSymbolChar(Ion::Charset::IComplex); } +protected: + char m_name[0]; // MUST be the last member variable private: template Evaluation templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const; bool isSymbolChar(char c) const { const char symbolName[2] = {c, 0}; return strcmp(m_name, symbolName) == 0; } - - char m_name[0]; }; class Symbol final : public Expression { diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index a4fb31773..ef0c6fc35 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,6 +9,16 @@ namespace Poincare { +/* TreePool uses adresses and sizes that are multiples of 4 in order to make + * node moves faster.*/ +static size_t NodeSize(size_t nameLength) { + return Helpers::AlignedSize(sizeof(FunctionNode)+nameLength+1, 4); +} + +size_t FunctionNode::size() const { + return NodeSize(strlen(m_name)); +} + Expression FunctionNode::replaceSymbolWithExpression(const Symbol & symbol, const Expression & expression) { return Function(this).replaceSymbolWithExpression(symbol, expression); } @@ -87,7 +98,7 @@ Evaluation FunctionNode::approximate(DoublePrecision p, Context& context } Function::Function(const char * name) : - Function(TreePool::sharedPool()->createTreeNode()) + Function(TreePool::sharedPool()->createTreeNode(NodeSize(strlen(name)))) { static_cast(Expression::node())->setName(name, strlen(name)); } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 0cfb86793..917e1fd43 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -1,10 +1,11 @@ #include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include #include #include #include @@ -16,17 +17,12 @@ constexpr char Symbol::k_ans[]; /* TreePool uses adresses and sizes that are multiples of 4 in order to make * node moves faster.*/ -size_t SymbolSize(size_t nameLength) { - size_t realSize = sizeof(SymbolNode)+nameLength+1; - size_t alignment = 4; - size_t modulo = realSize % alignment; - size_t result = realSize + (modulo == 0 ? 0 : alignment - modulo); - assert(result % 4 == 0); - return result; +static size_t NodeSize(size_t nameLength) { + return Helpers::AlignedSize(sizeof(SymbolNode)+nameLength+1, 4); } size_t SymbolNode::size() const { - return SymbolSize(strlen(m_name)); + return NodeSize(strlen(m_name)); } ExpressionNode::Sign SymbolNode::sign() const { @@ -166,7 +162,7 @@ Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::An return e.approximateToEvaluation(context, angleUnit); } -Symbol::Symbol(const char * name, int length) : Expression(TreePool::sharedPool()->createTreeNode(SymbolSize(length))) { +Symbol::Symbol(const char * name, int length) : Expression(TreePool::sharedPool()->createTreeNode(NodeSize(length))) { node()->setName(name, length); }