@@ -101,7 +101,7 @@ public class MathExpression implements Savable, Solvable {
101101 */
102102 private boolean willFoldConstants = true ;
103103
104- private ExpressionSolver expressionSolver = new ExpressionSolver () ;
104+ private ExpressionSolver expressionSolver ;
105105
106106 /**
107107 * If set to true, MathExpression objects will automatically initialize
@@ -1356,32 +1356,41 @@ private void compileToPostfix() {
13561356 executionFrame [t .frameIndex ] = t .v .getValue ();
13571357 }
13581358 }
1359+ expressionSolver = new ExpressionSolver ();
13591360 }
13601361
13611362 private final class ExpressionSolver {
13621363
13631364 private static final int MAX_ARITY = 32 ;
13641365 private static final int ABSOLUTE_MAX_ARITY = 100_000 ;
13651366
1366- private EvalResult [][] argCache = new EvalResult [MAX_ARITY + 1 ][];
1367- private EvalResult [] stack ;
1367+ // Pre-allocate and reuse
1368+ private final EvalResult [] stack ;
1369+ private final EvalResult [][] argCache ;
13681370
13691371 public ExpressionSolver () {
1370- // Pre-allocate ONE array per arity that we reuse
1372+ // Allocate stack ONCE, with sufficient capacity
1373+ // Max stack depth is usually cachedPostfix.length, but we pad for safety
1374+ int maxStackDepth = Math .max (cachedPostfix .length * 2 , 256 );
1375+ this .stack = new EvalResult [maxStackDepth ];
1376+
1377+ // CRITICAL: Initialize all stack slots with EvalResult objects
1378+ for (int i = 0 ; i < stack .length ; i ++) {
1379+ stack [i ] = new EvalResult ();
1380+ }
1381+
1382+ // Pre-allocate argument arrays
1383+ this .argCache = new EvalResult [MAX_ARITY + 1 ][];
13711384 for (int i = 0 ; i <= MAX_ARITY ; i ++) {
13721385 argCache [i ] = new EvalResult [i ];
1386+ for (int j = 0 ; j < i ; j ++) {
1387+ argCache [i ][j ] = new EvalResult (); // Initialize
1388+ }
13731389 }
13741390 }
13751391
13761392 public EvalResult evaluate () {
1377- if (stack == null ){
1378- stack = new EvalResult [Math .max (cachedPostfix .length * 2 , 64 )];
1379- }else {
1380- if (cachedPostfix .length > stack .length ){
1381- stack = new EvalResult [Math .max (cachedPostfix .length * 2 , 64 )];
1382- }
1383- }
1384-
1393+ // Just use the pre-allocated stack - no allocation per call
13851394 int ptr = -1 ;
13861395
13871396 for (int i = 0 ; i < cachedPostfix .length ; i ++) {
@@ -1452,7 +1461,7 @@ public EvalResult evaluate() {
14521461 int valuesOnStack = ptr + 1 ;
14531462
14541463 if (arity == 0 ) {
1455- EvalResult result = t .action .calc (getNextResult (), arity ,argCache [arity ]);
1464+ EvalResult result = t .action .calc (getNextResult (), arity , argCache [arity ]);
14561465 stack [++ptr ] = result ;
14571466 break ;
14581467 }
0 commit comments