diff --git a/mozilla/js2/src/bytecodecontainer.h b/mozilla/js2/src/bytecodecontainer.h index 988fedd2023..2c6abb944e2 100644 --- a/mozilla/js2/src/bytecodecontainer.h +++ b/mozilla/js2/src/bytecodecontainer.h @@ -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 }; diff --git a/mozilla/js2/src/epimetheus.cpp b/mozilla/js2/src/epimetheus.cpp index 44d18f2bee1..13c9614f3e4 100644 --- a/mozilla/js2/src/epimetheus.cpp +++ b/mozilla/js2/src/epimetheus.cpp @@ -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; diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index d285d7c5702..2d086930747 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -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 }, // @@ -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; diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 7ba11819c1e..c8351c26181 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -78,7 +78,8 @@ enum JS2Op { eNumber, eInteger, eRegExp, - eFunction, + eFunction, // + eClosure, // eUInt64, eInt64, eString, // @@ -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 } } diff --git a/mozilla/js2/src/js2eval.cpp b/mozilla/js2/src/js2eval.cpp index 1febe185d75..c5b587209a5 100644 --- a/mozilla/js2/src/js2eval.cpp +++ b/mozilla/js2/src/js2eval.cpp @@ -652,14 +652,15 @@ namespace MetaData { return false; } switch (m->memberKind) { + case Member::FrameVariableMember: + return meta->readLocalMember(checked_cast(m), phase, rval, checked_cast(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(m), phase, rval); + return meta->readLocalMember(checked_cast(m), phase, rval, NULL); case Member::InstanceVariableMember: case Member::InstanceMethodMember: case Member::InstanceGetterMember: diff --git a/mozilla/js2/src/js2function.cpp b/mozilla/js2/src/js2function.cpp index e5d40036d3f..38e12a35b9a 100644 --- a/mozilla/js2/src/js2function.cpp +++ b/mozilla/js2/src/js2function.cpp @@ -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)); diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index f2f3d5528dd..03a5593a34a 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -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(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(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(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(p); @@ -1938,7 +1960,7 @@ namespace MetaData { case ExprNode::functionLiteral: { FunctionExprNode *f = checked_cast(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(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(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(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(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(m); - switch (f->kind) { + FrameVariable *fv = checked_cast(m); + switch (fv->kind) { case FrameVariable::Package: - *rval = (*env->getPackageFrame()->slots)[f->frameSlot]; + { + ASSERT(container->kind == PackageKind); + *rval = (*(checked_cast(container))->slots)[fv->frameSlot]; + } break; case FrameVariable::Local: { - FrameListIterator fi = env->getRegionalFrame(); - ASSERT((fi->first)->kind == ParameterFrameKind); - *rval = (*checked_cast((fi - 1)->first)->slots)[f->frameSlot]; + ASSERT(container->kind == BlockFrameKind); + *rval = (*(checked_cast(container))->slots)[fv->frameSlot]; } break; case FrameVariable::Parameter: { - FrameListIterator fi = env->getRegionalFrame(); - ASSERT((fi->first)->kind == ParameterFrameKind); - *rval = (*checked_cast(fi->first)->slots)[f->frameSlot]; + ASSERT(container->kind == ParameterFrameKind); + *rval = (*(checked_cast(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((fi - 1)->first)->slots)[f->frameSlot] = newValue; + NonWithFrame *nwf = checked_cast((fi - 1)->first); + (*nwf->slots)[f->frameSlot] = newValue; } break; case FrameVariable::Parameter: { FrameListIterator fi = env->getRegionalFrame(); ASSERT((fi->first)->kind == ParameterFrameKind); - (*checked_cast(fi->first)->slots)[f->frameSlot] = newValue; + ParameterFrame *pFrame = checked_cast(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); } diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index e98309b063f..7fcfeac49c4 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -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); diff --git a/mozilla/js2/src/js2op_invocation.cpp b/mozilla/js2/src/js2op_invocation.cpp index a3ee948cfb2..eb2f609b74b 100644 --- a/mozilla/js2/src/js2op_invocation.cpp +++ b/mozilla/js2/src/js2op_invocation.cpp @@ -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(); diff --git a/mozilla/js2/src/js2op_literal.cpp b/mozilla/js2/src/js2op_literal.cpp index 456772cdd62..9f4bfff1046 100644 --- a/mozilla/js2/src/js2op_literal.cpp +++ b/mozilla/js2/src/js2op_literal.cpp @@ -91,12 +91,37 @@ case eFunction: { - JS2Object *x = checked_cast(bCon->mObjectList[BytecodeContainer::getShort(pc)]); + FunctionInstance *x = checked_cast(bCon->mObjectList[BytecodeContainer::getShort(pc)]); push(OBJECT_TO_JS2VAL(x)); pc += sizeof(short); } break; + case eClosure: + { + FunctionInstance *x = checked_cast(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); diff --git a/mozilla/js2/src/js2string.cpp b/mozilla/js2/src/js2string.cpp index 841dbb0eaa6..246d15802b5 100644 --- a/mozilla/js2/src/js2string.cpp +++ b/mozilla/js2/src/js2string.cpp @@ -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(JS2VAL_TO_OBJECT(searchValue)); JS2RegExp *re = reInst->mRegExp; REMatchResult *match; diff --git a/mozilla/js2/src/parser.h b/mozilla/js2/src/parser.h index f6b76117b7b..a83efb75874 100644 --- a/mozilla/js2/src/parser.h +++ b/mozilla/js2/src/parser.h @@ -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 };