зеркало из https://github.com/mozilla/pjs.git
Fixed missing pop after var initialization. Added instruction trace.
This commit is contained in:
Родитель
5eb7567cee
Коммит
bbdfe41e76
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче