DumpByteCode implemented/
This commit is contained in:
Родитель
e94321a746
Коммит
cee474f132
|
@ -92,6 +92,7 @@ public:
|
|||
void mark();
|
||||
|
||||
uint8 *getCodeStart() { return mBuffer.begin(); }
|
||||
uint8 *getCodeEnd() { return mBuffer.begin() + mBuffer.size(); }
|
||||
|
||||
typedef std::pair<uint16, size_t> MapEntry;
|
||||
std::vector<MapEntry> pcMap;
|
||||
|
|
|
@ -209,6 +209,30 @@ js2val print(JS2Metadata * /* meta */, const js2val /* thisValue */, js2val argv
|
|||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc)
|
||||
{
|
||||
if (argc) {
|
||||
if (JS2VAL_IS_OBJECT(argv[0])) {
|
||||
JS2Object *fObj = JS2VAL_TO_OBJECT(argv[0]);
|
||||
if ((((fObj->kind == FixedInstanceKind) || (fObj->kind == DynamicInstanceKind))
|
||||
&& (meta->objectType(argv[0]) == meta->functionClass))) {
|
||||
FunctionWrapper *fWrap;
|
||||
if (fObj->kind == FixedInstanceKind)
|
||||
fWrap = (checked_cast<FixedInstance *>(fObj))->fWrap;
|
||||
else
|
||||
fWrap = (checked_cast<DynamicInstance *>(fObj))->fWrap;
|
||||
if (fWrap->code)
|
||||
stdOut << "<native code>\n";
|
||||
else
|
||||
dumpBytecode(fWrap->bCon);
|
||||
}
|
||||
}
|
||||
}
|
||||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
#endif
|
||||
|
||||
js2val load(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc)
|
||||
{
|
||||
// Set the environment to global object and system frame so that the
|
||||
|
@ -244,7 +268,9 @@ int main(int argc, char **argv)
|
|||
metadata = new MetaData::JS2Metadata(world);
|
||||
metadata->addGlobalObjectFunction("print", print);
|
||||
metadata->addGlobalObjectFunction("load", load);
|
||||
|
||||
#ifdef DEBUG
|
||||
metadata->addGlobalObjectFunction("dump", dump);
|
||||
#endif
|
||||
|
||||
try {
|
||||
bool doInteractive = true;
|
||||
|
|
|
@ -382,9 +382,9 @@ namespace MetaData {
|
|||
activationStackTop = activationStack = new ActivationFrame[MAX_ACTIVATION_STACK];
|
||||
}
|
||||
|
||||
#ifdef NYI_DEBUG
|
||||
#ifdef DEBUG
|
||||
|
||||
enum { BRANCH_OFFSET = 1, STR_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16 };
|
||||
enum { BRANCH_OFFSET = 1, STR_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16, FLOAT64 };
|
||||
struct {
|
||||
JS2Op op;
|
||||
char *name;
|
||||
|
@ -416,8 +416,8 @@ namespace MetaData {
|
|||
{ eTrue, "True", 0 },
|
||||
{ eFalse, "False", 0 },
|
||||
{ eNull, "Null", 0 },
|
||||
{ eNumber, "Number", 0 },
|
||||
{ eRegExp, "RegExp", 0 },
|
||||
{ eNumber, "Number", FLOAT64 },
|
||||
{ eRegExp, "RegExp", U16 },
|
||||
{ eUInt64, "UInt64", 0 },
|
||||
{ eInt64, "Int64", 0 },
|
||||
{ eString, "String", STR_PTR }, // <string pointer:u32>
|
||||
|
@ -484,10 +484,65 @@ namespace MetaData {
|
|||
|
||||
};
|
||||
|
||||
void dumpBytecode(uint8 *start, uint8 *end)
|
||||
void dumpBytecode(BytecodeContainer *bCon)
|
||||
{
|
||||
uint8 *start = bCon->getCodeStart();
|
||||
uint8 *end = bCon->getCodeEnd();
|
||||
uint8 *pc = start;
|
||||
while () {
|
||||
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 == NotALabel)
|
||||
stdOut << "no finally; ";
|
||||
else
|
||||
stdOut << "(finally) " << offset1 << " --> " << (pc - start) + offset1 << "; ";
|
||||
if (offset2 == -1)
|
||||
stdOut << "no catch;";
|
||||
else
|
||||
stdOut << "(catch) " << offset2 << " --> " << (pc - start) + offset2;
|
||||
}
|
||||
break;
|
||||
case FLOAT64:
|
||||
{
|
||||
stdOut << " " << BytecodeContainer::getFloat64(pc);
|
||||
pc += sizeof(float64);
|
||||
}
|
||||
break;
|
||||
}
|
||||
stdOut << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,8 +139,6 @@ enum JS2Op {
|
|||
|
||||
};
|
||||
|
||||
int getStackEffect(JS2Op op);
|
||||
|
||||
|
||||
class Frame;
|
||||
class JS2Object;
|
||||
|
@ -148,6 +146,9 @@ class JS2Metadata;
|
|||
class BytecodeContainer;
|
||||
class JS2Class;
|
||||
|
||||
int getStackEffect(JS2Op op);
|
||||
void dumpBytecode(BytecodeContainer *bCon);
|
||||
|
||||
class JS2Engine {
|
||||
public:
|
||||
|
||||
|
|
|
@ -3091,8 +3091,13 @@ doUnary:
|
|||
reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos());
|
||||
break;
|
||||
case StaticMember::Variable:
|
||||
*rval = (checked_cast<Variable *>(m))->value;
|
||||
return true;
|
||||
{
|
||||
Variable *v = checked_cast<Variable *>(m);
|
||||
if ((phase == CompilePhase) && !v->immutable)
|
||||
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
|
||||
*rval = v->value;
|
||||
return true;
|
||||
}
|
||||
case StaticMember::HoistedVariable:
|
||||
if (phase == CompilePhase)
|
||||
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
|
||||
|
|
Загрузка…
Ссылка в новой задаче