зеркало из https://github.com/mozilla/gecko-dev.git
Optimize ++name and --name similarly to name++ and name-- via special runtime support
This commit is contained in:
Родитель
fe2f9330ea
Коммит
8f9ce34d52
|
@ -822,29 +822,10 @@ class IRFactory
|
|||
Node childNode = (Node)child;
|
||||
int childType = childNode.getType();
|
||||
|
||||
if (childType == Token.NAME) {
|
||||
if (post) {
|
||||
return new Node(nodeType, childNode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform INC/DEC ops to +=1, -=1,
|
||||
* expecting later optimization of all +/-=1 cases to INC, DEC.
|
||||
*/
|
||||
Node rhs = (Node) createNumber(1.0);
|
||||
|
||||
String s = childNode.getString();
|
||||
Node opLeft = Node.newString(Token.NAME, s);
|
||||
opLeft = new Node(Token.POS, opLeft);
|
||||
|
||||
int opType = (nodeType == Token.INC) ? Token.ADD : Token.SUB;
|
||||
Node op = new Node(opType, opLeft, rhs);
|
||||
Node lvalueLeft = Node.newString(Token.BINDNAME, s);
|
||||
return new Node(Token.SETNAME, lvalueLeft, op);
|
||||
|
||||
} else if (childType == Token.GETPROP
|
||||
|| childType == Token.GETELEM
|
||||
|| childType == Token.GET_REF)
|
||||
if (childType == Token.NAME
|
||||
|| childType == Token.GETPROP
|
||||
|| childType == Token.GETELEM
|
||||
|| childType == Token.GET_REF)
|
||||
{
|
||||
Node n = new Node(nodeType, childNode);
|
||||
int type;
|
||||
|
|
|
@ -62,81 +62,78 @@ public class Interpreter
|
|||
Icode_IFEQ_POP = -4,
|
||||
|
||||
// various types of ++/--
|
||||
Icode_NAMEINC = -5,
|
||||
Icode_VARINC = -6,
|
||||
Icode_NAMEDEC = -7,
|
||||
Icode_VARDEC = -8,
|
||||
|
||||
Icode_PROP_INC_DEC = -9,
|
||||
Icode_ELEM_INC_DEC = -10,
|
||||
Icode_REF_INC_DEC = -11,
|
||||
Icode_VAR_INC_DEC = -5,
|
||||
Icode_NAME_INC_DEC = -6,
|
||||
Icode_PROP_INC_DEC = -7,
|
||||
Icode_ELEM_INC_DEC = -8,
|
||||
Icode_REF_INC_DEC = -9,
|
||||
|
||||
// helper codes to deal with activation
|
||||
Icode_SCOPE = -12,
|
||||
Icode_TYPEOFNAME = -13,
|
||||
Icode_SCOPE = -10,
|
||||
Icode_TYPEOFNAME = -11,
|
||||
|
||||
// helper for function calls
|
||||
Icode_NAME_FAST_THIS = -14,
|
||||
Icode_NAME_SLOW_THIS = -15,
|
||||
Icode_PUSH_PARENT = -16,
|
||||
Icode_NAME_FAST_THIS = -12,
|
||||
Icode_NAME_SLOW_THIS = -13,
|
||||
Icode_PUSH_PARENT = -14,
|
||||
|
||||
// Create closure object for nested functions
|
||||
Icode_CLOSURE = -17,
|
||||
Icode_CLOSURE = -15,
|
||||
|
||||
// Special calls
|
||||
Icode_CALLSPECIAL = -18,
|
||||
Icode_CALLSPECIAL = -16,
|
||||
|
||||
// To return undefined value
|
||||
Icode_RETUNDEF = -19,
|
||||
Icode_RETUNDEF = -17,
|
||||
|
||||
// Exception handling implementation
|
||||
Icode_CATCH = -20,
|
||||
Icode_GOSUB = -21,
|
||||
Icode_RETSUB = -22,
|
||||
Icode_CATCH = -18,
|
||||
Icode_GOSUB = -19,
|
||||
Icode_RETSUB = -20,
|
||||
|
||||
// To indicating a line number change in icodes.
|
||||
Icode_LINE = -23,
|
||||
Icode_LINE = -21,
|
||||
|
||||
// To store shorts and ints inline
|
||||
Icode_SHORTNUMBER = -24,
|
||||
Icode_INTNUMBER = -25,
|
||||
Icode_SHORTNUMBER = -22,
|
||||
Icode_INTNUMBER = -23,
|
||||
|
||||
// To create and populate array to hold values for [] and {} literals
|
||||
Icode_LITERAL_NEW = -26,
|
||||
Icode_LITERAL_SET = -27,
|
||||
Icode_LITERAL_NEW = -24,
|
||||
Icode_LITERAL_SET = -25,
|
||||
|
||||
// Array literal with skipped index like [1,,2]
|
||||
Icode_SPARE_ARRAYLIT = -28,
|
||||
Icode_SPARE_ARRAYLIT = -26,
|
||||
|
||||
// Load index register to prepare for the following index operation
|
||||
Icode_REG_IND_C0 = -29,
|
||||
Icode_REG_IND_C1 = -30,
|
||||
Icode_REG_IND_C2 = -31,
|
||||
Icode_REG_IND_C3 = -32,
|
||||
Icode_REG_IND_C4 = -33,
|
||||
Icode_REG_IND_C5 = -34,
|
||||
Icode_REG_IND1 = -35,
|
||||
Icode_REG_IND2 = -36,
|
||||
Icode_REG_IND4 = -37,
|
||||
Icode_REG_IND_C0 = -27,
|
||||
Icode_REG_IND_C1 = -28,
|
||||
Icode_REG_IND_C2 = -29,
|
||||
Icode_REG_IND_C3 = -30,
|
||||
Icode_REG_IND_C4 = -31,
|
||||
Icode_REG_IND_C5 = -32,
|
||||
Icode_REG_IND1 = -33,
|
||||
Icode_REG_IND2 = -34,
|
||||
Icode_REG_IND4 = -35,
|
||||
|
||||
// Load string register to prepare for the following string operation
|
||||
Icode_REG_STR_C0 = -38,
|
||||
Icode_REG_STR_C1 = -39,
|
||||
Icode_REG_STR_C2 = -40,
|
||||
Icode_REG_STR_C3 = -41,
|
||||
Icode_REG_STR1 = -42,
|
||||
Icode_REG_STR2 = -43,
|
||||
Icode_REG_STR4 = -44,
|
||||
Icode_REG_STR_C0 = -36,
|
||||
Icode_REG_STR_C1 = -37,
|
||||
Icode_REG_STR_C2 = -38,
|
||||
Icode_REG_STR_C3 = -39,
|
||||
Icode_REG_STR1 = -40,
|
||||
Icode_REG_STR2 = -41,
|
||||
Icode_REG_STR4 = -42,
|
||||
|
||||
// Version of getvar/setvar that read var index directly from bytecode
|
||||
Icode_GETVAR1 = -45,
|
||||
Icode_SETVAR1 = -46,
|
||||
Icode_GETVAR1 = -43,
|
||||
Icode_SETVAR1 = -44,
|
||||
|
||||
// Construct special reference
|
||||
Icode_SPECIAL_REF = -47,
|
||||
Icode_SPECIAL_REF = -45,
|
||||
|
||||
// Last icode
|
||||
MIN_ICODE = -47;
|
||||
MIN_ICODE = -45;
|
||||
|
||||
static {
|
||||
// Checks for byte code consistencies, good compiler can eliminate them
|
||||
|
@ -834,7 +831,7 @@ public class Interpreter
|
|||
case Token.INC :
|
||||
case Token.DEC :
|
||||
stackDelta = 1;
|
||||
iCodeTop = visitIncDec(iCodeTop, node, child);
|
||||
iCodeTop = visitIncDec(node, child, iCodeTop);
|
||||
break;
|
||||
|
||||
case Token.NUMBER : {
|
||||
|
@ -1153,31 +1150,34 @@ public class Interpreter
|
|||
return iCodeTop;
|
||||
}
|
||||
|
||||
private int visitIncDec(int iCodeTop, Node node, Node child)
|
||||
private int visitIncDec(Node node, Node child, int iCodeTop)
|
||||
{
|
||||
int type = node.getType();
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
int childType = child.getType();
|
||||
switch (childType) {
|
||||
case Token.GETVAR : {
|
||||
String name = child.getString();
|
||||
if (itsData.itsNeedsActivation) {
|
||||
int incrDecrType = (type == Token.INC)
|
||||
? Node.POST_INC : Node.POST_DEC;
|
||||
iCodeTop = addIcode(Icode_SCOPE, iCodeTop);
|
||||
stackChange(1);
|
||||
iCodeTop = addStringOp(Icode_PROP_INC_DEC, name, iCodeTop);
|
||||
iCodeTop = addByte(incrDecrType, iCodeTop);
|
||||
} else {
|
||||
int i = scriptOrFn.getParamOrVarIndex(name);
|
||||
int op = (type == Token.INC)
|
||||
? Icode_VARINC : Icode_VARDEC;
|
||||
iCodeTop = addVarOp(op, i, iCodeTop);
|
||||
iCodeTop = addVarOp(Icode_VAR_INC_DEC, i, iCodeTop);
|
||||
iCodeTop = addByte(incrDecrType, iCodeTop);
|
||||
stackChange(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Token.NAME : {
|
||||
String name = child.getString();
|
||||
iCodeTop = addStringOp(Icode_NAME_INC_DEC, name, iCodeTop);
|
||||
iCodeTop = addByte(incrDecrType, iCodeTop);
|
||||
stackChange(1);
|
||||
break;
|
||||
}
|
||||
case Token.GETPROP : {
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node object = child.getFirstChild();
|
||||
iCodeTop = generateICode(object, iCodeTop);
|
||||
String property = object.getNext().getString();
|
||||
|
@ -1186,7 +1186,6 @@ public class Interpreter
|
|||
break;
|
||||
}
|
||||
case Token.GETELEM : {
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node object = child.getFirstChild();
|
||||
iCodeTop = generateICode(object, iCodeTop);
|
||||
Node index = object.getNext();
|
||||
|
@ -1197,7 +1196,6 @@ public class Interpreter
|
|||
break;
|
||||
}
|
||||
case Token.GET_REF : {
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node ref = child.getFirstChild();
|
||||
iCodeTop = generateICode(ref, iCodeTop);
|
||||
iCodeTop = addIcode(Icode_REF_INC_DEC, iCodeTop);
|
||||
|
@ -1205,14 +1203,7 @@ public class Interpreter
|
|||
break;
|
||||
}
|
||||
default : {
|
||||
iCodeTop = addStringOp(type == Token.INC
|
||||
? Icode_NAMEINC
|
||||
: Icode_NAMEDEC,
|
||||
child.getString(), iCodeTop);
|
||||
itsStackDepth++;
|
||||
if (itsStackDepth > itsData.itsMaxStack)
|
||||
itsData.itsMaxStack = itsStackDepth;
|
||||
break;
|
||||
throw badTree(node);
|
||||
}
|
||||
}
|
||||
return iCodeTop;
|
||||
|
@ -1448,8 +1439,7 @@ public class Interpreter
|
|||
return addByte(varIndex, iCodeTop);
|
||||
}
|
||||
// fallthrough
|
||||
case Icode_VARINC:
|
||||
case Icode_VARDEC:
|
||||
case Icode_VAR_INC_DEC:
|
||||
return addIndexOp(op, varIndex, iCodeTop);
|
||||
}
|
||||
throw Kit.codeBug();
|
||||
|
@ -1607,10 +1597,8 @@ public class Interpreter
|
|||
case Icode_DUP2: return "DUP2";
|
||||
case Icode_SWAP: return "SWAP";
|
||||
case Icode_IFEQ_POP: return "IFEQ_POP";
|
||||
case Icode_NAMEINC: return "NAMEINC";
|
||||
case Icode_VARINC: return "VARINC";
|
||||
case Icode_NAMEDEC: return "NAMEDEC";
|
||||
case Icode_VARDEC: return "VARDEC";
|
||||
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";
|
||||
|
@ -1695,6 +1683,8 @@ public class Interpreter
|
|||
pc += 2;
|
||||
break;
|
||||
}
|
||||
case Icode_VAR_INC_DEC :
|
||||
case Icode_NAME_INC_DEC :
|
||||
case Icode_PROP_INC_DEC :
|
||||
case Icode_ELEM_INC_DEC :
|
||||
case Icode_REF_INC_DEC: {
|
||||
|
@ -1860,6 +1850,8 @@ public class Interpreter
|
|||
// index of potential function name for debugging
|
||||
return 1 + 2;
|
||||
|
||||
case Icode_VAR_INC_DEC:
|
||||
case Icode_NAME_INC_DEC:
|
||||
case Icode_PROP_INC_DEC:
|
||||
case Icode_ELEM_INC_DEC:
|
||||
case Icode_REF_INC_DEC:
|
||||
|
@ -2690,10 +2682,10 @@ switch (op) {
|
|||
case Token.NAME :
|
||||
stack[++stackTop] = ScriptRuntime.name(scope, stringReg);
|
||||
continue Loop;
|
||||
case Icode_NAMEINC :
|
||||
case Icode_NAMEDEC :
|
||||
stack[++stackTop] = ScriptRuntime.postIncrDecr(scope, stringReg,
|
||||
op == Icode_NAMEINC);
|
||||
case Icode_NAME_INC_DEC :
|
||||
stack[++stackTop] = ScriptRuntime.nameIncrDecr(scope, stringReg,
|
||||
iCode[pc]);
|
||||
++pc;
|
||||
continue Loop;
|
||||
case Icode_SETVAR1:
|
||||
indexReg = iCode[pc++];
|
||||
|
@ -2720,29 +2712,32 @@ switch (op) {
|
|||
stack[stackTop] = activationGet(fnOrScript, scope, indexReg);
|
||||
}
|
||||
continue Loop;
|
||||
case Icode_VARINC :
|
||||
case Icode_VARDEC :
|
||||
case Icode_VAR_INC_DEC : {
|
||||
// indexReg : varindex
|
||||
++stackTop;
|
||||
int type = iCode[pc];
|
||||
if (!useActivationVars) {
|
||||
Object val = stack[indexReg];
|
||||
stack[stackTop] = val;
|
||||
stack[stackTop] = DBL_MRK;
|
||||
Object varValue = stack[indexReg];
|
||||
double d;
|
||||
if (val == DBL_MRK) {
|
||||
if (varValue == DBL_MRK) {
|
||||
d = sDbl[indexReg];
|
||||
sDbl[stackTop] = d;
|
||||
} else {
|
||||
d = ScriptRuntime.toNumber(val);
|
||||
d = ScriptRuntime.toNumber(varValue);
|
||||
stack[indexReg] = DBL_MRK;
|
||||
}
|
||||
stack[indexReg] = DBL_MRK;
|
||||
sDbl[indexReg] = (op == Icode_VARINC) ? d + 1.0 : d - 1.0;
|
||||
double d2 = (type == Node.PRE_INC || type == Node.POST_INC)
|
||||
? d + 1.0 : d - 1.0;
|
||||
sDbl[indexReg] = d2;
|
||||
sDbl[stackTop] = (type == Node.POST_INC
|
||||
|| type == Node.POST_DEC) ? d : d2;
|
||||
} else {
|
||||
Object val = activationGet(fnOrScript, scope, indexReg);
|
||||
stack[stackTop] = val;
|
||||
double d = ScriptRuntime.toNumber(val);
|
||||
val = doubleWrap((op == Icode_VARINC) ? d + 1.0 : d - 1.0);
|
||||
activationPut(fnOrScript, scope, indexReg, val);
|
||||
String varName = fnOrScript.argNames[indexReg];
|
||||
stack[stackTop] = ScriptRuntime.nameIncrDecr(scope, varName, type);
|
||||
}
|
||||
++pc;
|
||||
continue Loop;
|
||||
}
|
||||
case Token.ZERO :
|
||||
++stackTop;
|
||||
stack[stackTop] = DBL_MRK;
|
||||
|
|
|
@ -1696,50 +1696,53 @@ public class ScriptRuntime {
|
|||
return toString(val1).concat(toString(val2));
|
||||
}
|
||||
|
||||
public static Object postIncrDecr(Scriptable scopeChain, String id, boolean increment)
|
||||
public static Object nameIncrDecr(Scriptable scopeChain, String id,
|
||||
int type)
|
||||
{
|
||||
Scriptable obj = scopeChain;
|
||||
while (obj != null) {
|
||||
Scriptable m = obj;
|
||||
Scriptable target;
|
||||
Object value;
|
||||
search: {
|
||||
do {
|
||||
Object value = m.get(id, obj);
|
||||
if (value != Scriptable.NOT_FOUND) {
|
||||
double number;
|
||||
if (value instanceof Number) {
|
||||
number = ((Number)value).doubleValue();
|
||||
} else {
|
||||
number = toNumber(value);
|
||||
// convert result to number
|
||||
value = new Double(number);
|
||||
target = scopeChain;
|
||||
do {
|
||||
value = target.get(id, scopeChain);
|
||||
if (value != Scriptable.NOT_FOUND) {
|
||||
break search;
|
||||
}
|
||||
if (increment) { ++number; }
|
||||
else { --number; }
|
||||
m.put(id, obj, new Double(number));
|
||||
return value;
|
||||
}
|
||||
m = m.getPrototype();
|
||||
} while (m != null);
|
||||
obj = obj.getParentScope();
|
||||
target = target.getPrototype();
|
||||
} while (target != null);
|
||||
scopeChain = scopeChain.getParentScope();
|
||||
} while (scopeChain != null);
|
||||
throw notFoundError(scopeChain, id);
|
||||
}
|
||||
throw notFoundError(scopeChain, id);
|
||||
return doScriptableIncrDecr(target, id, scopeChain, value, type);
|
||||
}
|
||||
|
||||
public static Object propIncrDecr(Object obj, String id,
|
||||
Scriptable scope, int type)
|
||||
{
|
||||
Scriptable start = toObject(scope, obj);
|
||||
Scriptable m = start;
|
||||
Scriptable target = start;
|
||||
Object value;
|
||||
search: {
|
||||
do {
|
||||
value = m.get(id, start);
|
||||
value = target.get(id, start);
|
||||
if (value != Scriptable.NOT_FOUND) {
|
||||
break search;
|
||||
}
|
||||
m = m.getPrototype();
|
||||
} while (m != null);
|
||||
target = target.getPrototype();
|
||||
} while (target != null);
|
||||
return Undefined.instance;
|
||||
}
|
||||
return doScriptableIncrDecr(target, id, start, value, type);
|
||||
}
|
||||
|
||||
private static Object doScriptableIncrDecr(Scriptable target,
|
||||
String id,
|
||||
Scriptable protoChainStart,
|
||||
Object value,
|
||||
int type)
|
||||
{
|
||||
boolean post = (type == Node.POST_INC || type == Node.POST_DEC);
|
||||
double number;
|
||||
if (value instanceof Number) {
|
||||
|
@ -1757,7 +1760,7 @@ public class ScriptRuntime {
|
|||
--number;
|
||||
}
|
||||
Number result = new Double(number);
|
||||
m.put(id, start, result);
|
||||
target.put(id, protoChainStart, result);
|
||||
if (post) {
|
||||
return value;
|
||||
} else {
|
||||
|
|
|
@ -467,53 +467,52 @@ class Block
|
|||
private static int findExpressionType(Node n, int[] varTypes)
|
||||
{
|
||||
switch (n.getType()) {
|
||||
case Token.NUMBER :
|
||||
return Optimizer.NumberType;
|
||||
case Token.NUMBER :
|
||||
return Optimizer.NumberType;
|
||||
|
||||
case Token.NEW :
|
||||
case Token.CALL :
|
||||
return Optimizer.NoType;
|
||||
case Token.NEW :
|
||||
case Token.CALL :
|
||||
return Optimizer.NoType;
|
||||
|
||||
case Token.GETELEM :
|
||||
return Optimizer.AnyType;
|
||||
case Token.GETELEM :
|
||||
return Optimizer.AnyType;
|
||||
|
||||
case Token.GETVAR :
|
||||
return varTypes[getVarIndex(n)];
|
||||
case Token.GETVAR :
|
||||
return varTypes[getVarIndex(n)];
|
||||
|
||||
case Token.INC :
|
||||
case Token.DEC :
|
||||
case Token.DIV:
|
||||
case Token.MOD:
|
||||
case Token.BITOR:
|
||||
case Token.BITXOR:
|
||||
case Token.BITAND:
|
||||
case Token.LSH:
|
||||
case Token.RSH:
|
||||
case Token.URSH:
|
||||
case Token.SUB :
|
||||
return Optimizer.NumberType;
|
||||
case Token.INC :
|
||||
case Token.DEC :
|
||||
case Token.DIV:
|
||||
case Token.MOD:
|
||||
case Token.BITOR:
|
||||
case Token.BITXOR:
|
||||
case Token.BITAND:
|
||||
case Token.LSH:
|
||||
case Token.RSH:
|
||||
case Token.URSH:
|
||||
case Token.SUB :
|
||||
return Optimizer.NumberType;
|
||||
|
||||
case Token.ADD : {
|
||||
// if the lhs & rhs are known to be numbers, we can be sure that's
|
||||
// the result, otherwise it could be a string.
|
||||
Node child = n.getFirstChild();
|
||||
int lType = findExpressionType(child, varTypes);
|
||||
int rType = findExpressionType(child.getNext(), varTypes);
|
||||
return lType | rType; // we're not distinguishng strings yet
|
||||
}
|
||||
default : {
|
||||
Node child = n.getFirstChild();
|
||||
if (child == null)
|
||||
return Optimizer.AnyType;
|
||||
else {
|
||||
int result = Optimizer.NoType;
|
||||
while (child != null) {
|
||||
result |= findExpressionType(child, varTypes);
|
||||
child = child.getNext();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
case Token.ADD : {
|
||||
// if the lhs & rhs are known to be numbers, we can be sure that's
|
||||
// the result, otherwise it could be a string.
|
||||
Node child = n.getFirstChild();
|
||||
int lType = findExpressionType(child, varTypes);
|
||||
int rType = findExpressionType(child.getNext(), varTypes);
|
||||
return lType | rType; // we're not distinguishng strings yet
|
||||
}
|
||||
}
|
||||
|
||||
Node child = n.getFirstChild();
|
||||
if (child == null) {
|
||||
return Optimizer.AnyType;
|
||||
} else {
|
||||
int result = Optimizer.NoType;
|
||||
while (child != null) {
|
||||
result |= findExpressionType(child, varTypes);
|
||||
child = child.getNext();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,43 +521,38 @@ class Block
|
|||
boolean result = false;
|
||||
Node child = n.getFirstChild();
|
||||
switch (n.getType()) {
|
||||
default : {
|
||||
while (child != null) {
|
||||
result |= findDefPoints(child, varTypes);
|
||||
child = child.getNext();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Token.DEC :
|
||||
case Token.INC : {
|
||||
if (child.getType() == Token.GETVAR) {
|
||||
// theVar is a Number now
|
||||
int i = getVarIndex(child);
|
||||
result |= assignType(varTypes, i, Optimizer.NumberType);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Token.SETPROP :
|
||||
case Token.SETPROP_OP : {
|
||||
if (child.getType() == Token.GETVAR) {
|
||||
int i = getVarIndex(child);
|
||||
assignType(varTypes, i, Optimizer.AnyType);
|
||||
}
|
||||
while (child != null) {
|
||||
result |= findDefPoints(child, varTypes);
|
||||
child = child.getNext();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Token.SETVAR : {
|
||||
Node rValue = child.getNext();
|
||||
int theType = findExpressionType(rValue, varTypes);
|
||||
int i = getVarIndex(n);
|
||||
result |= assignType(varTypes, i, theType);
|
||||
}
|
||||
break;
|
||||
default :
|
||||
while (child != null) {
|
||||
result |= findDefPoints(child, varTypes);
|
||||
child = child.getNext();
|
||||
}
|
||||
break;
|
||||
case Token.DEC :
|
||||
case Token.INC :
|
||||
if (child.getType() == Token.GETVAR) {
|
||||
// theVar is a Number now
|
||||
int i = getVarIndex(child);
|
||||
result |= assignType(varTypes, i, Optimizer.NumberType);
|
||||
}
|
||||
break;
|
||||
case Token.SETPROP :
|
||||
case Token.SETPROP_OP :
|
||||
if (child.getType() == Token.GETVAR) {
|
||||
int i = getVarIndex(child);
|
||||
assignType(varTypes, i, Optimizer.AnyType);
|
||||
}
|
||||
while (child != null) {
|
||||
result |= findDefPoints(child, varTypes);
|
||||
child = child.getNext();
|
||||
}
|
||||
break;
|
||||
case Token.SETVAR : {
|
||||
Node rValue = child.getNext();
|
||||
int theType = findExpressionType(rValue, varTypes);
|
||||
int i = getVarIndex(n);
|
||||
result |= assignType(varTypes, i, theType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1636,9 +1636,6 @@ class BodyCodegen
|
|||
break;
|
||||
|
||||
case Token.INC:
|
||||
visitIncDec(node, true);
|
||||
break;
|
||||
|
||||
case Token.DEC:
|
||||
visitIncDec(node, false);
|
||||
break;
|
||||
|
@ -2704,29 +2701,56 @@ class BodyCodegen
|
|||
|
||||
private void visitIncDec(Node node, boolean isInc)
|
||||
{
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node child = node.getFirstChild();
|
||||
switch (child.getType()) {
|
||||
case Token.GETVAR:
|
||||
if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) {
|
||||
boolean post = (incrDecrType == Node.POST_INC
|
||||
|| incrDecrType == Node.POST_DEC);
|
||||
OptLocalVariable lVar = OptLocalVariable.get(child);
|
||||
short reg = lVar.getJRegister();
|
||||
cfw.addDLoad(reg);
|
||||
cfw.add(ByteCode.DUP2);
|
||||
if (post) {
|
||||
cfw.add(ByteCode.DUP2);
|
||||
}
|
||||
cfw.addPush(1.0);
|
||||
cfw.add((isInc) ? ByteCode.DADD : ByteCode.DSUB);
|
||||
if (incrDecrType == Node.PRE_INC
|
||||
|| incrDecrType == Node.POST_INC)
|
||||
{
|
||||
cfw.add(ByteCode.DADD);
|
||||
} else {
|
||||
cfw.add(ByteCode.DSUB);
|
||||
}
|
||||
if (!post) {
|
||||
cfw.add(ByteCode.DUP2);
|
||||
}
|
||||
cfw.addDStore(reg);
|
||||
break;
|
||||
} else if (hasVarsInRegs) {
|
||||
boolean post = (incrDecrType == Node.POST_INC
|
||||
|| incrDecrType == Node.POST_DEC);
|
||||
OptLocalVariable lVar = OptLocalVariable.get(child);
|
||||
if (lVar == null)
|
||||
lVar = fnCurrent.getVar(child.getString());
|
||||
short reg = lVar.getJRegister();
|
||||
cfw.addALoad(reg);
|
||||
cfw.add(ByteCode.DUP);
|
||||
if (post) {
|
||||
cfw.add(ByteCode.DUP);
|
||||
}
|
||||
addObjectToDouble();
|
||||
cfw.addPush(1.0);
|
||||
cfw.add((isInc) ? ByteCode.DADD : ByteCode.DSUB);
|
||||
if (incrDecrType == Node.PRE_INC
|
||||
|| incrDecrType == Node.POST_INC)
|
||||
{
|
||||
cfw.add(ByteCode.DADD);
|
||||
} else {
|
||||
cfw.add(ByteCode.DSUB);
|
||||
}
|
||||
addDoubleWrap();
|
||||
if (!post) {
|
||||
cfw.add(ByteCode.DUP);
|
||||
}
|
||||
cfw.addAStore(reg);
|
||||
break;
|
||||
}
|
||||
|
@ -2734,14 +2758,13 @@ class BodyCodegen
|
|||
case Token.NAME:
|
||||
cfw.addALoad(variableObjectLocal);
|
||||
cfw.addPush(child.getString()); // push name
|
||||
cfw.addPush(isInc);
|
||||
addScriptRuntimeInvoke("postIncrDecr",
|
||||
cfw.addPush(incrDecrType);
|
||||
addScriptRuntimeInvoke("nameIncrDecr",
|
||||
"(Lorg/mozilla/javascript/Scriptable;"
|
||||
+"Ljava/lang/String;"
|
||||
+"Z)Ljava/lang/Object;");
|
||||
+"I)Ljava/lang/Object;");
|
||||
break;
|
||||
case Token.GETPROP: {
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node getPropChild = child.getFirstChild();
|
||||
generateCodeFromNode(getPropChild, node);
|
||||
generateCodeFromNode(getPropChild.getNext(), node);
|
||||
|
@ -2755,7 +2778,6 @@ class BodyCodegen
|
|||
break;
|
||||
}
|
||||
case Token.GETELEM: {
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node getElemChild = child.getFirstChild();
|
||||
generateCodeFromNode(getElemChild, node);
|
||||
generateCodeFromNode(getElemChild.getNext(), node);
|
||||
|
@ -2769,7 +2791,6 @@ class BodyCodegen
|
|||
break;
|
||||
}
|
||||
case Token.GET_REF: {
|
||||
int incrDecrType = node.getExistingIntProp(Node.INCRDECR_PROP);
|
||||
Node refChild = child.getFirstChild();
|
||||
generateCodeFromNode(refChild, node);
|
||||
cfw.addPush(incrDecrType);
|
||||
|
|
Загрузка…
Ссылка в новой задаче