зеркало из https://github.com/mozilla/gecko-dev.git
Inlining back code that were moved recently to do_call/do_new: if continuation support materializes, it would be much easier to transfer control to appropriate part of interpretation loop from the inlined code then to pass the necessary information from do_call.
This commit is contained in:
Родитель
8261446984
Коммит
ef60132dfa
|
@ -2381,7 +2381,8 @@ switch (op) {
|
||||||
continue Loop;
|
continue Loop;
|
||||||
}
|
}
|
||||||
case Token.ADD :
|
case Token.ADD :
|
||||||
stackTop = do_add(stack, sDbl, stackTop, cx);
|
--stackTop;
|
||||||
|
do_add(stack, sDbl, stackTop, cx);
|
||||||
continue Loop;
|
continue Loop;
|
||||||
case Token.SUB : {
|
case Token.SUB : {
|
||||||
double rDbl = stack_double(frame, stackTop);
|
double rDbl = stack_double(frame, stackTop);
|
||||||
|
@ -2607,10 +2608,61 @@ switch (op) {
|
||||||
// stack change: function thisObj arg0 .. argN -> result
|
// stack change: function thisObj arg0 .. argN -> result
|
||||||
// indexReg: number of arguments
|
// indexReg: number of arguments
|
||||||
stackTop -= 1 + indexReg;
|
stackTop -= 1 + indexReg;
|
||||||
CallFrame switchFrame = do_call(cx, frame, stackTop, indexReg, op);
|
|
||||||
if (switchFrame != null) {
|
// CALL generation ensures that fun and funThisObj
|
||||||
frame = switchFrame;
|
// are already Scriptable and Function objects respectively
|
||||||
continue StateLoop;
|
Function fun = (Function)stack[stackTop];
|
||||||
|
Scriptable funThisObj = (Scriptable)stack[stackTop + 1];
|
||||||
|
Scriptable calleeScope = frame.scope;
|
||||||
|
if (frame.useActivation) {
|
||||||
|
calleeScope = ScriptableObject.getTopLevelScope(frame.scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fun instanceof InterpretedFunction && op != Token.REF_CALL) {
|
||||||
|
InterpretedFunction ifun = (InterpretedFunction)fun;
|
||||||
|
if (frame.fnOrScript.securityDomain == ifun.securityDomain) {
|
||||||
|
CallFrame callParentFrame = frame;
|
||||||
|
CallFrame calleeFrame = new CallFrame();
|
||||||
|
if (op == Icode_TAIL_CALL) {
|
||||||
|
// In principle tail call can re-use the current
|
||||||
|
// frame and its stack arrays but it is hard to
|
||||||
|
// do properly. Any exceptions that can legally
|
||||||
|
// happen during frame re-initialization including
|
||||||
|
// StackOverflowException during innocent looking
|
||||||
|
// System.arraycopy may leave the current frame
|
||||||
|
// data corrupted leading to undefined behaviour
|
||||||
|
// in the catch code bellow that unwinds JS stack
|
||||||
|
// on exceptions. Then there is issue about frame release
|
||||||
|
// end exceptions there.
|
||||||
|
// To avoid frame allocation a released frame
|
||||||
|
// can be cached for re-use which would also benefit
|
||||||
|
// non-tail calls but it is not clear that this caching
|
||||||
|
// would gain in performance due to potentially
|
||||||
|
// bad iteraction with GC.
|
||||||
|
callParentFrame = frame.parentFrame;
|
||||||
|
}
|
||||||
|
initFrame(cx, calleeScope, funThisObj, stack, frame.sDbl,
|
||||||
|
stackTop + 2, indexReg, ifun, callParentFrame,
|
||||||
|
calleeFrame);
|
||||||
|
if (op == Icode_TAIL_CALL) {
|
||||||
|
// Release the parent
|
||||||
|
exitFrame(cx, frame, null);
|
||||||
|
} else {
|
||||||
|
frame.savedStackTop = stackTop;
|
||||||
|
frame.savedCallOp = op;
|
||||||
|
}
|
||||||
|
frame = calleeFrame;
|
||||||
|
continue StateLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object[] outArgs = getArgsArray(stack, frame.sDbl, stackTop + 2,
|
||||||
|
indexReg);
|
||||||
|
if (op != Token.REF_CALL) {
|
||||||
|
stack[stackTop] = fun.call(cx, calleeScope, funThisObj, outArgs);
|
||||||
|
} else {
|
||||||
|
stack[stackTop] = ScriptRuntime.referenceCall(fun, funThisObj,
|
||||||
|
outArgs, cx,
|
||||||
|
calleeScope);
|
||||||
}
|
}
|
||||||
continue Loop;
|
continue Loop;
|
||||||
}
|
}
|
||||||
|
@ -2621,11 +2673,32 @@ switch (op) {
|
||||||
// stack change: function arg0 .. argN -> newResult
|
// stack change: function arg0 .. argN -> newResult
|
||||||
// indexReg: number of arguments
|
// indexReg: number of arguments
|
||||||
stackTop -= indexReg;
|
stackTop -= indexReg;
|
||||||
CallFrame switchFrame = do_new(cx, frame, stackTop, indexReg, op);
|
|
||||||
if (switchFrame != null) {
|
Object lhs = stack[stackTop];
|
||||||
frame = switchFrame;
|
if (lhs instanceof InterpretedFunction) {
|
||||||
continue StateLoop;
|
InterpretedFunction f = (InterpretedFunction)lhs;
|
||||||
|
if (frame.fnOrScript.securityDomain == f.securityDomain) {
|
||||||
|
Scriptable newInstance = f.createObject(cx, frame.scope);
|
||||||
|
CallFrame calleeFrame = new CallFrame();
|
||||||
|
initFrame(cx, frame.scope, newInstance, stack, frame.sDbl,
|
||||||
|
stackTop + 1, indexReg, f, frame,
|
||||||
|
calleeFrame);
|
||||||
|
|
||||||
|
stack[stackTop] = newInstance;
|
||||||
|
frame.savedStackTop = stackTop;
|
||||||
|
frame.savedCallOp = op;
|
||||||
|
frame = calleeFrame;
|
||||||
|
continue StateLoop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!(lhs instanceof Function)) {
|
||||||
|
if (lhs == DBL_MRK) lhs = doubleWrap(frame.sDbl[stackTop]);
|
||||||
|
throw ScriptRuntime.notFunctionError(lhs);
|
||||||
|
}
|
||||||
|
Function f = (Function)lhs;
|
||||||
|
Object[] outArgs = getArgsArray(stack, frame.sDbl, stackTop + 1,
|
||||||
|
indexReg);
|
||||||
|
stack[stackTop] = f.construct(cx, frame.scope, outArgs);
|
||||||
continue Loop;
|
continue Loop;
|
||||||
}
|
}
|
||||||
case Token.TYPEOF : {
|
case Token.TYPEOF : {
|
||||||
|
@ -2675,7 +2748,8 @@ switch (op) {
|
||||||
} else {
|
} else {
|
||||||
Object val = stack[stackTop];
|
Object val = stack[stackTop];
|
||||||
if (val == DBL_MRK) val = doubleWrap(sDbl[stackTop]);
|
if (val == DBL_MRK) val = doubleWrap(sDbl[stackTop]);
|
||||||
activationPut(frame, indexReg, val);
|
stringReg = frame.fnOrScript.argNames[indexReg];
|
||||||
|
frame.scope.put(stringReg, frame.scope, val);
|
||||||
}
|
}
|
||||||
continue Loop;
|
continue Loop;
|
||||||
case Icode_GETVAR1:
|
case Icode_GETVAR1:
|
||||||
|
@ -2687,7 +2761,8 @@ switch (op) {
|
||||||
stack[stackTop] = stack[indexReg];
|
stack[stackTop] = stack[indexReg];
|
||||||
sDbl[stackTop] = sDbl[indexReg];
|
sDbl[stackTop] = sDbl[indexReg];
|
||||||
} else {
|
} else {
|
||||||
stack[stackTop] = activationGet(frame, indexReg);
|
stringReg = frame.fnOrScript.argNames[indexReg];
|
||||||
|
stack[stackTop] = frame.scope.get(stringReg, frame.scope);
|
||||||
}
|
}
|
||||||
continue Loop;
|
continue Loop;
|
||||||
case Icode_VAR_INC_DEC : {
|
case Icode_VAR_INC_DEC : {
|
||||||
|
@ -2754,14 +2829,27 @@ switch (op) {
|
||||||
case Token.LEAVEWITH :
|
case Token.LEAVEWITH :
|
||||||
frame.scope = ScriptRuntime.leaveWith(frame.scope);
|
frame.scope = ScriptRuntime.leaveWith(frame.scope);
|
||||||
continue Loop;
|
continue Loop;
|
||||||
case Token.CATCH_SCOPE :
|
case Token.CATCH_SCOPE : {
|
||||||
// stack top: exception object
|
// stack top: exception object
|
||||||
// stringReg: name of exception variable
|
// stringReg: name of exception variable
|
||||||
// indexReg: local for exception scope
|
// indexReg: local for exception scope
|
||||||
--stackTop;
|
--stackTop;
|
||||||
indexReg += frame.localShift;
|
indexReg += frame.localShift;
|
||||||
do_catchScope(cx, frame, stackTop + 1, indexReg, stringReg);
|
|
||||||
|
boolean afterFirstScope = (frame.idata.itsICode[frame.pc] != 0);
|
||||||
|
Throwable caughtException = (Throwable)stack[stackTop + 1];
|
||||||
|
Scriptable lastCatchScope;
|
||||||
|
if (!afterFirstScope) {
|
||||||
|
lastCatchScope = null;
|
||||||
|
} else {
|
||||||
|
lastCatchScope = (Scriptable)stack[indexReg];
|
||||||
|
}
|
||||||
|
stack[indexReg] = ScriptRuntime.newCatchScope(caughtException,
|
||||||
|
lastCatchScope, stringReg,
|
||||||
|
cx, frame.scope);
|
||||||
|
++frame.pc;
|
||||||
continue Loop;
|
continue Loop;
|
||||||
|
}
|
||||||
case Token.ENUM_INIT_KEYS : {
|
case Token.ENUM_INIT_KEYS : {
|
||||||
Object lhs = stack[stackTop];
|
Object lhs = stack[stackTop];
|
||||||
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
|
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
|
||||||
|
@ -3295,107 +3383,6 @@ switch (op) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return null to indicate no frame change or reference to the new frame.
|
|
||||||
*/
|
|
||||||
private static CallFrame do_call(Context cx, CallFrame frame, int stackTop,
|
|
||||||
int argCount, int op)
|
|
||||||
{
|
|
||||||
Object[] stack = frame.stack;
|
|
||||||
|
|
||||||
// CALL generation ensures that fun and funThisObj
|
|
||||||
// are already Scriptable and Function objects respectively
|
|
||||||
Function fun = (Function)stack[stackTop];
|
|
||||||
Scriptable funThisObj = (Scriptable)stack[stackTop + 1];
|
|
||||||
|
|
||||||
Scriptable calleeScope = frame.scope;
|
|
||||||
if (frame.useActivation) {
|
|
||||||
calleeScope = ScriptableObject.getTopLevelScope(frame.scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fun instanceof InterpretedFunction && op != Token.REF_CALL) {
|
|
||||||
InterpretedFunction ifun = (InterpretedFunction)fun;
|
|
||||||
if (frame.fnOrScript.securityDomain == ifun.securityDomain) {
|
|
||||||
CallFrame callParentFrame = frame;
|
|
||||||
CallFrame calleeFrame = new CallFrame();
|
|
||||||
if (op == Icode_TAIL_CALL) {
|
|
||||||
// In principle tail call can re-use the current
|
|
||||||
// frame and its stack arrays but it is hard to
|
|
||||||
// do properly. Any exceptions that can legally
|
|
||||||
// happen during frame re-initialization including
|
|
||||||
// StackOverflowException during innocent looking
|
|
||||||
// System.arraycopy may leave the current frame
|
|
||||||
// data corrupted leading to undefined behaviour
|
|
||||||
// in the catch code bellow that unwinds JS stack
|
|
||||||
// on exceptions. Then there is issue about frame release
|
|
||||||
// end exceptions there.
|
|
||||||
// To avoid frame allocation a released frame
|
|
||||||
// can be cached for re-use which would also benefit
|
|
||||||
// non-tail calls but it is not clear that this caching
|
|
||||||
// would gain in performance due to potentially
|
|
||||||
// bad iteraction with GC.
|
|
||||||
callParentFrame = frame.parentFrame;
|
|
||||||
}
|
|
||||||
initFrame(cx, calleeScope, funThisObj, stack, frame.sDbl,
|
|
||||||
stackTop + 2, argCount, ifun, callParentFrame,
|
|
||||||
calleeFrame);
|
|
||||||
if (op == Icode_TAIL_CALL) {
|
|
||||||
// Release the parent
|
|
||||||
exitFrame(cx, frame, null);
|
|
||||||
} else {
|
|
||||||
frame.savedStackTop = stackTop;
|
|
||||||
frame.savedCallOp = op;
|
|
||||||
}
|
|
||||||
return calleeFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object[] outArgs = getArgsArray(stack, frame.sDbl, stackTop + 2,
|
|
||||||
argCount);
|
|
||||||
if (op != Token.REF_CALL) {
|
|
||||||
stack[stackTop] = fun.call(cx, calleeScope, funThisObj, outArgs);
|
|
||||||
} else {
|
|
||||||
stack[stackTop] = ScriptRuntime.referenceCall(fun, funThisObj,
|
|
||||||
outArgs, cx,
|
|
||||||
calleeScope);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return null to indicate no frame change or reference to the new frame.
|
|
||||||
*/
|
|
||||||
private static CallFrame do_new(Context cx, CallFrame frame, int stackTop,
|
|
||||||
int argCount, int op)
|
|
||||||
{
|
|
||||||
Object[] stack = frame.stack;
|
|
||||||
Object lhs = stack[stackTop];
|
|
||||||
|
|
||||||
if (lhs instanceof InterpretedFunction) {
|
|
||||||
InterpretedFunction f = (InterpretedFunction)lhs;
|
|
||||||
if (frame.fnOrScript.securityDomain == f.securityDomain) {
|
|
||||||
Scriptable newInstance = f.createObject(cx, frame.scope);
|
|
||||||
CallFrame calleeFrame = new CallFrame();
|
|
||||||
initFrame(cx, frame.scope, newInstance, stack, frame.sDbl,
|
|
||||||
stackTop + 1, argCount, f, frame,
|
|
||||||
calleeFrame);
|
|
||||||
|
|
||||||
stack[stackTop] = newInstance;
|
|
||||||
frame.savedStackTop = stackTop;
|
|
||||||
frame.savedCallOp = op;
|
|
||||||
return calleeFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!(lhs instanceof Function)) {
|
|
||||||
if (lhs == DBL_MRK) lhs = doubleWrap(frame.sDbl[stackTop]);
|
|
||||||
throw ScriptRuntime.notFunctionError(lhs);
|
|
||||||
}
|
|
||||||
Function f = (Function)lhs;
|
|
||||||
Object[] outArgs = getArgsArray(stack, frame.sDbl, stackTop + 1,
|
|
||||||
argCount);
|
|
||||||
stack[stackTop] = f.construct(cx, frame.scope, outArgs);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object doubleWrap(double x)
|
private static Object doubleWrap(double x)
|
||||||
{
|
{
|
||||||
return new Double(x);
|
return new Double(x);
|
||||||
|
@ -3441,27 +3428,30 @@ switch (op) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int do_add(Object[] stack, double[] sDbl, int stackTop,
|
private static void do_add(Object[] stack, double[] sDbl, int stackTop,
|
||||||
Context cx)
|
Context cx)
|
||||||
{
|
{
|
||||||
--stackTop;
|
|
||||||
Object rhs = stack[stackTop + 1];
|
Object rhs = stack[stackTop + 1];
|
||||||
Object lhs = stack[stackTop];
|
Object lhs = stack[stackTop];
|
||||||
|
double d;
|
||||||
|
boolean leftRightOrder;
|
||||||
if (rhs == DBL_MRK) {
|
if (rhs == DBL_MRK) {
|
||||||
double rDbl = sDbl[stackTop + 1];
|
d = sDbl[stackTop + 1];
|
||||||
if (lhs == DBL_MRK) {
|
if (lhs == DBL_MRK) {
|
||||||
sDbl[stackTop] += rDbl;
|
sDbl[stackTop] += d;
|
||||||
} else {
|
return;
|
||||||
do_add(lhs, rDbl, stack, sDbl, stackTop, true, cx);
|
|
||||||
}
|
}
|
||||||
|
leftRightOrder = true;
|
||||||
|
// fallthrough to object + number code
|
||||||
} else if (lhs == DBL_MRK) {
|
} else if (lhs == DBL_MRK) {
|
||||||
do_add(rhs, sDbl[stackTop], stack, sDbl, stackTop, false, cx);
|
d = sDbl[stackTop];
|
||||||
|
lhs = rhs;
|
||||||
|
leftRightOrder = false;
|
||||||
|
// fallthrough to object + number code
|
||||||
} else {
|
} else {
|
||||||
if (lhs instanceof Scriptable || rhs instanceof Scriptable) {
|
if (lhs instanceof Scriptable || rhs instanceof Scriptable) {
|
||||||
stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
|
stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
|
||||||
return stackTop;
|
} else if (lhs instanceof String) {
|
||||||
}
|
|
||||||
if (lhs instanceof String) {
|
|
||||||
String lstr = (String)lhs;
|
String lstr = (String)lhs;
|
||||||
String rstr = ScriptRuntime.toString(rhs);
|
String rstr = ScriptRuntime.toString(rhs);
|
||||||
stack[stackTop] = lstr.concat(rstr);
|
stack[stackTop] = lstr.concat(rstr);
|
||||||
|
@ -3477,30 +3467,22 @@ switch (op) {
|
||||||
stack[stackTop] = DBL_MRK;
|
stack[stackTop] = DBL_MRK;
|
||||||
sDbl[stackTop] = lDbl + rDbl;
|
sDbl[stackTop] = lDbl + rDbl;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return stackTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
// x + y when x is Number
|
// handle object(lhs) + number(d) code
|
||||||
private static void do_add
|
|
||||||
(Object lhs, double rDbl,
|
|
||||||
Object[] stack, double[] stackDbl, int stackTop,
|
|
||||||
boolean left_right_order, Context cx)
|
|
||||||
{
|
|
||||||
if (lhs instanceof Scriptable) {
|
if (lhs instanceof Scriptable) {
|
||||||
Object rhs = doubleWrap(rDbl);
|
rhs = doubleWrap(d);
|
||||||
if (!left_right_order) {
|
if (!leftRightOrder) {
|
||||||
Object tmp = lhs;
|
Object tmp = lhs;
|
||||||
lhs = rhs;
|
lhs = rhs;
|
||||||
rhs = tmp;
|
rhs = tmp;
|
||||||
}
|
}
|
||||||
stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
|
stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx);
|
||||||
return;
|
} else if (lhs instanceof String) {
|
||||||
}
|
|
||||||
if (lhs instanceof String) {
|
|
||||||
String lstr = (String)lhs;
|
String lstr = (String)lhs;
|
||||||
String rstr = ScriptRuntime.toString(rDbl);
|
String rstr = ScriptRuntime.toString(d);
|
||||||
if (left_right_order) {
|
if (leftRightOrder) {
|
||||||
stack[stackTop] = lstr.concat(rstr);
|
stack[stackTop] = lstr.concat(rstr);
|
||||||
} else {
|
} else {
|
||||||
stack[stackTop] = rstr.concat(lstr);
|
stack[stackTop] = rstr.concat(lstr);
|
||||||
|
@ -3509,7 +3491,7 @@ switch (op) {
|
||||||
double lDbl = (lhs instanceof Number)
|
double lDbl = (lhs instanceof Number)
|
||||||
? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs);
|
? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs);
|
||||||
stack[stackTop] = DBL_MRK;
|
stack[stackTop] = DBL_MRK;
|
||||||
stackDbl[stackTop] = lDbl + rDbl;
|
sDbl[stackTop] = lDbl + d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3688,25 +3670,6 @@ switch (op) {
|
||||||
frame.stack[i] = result;
|
frame.stack[i] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void do_catchScope(Context cx, CallFrame frame,
|
|
||||||
int exceptionOffset,
|
|
||||||
int local, String name)
|
|
||||||
{
|
|
||||||
Object[] stack = frame.stack;
|
|
||||||
boolean afterFirstScope = (frame.idata.itsICode[frame.pc] != 0);
|
|
||||||
Throwable caughtException = (Throwable)stack[exceptionOffset];
|
|
||||||
Scriptable lastCatchScope;
|
|
||||||
if (!afterFirstScope) {
|
|
||||||
lastCatchScope = null;
|
|
||||||
} else {
|
|
||||||
lastCatchScope = (Scriptable)stack[local];
|
|
||||||
}
|
|
||||||
stack[local] = ScriptRuntime.newCatchScope(caughtException,
|
|
||||||
lastCatchScope, name,
|
|
||||||
cx, frame.scope);
|
|
||||||
++frame.pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object[] getArgsArray(Object[] stack, double[] sDbl,
|
private static Object[] getArgsArray(Object[] stack, double[] sDbl,
|
||||||
int shift, int count)
|
int shift, int count)
|
||||||
{
|
{
|
||||||
|
@ -3722,23 +3685,6 @@ switch (op) {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object activationGet(CallFrame frame, int slot)
|
|
||||||
{
|
|
||||||
String name = frame.fnOrScript.argNames[slot];
|
|
||||||
Scriptable scope = frame.scope;
|
|
||||||
Object val = scope.get(name, scope);
|
|
||||||
// Activation parameter or var is permanent
|
|
||||||
if (val == Scriptable.NOT_FOUND) Kit.codeBug();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void activationPut(CallFrame frame, int slot, Object value)
|
|
||||||
{
|
|
||||||
String name = frame.fnOrScript.argNames[slot];
|
|
||||||
Scriptable scope = frame.scope;
|
|
||||||
scope.put(name, scope, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addInstructionCount(Context cx, CallFrame frame,
|
private static void addInstructionCount(Context cx, CallFrame frame,
|
||||||
int extra)
|
int extra)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче