trace JSOP_CALLELEM (484334, r=mrbkap)

This commit is contained in:
Andreas Gal 2009-03-20 17:21:57 -07:00
parent 4017bf1be3
commit 9bee45ca8e
4 changed files with 80 additions and 8 deletions

View File

@ -640,6 +640,29 @@ static struct {
/* 9*/ JSOP_STOP,
},
};
static struct {
jsbytecode callprop[12];
jsbytecode callelem[12];
} callelem_imacros = {
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_CALLBUILTIN, ((JSBUILTIN_GetProperty) & 0xff00) >> 8, ((JSBUILTIN_GetProperty) & 0xff),
/* 5*/ JSOP_PICK, 3,
/* 7*/ JSOP_CALL, 0, 1,
/*10*/ JSOP_SWAP,
/*11*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_CALLBUILTIN, ((JSBUILTIN_GetElement) & 0xff00) >> 8, ((JSBUILTIN_GetElement) & 0xff),
/* 5*/ JSOP_PICK, 3,
/* 7*/ JSOP_CALL, 0, 1,
/*10*/ JSOP_SWAP,
/*11*/ JSOP_STOP,
},
};
static struct {
jsbytecode setprop[15];
jsbytecode setelem[15];
@ -885,7 +908,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_RESETBASE0 */
0, /* JSOP_STARTXML */
0, /* JSOP_STARTXMLEXPR */
0, /* JSOP_CALLELEM */
3, /* JSOP_CALLELEM */
0, /* JSOP_STOP */
0, /* JSOP_GETXPROP */
0, /* JSOP_CALLXMLNAME */
@ -952,4 +975,5 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
|| x == JSOP_NEXTITER \
|| x == JSOP_APPLY \
|| x == JSOP_INITELEM \
|| x == JSOP_CALLELEM \
)

View File

@ -685,6 +685,30 @@
.end
.igroup callelem JSOP_CALLELEM
.imacro callprop # obj name
swap # name obj
dup # name obj obj
callbuiltin (JSBUILTIN_GetProperty) # name obj fun obj
pick 3 # obj fun obj name
call 1 # obj propval
swap # propval obj
stop
.end
.imacro callelem # obj i
swap # i obj
dup # i obj obj
callbuiltin (JSBUILTIN_GetElement) # i obj fun obj
pick 3 # obj fun obj i
call 1 # obj propval
swap # propval obj
stop
.end
.end
.igroup setelem JSOP_SETELEM
.imacro setprop # obj name val

View File

@ -6729,11 +6729,10 @@ TraceRecorder::functionCall(bool constructing, uintN argc)
LIns* this_ins = get(&tval);
/*
* If this is NULL, this is a shapeless call. If we observe a shapeless call
* at recording time, the call at this point will always be shapeless so we
* can make the decision based on recording-time introspection of this.
* If callee is not constant, it's a shapeless call and we have to guard
* explicitly that we will get this callee again at runtime.
*/
if (tval == JSVAL_NULL && !guardCallee(fval))
if (!get(&fval)->isconst() && !guardCallee(fval))
return false;
/*
@ -7266,6 +7265,8 @@ JS_DEFINE_TRCINFO_1(GetElement,
JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_GETELEM()
{
bool call = js_GetOpcode(cx, cx->fp->script, cx->fp->regs->pc) == JSOP_CALLELEM;
jsval& idx = stackval(-1);
jsval& lval = stackval(-2);
@ -7274,6 +7275,8 @@ TraceRecorder::record_JSOP_GETELEM()
// Special case for array-like access of strings.
if (JSVAL_IS_STRING(lval) && isInt32(idx)) {
if (call)
ABORT_TRACE("JSOP_CALLELEM on a string");
int i = asInt32(idx);
if (size_t(i) >= JSSTRING_LENGTH(JSVAL_TO_STRING(lval)))
ABORT_TRACE("Invalid string index in JSOP_GETELEM");
@ -7309,7 +7312,7 @@ TraceRecorder::record_JSOP_GETELEM()
if (!guardNotGlobalObject(obj, obj_ins))
return false;
return call_imacro(getelem_imacros.getprop);
return call_imacro(call ? callelem_imacros.callprop : getelem_imacros.getprop);
}
// Invalid dense array index or not a dense array.
@ -7317,7 +7320,7 @@ TraceRecorder::record_JSOP_GETELEM()
if (!guardNotGlobalObject(obj, obj_ins))
return false;
return call_imacro(getelem_imacros.getelem);
return call_imacro(call ? callelem_imacros.callelem : getelem_imacros.getelem);
}
// Fast path for dense arrays accessed with a non-negative integer index.
@ -7326,6 +7329,8 @@ TraceRecorder::record_JSOP_GETELEM()
if (!elem(lval, idx, vp, v_ins, addr_ins))
return false;
set(&lval, v_ins);
if (call)
set(&idx, obj_ins);
return true;
}
@ -9108,7 +9113,7 @@ TraceRecorder::record_JSOP_RESETBASE0()
JS_REQUIRES_STACK bool
TraceRecorder::record_JSOP_CALLELEM()
{
return false;
return record_JSOP_GETELEM();
}
JS_REQUIRES_STACK bool

View File

@ -4692,6 +4692,25 @@ testIntUnderflow.jitstats = {
};
test(testIntUnderflow);
function testCALLELEM()
{
function f() {
return 5;
}
function g() {
return 7;
}
var x = [f,f,f,f,g];
var y = 0;
for (var i = 0; i < 5; ++i)
y = x[i]();
return y;
}
testCALLELEM.expected = 7;
test(testCALLELEM);
/*****************************************************************************
* *
* _____ _ _ _____ ______ _____ _______ *