diff --git a/mozilla/js2/src/bytecodecontainer.h b/mozilla/js2/src/bytecodecontainer.h index 522fb45314b..d62d30f95c4 100644 --- a/mozilla/js2/src/bytecodecontainer.h +++ b/mozilla/js2/src/bytecodecontainer.h @@ -136,6 +136,7 @@ public: // Maintain list of associated pointers, so as to keep the objects safe across gc's void addMultiname(Multiname *mn) { mMultinameList.push_back(mn); addShort((uint16)(mMultinameList.size() - 1)); } + void saveMultiname(Multiname *mn) { mMultinameList.push_back(mn); } void addFrame(Frame *f) { mFrameList.push_back(f); addShort((uint16)(mFrameList.size() - 1)); } void saveFrame(Frame *f) { mFrameList.push_back(f); } void addRegExp(RegExpInstance *x, size_t pos) { emitOp(eRegExp, pos); mRegExpList.push_back(x); addShort((uint16)(mRegExpList.size() - 1)); } diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 10403bcfd26..ed63f7251b7 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -106,7 +106,7 @@ namespace MetaData { default: NOT_REACHED("Bad opcode, no biscuit"); } -// JS2Object::gc(meta); // XXX temporarily, for testing + JS2Object::gc(meta); // XXX temporarily, for testing } catch (Exception &jsx) { if (mTryStack.size() > 0) { @@ -488,6 +488,7 @@ namespace MetaData { { ePopv, "Popv", 0 }, { ePop, "Pop", 0 }, { eDup, "Dup", 0 }, + { eVoid, "Void", 0 }, { eLexicalPostInc, "LexicalPostInc", NAME_INDEX }, // { eLexicalPostDec, "LexicalPostDec", NAME_INDEX }, // @@ -690,6 +691,9 @@ namespace MetaData { case eBranch: return 0; + case eVoid: // remove top item, push undefined + return 1; + case eDup: // duplicate top item return 1; diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 5a56d932e70..7f056ae7bfe 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -131,6 +131,7 @@ enum JS2Op { ePopv, ePop, eDup, + eVoid, eLexicalPostInc, // eLexicalPostDec, // @@ -260,7 +261,7 @@ public: // The execution stack for expression evaluation, should be empty // between statements. -#define INITIAL_EXEC_STACK (20) +#define INITIAL_EXEC_STACK (40) js2val *execStackLimit; js2val *execStack; diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 7dcc1d7c0f2..fb7e1092138 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -510,7 +510,7 @@ namespace MetaData { } else { Variable *v = new Variable(functionClass, OBJECT_TO_JS2VAL(fInst), true); - defineStaticMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); + vb->mn = defineStaticMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); } } } @@ -530,7 +530,7 @@ namespace MetaData { // XXX Here the spec. has ???, so the following is tentative CallableInstance *fInst = validateStaticFunction(f, compileThis, prototype, unchecked, cxt, env); ConstructorMethod *cm = new ConstructorMethod(OBJECT_TO_JS2VAL(fInst)); - defineStaticMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, cm, p->pos); + vb->mn = defineStaticMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, cm, p->pos); } break; } @@ -557,7 +557,7 @@ namespace MetaData { ValidateTypeExpression(cxt, env, vb->type); vb->member = NULL; - if (cxt->strict && ((regionalFrame->kind == GlobalObjectKind) + if (!cxt->strict && ((regionalFrame->kind == GlobalObjectKind) || (regionalFrame->kind == ParameterKind)) && !immutable && (vs->attributes == NULL) @@ -583,6 +583,7 @@ namespace MetaData { vb->member = v; v->vb = vb; vb->mn = defineStaticMember(env, name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); + bCon->saveMultiname(vb->mn); } break; case Attribute::Virtual: @@ -682,7 +683,7 @@ namespace MetaData { reportError(Exception::definitionError, "Illegal modifier for class definition", p->pos); break; } - JS2Class *c = new JS2Class(superClass, proto, new Namespace(engine->private_StringAtom), (a->dynamic || superClass->dynamic), true, final, &classStmt->name); + JS2Class *c = new JS2Class(superClass, proto, new Namespace(engine->private_StringAtom), (a->dynamic || superClass->dynamic), true, final, engine->allocStringPtr(&classStmt->name)); classStmt->c = c; Variable *v = new Variable(classClass, OBJECT_TO_JS2VAL(c), true); defineStaticMember(env, &classStmt->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); @@ -1211,8 +1212,7 @@ namespace MetaData { throw x; Reference *r = SetupExprNode(env, phase, vb->initializer, &exprType); if (r) r->emitReadBytecode(bCon, p->pos); - LexicalReference *lVal = new LexicalReference(vb->name, cxt.strict); - lVal->variableMultiname->addNamespace(publicNamespace); + LexicalReference *lVal = new LexicalReference(vb->mn, cxt.strict); lVal->emitWriteBytecode(bCon, p->pos); bCon->emitOp(ePop, p->pos); } @@ -1230,15 +1230,13 @@ namespace MetaData { if (r) r->emitReadBytecode(bCon, p->pos); bCon->emitOp(eCoerce, p->pos); bCon->addType(v->type); - LexicalReference *lVal = new LexicalReference(vb->name, cxt.strict); - lVal->variableMultiname->addNamespace(publicNamespace); + LexicalReference *lVal = new LexicalReference(vb->mn, cxt.strict); lVal->emitWriteBytecode(bCon, p->pos); bCon->emitOp(ePop, p->pos); } else { v->type->emitDefaultValue(bCon, p->pos); - LexicalReference *lVal = new LexicalReference(vb->name, cxt.strict); - lVal->variableMultiname->addNamespace(publicNamespace); + LexicalReference *lVal = new LexicalReference(vb->mn, cxt.strict); lVal->emitWriteBytecode(bCon, p->pos); bCon->emitOp(ePop, p->pos); } @@ -1697,6 +1695,7 @@ namespace MetaData { case ExprNode::parentheses: case ExprNode::Typeof: case ExprNode::logicalNot: + case ExprNode::Void: { UnaryExprNode *u = checked_cast(p); ValidateExpression(cxt, env, u->op); @@ -1929,6 +1928,14 @@ doBinary: bCon->emitOp(op, p->pos); } break; + case ExprNode::Void: + { + UnaryExprNode *u = checked_cast(p); + Reference *rVal = SetupExprNode(env, phase, u->op, exprType); + bCon->emitOp(eVoid, p->pos); + } + break; + case ExprNode::logicalNot: op = eLogicalNot; goto doUnary; @@ -2491,6 +2498,10 @@ doUnary: void Environment::instantiateFrame(Frame *pluralFrame, Frame *singularFrame) { StaticBindingIterator sbi, sbend; + + singularFrame->staticReadBindings.clear(); + singularFrame->staticWriteBindings.clear(); + for (sbi = pluralFrame->staticReadBindings.begin(), sbend = pluralFrame->staticReadBindings.end(); (sbi != sbend); sbi++) { sbi->second->content->cloneContent = NULL; } @@ -2735,7 +2746,7 @@ doUnary: // Examine class 'c' and find all instance members that would be overridden // by 'id' in any of the given namespaces. - OverrideStatus *JS2Metadata::searchForOverrides(JS2Class *c, const StringAtom *id, NamespaceList *namespaces, Access access, size_t pos) + OverrideStatus *JS2Metadata::searchForOverrides(JS2Class *c, const String *id, NamespaceList *namespaces, Access access, size_t pos) { OverrideStatus *os = new OverrideStatus(NULL, id); for (NamespaceListIterator ns = namespaces->begin(), end = namespaces->end(); (ns != end); ns++) { @@ -2755,7 +2766,7 @@ doUnary: // Find the possible override conflicts that arise from the given id and namespaces // Fall back on the currently open namespace list if no others are specified. - OverrideStatus *JS2Metadata::resolveOverrides(JS2Class *c, Context *cxt, const StringAtom *id, NamespaceList *namespaces, Access access, bool expectMethod, size_t pos) + OverrideStatus *JS2Metadata::resolveOverrides(JS2Class *c, Context *cxt, const String *id, NamespaceList *namespaces, Access access, bool expectMethod, size_t pos) { OverrideStatus *os = NULL; if ((namespaces == NULL) || namespaces->empty()) { @@ -2820,7 +2831,7 @@ doUnary: // Define an instance member in the class. Verify that, if any overriding is happening, it's legal. The result pair indicates // the members being overridden. - OverrideStatusPair *JS2Metadata::defineInstanceMember(JS2Class *c, Context *cxt, const StringAtom *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, InstanceMember *m, size_t pos) + OverrideStatusPair *JS2Metadata::defineInstanceMember(JS2Class *c, Context *cxt, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, InstanceMember *m, size_t pos) { OverrideStatus *readStatus; OverrideStatus *writeStatus; @@ -2877,7 +2888,7 @@ doUnary: // instance or open instance. According to rules inherited from ECMAScript Edition 3, if there are multiple // definitions of a hoisted variable, then the initial value of that variable is undefined if none of the definitions // is a function definition; otherwise, the initial value is the last function definition. - HoistedVar *JS2Metadata::defineHoistedVar(Environment *env, const StringAtom *id, StmtNode *p) + HoistedVar *JS2Metadata::defineHoistedVar(Environment *env, const String *id, StmtNode *p) { HoistedVar *result = NULL; QualifiedName qName(publicNamespace, id); @@ -3016,17 +3027,17 @@ doUnary: MAKEBUILTINCLASS(objectClass, NULL, false, true, false, engine->object_StringAtom, JS2VAL_VOID); MAKEBUILTINCLASS(undefinedClass, objectClass, false, false, true, engine->undefined_StringAtom, JS2VAL_VOID); MAKEBUILTINCLASS(nullClass, objectClass, false, true, true, engine->null_StringAtom, JS2VAL_NULL); - MAKEBUILTINCLASS(booleanClass, objectClass, false, false, true, &world.identifiers["Boolean"], JS2VAL_FALSE); - MAKEBUILTINCLASS(generalNumberClass, objectClass, false, false, false, &world.identifiers["general number"], engine->nanValue); - MAKEBUILTINCLASS(numberClass, generalNumberClass, false, false, true, &world.identifiers["Number"], engine->nanValue); - MAKEBUILTINCLASS(characterClass, objectClass, false, false, true, &world.identifiers["Character"], JS2VAL_ZERO); - MAKEBUILTINCLASS(stringClass, objectClass, false, false, true, &world.identifiers["String"], JS2VAL_NULL); - MAKEBUILTINCLASS(namespaceClass, objectClass, false, true, true, &world.identifiers["namespace"], JS2VAL_NULL); - MAKEBUILTINCLASS(attributeClass, objectClass, false, true, true, &world.identifiers["attribute"], JS2VAL_NULL); - MAKEBUILTINCLASS(classClass, objectClass, false, true, true, &world.identifiers["Class"], JS2VAL_NULL); + MAKEBUILTINCLASS(booleanClass, objectClass, false, false, true, engine->allocStringPtr(&world.identifiers["Boolean"]), JS2VAL_FALSE); + MAKEBUILTINCLASS(generalNumberClass, objectClass, false, false, false, engine->allocStringPtr(&world.identifiers["general number"]), engine->nanValue); + MAKEBUILTINCLASS(numberClass, generalNumberClass, false, false, true, engine->allocStringPtr(&world.identifiers["Number"]), engine->nanValue); + MAKEBUILTINCLASS(characterClass, objectClass, false, false, true, engine->allocStringPtr(&world.identifiers["Character"]), JS2VAL_ZERO); + MAKEBUILTINCLASS(stringClass, objectClass, false, false, true, engine->allocStringPtr(&world.identifiers["String"]), JS2VAL_NULL); + MAKEBUILTINCLASS(namespaceClass, objectClass, false, true, true, engine->allocStringPtr(&world.identifiers["namespace"]), JS2VAL_NULL); + MAKEBUILTINCLASS(attributeClass, objectClass, false, true, true, engine->allocStringPtr(&world.identifiers["attribute"]), JS2VAL_NULL); + MAKEBUILTINCLASS(classClass, objectClass, false, true, true, engine->allocStringPtr(&world.identifiers["Class"]), JS2VAL_NULL); MAKEBUILTINCLASS(functionClass, objectClass, false, true, true, engine->Function_StringAtom, JS2VAL_NULL); - MAKEBUILTINCLASS(prototypeClass, objectClass, true, true, true, &world.identifiers["prototype"], JS2VAL_NULL); - MAKEBUILTINCLASS(packageClass, objectClass, true, true, true, &world.identifiers["Package"], JS2VAL_NULL); + MAKEBUILTINCLASS(prototypeClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["prototype"]), JS2VAL_NULL); + MAKEBUILTINCLASS(packageClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Package"]), JS2VAL_NULL); @@ -3056,14 +3067,24 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... writeDynamicProperty(glob, new Multiname(engine->undefined_StringAtom, publicNamespace), true, JS2VAL_UNDEFINED, RunPhase); writeDynamicProperty(glob, new Multiname(&world.identifiers["NaN"], publicNamespace), true, engine->nanValue, RunPhase); writeDynamicProperty(glob, new Multiname(&world.identifiers["Infinity"], publicNamespace), true, engine->posInfValue, RunPhase); + // XXX add 'version' + writeDynamicProperty(glob, new Multiname(&world.identifiers["version"], publicNamespace), true, INT_TO_JS2VAL(0), RunPhase); // Function properties of the global object addGlobalObjectFunction("isNaN", GlobalObject_isNaN); addGlobalObjectFunction("eval", GlobalObject_eval); /*** ECMA 3 Object Class ***/ + v = new Variable(classClass, OBJECT_TO_JS2VAL(objectClass), true); + defineStaticMember(env, &world.identifiers["Object"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); // Function properties of the Object prototype object objectClass->prototype = new PrototypeInstance(NULL, objectClass); + // Adding "prototype" as a static member of the class - not a dynamic property + env->addFrame(objectClass); + v = new Variable(objectClass, OBJECT_TO_JS2VAL(objectClass->prototype), true); + defineStaticMember(env, engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + env->removeTopFrame(); + // XXX Or make this a static class member? CallableInstance *fInst = new CallableInstance(functionClass); fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_toString); @@ -3845,6 +3866,7 @@ deleteClassProperty: access = WriteAccess; b = container->staticWriteBindings.lower_bound(*multiname->name); end = container->staticWriteBindings.upper_bound(*multiname->name); + found = NULL; continue; } else @@ -4326,6 +4348,8 @@ deleteClassProperty: GCMARKOBJECT(super) GCMARKOBJECT(prototype) GCMARKOBJECT(privateNamespace) + JS2Object::mark(name); +// GCMARKVALUE(defaultValue); InstanceBindingIterator ib, iend; for (ib = instanceReadBindings.begin(), iend = instanceReadBindings.end(); (ib != iend); ib++) { ib->second->content->mark(); diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index d3feb1972a0..4a9f6291030 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -252,7 +252,7 @@ public: class NamedParameter { public: - StringAtom &name; // This parameter's name + const String *name; // This parameter's name JS2Class *type; // This parameter's type }; @@ -320,6 +320,7 @@ public: js2val value; // This variable's current value bool hasFunctionInitializer; // true if this variable was created by a function statement + virtual StaticMember *clone() { return new HoistedVar(); } virtual void mark() { GCMARKVALUE(value); } }; @@ -408,7 +409,7 @@ public: #define POTENTIAL_CONFLICT ((InstanceMember *)(-1)) class OverrideStatus { public: - OverrideStatus(InstanceMember *overriddenMember, const StringAtom *name) + OverrideStatus(InstanceMember *overriddenMember, const String *name) : overriddenMember(overriddenMember), multiname(name) { } InstanceMember *overriddenMember; // NULL for none @@ -726,8 +727,9 @@ class LexicalReference : public Reference { // of a given set of qualified names. LEXICALREFERENCE tuples arise from evaluating identifiers a and qualified identifiers // q::a. public: - LexicalReference(const StringAtom *name, bool strict) : variableMultiname(new Multiname(name)), env(NULL), strict(strict) { } - LexicalReference(const StringAtom *name, Namespace *nameSpace, bool strict) : variableMultiname(new Multiname(name, nameSpace)), env(NULL), strict(strict) { } + LexicalReference(Multiname *mname, bool strict) : variableMultiname(mname), env(NULL), strict(strict) { } + LexicalReference(const String *name, bool strict) : variableMultiname(new Multiname(name)), env(NULL), strict(strict) { } + LexicalReference(const String *name, Namespace *nameSpace, bool strict) : variableMultiname(new Multiname(name, nameSpace)), env(NULL), strict(strict) { } Multiname *variableMultiname; // A nonempty set of qualified names to which this reference can refer @@ -754,7 +756,7 @@ class DotReference : public Reference { // object with one of a given set of qualified names. DOTREFERENCE tuples arise from evaluating subexpressions such as a.b or // a.q::b. public: - DotReference(const StringAtom *name) : propertyMultiname(new Multiname(name)) { } + DotReference(const String *name) : propertyMultiname(new Multiname(name)) { } DotReference(Multiname *mn) : propertyMultiname(mn) { } // In this implementation, the base is established by the execution of the preceding expression and @@ -804,7 +806,7 @@ public: class NamedArgument { public: - StringAtom &name; // This argument's name + const String *name; // This argument's name js2val value; // This argument's value }; @@ -1034,11 +1036,11 @@ public: StaticMember *findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase); InstanceBinding *resolveInstanceMemberName(JS2Class *js2class, Multiname *multiname, Access access, Phase phase); - HoistedVar *defineHoistedVar(Environment *env, const StringAtom *id, StmtNode *p); + HoistedVar *defineHoistedVar(Environment *env, const String *id, StmtNode *p); Multiname *defineStaticMember(Environment *env, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, StaticMember *m, size_t pos); - OverrideStatusPair *defineInstanceMember(JS2Class *c, Context *cxt, const StringAtom *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, InstanceMember *m, size_t pos); - OverrideStatus *resolveOverrides(JS2Class *c, Context *cxt, const StringAtom *id, NamespaceList *namespaces, Access access, bool expectMethod, size_t pos); - OverrideStatus *searchForOverrides(JS2Class *c, const StringAtom *id, NamespaceList *namespaces, Access access, size_t pos); + OverrideStatusPair *defineInstanceMember(JS2Class *c, Context *cxt, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, InstanceMember *m, size_t pos); + OverrideStatus *resolveOverrides(JS2Class *c, Context *cxt, const String *id, NamespaceList *namespaces, Access access, bool expectMethod, size_t pos); + OverrideStatus *searchForOverrides(JS2Class *c, const String *id, NamespaceList *namespaces, Access access, size_t pos); InstanceMember *findInstanceMember(JS2Class *c, QualifiedName *qname, Access access); Slot *findSlot(js2val thisObjVal, InstanceVariable *id); bool findStaticMember(JS2Class *c, Multiname *multiname, Access access, Phase phase, MemberDescriptor *result); diff --git a/mozilla/js2/src/js2op_invocation.cpp b/mozilla/js2/src/js2op_invocation.cpp index aad18286277..f2d1f0392df 100644 --- a/mozilla/js2/src/js2op_invocation.cpp +++ b/mozilla/js2/src/js2op_invocation.cpp @@ -76,7 +76,7 @@ PrototypeInstance *pInst = new PrototypeInstance(protoObj, meta->objectClass); baseVal = OBJECT_TO_JS2VAL(pInst); runtimeFrame->thisObject = baseVal; - // assignArguments(runtimeFrame, fWrap->compileFrame->signature); + runtimeFrame->assignArguments(base(argCount), argCount); if (!fWrap->code) jsr(phase, fWrap->bCon, base(argCount + 1), baseVal); // seems out of order, but we need to catch the current top frame meta->env->addFrame(runtimeFrame); @@ -165,7 +165,7 @@ a = c->call(meta, JS2VAL_NULL, base(argCount), argCount); else a = JS2VAL_UNDEFINED; - pop(argCount + 1); + pop(argCount + 2); push(a); } else @@ -179,6 +179,13 @@ } break; + case eVoid: + { + pop(); + push(JS2VAL_VOID); + } + break; + case eReturn: { retval = top();