提交 c47d08e2 编写于 作者: A aefimov

8134007: Improve string folding

Summary: Generalize string folding algorithm to detect mulitple groups of foldable constants within an concat expression
Reviewed-by: jlahoda
上级 c1e73080
......@@ -515,7 +515,7 @@ public class JavacParser implements Parser {
if (mods != 0) {
long lowestMod = mods & -mods;
error(token.pos, "mod.not.allowed.here",
Flags.asFlagSet(lowestMod));
Flags.asFlagSet(lowestMod));
}
}
......@@ -954,10 +954,7 @@ public class JavacParser implements Parser {
t = odStack[0];
if (t.hasTag(JCTree.Tag.PLUS)) {
StringBuilder buf = foldStrings(t);
if (buf != null) {
t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
}
t = foldStrings(t);
}
odStackSupply.add(odStack);
......@@ -981,37 +978,79 @@ public class JavacParser implements Parser {
/** If tree is a concatenation of string literals, replace it
* by a single literal representing the concatenated string.
*/
protected StringBuilder foldStrings(JCTree tree) {
protected JCExpression foldStrings(JCExpression tree) {
if (!allowStringFolding)
return null;
List<String> buf = List.nil();
ListBuffer<JCExpression> opStack = new ListBuffer<>();
ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
boolean needsFolding = false;
JCExpression curr = tree;
while (true) {
if (tree.hasTag(LITERAL)) {
JCLiteral lit = (JCLiteral) tree;
if (lit.typetag == TypeTag.CLASS) {
StringBuilder sbuf =
new StringBuilder((String)lit.value);
while (buf.nonEmpty()) {
sbuf.append(buf.head);
buf = buf.tail;
}
return sbuf;
}
} else if (tree.hasTag(JCTree.Tag.PLUS)) {
JCBinary op = (JCBinary)tree;
if (op.rhs.hasTag(LITERAL)) {
JCLiteral lit = (JCLiteral) op.rhs;
if (lit.typetag == TypeTag.CLASS) {
buf = buf.prepend((String) lit.value);
tree = op.lhs;
continue;
}
}
if (curr.hasTag(JCTree.Tag.PLUS)) {
JCBinary op = (JCBinary)curr;
needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
curr = op.lhs;
} else {
needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
break; //last one!
}
return null;
}
if (needsFolding) {
List<JCExpression> ops = opStack.toList();
JCExpression res = ops.head;
for (JCExpression op : ops.tail) {
res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op);
storeEnd(res, getEndPos(op));
}
return res;
} else {
return tree;
}
}
private boolean foldIfNeeded(JCExpression tree, ListBuffer<JCLiteral> litBuf,
ListBuffer<JCExpression> opStack, boolean last) {
JCLiteral str = stringLiteral(tree);
if (str != null) {
litBuf.prepend(str);
return last && merge(litBuf, opStack);
} else {
boolean res = merge(litBuf, opStack);
litBuf.clear();
opStack.prepend(tree);
return res;
}
}
boolean merge(ListBuffer<JCLiteral> litBuf, ListBuffer<JCExpression> opStack) {
if (litBuf.isEmpty()) {
return false;
} else if (litBuf.size() == 1) {
opStack.prepend(litBuf.first());
return false;
} else {
StringBuilder sb = new StringBuilder();
for (JCLiteral lit : litBuf) {
sb.append(lit.getValue());
}
JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS, sb.toString());
storeEnd(t, litBuf.last().getEndPosition(endPosTable));
opStack.prepend(t);
return true;
}
}
private JCLiteral stringLiteral(JCTree tree) {
if (tree.hasTag(LITERAL)) {
JCLiteral lit = (JCLiteral)tree;
if (lit.typetag == TypeTag.CLASS) {
return lit;
}
}
return null;
}
/** optimization: To save allocating a new operand/operator stack
* for every binary operation, we use supplys.
*/
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册