This commit is contained in:
David Anderson 2008-08-25 16:06:17 -07:00
commit e4ef2c3451
6 changed files with 67 additions and 24 deletions

View File

@ -4664,7 +4664,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
ale = NULL;
while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH)
stmt = stmt->down;
noteType = SRC_NULL;
noteType = SRC_BREAK;
}
if (EmitGoto(cx, cg, stmt, &stmt->breaks, ale, noteType) < 0)

View File

@ -563,6 +563,7 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
typedef enum JSSrcNoteType {
SRC_NULL = 0, /* terminates a note vector */
SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */
SRC_BREAK = 1, /* JSOP_GOTO is a break */
SRC_INITPROP = 1, /* disjoint meaning applied to JSOP_INITELEM or
to an index label in a regular (structuring)
or a destructuring object initialiser */

View File

@ -1483,6 +1483,34 @@ TraceRecorder::isLoopHeader(JSContext* cx) const
return cx->fp->regs->pc == fragment->root->ip;
}
/* Compile the current fragment. */
void
TraceRecorder::compile(Fragmento* fragmento)
{
if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) {
debug_only_v(printf("Trace rejected: excessive stack use.\n"));
fragment->blacklist();
return;
}
::compile(fragmento->assm(), fragment);
if (anchor) {
fragment->addLink(anchor);
fragmento->assm()->patch(anchor);
}
JS_ASSERT(fragment->code());
JS_ASSERT(!fragment->vmprivate);
if (fragment == fragment->root)
fragment->vmprivate = treeInfo;
/* :TODO: windows support */
#if defined DEBUG && !defined WIN32
char* label = (char*)malloc(strlen(cx->fp->script->filename) + 64);
sprintf(label, "%s:%u", cx->fp->script->filename,
js_PCToLineNumber(cx, cx->fp->script, cx->fp->regs->pc));
fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
free(label);
#endif
}
/* Complete and compile a trace and link it to the existing tree if appropriate. */
void
TraceRecorder::closeLoop(Fragmento* fragmento)
@ -1492,11 +1520,6 @@ TraceRecorder::closeLoop(Fragmento* fragmento)
debug_only_v(printf("Trace rejected: unstable loop variables.\n");)
return;
}
if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) {
debug_only_v(printf("Trace rejected: excessive stack use.\n"));
fragment->blacklist();
return;
}
SideExit *exit = snapshot(LOOP_EXIT);
exit->target = fragment->root;
if (fragment == fragment->root) {
@ -1504,23 +1527,16 @@ TraceRecorder::closeLoop(Fragmento* fragmento)
} else {
fragment->lastIns = lir->insGuard(LIR_x, lir->insImm(1), exit);
}
compile(fragmento->assm(), fragment);
if (anchor) {
fragment->addLink(anchor);
fragmento->assm()->patch(anchor);
}
JS_ASSERT(fragment->code());
JS_ASSERT(!fragment->vmprivate);
if (fragment == fragment->root)
fragment->vmprivate = treeInfo;
/* :TODO: windows support */
#if defined DEBUG && !defined WIN32
char* label = (char*)malloc(strlen(cx->fp->script->filename) + 64);
sprintf(label, "%s:%u", cx->fp->script->filename,
js_PCToLineNumber(cx, cx->fp->script, cx->fp->regs->pc));
fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
free(label);
#endif
compile(fragmento);
}
/* Emit an always-exit guard and compile the tree (used for break statements. */
void
TraceRecorder::endLoop(Fragmento* fragmento)
{
SideExit *exit = snapshot(LOOP_EXIT);
fragment->lastIns = lir->insGuard(LIR_x, lir->insImm(1), exit);
compile(fragmento);
}
/* Emit code to adjust the stack to match the inner tree's stack expectations. */

View File

@ -318,7 +318,9 @@ public:
nanojit::SideExit* snapshot(nanojit::ExitType exitType);
nanojit::Fragment* getFragment() const { return fragment; }
bool isLoopHeader(JSContext* cx) const;
void compile(nanojit::Fragmento* fragmento);
void closeLoop(nanojit::Fragmento* fragmento);
void endLoop(nanojit::Fragmento* fragmento);
void blacklist() { fragment->blacklist(); }
bool adjustCallerTypes(nanojit::Fragment* f);
bool selectCallablePeerFragment(nanojit::Fragment** first);

View File

@ -875,6 +875,29 @@ function forVarInWith() {
forVarInWith.expected = "pqrst";
test(forVarInWith);
function addAccumulations(f) {
var a = f();
var b = f();
return a() + b();
}
function loopingAccumulator() {
var x = 0;
return function () {
for (var i = 0; i < 10; ++i) {
++x;
}
return x;
}
}
function testLoopingAccumulator() {
var x = addAccumulations(loopingAccumulator);
return x;
}
testLoopingAccumulator.expected = 20;
test(testLoopingAccumulator);
/* Keep these at the end so that we can see the summary after the trace-debug spew. */
print("\npassed:", passes.length && passes.join(","));
print("\nFAILED:", fails.length && fails.join(","));

View File

@ -110,7 +110,8 @@ done
for t in $testdir/test_*.js
do
NATIVE_TOPSRCDIR="$native_topsrcdir" TOPSRCDIR="$topsrcdir" $xpcshell -s $headfiles -f $t $tailfiles 2> $t.log 1>&2
echo "NATIVE_TOPSRCDIR=\"$native_topsrcdir\" TOPSRCDIR=\"$topsrcdir\" $xpcshell -j -s $headfiles -f $t $tailfiles 2> $t.log 1>&2"
NATIVE_TOPSRCDIR="$native_topsrcdir" TOPSRCDIR="$topsrcdir" $xpcshell -j -s $headfiles -f $t $tailfiles 2> $t.log 1>&2
rv="$?"
if [ ! "$rv" = "0" -o \
`grep -c '\*\*\* PASS' $t.log` = 0 ]