зеркало из https://github.com/mozilla/gecko-dev.git
Leak plugging.
This commit is contained in:
Родитель
967e208b55
Коммит
5ad3348af0
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче