Replace usages of j.u.Stack with fastutil's

Java's is synchronized everywhere, reducing performance given we don't need it to be. It's recommended to use `Deque` as a replacement, but given we have fastutil's, we use those

Closes #1640
This commit is contained in:
altrisi committed 2023-01-24 13:46:53 +01:00
1 parent fb7b1f79a5
commit 889e3b6999
1 file changed
+21 -19
+21 -19
View File
@@ -32,7 +32,10 @@ import carpet.script.value.FunctionValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import it.unimi.dsi.fastutil.Stack;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
@@ -41,7 +44,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Stack;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -763,7 +765,7 @@ public class Expression
private List<Tokenizer.Token> shuntingYard(Context c) private List<Tokenizer.Token> shuntingYard(Context c)
{ {
List<Tokenizer.Token> outputQueue = new ArrayList<>(); List<Tokenizer.Token> outputQueue = new ArrayList<>();
Stack<Tokenizer.Token> stack = new Stack<>(); Stack<Tokenizer.Token> stack = new ObjectArrayList<>();
Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions); Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions);
// stripping lousy but acceptable semicolons // stripping lousy but acceptable semicolons
@@ -801,7 +803,7 @@ public class Expression
{ {
throw new ExpressionException(c, this, previousToken, "Missing parameter(s) for operator "); throw new ExpressionException(c, this, previousToken, "Missing parameter(s) for operator ");
} }
while (!stack.isEmpty() && stack.peek().type != Tokenizer.Token.TokenType.OPEN_PAREN) while (!stack.isEmpty() && stack.top().type != Tokenizer.Token.TokenType.OPEN_PAREN)
{ {
outputQueue.add(stack.pop()); outputQueue.add(stack.pop());
} }
@@ -878,7 +880,7 @@ public class Expression
{ {
throw new ExpressionException(c, this, previousToken, "Missing parameter(s) for operator " + previousToken); throw new ExpressionException(c, this, previousToken, "Missing parameter(s) for operator " + previousToken);
} }
while (!stack.isEmpty() && stack.peek().type != Tokenizer.Token.TokenType.OPEN_PAREN) while (!stack.isEmpty() && stack.top().type != Tokenizer.Token.TokenType.OPEN_PAREN)
{ {
outputQueue.add(stack.pop()); outputQueue.add(stack.pop());
} }
@@ -887,7 +889,7 @@ public class Expression
throw new ExpressionException(c, this, "Mismatched parentheses"); throw new ExpressionException(c, this, "Mismatched parentheses");
} }
stack.pop(); stack.pop();
if (!stack.isEmpty() && stack.peek().type == Tokenizer.Token.TokenType.FUNCTION) if (!stack.isEmpty() && stack.top().type == Tokenizer.Token.TokenType.FUNCTION)
{ {
outputQueue.add(stack.pop()); outputQueue.add(stack.pop());
} }
@@ -918,7 +920,7 @@ public class Expression
private void shuntOperators(List<Tokenizer.Token> outputQueue, Stack<Tokenizer.Token> stack, ILazyOperator o1) private void shuntOperators(List<Tokenizer.Token> outputQueue, Stack<Tokenizer.Token> stack, ILazyOperator o1)
{ {
Tokenizer.Token nextToken = stack.isEmpty() ? null : stack.peek(); Tokenizer.Token nextToken = stack.isEmpty() ? null : stack.top();
while (nextToken != null while (nextToken != null
&& (nextToken.type == Tokenizer.Token.TokenType.OPERATOR && (nextToken.type == Tokenizer.Token.TokenType.OPERATOR
|| nextToken.type == Tokenizer.Token.TokenType.UNARY_OPERATOR) || nextToken.type == Tokenizer.Token.TokenType.UNARY_OPERATOR)
@@ -926,7 +928,7 @@ public class Expression
|| (o1.getPrecedence() < operators.get(nextToken.surface).getPrecedence()))) || (o1.getPrecedence() < operators.get(nextToken.surface).getPrecedence())))
{ {
outputQueue.add(stack.pop()); outputQueue.add(stack.pop());
nextToken = stack.isEmpty() ? null : stack.peek(); nextToken = stack.isEmpty() ? null : stack.top();
} }
} }
@@ -995,7 +997,7 @@ public class Expression
private ExpressionNode RPNToParseTree(List<Tokenizer.Token> tokens, Context context) private ExpressionNode RPNToParseTree(List<Tokenizer.Token> tokens, Context context)
{ {
Stack<ExpressionNode> nodeStack = new Stack<>(); Stack<ExpressionNode> nodeStack = new ObjectArrayList<>();
for (final Tokenizer.Token token : tokens) for (final Tokenizer.Token token : tokens)
{ {
switch (token.type) switch (token.type)
@@ -1041,7 +1043,7 @@ public class Expression
} }
// pop parameters off the stack until we hit the start of // pop parameters off the stack until we hit the start of
// this function's parameter list // this function's parameter list
while (!nodeStack.isEmpty() && nodeStack.peek() != ExpressionNode.PARAMS_START) while (!nodeStack.isEmpty() && nodeStack.top() != ExpressionNode.PARAMS_START)
{ {
p.add(nodeStack.pop()); p.add(nodeStack.pop());
} }
@@ -1052,7 +1054,7 @@ public class Expression
} }
Collections.reverse(p); Collections.reverse(p);
if (nodeStack.peek() == ExpressionNode.PARAMS_START) if (nodeStack.top() == ExpressionNode.PARAMS_START)
{ {
nodeStack.pop(); nodeStack.pop();
}; };
@@ -1377,7 +1379,7 @@ public class Expression
// each // each
// layer on the stack being the count of the number of parameters in // layer on the stack being the count of the number of parameters in
// that scope // that scope
Stack<Integer> stack = new Stack<>(); IntArrayList stack = new IntArrayList(); // IntArrayList instead of just IntStack because we need to query the size
// push the 'global' scope // push the 'global' scope
stack.push(0); stack.push(0);
@@ -1387,13 +1389,13 @@ public class Expression
switch (token.type) switch (token.type)
{ {
case UNARY_OPERATOR: case UNARY_OPERATOR:
if (stack.peek() < 1) if (stack.topInt() < 1)
{ {
throw new ExpressionException(c, this, token, "Missing parameter(s) for operator " + token); throw new ExpressionException(c, this, token, "Missing parameter(s) for operator " + token);
} }
break; break;
case OPERATOR: case OPERATOR:
if (stack.peek() < 2) if (stack.topInt() < 2)
{ {
if (token.surface.equals(";")) if (token.surface.equals(";"))
{ {
@@ -1402,7 +1404,7 @@ public class Expression
throw new ExpressionException(c, this, token, "Missing parameter(s) for operator " + token); throw new ExpressionException(c, this, token, "Missing parameter(s) for operator " + token);
} }
// pop the operator's 2 parameters and add the result // pop the operator's 2 parameters and add the result
stack.set(stack.size() - 1, stack.peek() - 2 + 1); stack.set(stack.size() - 1, stack.topInt() - 2 + 1);
break; break;
case FUNCTION: case FUNCTION:
//ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions //ILazyFunction f = functions.get(token.surface);// don't validate global - userdef functions
@@ -1411,7 +1413,7 @@ public class Expression
//{ //{
// throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams); // throw new ExpressionException(c, this, token, "Function " + token + " expected " + f.getNumParams() + " parameters, got " + numParams);
//} //}
stack.pop(); stack.popInt();
// due to unpacking, all functions can have variable number of arguments // due to unpacking, all functions can have variable number of arguments
// we will be checking that at runtime. // we will be checking that at runtime.
// TODO try analyze arguments and assess if its possible that they are static // TODO try analyze arguments and assess if its possible that they are static
@@ -1420,13 +1422,13 @@ public class Expression
throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded"); throw new ExpressionException(c, this, token, "Too many function calls, maximum scope exceeded");
} }
// push the result of the function // push the result of the function
stack.set(stack.size() - 1, stack.peek() + 1); stack.set(stack.size() - 1, stack.topInt() + 1);
break; break;
case OPEN_PAREN: case OPEN_PAREN:
stack.push(0); stack.push(0);
break; break;
default: default:
stack.set(stack.size() - 1, stack.peek() + 1); stack.set(stack.size() - 1, stack.topInt() + 1);
} }
} }
@@ -1434,11 +1436,11 @@ public class Expression
{ {
throw new ExpressionException(c, this, "Too many unhandled function parameter lists"); throw new ExpressionException(c, this, "Too many unhandled function parameter lists");
} }
else if (stack.peek() > 1) else if (stack.topInt() > 1)
{ {
throw new ExpressionException(c, this, "Too many numbers or variables"); throw new ExpressionException(c, this, "Too many numbers or variables");
} }
else if (stack.peek() < 1) else if (stack.topInt() < 1)
{ {
throw new ExpressionException(c, this, "Empty expression"); throw new ExpressionException(c, this, "Empty expression");
} }