зеркало из https://github.com/mozilla/pjs.git
Added more fast index load instructions and removed 0xFF & when extracting bytecode as all byte codes are less then 128.
This commit is contained in:
Родитель
abee7b88f0
Коммит
8bc0a7f9ea
|
@ -2045,6 +2045,7 @@ public class Context
|
|||
public final void setInstructionObserverThreshold(int threshold)
|
||||
{
|
||||
if (sealed) onSealedMutation();
|
||||
if (threshold < 0) throw new IllegalArgumentException();
|
||||
instructionThreshold = threshold;
|
||||
}
|
||||
|
||||
|
@ -2067,6 +2068,15 @@ public class Context
|
|||
{
|
||||
}
|
||||
|
||||
final void addInstructionCount(int n)
|
||||
{
|
||||
instructionCount += n;
|
||||
if (instructionCount > instructionThreshold) {
|
||||
observeInstructionCount(instructionCount);
|
||||
instructionCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public GeneratedClassLoader createClassLoader(ClassLoader parent)
|
||||
{
|
||||
return new DefiningClassLoader(parent);
|
||||
|
|
|
@ -120,21 +120,31 @@ public class Interpreter
|
|||
Icode_REG_IND_C1 = BASE_ICODE + 35,
|
||||
Icode_REG_IND_C2 = BASE_ICODE + 36,
|
||||
Icode_REG_IND_C3 = BASE_ICODE + 37,
|
||||
Icode_REG_IND1 = BASE_ICODE + 38,
|
||||
Icode_REG_IND2 = BASE_ICODE + 39,
|
||||
Icode_REG_IND4 = BASE_ICODE + 40,
|
||||
Icode_REG_IND_C4 = BASE_ICODE + 38,
|
||||
Icode_REG_IND_C5 = BASE_ICODE + 39,
|
||||
Icode_REG_IND1 = BASE_ICODE + 40,
|
||||
Icode_REG_IND2 = BASE_ICODE + 41,
|
||||
Icode_REG_IND4 = BASE_ICODE + 42,
|
||||
|
||||
// Load string register to prepare for the following string operation
|
||||
Icode_REG_STR_C0 = BASE_ICODE + 41,
|
||||
Icode_REG_STR_C1 = BASE_ICODE + 42,
|
||||
Icode_REG_STR_C2 = BASE_ICODE + 43,
|
||||
Icode_REG_STR_C3 = BASE_ICODE + 44,
|
||||
Icode_REG_STR1 = BASE_ICODE + 45,
|
||||
Icode_REG_STR2 = BASE_ICODE + 46,
|
||||
Icode_REG_STR4 = BASE_ICODE + 47,
|
||||
Icode_REG_STR_C0 = BASE_ICODE + 43,
|
||||
Icode_REG_STR_C1 = BASE_ICODE + 44,
|
||||
Icode_REG_STR_C2 = BASE_ICODE + 45,
|
||||
Icode_REG_STR_C3 = BASE_ICODE + 46,
|
||||
Icode_REG_STR1 = BASE_ICODE + 47,
|
||||
Icode_REG_STR2 = BASE_ICODE + 48,
|
||||
Icode_REG_STR4 = BASE_ICODE + 49,
|
||||
|
||||
// Last icode
|
||||
MAX_ICODE = BASE_ICODE + 47;
|
||||
MAX_ICODE = BASE_ICODE + 49;
|
||||
|
||||
static {
|
||||
if (MAX_ICODE > 127) {
|
||||
// This allows to drop (0xFF & ...) in the interpreter loop
|
||||
System.err.println("MAX_ICODE should be <= 128");
|
||||
throw new IllegalStateException("MAX_ICODE should be <= 128");
|
||||
}
|
||||
}
|
||||
|
||||
public Object compile(Scriptable scope,
|
||||
CompilerEnvirons compilerEnv,
|
||||
|
@ -216,10 +226,6 @@ public class Interpreter
|
|||
itsData.itsFunctionType = theFunction.getFunctionType();
|
||||
itsData.itsNeedsActivation = theFunction.requiresActivation();
|
||||
itsData.itsName = theFunction.getFunctionName();
|
||||
if ((theFunction.getParamAndVarCount() & ~0xFF) != 0) {
|
||||
// Can not optimize vars as their index should fit 1 byte
|
||||
itsData.itsNeedsActivation = true;
|
||||
}
|
||||
if (!theFunction.getIgnoreDynamicScope()) {
|
||||
if (compilerEnv.isUseDynamicScope()) {
|
||||
itsData.useDynamicScope = true;
|
||||
|
@ -422,10 +428,6 @@ public class Interpreter
|
|||
|
||||
case Token.LOCAL_BLOCK :
|
||||
stackShouldBeZero = true;
|
||||
if ((itsLocalTop & ~0xFF) != 0) {
|
||||
throw Context.reportRuntimeError(
|
||||
"Program too complex (out of locals)");
|
||||
}
|
||||
node.putIntProp(Node.LOCAL_PROP, itsLocalTop);
|
||||
++itsLocalTop;
|
||||
if (itsLocalTop > itsData.itsMaxLocals) {
|
||||
|
@ -1406,32 +1408,20 @@ public class Interpreter
|
|||
index = itsStrings.size();
|
||||
itsStrings.put(str, index);
|
||||
}
|
||||
int indexSize = 0;
|
||||
int indexSize;
|
||||
int indexOp;
|
||||
switch (index) {
|
||||
case 0:
|
||||
indexOp = Icode_REG_STR_C0;
|
||||
break;
|
||||
case 1:
|
||||
indexOp = Icode_REG_STR_C1;
|
||||
break;
|
||||
case 2:
|
||||
indexOp = Icode_REG_STR_C2;
|
||||
break;
|
||||
case 3:
|
||||
indexOp = Icode_REG_STR_C3;
|
||||
break;
|
||||
default:
|
||||
if (index <= 0xFF) {
|
||||
indexOp = Icode_REG_STR1;
|
||||
indexSize = 1;
|
||||
} else if (index <= 0xFFFF) {
|
||||
indexOp = Icode_REG_STR2;
|
||||
indexSize = 2;
|
||||
} else {
|
||||
indexOp = Icode_REG_STR4;
|
||||
indexSize = 4;
|
||||
}
|
||||
if (index < 4) {
|
||||
indexOp = Icode_REG_STR_C0 + index;
|
||||
indexSize = 0;
|
||||
} else if (index <= 0xFF) {
|
||||
indexOp = Icode_REG_STR1;
|
||||
indexSize = 1;
|
||||
} else if (index <= 0xFFFF) {
|
||||
indexOp = Icode_REG_STR2;
|
||||
indexSize = 2;
|
||||
} else {
|
||||
indexOp = Icode_REG_STR4;
|
||||
indexSize = 4;
|
||||
}
|
||||
iCodeTop = addIcode(indexOp, iCodeTop);
|
||||
switch (indexSize) {
|
||||
|
@ -1456,32 +1446,20 @@ public class Interpreter
|
|||
private int addIndexOp(int op, int index, int iCodeTop)
|
||||
{
|
||||
if (index < 0) Kit.codeBug();
|
||||
int indexSize = 0;
|
||||
int indexSize;
|
||||
int indexOp;
|
||||
switch (index) {
|
||||
case 0:
|
||||
indexOp = Icode_REG_IND_C0;
|
||||
break;
|
||||
case 1:
|
||||
indexOp = Icode_REG_IND_C1;
|
||||
break;
|
||||
case 2:
|
||||
indexOp = Icode_REG_IND_C2;
|
||||
break;
|
||||
case 3:
|
||||
indexOp = Icode_REG_IND_C3;
|
||||
break;
|
||||
default:
|
||||
if (index <= 0xFF) {
|
||||
indexOp = Icode_REG_IND1;
|
||||
indexSize = 1;
|
||||
} else if (index <= 0xFFFF) {
|
||||
indexOp = Icode_REG_IND2;
|
||||
indexSize = 2;
|
||||
} else {
|
||||
indexOp = Icode_REG_IND4;
|
||||
indexSize = 4;
|
||||
}
|
||||
if (index < 6) {
|
||||
indexOp = Icode_REG_IND_C0 + index;
|
||||
indexSize = 0;
|
||||
} else if (index <= 0xFF) {
|
||||
indexOp = Icode_REG_IND1;
|
||||
indexSize = 1;
|
||||
} else if (index <= 0xFFFF) {
|
||||
indexOp = Icode_REG_IND2;
|
||||
indexSize = 2;
|
||||
} else {
|
||||
indexOp = Icode_REG_IND4;
|
||||
indexSize = 4;
|
||||
}
|
||||
iCodeTop = addIcode(indexOp, iCodeTop);
|
||||
switch (indexSize) {
|
||||
|
@ -1630,6 +1608,8 @@ public class Interpreter
|
|||
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";
|
||||
|
@ -1949,13 +1929,11 @@ public class Interpreter
|
|||
final Object DBL_MRK = Interpreter.DBL_MRK;
|
||||
final Scriptable undefined = Undefined.instance;
|
||||
|
||||
final int VAR_SHFT = 0;
|
||||
final int maxVars = idata.itsMaxVars;
|
||||
final int LOCAL_SHFT = VAR_SHFT + maxVars;
|
||||
final int LOCAL_SHFT = idata.itsMaxVars;
|
||||
final int STACK_SHFT = LOCAL_SHFT + idata.itsMaxLocals;
|
||||
|
||||
// stack[VAR_SHFT <= i < LOCAL_SHFT]: variables
|
||||
// stack[LOCAL_SHFT <= i < TRY_STACK_SHFT]: used for newtemp/usetemp
|
||||
// stack[0 <= i < LOCAL_SHFT]: variables
|
||||
// stack[LOCAL_SHFT <= i < TRY_STACK_SHFT]: used for local temporaries
|
||||
// stack[STACK_SHFT <= i < STACK_SHFT + idata.itsMaxStack]: stack data
|
||||
|
||||
// sDbl[i]: if stack[i] is DBL_MRK, sDbl[i] holds the number value
|
||||
|
@ -1975,13 +1953,13 @@ public class Interpreter
|
|||
if (definedArgs > argCount) { definedArgs = argCount; }
|
||||
for (int i = 0; i != definedArgs; ++i) {
|
||||
Object arg = args[argShift + i];
|
||||
stack[VAR_SHFT + i] = arg;
|
||||
stack[i] = arg;
|
||||
if (arg == DBL_MRK) {
|
||||
sDbl[VAR_SHFT + i] = argsDbl[argShift + i];
|
||||
sDbl[i] = argsDbl[argShift + i];
|
||||
}
|
||||
}
|
||||
for (int i = definedArgs; i != maxVars; ++i) {
|
||||
stack[VAR_SHFT + i] = undefined;
|
||||
for (int i = definedArgs; i != idata.itsMaxVars; ++i) {
|
||||
stack[i] = undefined;
|
||||
}
|
||||
|
||||
DebugFrame debuggerFrame = null;
|
||||
|
@ -2057,10 +2035,7 @@ public class Interpreter
|
|||
byte[] iCode = idata.itsICode;
|
||||
int pc = 0;
|
||||
int pcPrevBranch = 0;
|
||||
final int instructionThreshold = cx.instructionThreshold;
|
||||
// During function call this will be set to -1 so catch can properly
|
||||
// adjust it
|
||||
int instructionCount = cx.instructionCount;
|
||||
final boolean instructionCounting = (cx.instructionThreshold != 0);
|
||||
// arbitrary number to add to instructionCount when calling
|
||||
// other functions
|
||||
final int INVOCATION_COST = 100;
|
||||
|
@ -2071,9 +2046,9 @@ public class Interpreter
|
|||
|
||||
Loop: for (;;) {
|
||||
try {
|
||||
int op = 0xFF & iCode[pc++];
|
||||
switch (op) {
|
||||
int op = iCode[pc++];
|
||||
// Back indent to ease imlementation reading
|
||||
switch (op) {
|
||||
|
||||
case Icode_CATCH: {
|
||||
// The following code should be executed inside try/catch inside main
|
||||
|
@ -2161,11 +2136,9 @@ public class Interpreter
|
|||
// clear exception
|
||||
javaException = null;
|
||||
|
||||
if (instructionThreshold != 0) {
|
||||
if (instructionCount > instructionThreshold) {
|
||||
cx.observeInstructionCount(instructionCount);
|
||||
instructionCount = 0;
|
||||
}
|
||||
if (instructionCounting) {
|
||||
// 500: catch cost
|
||||
cx.addInstructionCount(500);
|
||||
pcPrevBranch = pc;
|
||||
}
|
||||
continue Loop;
|
||||
|
@ -2240,12 +2213,8 @@ public class Interpreter
|
|||
break;
|
||||
case Icode_RETSUB : {
|
||||
// indexReg: local to store return address
|
||||
if (instructionThreshold != 0) {
|
||||
instructionCount += pc - pcPrevBranch;
|
||||
if (instructionCount > instructionThreshold) {
|
||||
cx.observeInstructionCount(instructionCount);
|
||||
instructionCount = 0;
|
||||
}
|
||||
if (instructionCounting) {
|
||||
cx.addInstructionCount(pc - pcPrevBranch);
|
||||
}
|
||||
Object value = stack[LOCAL_SHFT + indexReg];
|
||||
if (value != DBL_MRK) {
|
||||
|
@ -2476,10 +2445,8 @@ public class Interpreter
|
|||
sDbl[stackTop] = sDbl[LOCAL_SHFT + indexReg];
|
||||
continue Loop;
|
||||
case Icode_CALLSPECIAL : {
|
||||
if (instructionThreshold != 0) {
|
||||
instructionCount += INVOCATION_COST;
|
||||
cx.instructionCount = instructionCount;
|
||||
instructionCount = -1;
|
||||
if (instructionCounting) {
|
||||
cx.instructionCount += INVOCATION_COST;
|
||||
}
|
||||
// indexReg: number of arguments
|
||||
int callType = iCode[pc] & 0xFF;
|
||||
|
@ -2503,15 +2470,12 @@ public class Interpreter
|
|||
cx, function, isNew, functionThis, outArgs,
|
||||
scope, thisObj, callType,
|
||||
idata.itsSourceFile, sourceLine);
|
||||
instructionCount = cx.instructionCount;
|
||||
pc += 4;
|
||||
continue Loop;
|
||||
}
|
||||
case Token.CALL : {
|
||||
if (instructionThreshold != 0) {
|
||||
instructionCount += INVOCATION_COST;
|
||||
cx.instructionCount = instructionCount;
|
||||
instructionCount = -1;
|
||||
if (instructionCounting) {
|
||||
cx.instructionCount += INVOCATION_COST;
|
||||
}
|
||||
// indexReg: number of arguments
|
||||
stackTop -= indexReg;
|
||||
|
@ -2554,15 +2518,11 @@ public class Interpreter
|
|||
throw ScriptRuntime.typeError1("msg.isnt.function",
|
||||
ScriptRuntime.toString(lhs));
|
||||
}
|
||||
|
||||
instructionCount = cx.instructionCount;
|
||||
continue Loop;
|
||||
}
|
||||
case Token.NEW : {
|
||||
if (instructionThreshold != 0) {
|
||||
instructionCount += INVOCATION_COST;
|
||||
cx.instructionCount = instructionCount;
|
||||
instructionCount = -1;
|
||||
if (instructionCounting) {
|
||||
cx.instructionCount += INVOCATION_COST;
|
||||
}
|
||||
// indexReg: number of arguments
|
||||
stackTop -= indexReg;
|
||||
|
@ -2598,7 +2558,6 @@ public class Interpreter
|
|||
ScriptRuntime.toString(lhs));
|
||||
|
||||
}
|
||||
instructionCount = cx.instructionCount;
|
||||
continue Loop;
|
||||
}
|
||||
case Token.TYPEOF : {
|
||||
|
@ -2643,8 +2602,8 @@ public class Interpreter
|
|||
continue Loop;
|
||||
case Token.SETVAR :
|
||||
if (!useActivationVars) {
|
||||
stack[VAR_SHFT + indexReg] = stack[stackTop];
|
||||
sDbl[VAR_SHFT + indexReg] = sDbl[stackTop];
|
||||
stack[indexReg] = stack[stackTop];
|
||||
sDbl[indexReg] = sDbl[stackTop];
|
||||
} else {
|
||||
Object val = stack[stackTop];
|
||||
if (val == DBL_MRK) val = doubleWrap(sDbl[stackTop]);
|
||||
|
@ -2654,8 +2613,8 @@ public class Interpreter
|
|||
case Token.GETVAR :
|
||||
++stackTop;
|
||||
if (!useActivationVars) {
|
||||
stack[stackTop] = stack[VAR_SHFT + indexReg];
|
||||
sDbl[stackTop] = sDbl[VAR_SHFT + indexReg];
|
||||
stack[stackTop] = stack[indexReg];
|
||||
sDbl[stackTop] = sDbl[indexReg];
|
||||
} else {
|
||||
stack[stackTop] = activationGet(fnOrScript, scope, indexReg);
|
||||
}
|
||||
|
@ -2664,18 +2623,17 @@ public class Interpreter
|
|||
case Icode_VARDEC :
|
||||
++stackTop;
|
||||
if (!useActivationVars) {
|
||||
Object val = stack[VAR_SHFT + indexReg];
|
||||
Object val = stack[indexReg];
|
||||
stack[stackTop] = val;
|
||||
double d;
|
||||
if (val == DBL_MRK) {
|
||||
d = sDbl[VAR_SHFT + indexReg];
|
||||
d = sDbl[indexReg];
|
||||
sDbl[stackTop] = d;
|
||||
} else {
|
||||
d = ScriptRuntime.toNumber(val);
|
||||
}
|
||||
stack[VAR_SHFT + indexReg] = DBL_MRK;
|
||||
sDbl[VAR_SHFT + indexReg] = (op == Icode_VARINC)
|
||||
? d + 1.0 : d - 1.0;
|
||||
stack[indexReg] = DBL_MRK;
|
||||
sDbl[indexReg] = (op == Icode_VARINC) ? d + 1.0 : d - 1.0;
|
||||
} else {
|
||||
Object val = activationGet(fnOrScript, scope, indexReg);
|
||||
stack[stackTop] = val;
|
||||
|
@ -2830,6 +2788,12 @@ public class Interpreter
|
|||
case Icode_REG_IND_C3:
|
||||
indexReg = 3;
|
||||
continue Loop;
|
||||
case Icode_REG_IND_C4:
|
||||
indexReg = 4;
|
||||
continue Loop;
|
||||
case Icode_REG_IND_C5:
|
||||
indexReg = 5;
|
||||
continue Loop;
|
||||
case Icode_REG_IND1:
|
||||
indexReg = 0xFF & iCode[pc];
|
||||
++pc;
|
||||
|
@ -2869,16 +2833,12 @@ public class Interpreter
|
|||
default :
|
||||
dumpICode(idata);
|
||||
throw new RuntimeException("Unknown icode : "+op+" @ pc : "+(pc-1));
|
||||
} // end of interpreter switch
|
||||
} // end of interpreter switch
|
||||
|
||||
// This should be reachable only for jump implementation
|
||||
// when pc points to encoded target offset
|
||||
if (instructionThreshold != 0) {
|
||||
instructionCount += pc + 2 - pcPrevBranch;
|
||||
if (instructionCount > instructionThreshold) {
|
||||
cx.observeInstructionCount(instructionCount);
|
||||
instructionCount = 0;
|
||||
}
|
||||
if (instructionCounting) {
|
||||
cx.addInstructionCount(pc + 2 - pcPrevBranch);
|
||||
}
|
||||
int offset = getShort(iCode, pc);
|
||||
if (offset != 0) {
|
||||
|
@ -2892,15 +2852,10 @@ public class Interpreter
|
|||
|
||||
} // end of interpreter try
|
||||
catch (Throwable ex) {
|
||||
if (instructionThreshold != 0) {
|
||||
if (instructionCount < 0) {
|
||||
// throw during function call
|
||||
instructionCount = cx.instructionCount;
|
||||
} else {
|
||||
// throw during any other operation
|
||||
instructionCount += pc - pcPrevBranch;
|
||||
cx.instructionCount = instructionCount;
|
||||
}
|
||||
if (instructionCounting) {
|
||||
// Can not call addInstructionCount as it may trigger
|
||||
// exception
|
||||
cx.instructionCount += pc - pcPrevBranch;
|
||||
}
|
||||
javaException = ex;
|
||||
exceptionPC = pc - 1;
|
||||
|
@ -2922,14 +2877,6 @@ public class Interpreter
|
|||
ScriptRuntime.popActivation(cx);
|
||||
}
|
||||
|
||||
if (instructionThreshold != 0) {
|
||||
if (instructionCount > instructionThreshold) {
|
||||
cx.observeInstructionCount(instructionCount);
|
||||
instructionCount = 0;
|
||||
}
|
||||
cx.instructionCount = instructionCount;
|
||||
}
|
||||
|
||||
if (javaException != null) {
|
||||
if (javaException instanceof JavaScriptException) {
|
||||
throw (JavaScriptException)javaException;
|
||||
|
|
Загрузка…
Ссылка в новой задаче