Replacing generic Token.EXPRSTMT by Token.EXPR_VOID and Token.EXPR_RESULT and removal of Token.POP and Token.POPV. Now parser creates appropriate expression statements itself so there is no need to replace the time in NodeTransformer.

This commit is contained in:
igor%mir2.org 2004-07-02 13:11:06 +00:00
Родитель 646420ac21
Коммит b91ef7e8a2
6 изменённых файлов: 152 добавлений и 142 удалений

Просмотреть файл

@ -93,12 +93,18 @@ final class IRFactory
Node createExprStatement(Node expr, int lineno)
{
return new Node(Token.EXPRSTMT, expr, lineno);
int type;
if (parser.insideFunction()) {
type = Token.EXPR_VOID;
} else {
type = Token.EXPR_RESULT;
}
return new Node(type, expr, lineno);
}
Node createExprStatementNoReturn(Node expr, int lineno)
{
return new Node(Token.POP, expr, lineno);
return new Node(Token.EXPR_VOID, expr, lineno);
}
/**
@ -245,7 +251,7 @@ final class IRFactory
// function to initialize a local variable of the
// function's name to the function value.
fnNode.addVar(name);
Node setFn = new Node(Token.POP,
Node setFn = new Node(Token.EXPR_VOID,
new Node(Token.SETVAR, Node.newString(name),
new Node(Token.THISFN)));
statements.addChildrenToFront(setFn);
@ -333,14 +339,14 @@ final class IRFactory
if (loopType == LOOP_FOR) {
if (init.getType() != Token.EMPTY) {
if (init.getType() != Token.VAR) {
init = new Node(Token.POP, init);
init = new Node(Token.EXPR_VOID, init);
}
result.addChildToFront(init);
}
Node.Target incrTarget = new Node.Target();
result.addChildAfter(incrTarget, body);
if (incr.getType() != Token.EMPTY) {
incr = createUnary(Token.POP, incr);
incr = new Node(Token.EXPR_VOID, incr);
result.addChildAfter(incr, incrTarget);
}
continueTarget = incrTarget;
@ -400,7 +406,7 @@ final class IRFactory
Node newBody = new Node(Token.BLOCK);
Node assign = createAssignment(lvalue, id);
newBody.addChildToBack(new Node(Token.POP, assign));
newBody.addChildToBack(new Node(Token.EXPR_VOID, assign));
newBody.addChildToBack(body);
Node loop = createWhile(cond, newBody, lineno);

Просмотреть файл

@ -131,8 +131,11 @@ public class Interpreter
Icode_UNDEF = -45,
Icode_POP = -46,
Icode_POP_RESULT = -47,
// Last icode
MIN_ICODE = -45;
MIN_ICODE = -47;
static {
// Checks for byte code consistencies, good compiler can eliminate them
@ -149,6 +152,74 @@ public class Interpreter
}
}
private static String bytecodeName(int bytecode)
{
if (!validBytecode(bytecode)) {
throw new IllegalArgumentException(String.valueOf(bytecode));
}
if (!Token.printICode) {
return String.valueOf(bytecode);
}
if (validTokenCode(bytecode)) {
return Token.name(bytecode);
}
switch (bytecode) {
case Icode_DUP: return "DUP";
case Icode_DUP2: return "DUP2";
case Icode_SWAP: return "SWAP";
case Icode_IFEQ_POP: return "IFEQ_POP";
case Icode_VAR_INC_DEC: return "VAR_INC_DEC";
case Icode_NAME_INC_DEC: return "NAME_INC_DEC";
case Icode_PROP_INC_DEC: return "PROP_INC_DEC";
case Icode_ELEM_INC_DEC: return "ELEM_INC_DEC";
case Icode_REF_INC_DEC: return "REF_INC_DEC";
case Icode_SCOPE: return "SCOPE";
case Icode_TYPEOFNAME: return "TYPEOFNAME";
case Icode_NAME_FAST_THIS: return "NAME_FAST_THIS";
case Icode_NAME_SLOW_THIS: return "NAME_SLOW_THIS";
case Icode_PUSH_PARENT: return "PUSH_PARENT";
case Icode_CLOSURE: return "CLOSURE";
case Icode_CALLSPECIAL: return "CALLSPECIAL";
case Icode_RETUNDEF: return "RETUNDEF";
case Icode_CATCH: return "CATCH";
case Icode_GOSUB: return "GOSUB";
case Icode_RETSUB: return "RETSUB";
case Icode_LINE: return "LINE";
case Icode_SHORTNUMBER: return "SHORTNUMBER";
case Icode_INTNUMBER: return "INTNUMBER";
case Icode_LITERAL_NEW: return "LITERAL_NEW";
case Icode_LITERAL_SET: return "LITERAL_SET";
case Icode_SPARE_ARRAYLIT: return "SPARE_ARRAYLIT";
case Icode_REG_IND_C0: return "REG_IND_C0";
case Icode_REG_IND_C1: return "REG_IND_C1";
case Icode_REG_IND_C2: return "REG_IND_C2";
case Icode_REG_IND_C3: return "REG_IND_C3";
case Icode_REG_IND_C4: return "REG_IND_C4";
case Icode_REG_IND_C5: return "REG_IND_C5";
case Icode_REG_IND1: return "LOAD_IND1";
case Icode_REG_IND2: return "LOAD_IND2";
case Icode_REG_IND4: return "LOAD_IND4";
case Icode_REG_STR_C0: return "REG_STR_C0";
case Icode_REG_STR_C1: return "REG_STR_C1";
case Icode_REG_STR_C2: return "REG_STR_C2";
case Icode_REG_STR_C3: return "REG_STR_C3";
case Icode_REG_STR1: return "LOAD_STR1";
case Icode_REG_STR2: return "LOAD_STR2";
case Icode_REG_STR4: return "LOAD_STR4";
case Icode_GETVAR1: return "GETVAR1";
case Icode_SETVAR1: return "SETVAR1";
case Icode_UNDEF: return "UNDEF";
case Icode_POP: return "POP";
case Icode_POP_RESULT: return "POP_RESULT";
}
// icode without name
throw new IllegalStateException(String.valueOf(bytecode));
}
private static boolean validIcode(int icode)
{
return MIN_ICODE <= icode && icode <= -1;
@ -263,9 +334,9 @@ public class Interpreter
int theICodeTop = 0;
theICodeTop = generateICode(tree, theICodeTop);
fixLabelGotos();
// add RETURN_POPV only to scripts as function always ends with RETURN
// add RETURN_RESULT only to scripts as function always ends with RETURN
if (itsData.itsFunctionType == 0) {
theICodeTop = addToken(Token.RETURN_POPV, theICodeTop);
theICodeTop = addToken(Token.RETURN_RESULT, theICodeTop);
}
// Add special CATCH to simplify Interpreter.interpret logic
// and workaround lack of goto in Java
@ -476,7 +547,7 @@ public class Interpreter
iCodeTop = generateICode(child, iCodeTop);
while (null != (child = child.getNext())) {
if (1 != itsStackDepth - savedStackDepth) Kit.codeBug();
iCodeTop = addToken(Token.POP, iCodeTop);
iCodeTop = addIcode(Icode_POP, iCodeTop);
itsStackDepth--;
iCodeTop = generateICode(child, iCodeTop);
}
@ -490,7 +561,7 @@ public class Interpreter
iCodeTop = addIcode(Icode_DUP, iCodeTop);
// No stack adjusting: USE_STACK in subtree will do it
iCodeTop = generateICode(child, iCodeTop);
iCodeTop = addToken(Token.POP, iCodeTop);
iCodeTop = addIcode(Icode_POP, iCodeTop);
itsStackDepth--;
}
break;
@ -530,7 +601,7 @@ public class Interpreter
iCodeTop = addGoto(target, Icode_IFEQ_POP, iCodeTop);
stackChange(-1);
}
iCodeTop = addToken(Token.POP, iCodeTop);
iCodeTop = addIcode(Icode_POP, iCodeTop);
stackChange(-1);
Node defaultNode = (Node) switchNode.getProp(Node.DEFAULT_PROP);
@ -648,7 +719,7 @@ public class Interpreter
int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
iCodeTop = addForwardGoto(jump, iCodeTop);
itsStackDepth--;
iCodeTop = addToken(Token.POP, iCodeTop);
iCodeTop = addIcode(Icode_POP, iCodeTop);
itsStackDepth--;
child = child.getNext();
iCodeTop = generateICode(child, iCodeTop);
@ -728,7 +799,7 @@ public class Interpreter
stackDelta = 1;
iCodeTop = generateICode(child, iCodeTop);
if (type == Token.VOID) {
iCodeTop = addToken(Token.POP, iCodeTop);
iCodeTop = addIcode(Icode_POP, iCodeTop);
iCodeTop = addIcode(Icode_UNDEF, iCodeTop);
} else {
iCodeTop = addToken(type, iCodeTop);
@ -862,13 +933,13 @@ public class Interpreter
break;
}
case Token.POPV :
case Token.EXPR_VOID :
case Token.EXPR_RESULT :
stackShouldBeZero = true;
// fallthrough
case Token.POP :
iCodeTop = updateLineNumber(node, iCodeTop);
iCodeTop = generateICode(child, iCodeTop);
iCodeTop = addToken(type, iCodeTop);
iCodeTop = addIcode((type == Token.EXPR_VOID)
? Icode_POP : Icode_POP_RESULT, iCodeTop);
itsStackDepth--;
break;
@ -964,10 +1035,10 @@ public class Interpreter
}
break;
case Token.RETURN_POPV :
case Token.RETURN_RESULT :
stackShouldBeZero = true;
iCodeTop = updateLineNumber(node, iCodeTop);
iCodeTop = addToken(Token.RETURN_POPV, iCodeTop);
iCodeTop = addToken(Token.RETURN_RESULT, iCodeTop);
break;
case Token.GETVAR : {
@ -1582,72 +1653,6 @@ public class Interpreter
return best;
}
private static String bytecodeName(int bytecode)
{
if (!validBytecode(bytecode)) {
throw new IllegalArgumentException(String.valueOf(bytecode));
}
if (!Token.printICode) {
return String.valueOf(bytecode);
}
if (validTokenCode(bytecode)) {
return Token.name(bytecode);
}
switch (bytecode) {
case Icode_DUP: return "DUP";
case Icode_DUP2: return "DUP2";
case Icode_SWAP: return "SWAP";
case Icode_IFEQ_POP: return "IFEQ_POP";
case Icode_VAR_INC_DEC: return "VAR_INC_DEC";
case Icode_NAME_INC_DEC: return "NAME_INC_DEC";
case Icode_PROP_INC_DEC: return "PROP_INC_DEC";
case Icode_ELEM_INC_DEC: return "ELEM_INC_DEC";
case Icode_REF_INC_DEC: return "REF_INC_DEC";
case Icode_SCOPE: return "SCOPE";
case Icode_TYPEOFNAME: return "TYPEOFNAME";
case Icode_NAME_FAST_THIS: return "NAME_FAST_THIS";
case Icode_NAME_SLOW_THIS: return "NAME_SLOW_THIS";
case Icode_PUSH_PARENT: return "PUSH_PARENT";
case Icode_CLOSURE: return "CLOSURE";
case Icode_CALLSPECIAL: return "CALLSPECIAL";
case Icode_RETUNDEF: return "RETUNDEF";
case Icode_CATCH: return "CATCH";
case Icode_GOSUB: return "GOSUB";
case Icode_RETSUB: return "RETSUB";
case Icode_LINE: return "LINE";
case Icode_SHORTNUMBER: return "SHORTNUMBER";
case Icode_INTNUMBER: return "INTNUMBER";
case Icode_LITERAL_NEW: return "LITERAL_NEW";
case Icode_LITERAL_SET: return "LITERAL_SET";
case Icode_SPARE_ARRAYLIT: return "SPARE_ARRAYLIT";
case Icode_REG_IND_C0: return "REG_IND_C0";
case Icode_REG_IND_C1: return "REG_IND_C1";
case Icode_REG_IND_C2: return "REG_IND_C2";
case Icode_REG_IND_C3: return "REG_IND_C3";
case Icode_REG_IND_C4: return "REG_IND_C4";
case Icode_REG_IND_C5: return "REG_IND_C5";
case Icode_REG_IND1: return "LOAD_IND1";
case Icode_REG_IND2: return "LOAD_IND2";
case Icode_REG_IND4: return "LOAD_IND4";
case Icode_REG_STR_C0: return "REG_STR_C0";
case Icode_REG_STR_C1: return "REG_STR_C1";
case Icode_REG_STR_C2: return "REG_STR_C2";
case Icode_REG_STR_C3: return "REG_STR_C3";
case Icode_REG_STR1: return "LOAD_STR1";
case Icode_REG_STR2: return "LOAD_STR2";
case Icode_REG_STR4: return "LOAD_STR4";
case Icode_GETVAR1: return "GETVAR1";
case Icode_SETVAR1: return "SETVAR1";
case Icode_UNDEF: return "UNDEF";
}
// icode without name
throw new IllegalStateException(String.valueOf(bytecode));
}
private static void dumpICode(InterpreterData idata)
{
if (!Token.printICode) {
@ -2296,10 +2301,16 @@ switch (op) {
}
continue Loop;
}
case Token.POP :
case Icode_POP :
stack[stackTop] = null;
stackTop--;
continue Loop;
case Icode_POP_RESULT :
result = stack[stackTop];
if (result == DBL_MRK) result = doubleWrap(sDbl[stackTop]);
stack[stackTop] = null;
--stackTop;
continue Loop;
case Icode_DUP :
stack[stackTop + 1] = stack[stackTop];
sDbl[stackTop + 1] = sDbl[stackTop];
@ -2321,18 +2332,12 @@ switch (op) {
sDbl[stackTop - 1] = d;
continue Loop;
}
case Token.POPV :
result = stack[stackTop];
if (result == DBL_MRK) result = doubleWrap(sDbl[stackTop]);
stack[stackTop] = null;
--stackTop;
continue Loop;
case Token.RETURN :
result = stack[stackTop];
if (result == DBL_MRK) result = doubleWrap(sDbl[stackTop]);
--stackTop;
break Loop;
case Token.RETURN_POPV :
case Token.RETURN_RESULT :
break Loop;
case Icode_RETUNDEF :
result = undefined;

Просмотреть файл

@ -225,25 +225,11 @@ public class NodeTransformer
*/
if (!hasFinally)
break; // skip the whole mess.
Node child = node.getFirstChild();
boolean inserted = false;
Node unwindBlock = null;
for (int i=loops.size()-1; i >= 0; i--) {
Node n = (Node) loops.get(i);
int elemtype = n.getType();
if (elemtype == Token.TRY || elemtype == Token.WITH) {
if (!inserted) {
inserted = true;
if (child != null) {
node.setType(Token.POPV);
// process children now as node will be
// changed to point to inserted RETURN_POPV
transformCompilationUnit_r(tree, node);
Node retPopv = new Node(Token.RETURN_POPV);
parent.addChildAfter(retPopv, node);
previous = node;
node = retPopv;
}
}
Node unwind;
if (elemtype == Token.TRY) {
Node.Jump jsrnode = new Node.Jump(Token.JSR);
@ -253,10 +239,30 @@ public class NodeTransformer
} else {
unwind = new Node(Token.LEAVEWITH);
}
previous = addBeforeCurrent(parent, previous, node,
unwind);
if (unwindBlock == null) {
unwindBlock = new Node(Token.BLOCK,
node.getLineno());
}
unwindBlock.addChildToBack(unwind);
}
}
if (unwindBlock != null) {
Node returnNode = node;
Node returnExpr = returnNode.getFirstChild();
node = replaceCurrent(parent, previous, node, unwindBlock);
if (returnExpr == null) {
unwindBlock.addChildToBack(returnNode);
} else {
Node store = new Node(Token.EXPR_RESULT, returnExpr);
unwindBlock.addChildToFront(store);
returnNode = new Node(Token.RETURN_RESULT);
unwindBlock.addChildToBack(returnNode);
// transform return expression
transformCompilationUnit_r(tree, store);
}
// skip transformCompilationUnit_r to avoid infinite loop
continue siblingLoop;
}
break;
}
@ -347,10 +353,6 @@ public class NodeTransformer
break;
}
case Token.EXPRSTMT:
node.setType(inFunction ? Token.POP : Token.POPV);
break;
case Token.VAR:
{
Node result = new Node(Token.BLOCK);
@ -366,7 +368,7 @@ public class NodeTransformer
n.removeChild(init);
n.setType(Token.BINDNAME);
n = new Node(Token.SETNAME, n, init);
Node pop = new Node(Token.POP, n, node.getLineno());
Node pop = new Node(Token.EXPR_VOID, n, node.getLineno());
result.addChildToBack(pop);
}
node = replaceCurrent(parent, previous, node, result);

