From 5ad3348af0e2f3ad754beb074e3cc3a73d199dc1 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Fri, 11 Apr 2003 18:53:59 +0000 Subject: [PATCH] Leak plugging. --- js2/src/epimetheus.cpp | 8 ++++-- js2/src/js2engine.cpp | 27 +++++++++-------- js2/src/js2metadata.cpp | 64 +++++++++++++++++++++++++++-------------- js2/src/js2metadata.h | 32 ++++++++++++++------- js2/src/token.cpp | 6 ++-- js2/src/world.h | 1 + 6 files changed, 89 insertions(+), 49 deletions(-) diff --git a/js2/src/epimetheus.cpp b/js2/src/epimetheus.cpp index b356f2295bad..86efce0ae808 100644 --- a/js2/src/epimetheus.cpp +++ b/js2/src/epimetheus.cpp @@ -72,7 +72,7 @@ static void initConsole(StringPtr consoleName, #endif -JavaScript::World world; +JavaScript::World *world = new World(); JavaScript::Arena a; namespace JavaScript { @@ -114,7 +114,7 @@ static int readEvalPrint(FILE *in) appendChars(buffer, line.data(), line.size()); try { Pragma::Flags flags = Pragma::es4; - Parser p(world, a, flags, buffer, ConsoleName); + Parser p(*world, a, flags, buffer, ConsoleName); if (showTokens) { Lexer &l = p.lexer; while (true) { @@ -392,7 +392,7 @@ int main(int argc, char **argv) DEFINE_ROOTKEEPER(rk, metadata); - metadata = new MetaData::JS2Metadata(world); + metadata = new MetaData::JS2Metadata(*world); metadata->addGlobalObjectFunction("print", print, 1); metadata->addGlobalObjectFunction("load", load, 1); @@ -413,6 +413,8 @@ int main(int argc, char **argv) if (doInteractive) result = readEvalPrint(stdin); delete metadata; + world->identifiers.clear(); + delete world; return result; } catch (Exception &e) { diff --git a/js2/src/js2engine.cpp b/js2/src/js2engine.cpp index 5cff1e60ce9d..9d9d6b90bdbe 100644 --- a/js2/src/js2engine.cpp +++ b/js2/src/js2engine.cpp @@ -196,13 +196,13 @@ namespace MetaData { if (*float64Table[hash] == x) return float64Table[hash]; else { - float64 *p = (float64 *)JS2Object::alloc(sizeof(float64), false); + float64 *p = (float64 *)JS2Object::alloc(sizeof(float64), PondScum::GenericFlag); *p = x; return p; } } else { - float64 *p = (float64 *)JS2Object::alloc(sizeof(float64), false); + float64 *p = (float64 *)JS2Object::alloc(sizeof(float64), PondScum::GenericFlag); float64Table[hash] = p; *p = x; return p; @@ -211,28 +211,31 @@ namespace MetaData { String *JS2Engine::allocStringPtr(const char *s) { - String *p = (String *)(JS2Object::alloc(sizeof(String), false)); + String *p = (String *)(JS2Object::alloc(sizeof(String), PondScum::StringFlag)); size_t len = strlen(s); String *result = new (p) String(len, uni::null); - std::transform(s, s+len, result->begin(), widen); + for (int i = 0; i < len; i++) { + (*result)[i] = widen(s[i]); + } +// std::transform(s, s+len, result->begin(), widen); return result; } String *JS2Engine::allocStringPtr(const String *s) { - String *p = (String *)(JS2Object::alloc(sizeof(String), false)); + String *p = (String *)(JS2Object::alloc(sizeof(String), PondScum::StringFlag)); return new (p) String(*s); } String *JS2Engine::allocStringPtr(const String *s, uint32 index, uint32 length) { - String *p = (String *)(JS2Object::alloc(sizeof(String), false)); + String *p = (String *)(JS2Object::alloc(sizeof(String), PondScum::StringFlag)); return new (p) String(*s, index, length); } String *JS2Engine::concatStrings(const String *s1, const String *s2) { - String *p = (String *)(JS2Object::alloc(sizeof(String), false)); + String *p = (String *)(JS2Object::alloc(sizeof(String), PondScum::StringFlag)); String *result = new (p) String(*s1); result->append(*s2); return result; @@ -257,7 +260,7 @@ namespace MetaData { // Don't store as an int, even if possible, we need to retain 'longness' js2val JS2Engine::allocULong(uint64 x) { - uint64 *p = (uint64 *)(JS2Object::alloc(sizeof(uint64), false)); + uint64 *p = (uint64 *)(JS2Object::alloc(sizeof(uint64), PondScum::GenericFlag)); *p = x; return ULONG_TO_JS2VAL(p); @@ -266,7 +269,7 @@ namespace MetaData { // Don't store as an int, even if possible, we need to retain 'longness' js2val JS2Engine::allocLong(int64 x) { - int64 *p = (int64 *)(JS2Object::alloc(sizeof(int64), false)); + int64 *p = (int64 *)(JS2Object::alloc(sizeof(int64), PondScum::GenericFlag)); *p = x; return LONG_TO_JS2VAL(p); } @@ -274,7 +277,7 @@ namespace MetaData { // Don't store as an int, even if possible, we need to retain 'floatness' js2val JS2Engine::allocFloat(float32 x) { - float32 *p = (float32 *)(JS2Object::alloc(sizeof(float32), false)); + float32 *p = (float32 *)(JS2Object::alloc(sizeof(float32), PondScum::GenericFlag)); *p = x; return FLOAT_TO_JS2VAL(p); } @@ -393,7 +396,7 @@ namespace MetaData { } - #define INIT_STRINGATOM(n) n##_StringAtom(allocStringPtr(&world.identifiers[#n])) + #define INIT_STRINGATOM(n) n##_StringAtom(allocStringPtr(#n)) JS2Engine::JS2Engine(World &world) : meta(NULL), @@ -428,7 +431,7 @@ namespace MetaData { for (int i = 0; i < 256; i++) float64Table[i] = NULL; - float64 *p = (float64 *)JS2Object::alloc(sizeof(float64), false); + float64 *p = (float64 *)JS2Object::alloc(sizeof(float64), PondScum::GenericFlag); *p = nan; nanValue = DOUBLE_TO_JS2VAL(p); posInfValue = DOUBLE_TO_JS2VAL(allocNumber(positiveInfinity)); diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index d65f6445a912..cc4e4ad680c3 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -2949,11 +2949,18 @@ doUnary: break; } m->multiname = new Multiname(definedMultiname); - InstanceBinding *ib = new InstanceBinding(access, m); - if (ibeP) { - for (NamespaceListIterator nli = definedMultiname.nsList->begin(), nlend = definedMultiname.nsList->end(); (nli != nlend); nli++) { - (*ibeP)->bindingList.push_back(InstanceBindingEntry::NamespaceBinding(*nli, ib)); - } + InstanceBindingEntry *ibe; + if (ibeP == NULL) { + ibe = new InstanceBindingEntry(*id); + c->instanceBindings.insert(*id, ibe); + } + else + ibe = *ibeP; + for (NamespaceListIterator nli = definedMultiname.nsList->begin(), nlend = definedMultiname.nsList->end(); (nli != nlend); nli++) { + // XXX here and in defineLocal... why a new binding for each namespace? + // (other than it would mess up the destructor sequence :-) + InstanceBinding *ib = new InstanceBinding(access, m); + ibe->bindingList.push_back(InstanceBindingEntry::NamespaceBinding(*nli, ib)); } return mOverridden; } @@ -3907,14 +3914,15 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... pf = protoFunctions; if (pf) { while (pf->name) { +/* SimpleInstance *callInst = new SimpleInstance(this, functionClass->prototype, functionClass); callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, env); Multiname *mn = new Multiname(&world.identifiers[pf->name], publicNamespaceList); InstanceMember *m = new InstanceMethod(mn, callInst, true, false); defineInstanceMember(builtinClass, &cxt, mn->name, *mn->nsList, Attribute::NoOverride, false, m, 0); - +*/ FunctionInstance *fInst = new FunctionInstance(this, functionClass->prototype, functionClass); - fInst->fWrap = callInst->fWrap; + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, env); createDynamicProperty(JS2VAL_TO_OBJECT(builtinClass->prototype), &world.identifiers[pf->name], OBJECT_TO_JS2VAL(fInst), ReadWriteAccess, false, false); createDynamicProperty(fInst, engine->length_StringAtom, INT_TO_JS2VAL(pf->length), ReadAccess, true, false); pf++; @@ -4110,7 +4118,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... } } - void SimpleInstance::finalize() + SimpleInstance::~SimpleInstance() { for (LocalBindingIterator bi = localBindings.begin(), bend = localBindings.end(); (bi != bend); bi++) { LocalBindingEntry *lbe = *bi; @@ -4121,6 +4129,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... delete lbe; } delete [] slots; + if (fWrap) + delete fWrap; } /************************************************************************************ @@ -4208,6 +4218,18 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... } +/************************************************************************************ + * + * InstanceMethod + * + ************************************************************************************/ + + InstanceMethod::~InstanceMethod() + { + delete fInst; + } + + /************************************************************************************ * * MethodClosure @@ -4500,13 +4522,13 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... } // Allocate a chunk of size s - void *JS2Object::alloc(size_t s, bool isJS2Object) + void *JS2Object::alloc(size_t s, PondScum::ScumFlag flag) { s += sizeof(PondScum); // make sure that the thing is a multiple of 16 bytes if (s & 0xF) s += 16 - (s & 0xF); ASSERT(s <= 0x7FFFFFFF); - void *p = pond.allocFromPond(s, isJS2Object); + void *p = pond.allocFromPond(s, flag); ASSERT(((ptrdiff_t)p & 0xF) == 0); return p; } @@ -4568,7 +4590,7 @@ 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) + void *Pond::allocFromPond(size_t sz, PondScum::ScumFlag flag) { // See if there's room left... if (sz > pondSize) { @@ -4584,10 +4606,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... freeHeader = (PondScum *)(p->owner); p->owner = this; p->resetMark(); // might have lingering mark from previous gc - if (isJS2Object) - p->setIsJS2Object(); - else - p->clearIsJS2Object(); + p->clearFlags(); + p->setFlag(flag); #ifdef DEBUG memset((p + 1), 0xB7, p->getSize() - sizeof(PondScum)); #endif @@ -4601,10 +4621,10 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... // there isn't one; run the gc uint32 released = JS2Object::gc(); if (released > sz) - return JS2Object::alloc(sz - sizeof(PondScum), isJS2Object); + return JS2Object::alloc(sz - sizeof(PondScum), flag); nextPond = new Pond(sz, nextPond); } - return nextPond->allocFromPond(sz, isJS2Object); + return nextPond->allocFromPond(sz, flag); } // there was room, so acquire it PondScum *p = (PondScum *)pondTop; @@ -4613,10 +4633,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... #endif p->owner = this; p->setSize(sz); - if (isJS2Object) - p->setIsJS2Object(); - else - p->clearIsJS2Object(); + p->setFlag(flag); pondTop += sz; pondSize -= sz; return (p + 1); @@ -4660,6 +4677,11 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... obj->finalize(); delete obj; } + else + if (p->isString()) { + String *s = (String *)(p + 1); + s->erase(); + } released += returnToPond(p); } t += p->getSize(); diff --git a/js2/src/js2metadata.h b/js2/src/js2metadata.h index adebd95e26e1..f94f97dc2f79 100644 --- a/js2/src/js2metadata.h +++ b/js2/src/js2metadata.h @@ -148,23 +148,31 @@ enum Hint { NoHint, NumberHint, StringHint }; class PondScum { public: + typedef enum { JS2ObjectFlag, StringFlag, GenericFlag } ScumFlag; + void resetMark() { markFlag = 0; } void mark() { markFlag = 1; } bool isMarked() { return (markFlag != 0); } - void setIsJS2Object() { js2Flag = 1; } - void clearIsJS2Object() { js2Flag = 0; } - bool isJS2Object() { return (js2Flag != 0); } + void setFlag(ScumFlag f){ flag = f; } + + void setIsJS2Object() { flag = JS2ObjectFlag; } + bool isJS2Object() { return (flag == JS2ObjectFlag); } + + void setIsString() { flag = StringFlag; } + bool isString() { return (flag == StringFlag); } + + void clearFlags() { flag = GenericFlag; } uint32 getSize() { return size; } - void setSize(uint32 sz) { ASSERT(sz < JS_BIT(30)); size = sz; } + void setSize(uint32 sz) { ASSERT(sz < JS_BIT(29)); size = sz; } Pond *owner; // for a piece of scum in use, this points to it's own Pond // otherwise it's a link to the next item on the free list private: unsigned int markFlag:1; - unsigned int js2Flag:1; - unsigned int size:30; + ScumFlag flag:2; + unsigned int size:29; }; // A pond is a place to get chunks of PondScum from and to return them to @@ -174,7 +182,7 @@ class Pond { public: Pond(size_t sz, Pond *nextPond); - void *allocFromPond(size_t sz, bool isJS2Object); + void *allocFromPond(size_t sz, PondScum::ScumFlag flag); uint32 returnToPond(PondScum *p); void resetMarks(); @@ -223,10 +231,10 @@ public: static void clear(JS2Metadata *meta); static void removeRoot(RootIterator ri); - static void *alloc(size_t s, bool isJS2Object); + static void *alloc(size_t s, PondScum::ScumFlag flag); static void unalloc(void *p); - void *operator new(size_t s) { return alloc(s, true); } + void *operator new(size_t s) { return alloc(s, PondScum::JS2ObjectFlag); } void operator delete(void *p) { } virtual void markChildren() { } // XXX !!!! XXXX these are supposed to not have vtables !!!! @@ -516,6 +524,7 @@ public: // Invokable *code; // This method itself (a callable object); null if this method is abstract SimpleInstance *fInst; + virtual ~InstanceMethod(); virtual void mark(); }; @@ -756,6 +765,8 @@ public: FunctionWrapper(bool unchecked, ParameterFrame *compileFrame, NativeCode *code, Environment *env) : bCon(NULL), code(code), unchecked(unchecked), compileFrame(compileFrame), env(new Environment(env)) { } + virtual ~FunctionWrapper() { if (bCon) delete bCon; } + BytecodeContainer *bCon; NativeCode *code; bool unchecked; // true if the function is untyped, non-method, normal @@ -778,8 +789,7 @@ public: FunctionWrapper *fWrap; virtual void markChildren(); - virtual void finalize(); - virtual ~SimpleInstance() { } + virtual ~SimpleInstance(); }; // Date instances are simple instances created by the Date class, they have an extra field diff --git a/js2/src/token.cpp b/js2/src/token.cpp index 5de7a2ed0302..34e66bfd57fd 100644 --- a/js2/src/token.cpp +++ b/js2/src/token.cpp @@ -327,8 +327,10 @@ const uchar JS::Token::kindFlags[kindsEnd] = { void JS::Token::initKeywords(World &world) { const char *const*keywordName = kindNames + keywordsBegin; - for (Kind kind = keywordsBegin; kind != keywordsEnd; kind = Kind(kind+1)) - world.identifiers[widenCString(*keywordName++)].tokenKind = kind; + for (Kind kind = keywordsBegin; kind != keywordsEnd; kind = Kind(kind+1)) { + String s = widenCString(*keywordName++); + world.identifiers[s].tokenKind = kind; + } } diff --git a/js2/src/world.h b/js2/src/world.h index a4568b566272..095a03faf385 100644 --- a/js2/src/world.h +++ b/js2/src/world.h @@ -70,6 +70,7 @@ namespace JavaScript { public: StringAtom &operator[](const String &s); StringAtom &operator[](const char *s) {return operator[](widenCString(s));} + void clear() { ht.clear(); } }; #ifdef DIKDIK