зеркало из https://github.com/mozilla/pjs.git
Avoid potentially expensive calls to Node.addChildBefore which may need to traverse a long child list to find the previous child when a reference to the previous child is available from context.
This commit is contained in:
Родитель
70475da4ec
Коммит
542ef1dbaf
|
@ -247,36 +247,16 @@ public class IRFactory {
|
|||
* While
|
||||
*/
|
||||
public Object createWhile(Object cond, Object body, int lineno) {
|
||||
// Just add a GOTO to the condition in the do..while
|
||||
Node result = (Node) createDoWhile(body, cond, lineno);
|
||||
Node condTarget = (Node) result.getProp(Node.CONTINUE_PROP);
|
||||
Node GOTO = new Node(TokenStream.GOTO);
|
||||
GOTO.putProp(Node.TARGET_PROP, condTarget);
|
||||
result.addChildToFront(GOTO);
|
||||
return result;
|
||||
return createLoop(LOOP_WHILE, (Node)body, (Node)cond, null, null,
|
||||
lineno);
|
||||
}
|
||||
|
||||
/**
|
||||
* DoWhile
|
||||
*/
|
||||
public Object createDoWhile(Object body, Object cond, int lineno) {
|
||||
Node result = new Node(TokenStream.LOOP, lineno);
|
||||
Node bodyTarget = new Node(TokenStream.TARGET);
|
||||
Node condTarget = new Node(TokenStream.TARGET);
|
||||
Node IFEQ = new Node(TokenStream.IFEQ, (Node)cond);
|
||||
IFEQ.putProp(Node.TARGET_PROP, bodyTarget);
|
||||
Node breakTarget = new Node(TokenStream.TARGET);
|
||||
|
||||
result.addChildToBack(bodyTarget);
|
||||
result.addChildrenToBack((Node)body);
|
||||
result.addChildToBack(condTarget);
|
||||
result.addChildToBack(IFEQ);
|
||||
result.addChildToBack(breakTarget);
|
||||
|
||||
result.putProp(Node.BREAK_PROP, breakTarget);
|
||||
result.putProp(Node.CONTINUE_PROP, condTarget);
|
||||
|
||||
return result;
|
||||
return createLoop(LOOP_DO_WHILE, (Node)body, (Node)cond, null, null,
|
||||
lineno);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,24 +265,57 @@ public class IRFactory {
|
|||
public Object createFor(Object init, Object test, Object incr,
|
||||
Object body, int lineno)
|
||||
{
|
||||
if (((Node) test).getType() == TokenStream.VOID) {
|
||||
test = new Node(TokenStream.PRIMARY, TokenStream.TRUE);
|
||||
return createLoop(LOOP_FOR, (Node)body, (Node)test,
|
||||
(Node)init, (Node)incr, lineno);
|
||||
}
|
||||
|
||||
private Node createLoop(int loopType, Node body, Node cond,
|
||||
Node init, Node incr, int lineno)
|
||||
{
|
||||
Node bodyTarget = new Node(TokenStream.TARGET);
|
||||
Node condTarget = new Node(TokenStream.TARGET);
|
||||
if (loopType == LOOP_FOR && cond.getType() == TokenStream.VOID) {
|
||||
cond = new Node(TokenStream.PRIMARY, TokenStream.TRUE);
|
||||
}
|
||||
Node result = (Node)createWhile(test, body, lineno);
|
||||
Node initNode = (Node) init;
|
||||
if (initNode.getType() != TokenStream.VOID) {
|
||||
if (initNode.getType() != TokenStream.VAR)
|
||||
initNode = new Node(TokenStream.POP, initNode);
|
||||
result.addChildToFront(initNode);
|
||||
Node IFEQ = new Node(TokenStream.IFEQ, (Node)cond);
|
||||
IFEQ.putProp(Node.TARGET_PROP, bodyTarget);
|
||||
Node breakTarget = new Node(TokenStream.TARGET);
|
||||
|
||||
Node result = new Node(TokenStream.LOOP, lineno);
|
||||
result.addChildToBack(bodyTarget);
|
||||
result.addChildrenToBack(body);
|
||||
result.addChildToBack(condTarget);
|
||||
result.addChildToBack(IFEQ);
|
||||
result.addChildToBack(breakTarget);
|
||||
|
||||
result.putProp(Node.BREAK_PROP, breakTarget);
|
||||
Node continueTarget = condTarget;
|
||||
|
||||
if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
|
||||
// Just add a GOTO to the condition in the do..while
|
||||
Node GOTO = new Node(TokenStream.GOTO);
|
||||
GOTO.putProp(Node.TARGET_PROP, condTarget);
|
||||
result.addChildToFront(GOTO);
|
||||
|
||||
if (loopType == LOOP_FOR) {
|
||||
if (init.getType() != TokenStream.VOID) {
|
||||
if (init.getType() != TokenStream.VAR) {
|
||||
init = new Node(TokenStream.POP, init);
|
||||
}
|
||||
result.addChildToFront(init);
|
||||
}
|
||||
Node incrTarget = new Node(TokenStream.TARGET);
|
||||
result.addChildAfter(incrTarget, body);
|
||||
if (incr.getType() != TokenStream.VOID) {
|
||||
incr = (Node)createUnary(TokenStream.POP, incr);
|
||||
result.addChildAfter(incr, incrTarget);
|
||||
}
|
||||
continueTarget = incrTarget;
|
||||
}
|
||||
}
|
||||
Node condTarget = (Node)result.getProp(Node.CONTINUE_PROP);
|
||||
Node incrTarget = new Node(TokenStream.TARGET);
|
||||
result.addChildBefore(incrTarget, condTarget);
|
||||
if (((Node) incr).getType() != TokenStream.VOID) {
|
||||
incr = createUnary(TokenStream.POP, incr);
|
||||
result.addChildAfter((Node)incr, incrTarget);
|
||||
}
|
||||
result.putProp(Node.CONTINUE_PROP, incrTarget);
|
||||
|
||||
result.putProp(Node.CONTINUE_PROP, continueTarget);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1028,5 +1041,9 @@ public class IRFactory {
|
|||
|
||||
// Only needed to pass to the Erorr exception constructors
|
||||
private Scriptable scope;
|
||||
|
||||
private static final int LOOP_DO_WHILE = 0;
|
||||
private static final int LOOP_WHILE = 1;
|
||||
private static final int LOOP_FOR = 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -269,7 +269,6 @@ public class NodeTransformer {
|
|||
if (!hasFinally)
|
||||
break; // skip the whole mess.
|
||||
|
||||
Node parent = iterator.getCurrentParent();
|
||||
for (int i=loops.size()-1; i >= 0; i--) {
|
||||
Node n = (Node) loops.get(i);
|
||||
int elemtype = n.getType();
|
||||
|
@ -277,10 +276,10 @@ public class NodeTransformer {
|
|||
Node jsrnode = new Node(TokenStream.JSR);
|
||||
Object jsrtarget = n.getProp(Node.FINALLY_PROP);
|
||||
jsrnode.putProp(Node.TARGET_PROP, jsrtarget);
|
||||
parent.addChildBefore(jsrnode, node);
|
||||
iterator.addBeforeCurrent(jsrnode);
|
||||
} else if (elemtype == TokenStream.WITH) {
|
||||
parent.addChildBefore(new Node(TokenStream.LEAVEWITH),
|
||||
node);
|
||||
Node leave = new Node(TokenStream.LEAVEWITH);
|
||||
iterator.addBeforeCurrent(leave);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -300,18 +299,17 @@ public class NodeTransformer {
|
|||
}
|
||||
|
||||
int i;
|
||||
Node parent = iterator.getCurrentParent();
|
||||
for (i=loops.size()-1; i >= 0; i--) {
|
||||
Node n = (Node) loops.get(i);
|
||||
int elemtype = n.getType();
|
||||
if (elemtype == TokenStream.WITH) {
|
||||
parent.addChildBefore(new Node(TokenStream.LEAVEWITH),
|
||||
node);
|
||||
Node leave = new Node(TokenStream.LEAVEWITH);
|
||||
iterator.addBeforeCurrent(leave);
|
||||
} else if (elemtype == TokenStream.TRY) {
|
||||
Node jsrFinally = new Node(TokenStream.JSR);
|
||||
Object jsrTarget = n.getProp(Node.FINALLY_PROP);
|
||||
jsrFinally.putProp(Node.TARGET_PROP, jsrTarget);
|
||||
parent.addChildBefore(jsrFinally, node);
|
||||
iterator.addBeforeCurrent(jsrFinally);
|
||||
} else if (!labelled &&
|
||||
(elemtype == TokenStream.LOOP ||
|
||||
(elemtype == TokenStream.SWITCH &&
|
||||
|
|
|
@ -101,6 +101,19 @@ public final class PreorderNodeIterator {
|
|||
current = newNode;
|
||||
}
|
||||
|
||||
public void addBeforeCurrent(Node newNode) {
|
||||
// Should not be used when stackTop == 0,
|
||||
// i.e. with start or its siblings
|
||||
Node parent = stack[stackTop - 1];
|
||||
if (cachedPrev != null && cachedPrev.next == current) {
|
||||
parent.addChildAfter(newNode, cachedPrev);
|
||||
}
|
||||
else {
|
||||
parent.addChildBefore(newNode, current);
|
||||
}
|
||||
cachedPrev = newNode;
|
||||
}
|
||||
|
||||
private void stackPush(Node n) {
|
||||
int N = stackTop;
|
||||
if (N == 0) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче