diff --git a/mozilla/js2/src/epimetheus.cpp b/mozilla/js2/src/epimetheus.cpp index 4c2fde04ac5..1e61666949f 100644 --- a/mozilla/js2/src/epimetheus.cpp +++ b/mozilla/js2/src/epimetheus.cpp @@ -115,7 +115,7 @@ static int readEvalPrint(FILE *in) try { Pragma::Flags flags = Pragma::es4; Parser p(world, a, flags, buffer, ConsoleName); - if (metadata->showTrees) { + if (showTokens) { Lexer &l = p.lexer; while (true) { const Token &t = l.get(true); @@ -128,7 +128,7 @@ static int readEvalPrint(FILE *in) } else { StmtNode *parsedStatements = p.parseProgram(); ASSERT(p.lexer.peek(true).hasKind(Token::end)); - if (true) + if (metadata->showTrees) { PrettyPrinter f(stdOut, 30); { @@ -165,10 +165,11 @@ static int readEvalPrint(FILE *in) return result; } -static bool processArgs(int argc, char **argv, int *result, bool *doTrees) +static bool processArgs(int argc, char **argv, int *result, bool *doTrees, bool *doTrace) { bool doInteractive = true; *doTrees = false; + *doTrace = false; for (int i = 0; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { @@ -179,6 +180,9 @@ static bool processArgs(int argc, char **argv, int *result, bool *doTrees) case 't': *doTrees = true; break; + case 'x': + *doTrace = true; + break; case 'i': doInteractive = true; break; @@ -217,6 +221,18 @@ js2val print(JS2Metadata * /* meta */, const js2val /* thisValue */, js2val argv } #ifdef DEBUG +js2val trees(JS2Metadata *meta, const js2val /* thisValue */, js2val /* argv */ [], uint32 /* argc */) +{ + meta->showTrees = !meta->showTrees; + return JS2VAL_UNDEFINED; +} + +js2val trace(JS2Metadata *meta, const js2val /* thisValue */, js2val /* argv */ [], uint32 /* argc */) +{ + meta->engine->traceInstructions = !meta->engine->traceInstructions; + return JS2VAL_UNDEFINED; +} + js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc) { if (argc) { @@ -288,13 +304,15 @@ int main(int argc, char **argv) metadata->addGlobalObjectFunction("load", load); #ifdef DEBUG metadata->addGlobalObjectFunction("dump", dump); + metadata->addGlobalObjectFunction("trees", dump); + metadata->addGlobalObjectFunction("trace", dump); #endif try { bool doInteractive = true; int result = 0; if (argc > 1) { - doInteractive = processArgs(argc - 1, argv + 1, &result, &metadata->showTrees); + doInteractive = processArgs(argc - 1, argv + 1, &result, &metadata->showTrees, &metadata->engine->traceInstructions); } if (doInteractive) result = readEvalPrint(stdin); diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index c75bbf5f819..7e74a3ed495 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -77,7 +77,7 @@ namespace MetaData { rts(); throw jsx; } - activationStackTop = f; // when execution falls 'off the bottom' an rts hasn't occurred + activationStackTop = f - 1; // when execution falls 'off the bottom' an rts hasn't occurred // so the activation stack is off by 1. return result; } @@ -92,6 +92,10 @@ namespace MetaData { try { a = JS2VAL_VOID; b = JS2VAL_VOID; +#ifdef DEBUG + if (traceInstructions) + printInstruction(pc, bCon->getCodeStart(), bCon, this); +#endif JS2Op op = (JS2Op)*pc++; switch (op) { #include "js2op_arithmetic.cpp" @@ -366,7 +370,8 @@ namespace MetaData { Dollar_StringAtom(&world.identifiers["$"]), INIT_STRINGATOM(prototype), INIT_STRINGATOM(length), - INIT_STRINGATOM(toString) + INIT_STRINGATOM(toString), + traceInstructions(false) { for (int i = 0; i < 256; i++) float64Table[i] = NULL; @@ -483,69 +488,78 @@ namespace MetaData { }; + uint8 *printInstruction(uint8 *pc, uint8 *start, BytecodeContainer *bCon, JS2Engine *engine) + { + if (engine) + printFormat(stdOut, "%.4d %.4d ", pc - start, (int32)(engine->sp - engine->execStack)); + else + printFormat(stdOut, "%.4d ", pc - start); + stdOut << opcodeData[*pc].name; + switch (opcodeData[*pc++].flags) { + case BRANCH_OFFSET: + { + int32 offset = BytecodeContainer::getOffset(pc); + stdOut << " " << offset << " --> " << (pc - start) + offset; + pc += sizeof(int32); + } + break; + case STR_PTR: + { + uint16 index = BytecodeContainer::getShort(pc); + stdOut << "\"" << bCon->mStringList[index] << "\""; + pc += sizeof(short); + } + break; + case NAME_INDEX: + { + Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; + stdOut << " " << *mn->name; + pc += sizeof(short); + } + break; + case FRAME_INDEX: + { + pc += sizeof(short); + } + break; + case BRANCH_PAIR: + { + int32 offset1 = BytecodeContainer::getOffset(pc); + pc += sizeof(int32); + int32 offset2 = BytecodeContainer::getOffset(pc); + pc += sizeof(int32); + if (offset1 == (int32)NotALabel) + stdOut << "no finally; "; + else + stdOut << "(finally) " << offset1 << " --> " << (pc - start) + offset1 << "; "; + if (offset2 == (int32)NotALabel) + stdOut << "no catch;"; + else + stdOut << "(catch) " << offset2 << " --> " << (pc - start) + offset2; + } + break; + case FLOAT64: + { + stdOut << " " << BytecodeContainer::getFloat64(pc); + pc += sizeof(float64); + } + break; + } + stdOut << "\n"; + return pc; + } + void dumpBytecode(BytecodeContainer *bCon) { uint8 *start = bCon->getCodeStart(); uint8 *end = bCon->getCodeEnd(); uint8 *pc = start; while (pc < end) { - printFormat(stdOut, "%.4d ", pc - start); - stdOut << opcodeData[*pc].name; - switch (opcodeData[*pc++].flags) { - case BRANCH_OFFSET: - { - int32 offset = BytecodeContainer::getOffset(pc); - stdOut << " " << offset << " --> " << (pc - start) + offset; - pc += sizeof(int32); - } - break; - case STR_PTR: - { - uint16 index = BytecodeContainer::getShort(pc); - stdOut << "\"" << bCon->mStringList[index] << "\""; - pc += sizeof(short); - } - break; - case NAME_INDEX: - { - Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; - stdOut << " " << *mn->name; - pc += sizeof(short); - } - break; - case FRAME_INDEX: - { - pc += sizeof(short); - } - break; - case BRANCH_PAIR: - { - int32 offset1 = BytecodeContainer::getOffset(pc); - pc += sizeof(int32); - int32 offset2 = BytecodeContainer::getOffset(pc); - pc += sizeof(int32); - if (offset1 == (int32)NotALabel) - stdOut << "no finally; "; - else - stdOut << "(finally) " << offset1 << " --> " << (pc - start) + offset1 << "; "; - if (offset2 == (int32)NotALabel) - stdOut << "no catch;"; - else - stdOut << "(catch) " << offset2 << " --> " << (pc - start) + offset2; - } - break; - case FLOAT64: - { - stdOut << " " << BytecodeContainer::getFloat64(pc); - pc += sizeof(float64); - } - break; - } - stdOut << "\n"; + pc = printInstruction(pc, start, bCon, NULL); } } -#endif +#endif // DEBUG // Return the effect of an opcode on the execution stack. // Some ops (e.g. eCall) have a variable effect, those are handled separately diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 8f3b68683b1..59d8ac3b86d 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -289,12 +289,16 @@ public: void mark(); + bool traceInstructions; // emit trace of each instruction executed static js2val defaultConstructor(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc); }; +#ifdef DEBUG +uint8 *printInstruction(uint8 *pc, uint8 *start, BytecodeContainer *bCon, JS2Engine *engine); +#endif } } diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 93a6aa77f04..326dca3de0f 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -1195,7 +1195,8 @@ namespace MetaData { if (r) r->emitReadBytecode(bCon, p->pos); LexicalReference *lVal = new LexicalReference(vb->name, cxt.strict); lVal->variableMultiname->addNamespace(publicNamespace); - lVal->emitWriteBytecode(bCon, p->pos); + lVal->emitWriteBytecode(bCon, p->pos); + bCon->emitOp(ePop, p->pos); } } }