diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 6bbe6911ea8..0a269ce987f 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -870,8 +870,9 @@ namespace MetaData { activationStackTop->phase = phase; activationStackTop->execStackBase = stackBase; activationStackTop->retval = returnVal; - activationStackTop->env = meta->env; // save current env. - activationStackTop->topFrame = env->getTopFrame(); // remember how big the new env. is supposed to be + activationStackTop->env = meta->env; // save current environment, to be restored on rts + activationStackTop->newEnv = env; // and save the new environment, if an exception occurs, we can't depend on meta->env + activationStackTop->topFrame = env->getTopFrame(); // remember how big the new env. is supposed to be so that local frames don't accumulate activationStackTop++; if (new_bCon) { bCon = new_bCon; @@ -900,8 +901,8 @@ namespace MetaData { pc = activationStackTop->pc; phase = activationStackTop->phase; // reset the env. top - while (meta->env->getTopFrame() != activationStackTop->topFrame) - meta->env->removeTopFrame(); + while (activationStackTop->newEnv->getTopFrame() != activationStackTop->topFrame) + activationStackTop->newEnv->removeTopFrame(); // reset to previous env. meta->env = activationStackTop->env; sp = execStack + activationStackTop->execStackBase; @@ -921,6 +922,7 @@ namespace MetaData { bCon->mark(); for (ActivationFrame *f = activationStack; (f < activationStackTop); f++) { GCMARKOBJECT(f->env); + GCMARKOBJECT(f->newEnv); if (f->bCon) f->bCon->mark(); } diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 9dd6decf7e3..23fb24a02c7 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -275,6 +275,7 @@ public: js2val retval; uint32 execStackBase; Environment *env; + Environment *newEnv; Frame *topFrame; }; void jsr(Phase execPhase, BytecodeContainer *bCon, uint32 stackBase, js2val returnVal, Environment *env); diff --git a/mozilla/js2/src/js2function.cpp b/mozilla/js2/src/js2function.cpp index c590e970045..89e2bb3fc9c 100644 --- a/mozilla/js2/src/js2function.cpp +++ b/mozilla/js2/src/js2function.cpp @@ -87,6 +87,7 @@ namespace MetaData { else { // construct an empty function wrapper js2val thatValue = OBJECT_TO_JS2VAL(new FunctionInstance(meta, meta->functionClass->prototype, meta->functionClass)); FunctionInstance *fnInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); + DEFINE_ROOTKEEPER(rk, fnInst); fnInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), meta->env); fnInst->fWrap->bCon->emitOp(eReturnVoid, meta->engine->errorPos()); meta->createDynamicProperty(fnInst, meta->engine->length_StringAtom, INT_TO_JS2VAL(0), ReadAccess, true, false); @@ -123,7 +124,12 @@ namespace MetaData { { NULL } }; - meta->functionClass->prototype = OBJECT_TO_JS2VAL(new FunctionInstance(meta, meta->objectClass->prototype, meta->functionClass)); + FunctionInstance *fnInst = new FunctionInstance(meta, meta->objectClass->prototype, meta->functionClass); + DEFINE_ROOTKEEPER(rk, fnInst); + fnInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), meta->env); + fnInst->fWrap->bCon->emitOp(eReturnVoid, 0); + + meta->functionClass->prototype = OBJECT_TO_JS2VAL(fnInst); meta->initBuiltinClass(meta->functionClass, &prototypeFunctions[0], NULL, Function_Constructor, Function_Constructor); } diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 038a18d09be..82023385ae0 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -3255,6 +3255,11 @@ static const uint8 urlCharType[256] = } } + static js2val Object_valueOf(JS2Metadata *meta, const js2val thisValue, js2val /* argv */ [], uint32 /* argc */) + { + return thisValue; + } + #define MAKEBUILTINCLASS(c, super, dynamic, allowNull, final, name, defaultVal) c = new JS2Class(super, NULL, new Namespace(engine->private_StringAtom), dynamic, allowNull, final, name); c->complete = true; c->defaultValue = defaultVal; JS2Metadata::JS2Metadata(World &world) : JS2Object(MetaDataKind), @@ -3349,6 +3354,12 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_toString, env); createDynamicProperty(JS2VAL_TO_OBJECT(objectClass->prototype), engine->toString_StringAtom, OBJECT_TO_JS2VAL(fInst), ReadAccess, true, false); createDynamicProperty(fInst, engine->length_StringAtom, INT_TO_JS2VAL(0), ReadAccess, true, false); + // and 'valueOf' + fInst = new FunctionInstance(this, functionClass->prototype, functionClass); + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_valueOf, env); + createDynamicProperty(JS2VAL_TO_OBJECT(objectClass->prototype), engine->valueOf_StringAtom, OBJECT_TO_JS2VAL(fInst), ReadAccess, true, false); + createDynamicProperty(fInst, engine->length_StringAtom, INT_TO_JS2VAL(0), ReadAccess, true, false); + /*** ECMA 3 Date Class ***/ MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Date"]), JS2VAL_NULL); @@ -4067,11 +4078,23 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... LocalBindingEntry *lbe = *bi; for (LocalBindingEntry::NS_Iterator i = lbe->begin(), end = lbe->end(); (i != end); i++) { LocalBindingEntry::NamespaceBinding ns = *i; + if (ns.first->name) JS2Object::mark(ns.first->name); ns.second->content->mark(); } } } + void SimpleInstance::finalize() + { + for (LocalBindingIterator bi = localBindings.begin(), bend = localBindings.end(); (bi != bend); bi++) { + LocalBindingEntry *lbe = *bi; + for (LocalBindingEntry::NS_Iterator i = lbe->begin(), end = lbe->end(); (i != end); i++) { + LocalBindingEntry::NamespaceBinding ns = *i; + delete ns.second->content; + } + } + } + /************************************************************************************ * * AlienInstance @@ -4501,7 +4524,6 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... // Allocate from this or the next Pond (make a new one if necessary) void *Pond::allocFromPond(size_t sz, bool isJS2Object) { - // See if there's room left... if (sz > pondSize) { // If not, try the free list... @@ -4531,9 +4553,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... // ok, then try the next Pond if (nextPond == NULL) { // there isn't one; run the gc - uint32 released = JS2Object::gc(); - if (released > sz) - return JS2Object::alloc(sz - sizeof(PondScum), isJS2Object); + uint32 released = JS2Object::gc(); + if (released > sz) + return JS2Object::alloc(sz - sizeof(PondScum), isJS2Object); nextPond = new Pond(sz, nextPond); } return nextPond->allocFromPond(sz, isJS2Object); @@ -4586,8 +4608,13 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... uint8 *t = pondBottom; while (t != pondTop) { PondScum *p = (PondScum *)t; - if (!p->isMarked() && (p->owner == this)) // (owner != this) ==> already on free list + if (!p->isMarked() && (p->owner == this)) { // (owner != this) ==> already on free list + if (p->isJS2Object()) { + JS2Object *obj = (JS2Object *)(p + 1); + obj->finalize(); + } released += returnToPond(p); + } t += p->getSize(); } if (nextPond) diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 3eb086728f1..ad2eb3a0e37 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -229,6 +229,8 @@ public: void operator delete(void *p) { unalloc(p); } virtual void markChildren() { } // XXX !!!! XXXX these are supposed to not have vtables !!!! + virtual void finalize() { } + bool isMarked() { return ((PondScum *)this)[-1].isMarked(); } void markObject() { ((PondScum *)this)[-1].mark(); } @@ -274,6 +276,7 @@ public: Attribute(AttributeKind akind) : JS2Object(AttributeObjectKind), attrKind(akind) { } + virtual void markChildren() { } static Attribute *combineAttributes(Attribute *a, Attribute *b); static CompoundAttribute *toCompoundAttribute(Attribute *a); @@ -289,6 +292,7 @@ public: Namespace(const String *name) : Attribute(NamespaceAttr), name(name) { } virtual CompoundAttribute *toCompoundAttribute(); + virtual void markChildren() { if (name) JS2Object::mark(name); } const String *name; // The namespace's name (used by toString) }; @@ -464,6 +468,8 @@ public: // The qualified name is to be inferred from the map where this binding is kept // QualifiedName qname; // The qualified name bound by this binding + virtual ~LocalBinding() { delete content; } + AccessSet accesses; LocalMember *content; // The member to which this qualified name was bound bool xplicit; // true if this binding should not be imported into the global scope by an import statement @@ -525,6 +531,7 @@ public: class InstanceBinding { public: InstanceBinding(AccessSet accesses, InstanceMember *content) : accesses(accesses), content(content) { } + virtual ~InstanceBinding() { delete content; } // The qualified name is to be inferred from the map where this binding is kept // QualifiedName qname; // The qualified name bound by this binding @@ -762,6 +769,7 @@ public: FunctionWrapper *fWrap; virtual void markChildren(); + virtual void finalize(); virtual ~SimpleInstance() { } };