This commit is contained in:
rogerl%netscape.com 2003-05-16 22:32:35 +00:00
Родитель 01ea097d3c
Коммит b322e2770d
12 изменённых файлов: 151 добавлений и 65 удалений

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

@ -188,9 +188,9 @@ public:
String mSource; // for error reporting
String mSourceLocation; // for error reporting
#ifdef DEBUG
//#ifdef DEBUG
String fName; // relevant function name for trace output
#endif
//#endif
};

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

@ -223,7 +223,7 @@ js2val print(JS2Metadata * /* meta */, const js2val /* thisValue */, js2val argv
return JS2VAL_UNDEFINED;
}
#ifdef DEBUG
//#ifdef DEBUG
js2val trees(JS2Metadata *meta, const js2val /* thisValue */, js2val /* argv */ [], uint32 /* argc */)
{
meta->showTrees = !meta->showTrees;
@ -436,7 +436,7 @@ js2val forceGC(JS2Metadata *meta, const js2val /* thisValue */, js2val /* argv *
return JS2VAL_VOID;
}
#endif
//#endif
js2val load(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc)
{
@ -483,13 +483,13 @@ int main(int argc, char **argv)
metadata->addGlobalObjectFunction("print", print, 1);
metadata->addGlobalObjectFunction("load", load, 1);
#ifdef DEBUG
//#ifdef DEBUG
metadata->addGlobalObjectFunction("dump", dump, 1);
metadata->addGlobalObjectFunction("dumpAt", dumpAt, 1);
metadata->addGlobalObjectFunction("trees", trees, 0);
metadata->addGlobalObjectFunction("trace", trace, 0);
metadata->addGlobalObjectFunction("gc", forceGC, 0);
#endif
//#endif
try {
bool doInteractive = true;

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

@ -107,10 +107,10 @@ namespace MetaData {
try {
a = JS2VAL_VOID;
b = JS2VAL_VOID;
#ifdef DEBUG
//#ifdef DEBUG
if (traceInstructions)
printInstruction(pc, bCon->getCodeStart(), bCon, this);
#endif
//#endif
JS2Op op = (JS2Op)*pc++;
switch (op) {
#include "js2op_arithmetic.cpp"
@ -493,7 +493,7 @@ namespace MetaData {
delete [] activationStack;
}
#ifdef DEBUG
//#ifdef DEBUG
enum { BRANCH_OFFSET = 1, STR_PTR, TYPE_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16, FLOAT64, S32, BREAK_OFFSET_AND_COUNT };
struct {
@ -535,6 +535,7 @@ namespace MetaData {
{ eInteger, "Integer", S32 },
{ eRegExp, "RegExp", U16 },
{ eFunction, "Function", U16 },
{ eClosure, "Closure", U16 },
{ eUInt64, "UInt64", 0 },
{ eInt64, "Int64", 0 },
{ eString, "String", STR_PTR }, // <string pointer:u32>
@ -619,6 +620,7 @@ namespace MetaData {
{ eTypeof, "Typeof", 0 },
{ eInstanceof, "Instanceof", 0 },
{ eIs, "Is", 0 },
{ eIn, "In", 0 },
{ ePopv, "Popv", 0 },
{ ePop, "Pop", 0 },
@ -749,7 +751,7 @@ namespace MetaData {
}
}
#endif // DEBUG
//#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
@ -791,6 +793,7 @@ namespace MetaData {
case eIs: // pop expr, pop type, push boolean
case eInstanceof:
case eIn:
return 1;
case eCoerce: // pop value, push coerced value (type is arg)
@ -821,6 +824,9 @@ namespace MetaData {
case eLongZero:
return 1; // push literal value
case eClosure:
return 0;
case eSuperExpr:
return 0;

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

@ -78,7 +78,8 @@ enum JS2Op {
eNumber,
eInteger,
eRegExp,
eFunction,
eFunction, // <object index:u16>
eClosure, // <object index:u16>
eUInt64,
eInt64,
eString, // <string pointer:u32>
@ -163,6 +164,7 @@ enum JS2Op {
eTypeof,
eInstanceof,
eIs,
eIn,
ePopv,
ePop,
@ -370,9 +372,9 @@ public:
};
#ifdef DEBUG
//#ifdef DEBUG
uint8 *printInstruction(uint8 *pc, uint8 *start, BytecodeContainer *bCon, JS2Engine *engine);
#endif
//#endif
}
}

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

@ -652,14 +652,15 @@ namespace MetaData {
return false;
}
switch (m->memberKind) {
case Member::FrameVariableMember:
return meta->readLocalMember(checked_cast<LocalMember *>(m), phase, rval, checked_cast<Frame *>(JS2VAL_TO_OBJECT(*base)));
case Member::ForbiddenMember:
case Member::DynamicVariableMember:
case Member::FrameVariableMember:
case Member::VariableMember:
case Member::ConstructorMethodMember:
case Member::SetterMember:
case Member::GetterMember:
return meta->readLocalMember(checked_cast<LocalMember *>(m), phase, rval);
return meta->readLocalMember(checked_cast<LocalMember *>(m), phase, rval, NULL);
case Member::InstanceVariableMember:
case Member::InstanceMethodMember:
case Member::InstanceGetterMember:

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

@ -76,16 +76,18 @@ namespace MetaData {
FunctionExprNode *fnExpr = parser.parseFunctionExpression(meta->engine->errorPos());
ASSERT(parser.lexer.peek(true).hasKind(Token::end));
ASSERT(fnExpr); // otherwise, an exception would have been thrown out of here
fnExpr->obj = NULL;
DEFINE_ROOTKEEPER(rk, fnExpr->obj);
fnExpr->function.fn = NULL;
DEFINE_ROOTKEEPER(rk, fnExpr->function.fn);
meta->ValidateExpression(&meta->cxt, meta->env, fnExpr);
Arena *oldArena = meta->referenceArena;
meta->referenceArena = new Arena;
try {
CompilationData *oldData = meta->startCompilationUnit(fnExpr->function.fWrap->bCon, *bodyStr, srcLoc);
meta->env->addFrame(fnExpr->function.fWrap->compileFrame);
FunctionInstance *fnInst = fnExpr->function.fn;
ASSERT(fnInst);
CompilationData *oldData = meta->startCompilationUnit(fnInst->fWrap->bCon, *bodyStr, srcLoc);
meta->env->addFrame(fnInst->fWrap->compileFrame);
meta->SetupStmt(meta->env, RunPhase, fnExpr->function.body);
fnExpr->function.fWrap->bCon->emitOp(eReturnVoid, meta->engine->errorPos());
fnInst->fWrap->bCon->emitOp(eReturnVoid, meta->engine->errorPos());
meta->env->removeTopFrame();
meta->restoreCompilationUnit(oldData);
}
@ -97,7 +99,7 @@ namespace MetaData {
meta->referenceArena->clear();
meta->referenceArena = oldArena;
ASSERT(fnExpr);
return OBJECT_TO_JS2VAL(fnExpr->obj);
return OBJECT_TO_JS2VAL(fnExpr->function.fn);
}
else { // construct an empty function wrapper
js2val thatValue = OBJECT_TO_JS2VAL(new FunctionInstance(meta, meta->functionClass->prototype, meta->functionClass));

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

@ -94,10 +94,10 @@ namespace MetaData {
FunctionInstance *result = new FunctionInstance(this, functionClass->prototype, functionClass);
DEFINE_ROOTKEEPER(rk2, result);
result->fWrap = new FunctionWrapper(unchecked, compileFrame, env);
fnDef->fWrap = result->fWrap;
fnDef->fn = result;
Frame *curTopFrame = env->getTopFrame();
CompilationData *oldData = startCompilationUnit(fnDef->fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
CompilationData *oldData = startCompilationUnit(result->fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
try {
env->addFrame(compileFrame);
VariableBinding *pb = fnDef->parameters;
@ -713,7 +713,14 @@ namespace MetaData {
{
UnaryStmtNode *w = checked_cast<UnaryStmtNode *>(p);
ValidateExpression(cxt, env, w->expr);
ValidateStmt(cxt, env, pl, w->stmt);
if (w->stmt->getKind() != StmtNode::block) {
w->compileFrame = new BlockFrame();
env->addFrame(w->compileFrame);
ValidateStmt(cxt, env, pl, w->stmt);
env->removeTopFrame();
}
else
ValidateStmt(cxt, env, pl, w->stmt);
}
break;
case StmtNode::empty:
@ -1294,18 +1301,21 @@ namespace MetaData {
if (r) r->emitReadBytecode(bCon, p->pos);
bCon->emitOp(eReturn, p->pos);
}
else
bCon->emitOp(eReturnVoid, p->pos);
}
break;
case StmtNode::Function:
{
FunctionStmtNode *f = checked_cast<FunctionStmtNode *>(p);
CompilationData *oldData = NULL;
FunctionInstance *fnInst = f->function.fn;
try {
oldData = startCompilationUnit(f->function.fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
env->addFrame(f->function.fWrap->compileFrame);
#ifdef DEBUG
oldData = startCompilationUnit(fnInst->fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
env->addFrame(fnInst->fWrap->compileFrame);
//#ifdef DEBUG
bCon->fName = *f->function.name;
#endif
//#endif
VariableBinding *pb = f->function.parameters;
while (pb) {
FrameVariable *v = checked_cast<FrameVariable *>(pb->member);
@ -1316,9 +1326,9 @@ namespace MetaData {
pb = pb->next;
}
if (f->function.resultType)
f->function.fWrap->resultType = EvalTypeExpression(env, CompilePhase, f->function.resultType);
fnInst->fWrap->resultType = EvalTypeExpression(env, CompilePhase, f->function.resultType);
else
f->function.fWrap->resultType = objectClass;
fnInst->fWrap->resultType = objectClass;
SetupStmt(env, phase, f->function.body);
// XXX need to make sure that all paths lead to an exit of some kind
@ -1331,6 +1341,8 @@ namespace MetaData {
restoreCompilationUnit(oldData);
throw x;
}
bCon->emitOp(eClosure, p->pos);
bCon->addObject(fnInst);
}
break;
case StmtNode::Var:
@ -1483,7 +1495,16 @@ namespace MetaData {
Reference *r = SetupExprNode(env, phase, w->expr, &exprType);
if (r) r->emitReadBytecode(bCon, p->pos);
bCon->emitOp(eWithin, p->pos);
SetupStmt(env, phase, w->stmt);
if (w->stmt->getKind() != StmtNode::block) {
env->addFrame(w->compileFrame);
bCon->emitOp(ePushFrame, p->pos);
bCon->addFrame(w->compileFrame);
SetupStmt(env, phase, w->stmt);
bCon->emitOp(ePopFrame, p->pos);
env->removeTopFrame();
}
else
SetupStmt(env, phase, w->stmt);
bCon->emitOp(eWithout, p->pos);
}
break;
@ -1872,6 +1893,7 @@ namespace MetaData {
case ExprNode::Instanceof:
case ExprNode::identical:
case ExprNode::notIdentical:
case ExprNode::In:
{
BinaryExprNode *b = checked_cast<BinaryExprNode *>(p);
@ -1938,7 +1960,7 @@ namespace MetaData {
case ExprNode::functionLiteral:
{
FunctionExprNode *f = checked_cast<FunctionExprNode *>(p);
f->obj = validateStaticFunction(cxt, env, &f->function, true, true, false, p->pos);
validateStaticFunction(cxt, env, &f->function, true, true, false, p->pos);
}
break;
case ExprNode::superStmt:
@ -2391,8 +2413,8 @@ doUnary:
returnRef = new (*referenceArena) ParameterSlotReference(checked_cast<FrameVariable *>(m)->frameSlot);
break;
}
keepLooking = false;
}
keepLooking = false;
}
break;
case BlockFrameKind:
@ -2703,18 +2725,29 @@ doUnary:
bCon->emitOp(eInstanceof, p->pos);
}
break;
case ExprNode::In:
{
BinaryExprNode *b = checked_cast<BinaryExprNode *>(p);
Reference *rVal = SetupExprNode(env, phase, b->op1, exprType);
if (rVal) rVal->emitReadBytecode(bCon, p->pos);
rVal = SetupExprNode(env, phase, b->op2, exprType);
if (rVal) rVal->emitReadBytecode(bCon, p->pos);
bCon->emitOp(eIn, p->pos);
}
break;
case ExprNode::functionLiteral:
{
FunctionExprNode *f = checked_cast<FunctionExprNode *>(p);
CompilationData *oldData = startCompilationUnit(f->function.fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
env->addFrame(f->function.fWrap->compileFrame);
FunctionInstance *fnInst = f->function.fn;
CompilationData *oldData = startCompilationUnit(fnInst->fWrap->bCon, bCon->mSource, bCon->mSourceLocation);
env->addFrame(fnInst->fWrap->compileFrame);
SetupStmt(env, phase, f->function.body);
// XXX need to make sure that all paths lead to an exit of some kind
bCon->emitOp(eReturnVoid, p->pos);
env->removeTopFrame();
restoreCompilationUnit(oldData);
bCon->emitOp(eFunction, p->pos);
bCon->addObject(f->obj);
bCon->addObject(fnInst);
}
break;
case ExprNode::superStmt:
@ -2856,7 +2889,7 @@ doUnary:
{
LocalMember *m = meta->findLocalMember(f, multiname, ReadAccess);
if (m)
result = meta->readLocalMember(m, phase, rval);
result = meta->readLocalMember(m, phase, rval, f);
}
break;
case WithFrameKind:
@ -3214,7 +3247,7 @@ doUnary:
// region if they haven't been marked as such already.
if (innerFrame != regionalFrame) {
fi = env->getBegin();
Frame *fr = ++fi->first;
Frame *fr = (++fi)->first;
while (true) {
if (fr->kind != WithFrameKind) {
NonWithFrame *nwfr = checked_cast<NonWithFrame *>(fr);
@ -3241,7 +3274,7 @@ doUnary:
}
if (fr == regionalFrame)
break;
fr = ++fi->first;
fr = (++fi)->first;
}
}
return multiname;
@ -4256,7 +4289,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
return false;
}
bool JS2Metadata::readLocalMember(LocalMember *m, Phase phase, js2val *rval)
bool JS2Metadata::readLocalMember(LocalMember *m, Phase phase, js2val *rval, Frame *container)
{
switch (m->memberKind) {
case LocalMember::ForbiddenMember:
@ -4272,25 +4305,27 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
}
case LocalMember::FrameVariableMember:
{
ASSERT(container);
if (phase == CompilePhase)
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
FrameVariable *f = checked_cast<FrameVariable *>(m);
switch (f->kind) {
FrameVariable *fv = checked_cast<FrameVariable *>(m);
switch (fv->kind) {
case FrameVariable::Package:
*rval = (*env->getPackageFrame()->slots)[f->frameSlot];
{
ASSERT(container->kind == PackageKind);
*rval = (*(checked_cast<Package *>(container))->slots)[fv->frameSlot];
}
break;
case FrameVariable::Local:
{
FrameListIterator fi = env->getRegionalFrame();
ASSERT((fi->first)->kind == ParameterFrameKind);
*rval = (*checked_cast<NonWithFrame *>((fi - 1)->first)->slots)[f->frameSlot];
ASSERT(container->kind == BlockFrameKind);
*rval = (*(checked_cast<NonWithFrame *>(container))->slots)[fv->frameSlot];
}
break;
case FrameVariable::Parameter:
{
FrameListIterator fi = env->getRegionalFrame();
ASSERT((fi->first)->kind == ParameterFrameKind);
*rval = (*checked_cast<NonWithFrame *>(fi->first)->slots)[f->frameSlot];
ASSERT(container->kind == ParameterFrameKind);
*rval = (*(checked_cast<ParameterFrame *>(container))->slots)[fv->frameSlot];
}
break;
}
@ -4352,14 +4387,16 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
{
FrameListIterator fi = env->getRegionalFrame();
ASSERT((fi->first)->kind == ParameterFrameKind);
(*checked_cast<NonWithFrame *>((fi - 1)->first)->slots)[f->frameSlot] = newValue;
NonWithFrame *nwf = checked_cast<NonWithFrame *>((fi - 1)->first);
(*nwf->slots)[f->frameSlot] = newValue;
}
break;
case FrameVariable::Parameter:
{
FrameListIterator fi = env->getRegionalFrame();
ASSERT((fi->first)->kind == ParameterFrameKind);
(*checked_cast<NonWithFrame *>(fi->first)->slots)[f->frameSlot] = newValue;
ParameterFrame *pFrame = checked_cast<ParameterFrame *>(fi->first);
(*pFrame->slots)[f->frameSlot] = newValue;
}
break;
}
@ -5252,9 +5289,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
p->resetMark(); // might have lingering mark from previous gc
p->clearFlags();
p->setFlag(flag);
#ifdef DEBUG
//#ifdef DEBUG
memset((p + 1), 0xB7, p->getSize() - sizeof(PondScum));
#endif
//#endif
return (p + 1);
}
pre = p;
@ -5272,9 +5309,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
}
// there was room, so acquire it
PondScum *p = (PondScum *)pondTop;
#ifdef DEBUG
//#ifdef DEBUG
memset(p, 0xB7, sz);
#endif
//#endif
p->owner = this;
p->setSize(sz);
p->setFlag(flag);
@ -5288,9 +5325,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
{
p->owner = (Pond *)freeHeader;
uint8 *t = (uint8 *)(p + 1);
#ifdef DEBUG
//#ifdef DEBUG
memset(t, 0xB3, p->getSize() - sizeof(PondScum));
#endif
//#endif
freeHeader = p;
return p->getSize() - sizeof(PondScum);
}

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

@ -1492,7 +1492,7 @@ public:
bool readLocalMember(LocalMember *m, Phase phase, js2val *rval);
bool readLocalMember(LocalMember *m, Phase phase, js2val *rval, Frame *container);
bool readInstanceMember(js2val containerVal, JS2Class *c, InstanceMember *mBase, Phase phase, js2val *rval);
bool JS2Metadata::hasOwnProperty(JS2Object *obj, const String *name);

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

@ -282,6 +282,22 @@ doCall:
}
break;
case eIn:
{
b = pop();
a = pop(); // doing 'a in b'
astr = meta->toString(a);
Multiname mn(astr);
JS2Class *c = meta->objectType(b);
bool result = ( (meta->findBaseInstanceMember(c, &mn, ReadAccess) != NULL)
|| (meta->findBaseInstanceMember(c, &mn, WriteAccess) != NULL)
|| (meta->findCommonMember(&b, &mn, ReadAccess, false) != NULL)
|| (meta->findCommonMember(&b, &mn, WriteAccess, false) != NULL));
push(BOOLEAN_TO_JS2VAL(result));
astr = NULL;
}
break;
case eInstanceof: // XXX prototype version
{
b = pop();

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

@ -91,12 +91,37 @@
case eFunction:
{
JS2Object *x = checked_cast<JS2Object *>(bCon->mObjectList[BytecodeContainer::getShort(pc)]);
FunctionInstance *x = checked_cast<FunctionInstance *>(bCon->mObjectList[BytecodeContainer::getShort(pc)]);
push(OBJECT_TO_JS2VAL(x));
pc += sizeof(short);
}
break;
case eClosure:
{
FunctionInstance *x = checked_cast<FunctionInstance *>(bCon->mObjectList[BytecodeContainer::getShort(pc)]);
pc += sizeof(short);
x->fWrap->env = new Environment(meta->env);
/*
// For each active plural frame in the function definition environment, we need
// to find it's current singular counterpart and use that as the dohickey
FrameListIterator closure_fi = x->fWrap.env->getBegin();
FrameListIterator current_fi = meta->env->getBegin();
while (true) {
Frame *closure_fr = closure_fi->first;
Frame *current_fr = current_fi->first;
ASSERT(closure_fr->kind == current_fr->kind);
if ((closure_fr->kind == ClassKind) || (closure_fr->kind == PackageKind) || (closure_fr->kind == SystemKind))
break;
}
*/
}
break;
case eNull:
{
push(JS2VAL_NULL);

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

@ -278,7 +278,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *
const String *replaceStr = meta->toString(replaceValue);
DEFINE_ROOTKEEPER(rk2, replaceStr);
if (meta->objectType(searchValue) != meta->regexpClass) {
if (meta->objectType(searchValue) == meta->regexpClass) {
RegExpInstance *reInst = checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(searchValue));
JS2RegExp *re = reInst->mRegExp;
REMatchResult *match;

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

@ -64,7 +64,6 @@ namespace JavaScript {
class Member;
class InstanceMember;
class Multiname;
class FunctionWrapper;
class BlockFrame;
class FunctionInstance;
typedef uint32 LabelID;
@ -315,7 +314,7 @@ namespace JavaScript {
void print(PrettyPrinter &f, const AttributeStmtNode *attributes, bool noSemi) const;
#ifdef EPIMETHEUS
MetaData::FunctionWrapper *fWrap; // Runtime data, bytecode, parameters etc.
MetaData::FunctionInstance *fn; // Runtime data, bytecode, parameters etc.
#endif
};
@ -398,9 +397,6 @@ namespace JavaScript {
explicit FunctionExprNode(size_t pos): ExprNode(pos, functionLiteral) {}
void print(PrettyPrinter &f) const;
#ifdef EPIMETHEUS
MetaData::FunctionInstance *obj; // used by backend to store the function object
#endif
};
struct ExprPairList: ArenaObject {
@ -595,6 +591,7 @@ namespace JavaScript {
#ifdef EPIMETHEUS
MetaData::LabelID breakLabelID;
MetaData::LabelID continueLabelID;
MetaData::BlockFrame *compileFrame;
#endif
};