Просмотреть файл

@ -73,7 +73,7 @@ public class Token
// Interpreter reuses the following as bytecodes
FIRST_BYTECODE_TOKEN = 2,
POPV = 2,
// XXX removed unused POPV
ENTERWITH = 3,
LEAVEWITH = 4,
RETURN = 5,
@ -122,7 +122,7 @@ public class Token
SHEQ = 48, // shallow equality (===)
SHNE = 49, // shallow inequality (!==)
REGEXP = 50,
POP = 51,
// XXX removed unused POP
BINDNAME = 52,
THROW = 53,
IN = 54,
@ -137,7 +137,7 @@ public class Token
ENUM_NEXT = 63,
ENUM_ID = 64,
THISFN = 65,
RETURN_POPV = 66, // to return result stored as popv in functions
RETURN_RESULT = 66, // to return result stored as popv in functions
ARRAYLIT = 67, // array literal
OBJECTLIT = 68, // object literal
GET_REF = 69, // *reference
@ -197,18 +197,19 @@ public class Token
LABEL = 113, // label
TARGET = 114,
LOOP = 115,
EXPRSTMT = 116,
JSR = 117,
SCRIPT = 118, // top-level node for entire script
TYPEOFNAME = 119, // for typeof(simple-name)
USE_STACK = 120,
SETPROP_OP = 121, // x.y op= something
SETELEM_OP = 122, // x[y] op= something
INIT_LIST = 123,
LOCAL_BLOCK = 124,
SET_REF_OP = 125, // *reference op= something
EXPR_VOID = 116,
EXPR_RESULT = 117,
JSR = 118,
SCRIPT = 119, // top-level node for entire script
TYPEOFNAME = 120, // for typeof(simple-name)
USE_STACK = 121,
SETPROP_OP = 122, // x.y op= something
SETELEM_OP = 123, // x[y] op= something
INIT_LIST = 124,
LOCAL_BLOCK = 125,
SET_REF_OP = 126, // *reference op= something
LAST_TOKEN = 125;
LAST_TOKEN = 126;
public static String name(int token)
{
@ -224,7 +225,6 @@ public class Token
case ERROR: return "ERROR";
case EOF: return "EOF";
case EOL: return "EOL";
case POPV: return "POPV";
case ENTERWITH: return "ENTERWITH";
case LEAVEWITH: return "LEAVEWITH";
case RETURN: return "RETURN";
@ -273,7 +273,6 @@ public class Token
case SHEQ: return "SHEQ";
case SHNE: return "SHNE";
case REGEXP: return "OBJECT";
case POP: return "POP";
case BINDNAME: return "BINDNAME";
case THROW: return "THROW";
case IN: return "IN";
@ -287,7 +286,7 @@ public class Token
case ENUM_NEXT: return "ENUM_NEXT";
case ENUM_ID: return "ENUM_ID";
case THISFN: return "THISFN";
case RETURN_POPV: return "RETURN_POPV";
case RETURN_RESULT: return "RETURN_RESULT";
case ARRAYLIT: return "ARRAYLIT";
case OBJECTLIT: return "OBJECTLIT";
case GET_REF: return "GET_REF";
@ -336,7 +335,8 @@ public class Token
case LABEL: return "LABEL";
case TARGET: return "TARGET";
case LOOP: return "LOOP";
case EXPRSTMT: return "EXPRSTMT";
case EXPR_VOID: return "EXPR_VOID";
case EXPR_RESULT: return "EXPR_RESULT";
case JSR: return "JSR";
case SCRIPT: return "SCRIPT";
case TYPEOFNAME: return "TYPEOFNAME";

Просмотреть файл

@ -1461,7 +1461,7 @@ class BodyCodegen
visitThrow(node, child);
break;
case Token.RETURN_POPV:
case Token.RETURN_RESULT:
if (fnCurrent == null) throw Codegen.badTree();
// fallthrough
case Token.RETURN:
@ -1540,7 +1540,7 @@ class BodyCodegen
break;
}
case Token.POP:
case Token.EXPR_VOID:
visitStatement(node);
if (child.getType() == Token.SETVAR) {
/* special case this so as to avoid unnecessary
@ -1548,10 +1548,7 @@ class BodyCodegen
visitSetVar(child, child.getFirstChild(), false);
}
else {
while (child != null) {
generateCodeFromNode(child, node);
child = child.getNext();
}
generateCodeFromNode(child, node);
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1)
cfw.add(ByteCode.POP2);
else
@ -1559,7 +1556,7 @@ class BodyCodegen
}
break;
case Token.POPV:
case Token.EXPR_RESULT:
visitStatement(node);
generateCodeFromNode(child, node);
if (popvLocal < 0) {

Просмотреть файл

@ -152,7 +152,7 @@ class Optimizer
private int rewriteForNumberVariables(Node n)
{
switch (n.getType()) {
case Token.POP : {
case Token.EXPR_VOID : {
Node child = n.getFirstChild();
int type = rewriteForNumberVariables(child);
if (type == NumberType)