Bug 398085: better handling of long jumps in the bytecode. r,a=brendan,aM9=beltzner

This commit is contained in:
igor@mir2.org 2007-11-06 11:41:04 -08:00
Родитель 4c818cf302
Коммит f33231e83b
1 изменённых файлов: 63 добавлений и 54 удалений

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

@ -559,79 +559,77 @@ AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2,
return JS_TRUE;
}
static jsbytecode *
AddSwitchSpanDeps(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc)
{
JSOp op;
jsbytecode *pc2;
ptrdiff_t off;
jsint low, high;
uintN njumps, indexlen;
op = (JSOp) *pc;
JS_ASSERT(op == JSOP_TABLESWITCH || op == JSOP_LOOKUPSWITCH);
pc2 = pc;
off = GET_JUMP_OFFSET(pc2);
if (!AddSpanDep(cx, cg, pc, pc2, off))
return NULL;
pc2 += JUMP_OFFSET_LEN;
if (op == JSOP_TABLESWITCH) {
low = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
high = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
njumps = (uintN) (high - low + 1);
indexlen = 0;
} else {
njumps = GET_UINT16(pc2);
pc2 += UINT16_LEN;
indexlen = INDEX_LEN;
}
while (njumps) {
--njumps;
pc2 += indexlen;
off = GET_JUMP_OFFSET(pc2);
if (!AddSpanDep(cx, cg, pc, pc2, off))
return NULL;
pc2 += JUMP_OFFSET_LEN;
}
return 1 + pc2;
}
static JSBool
BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg)
{
jsbytecode *pc, *end;
JSOp op;
const JSCodeSpec *cs;
ptrdiff_t len, off;
ptrdiff_t off;
pc = CG_BASE(cg) + cg->spanDepTodo;
end = CG_NEXT(cg);
while (pc < end) {
while (pc != end) {
JS_ASSERT(pc < end);
op = (JSOp)*pc;
cs = &js_CodeSpec[op];
len = (ptrdiff_t)cs->length;
switch (cs->format & JOF_TYPEMASK) {
case JOF_TABLESWITCH:
case JOF_LOOKUPSWITCH:
pc = AddSwitchSpanDeps(cx, cg, pc);
if (!pc)
return JS_FALSE;
break;
case JOF_JUMP:
off = GET_JUMP_OFFSET(pc);
if (!AddSpanDep(cx, cg, pc, pc, off))
return JS_FALSE;
/* FALL THROUGH */
default:
pc += cs->length;
break;
case JOF_TABLESWITCH:
{
jsbytecode *pc2;
jsint i, low, high;
pc2 = pc;
off = GET_JUMP_OFFSET(pc2);
if (!AddSpanDep(cx, cg, pc, pc2, off))
return JS_FALSE;
pc2 += JUMP_OFFSET_LEN;
low = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
high = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
for (i = low; i <= high; i++) {
off = GET_JUMP_OFFSET(pc2);
if (!AddSpanDep(cx, cg, pc, pc2, off))
return JS_FALSE;
pc2 += JUMP_OFFSET_LEN;
}
len = 1 + pc2 - pc;
break;
}
case JOF_LOOKUPSWITCH:
{
jsbytecode *pc2;
jsint npairs;
pc2 = pc;
off = GET_JUMP_OFFSET(pc2);
if (!AddSpanDep(cx, cg, pc, pc2, off))
return JS_FALSE;
pc2 += JUMP_OFFSET_LEN;
npairs = (jsint) GET_UINT16(pc2);
pc2 += UINT16_LEN;
while (npairs) {
pc2 += INDEX_LEN;
off = GET_JUMP_OFFSET(pc2);
if (!AddSpanDep(cx, cg, pc, pc2, off))
return JS_FALSE;
pc2 += JUMP_OFFSET_LEN;
npairs--;
}
len = 1 + pc2 - pc;
break;
}
}
JS_ASSERT(len > 0);
pc += len;
}
return JS_TRUE;
@ -3032,6 +3030,17 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
* must set ok and goto out to exit this function. To keep things
* simple, all switchOp cases exit that way.
*/
if (cg->spanDeps) {
/*
* We have already generated at least one big jump so we must
* explicitly add span dependencies for the switch jumps. When
* called below, js_SetJumpOffset can only do it when patching
* the first big jump or when cg->spanDeps is null.
*/
if (!AddSwitchSpanDeps(cx, cg, CG_CODE(cg, top)))
goto bad;
}
if (constPropagated) {
/*
* Skip switchOp, as we are not setting jump offsets in the two