GC fixes, added debug info to roots.
This commit is contained in:
Родитель
0ce213e52c
Коммит
41420ce62b
|
@ -320,7 +320,7 @@ js2val load(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint
|
|||
if (argc) {
|
||||
// Save off the current top frame and root it.
|
||||
Environment *curEnv = meta->env;
|
||||
RootKeeper rk(&curEnv);
|
||||
DEFINE_ROOTKEEPER(rk, curEnv);
|
||||
// Set the environment to global object and system frame so that the
|
||||
// load happens into the top frame.
|
||||
meta->env = new Environment(curEnv->getSystemFrame(), curEnv->getPackageFrame());
|
||||
|
@ -354,7 +354,7 @@ int main(int argc, char **argv)
|
|||
stdOut << "Welcome to Epimetheus.\n";
|
||||
#endif
|
||||
|
||||
RootKeeper rk(&metadata);
|
||||
DEFINE_ROOTKEEPER(rk, metadata);
|
||||
|
||||
metadata = new MetaData::JS2Metadata(world);
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 newLength)
|
|||
}
|
||||
}
|
||||
Multiname *mn = new Multiname(meta->engine->length_StringAtom, meta->publicNamespace);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
LookupKind lookup(false, JS2VAL_NULL);
|
||||
defaultWriteProperty(meta, OBJECT_TO_JS2VAL(obj), meta->arrayClass, mn, &lookup, true, result);
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *
|
|||
{
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *arrInst = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
RootKeeper rk(&arrInst);
|
||||
DEFINE_ROOTKEEPER(rk, arrInst);
|
||||
if (argc > 0) {
|
||||
if (argc == 1) {
|
||||
if (JS2VAL_IS_NUMBER(argv[0])) {
|
||||
|
@ -290,8 +290,8 @@ static js2val Array_reverse(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
// XXX Need to root the Strings somewhere, this'll do for now..
|
||||
Multiname *mn1 = new Multiname(meta->publicNamespace);
|
||||
Multiname *mn2 = new Multiname(meta->publicNamespace);
|
||||
RootKeeper rk1(&mn1);
|
||||
RootKeeper rk2(&mn2);
|
||||
DEFINE_ROOTKEEPER(rk1, mn1);
|
||||
DEFINE_ROOTKEEPER(rk2, mn2);
|
||||
|
||||
for (uint32 k = 0; k < halfway; k++) {
|
||||
bool deleteResult;
|
||||
|
@ -345,8 +345,8 @@ static js2val Array_shift(JS2Metadata *meta, const js2val thisValue, js2val * /*
|
|||
// XXX Need to root the Strings somewhere, this'll do for now..
|
||||
Multiname *mn1 = new Multiname(meta->publicNamespace);
|
||||
Multiname *mn2 = new Multiname(meta->publicNamespace);
|
||||
RootKeeper rk1(&mn1);
|
||||
RootKeeper rk2(&mn2);
|
||||
DEFINE_ROOTKEEPER(rk1, mn1);
|
||||
DEFINE_ROOTKEEPER(rk2, mn2);
|
||||
|
||||
js2val result;
|
||||
bool deleteResult;
|
||||
|
@ -425,8 +425,8 @@ static js2val Array_slice(JS2Metadata *meta, const js2val thisValue, js2val *arg
|
|||
// XXX Need to root the Strings somewhere, this'll do for now..
|
||||
Multiname *mn1 = new Multiname(meta->publicNamespace);
|
||||
Multiname *mn2 = new Multiname(meta->publicNamespace);
|
||||
RootKeeper rk1(&mn1);
|
||||
RootKeeper rk2(&mn2);
|
||||
DEFINE_ROOTKEEPER(rk1, mn1);
|
||||
DEFINE_ROOTKEEPER(rk2, mn2);
|
||||
uint32 n = 0;
|
||||
while (start < end) {
|
||||
mn1->name = meta->engine->numberToString(start);
|
||||
|
@ -584,7 +584,7 @@ static js2val Array_sort(JS2Metadata *meta, const js2val thisValue, js2val *argv
|
|||
JS2Class *c = meta->objectType(thisObj);
|
||||
// XXX Need to root the Strings somewhere, this'll do for now..
|
||||
Multiname *mn1 = new Multiname(meta->publicNamespace);
|
||||
RootKeeper rk1(&mn1);
|
||||
DEFINE_ROOTKEEPER(rk1, mn1);
|
||||
for (i = 0; i < length; i++) {
|
||||
mn1->name = meta->engine->numberToString(i);
|
||||
c->readPublic(meta, &thatValue, c, mn1->name, RunPhase, &vec[i]);
|
||||
|
@ -643,8 +643,8 @@ static js2val Array_splice(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
// XXX Need to root the Strings somewhere, this'll do for now..
|
||||
Multiname *mn1 = new Multiname(meta->publicNamespace);
|
||||
Multiname *mn2 = new Multiname(meta->publicNamespace);
|
||||
RootKeeper rk1(&mn1);
|
||||
RootKeeper rk2(&mn2);
|
||||
DEFINE_ROOTKEEPER(rk1, mn1);
|
||||
DEFINE_ROOTKEEPER(rk2, mn2);
|
||||
|
||||
for (k = 0; k < deleteCount; k++) {
|
||||
mn1->name = meta->engine->numberToString(start + k);
|
||||
|
@ -682,7 +682,7 @@ static js2val Array_splice(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
bool deleteResult;
|
||||
mn1->name = meta->engine->numberToString(k + deleteCount - 1);
|
||||
mn2->name = meta->engine->numberToString(k + newItemCount - 1);
|
||||
if (meta->hasOwnProperty(thisObj, meta->mn1->name)) {
|
||||
if (meta->hasOwnProperty(thisObj, mn1->name)) {
|
||||
js2val rval;
|
||||
c->readPublic(meta, &thatValue, c, mn1->name, RunPhase, &rval);
|
||||
meta->arrayClass->writePublic(meta, result, meta->arrayClass, mn2->name, true, rval);
|
||||
|
@ -716,8 +716,8 @@ static js2val Array_unshift(JS2Metadata *meta, const js2val thisValue, js2val *a
|
|||
// XXX Need to root the Strings somewhere, this'll do for now..
|
||||
Multiname *mn1 = new Multiname(meta->publicNamespace);
|
||||
Multiname *mn2 = new Multiname(meta->publicNamespace);
|
||||
RootKeeper rk1(&mn1);
|
||||
RootKeeper rk2(&mn2);
|
||||
DEFINE_ROOTKEEPER(rk1, mn1);
|
||||
DEFINE_ROOTKEEPER(rk2, mn2);
|
||||
|
||||
for (k = length; k > 0; k--) {
|
||||
bool deleteResult;
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace MetaData {
|
|||
{
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new BooleanInstance(meta, meta->booleanClass->prototype, meta->booleanClass));
|
||||
BooleanInstance *boolInst = checked_cast<BooleanInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
RootKeeper rk(&boolInst);
|
||||
DEFINE_ROOTKEEPER(rk, boolInst);
|
||||
|
||||
if (argc > 0)
|
||||
boolInst->mValue = meta->toBoolean(argv[0]);
|
||||
|
|
|
@ -871,7 +871,7 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val /* thisValue */, js2val
|
|||
{
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new DateInstance(meta, meta->dateClass->prototype, meta->dateClass));
|
||||
DateInstance *thisInst = checked_cast<DateInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
RootKeeper rk(&thisInst);
|
||||
DEFINE_ROOTKEEPER(rk, thisInst);
|
||||
|
||||
/* Date called as constructor */
|
||||
if (argc == 0) {
|
||||
|
|
|
@ -267,7 +267,7 @@ namespace MetaData {
|
|||
|
||||
CompilationData *oldData = startCompilationUnit(bCon, bCon->mSource, bCon->mSourceLocation);
|
||||
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
|
||||
RootKeeper rk(&runtimeFrame);
|
||||
DEFINE_ROOTKEEPER(rk, runtimeFrame);
|
||||
runtimeFrame->instantiate(env);
|
||||
runtimeFrame->thisObject = thisValue;
|
||||
runtimeFrame->assignArguments(this, fnObj, argv, argc);
|
||||
|
@ -591,7 +591,7 @@ namespace MetaData {
|
|||
// XXX could speed up by pushing knowledge of single namespace?
|
||||
LookupKind lookup(false, JS2VAL_NULL);
|
||||
Multiname *mn = new Multiname(name, meta->publicNamespace);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
return defaultReadProperty(meta, base, limit, mn, &lookup, phase, rval);
|
||||
}
|
||||
|
||||
|
@ -600,7 +600,7 @@ namespace MetaData {
|
|||
// XXX could speed up by pushing knowledge of single namespace & lookup?
|
||||
LookupKind lookup(false, JS2VAL_NULL);
|
||||
Multiname *mn = new Multiname(name, meta->publicNamespace);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
return defaultDeleteProperty(meta, base, limit, mn, &lookup, result);
|
||||
}
|
||||
|
||||
|
@ -609,7 +609,7 @@ namespace MetaData {
|
|||
// XXX could speed up by pushing knowledge of single namespace?
|
||||
LookupKind lookup(false, JS2VAL_NULL);
|
||||
Multiname *mn = new Multiname(name, meta->publicNamespace);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
return defaultWriteProperty(meta, base, limit, mn, &lookup, createIfMissing, newValue);
|
||||
}
|
||||
|
||||
|
@ -666,7 +666,7 @@ namespace MetaData {
|
|||
|| ( (JS2VAL_TO_OBJECT(base)->kind == PackageKind) && !checked_cast<Package *>(JS2VAL_TO_OBJECT(base))->sealed)) ) {
|
||||
QualifiedName qName = multiname->selectPrimaryName(meta);
|
||||
Multiname *mn = new Multiname(qName);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
if ( (meta->findBaseInstanceMember(limit, mn, ReadAccess) == NULL)
|
||||
&& (meta->findCommonMember(&base, mn, ReadAccess, true) == NULL) ) {
|
||||
meta->createDynamicProperty(JS2VAL_TO_OBJECT(base), &qName, newValue, ReadWriteAccess, false, true);
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace MetaData {
|
|||
ASSERT(parser.lexer.peek(true).hasKind(Token::end));
|
||||
ASSERT(fnExpr); // otherwise, an exception would have been thrown out of here
|
||||
fnExpr->obj = NULL;
|
||||
RootKeeper rk(&fnExpr->obj);
|
||||
DEFINE_ROOTKEEPER(rk, fnExpr->obj);
|
||||
JS2Class *exprType;
|
||||
meta->ValidateExpression(&meta->cxt, meta->env, fnExpr);
|
||||
meta->SetupExprNode(meta->env, RunPhase, fnExpr, &exprType);
|
||||
|
|
|
@ -88,10 +88,10 @@ namespace MetaData {
|
|||
FunctionInstance *JS2Metadata::validateStaticFunction(FunctionDefinition *fnDef, js2val compileThis, bool prototype, bool unchecked, Context *cxt, Environment *env)
|
||||
{
|
||||
ParameterFrame *compileFrame = new ParameterFrame(compileThis, prototype);
|
||||
RootKeeper rk1(&compileFrame);
|
||||
DEFINE_ROOTKEEPER(rk1, compileFrame);
|
||||
|
||||
FunctionInstance *result = new FunctionInstance(this, functionClass->prototype, functionClass);
|
||||
RootKeeper rk2(&result);
|
||||
DEFINE_ROOTKEEPER(rk2, result);
|
||||
result->fWrap = new FunctionWrapper(unchecked, compileFrame, env);
|
||||
fnDef->fWrap = result->fWrap;
|
||||
|
||||
|
@ -140,7 +140,7 @@ namespace MetaData {
|
|||
void JS2Metadata::ValidateStmt(Context *cxt, Environment *env, Plurality pl, StmtNode *p)
|
||||
{
|
||||
CompoundAttribute *a = NULL;
|
||||
RootKeeper rk(&a);
|
||||
DEFINE_ROOTKEEPER(rk, a);
|
||||
Frame *curTopFrame = env->getTopFrame();
|
||||
|
||||
try {
|
||||
|
@ -2858,7 +2858,7 @@ doUnary:
|
|||
if (s) {
|
||||
for (NamespaceListIterator nli = multiname->nsList->begin(), nlend = multiname->nsList->end(); (nli != nlend); nli++) {
|
||||
Multiname *mn = new Multiname(multiname->name, *nli);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
InstanceMember *m = findBaseInstanceMember(s, mn, access);
|
||||
if (mBase == NULL)
|
||||
mBase = m;
|
||||
|
@ -3235,8 +3235,6 @@ static const uint8 urlCharType[256] =
|
|||
world(world),
|
||||
engine(new JS2Engine(world)),
|
||||
publicNamespace(new Namespace(engine->public_StringAtom)),
|
||||
mn1(new Multiname(NULL, publicNamespace)),
|
||||
mn2(new Multiname(NULL, publicNamespace)),
|
||||
bCon(new BytecodeContainer()),
|
||||
glob(new Package(new Namespace(&world.identifiers["internal"]))),
|
||||
env(new Environment(new MetaData::SystemFrame(), glob)),
|
||||
|
@ -3245,9 +3243,6 @@ static const uint8 urlCharType[256] =
|
|||
{
|
||||
engine->meta = this;
|
||||
|
||||
JS2Object::addRoot(&mn1);
|
||||
JS2Object::addRoot(&mn2);
|
||||
|
||||
cxt.openNamespaces.clear();
|
||||
cxt.openNamespaces.push_back(publicNamespace);
|
||||
|
||||
|
@ -3713,7 +3708,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
bool JS2Metadata::hasOwnProperty(JS2Object *obj, const String *name)
|
||||
{
|
||||
Multiname *mn = new Multiname(name, publicNamespace);
|
||||
RootKeeper rk(&mn);
|
||||
DEFINE_ROOTKEEPER(rk, mn);
|
||||
js2val val = OBJECT_TO_JS2VAL(obj);
|
||||
return (findCommonMember(&val, mn, ReadWriteAccess, true) != NULL);
|
||||
}
|
||||
|
@ -4224,14 +4219,14 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
void ParameterFrame::assignArguments(JS2Metadata *meta, JS2Object *fnObj, js2val *argBase, uint32 argCount)
|
||||
{
|
||||
Multiname *mn = new Multiname(NULL, meta->publicNamespace);
|
||||
RootKeeper rk1(&mn);
|
||||
DEFINE_ROOTKEEPER(rk1, mn);
|
||||
|
||||
ASSERT(pluralFrame->kind == ParameterKind);
|
||||
ParameterFrame *plural = checked_cast<ParameterFrame *>(pluralFrame);
|
||||
ASSERT((plural->positionalCount == 0) || (plural->positional != NULL));
|
||||
|
||||
SimpleInstance *argsObj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass);;
|
||||
RootKeeper rk2(&argsObj);
|
||||
DEFINE_ROOTKEEPER(rk2, argsObj);
|
||||
|
||||
// Add the 'arguments' property
|
||||
String *name = &meta->world.identifiers["arguments"];
|
||||
|
@ -4326,17 +4321,28 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
************************************************************************************/
|
||||
|
||||
Pond JS2Object::pond(POND_SIZE, NULL);
|
||||
#ifdef DEBUG
|
||||
std::list<RootKeeper *> JS2Object::rootList;
|
||||
#else
|
||||
std::list<PondScum **> JS2Object::rootList;
|
||||
#endif
|
||||
|
||||
// Add a pointer to a gc-allocated object to the root list
|
||||
// Add a pointer to the (address of a) gc-allocated object to the root list
|
||||
// (Note - we hand out an iterator, so it's essential to
|
||||
// use something like std::list that doesn't mess with locations)
|
||||
#ifdef DEBUG
|
||||
JS2Object::RootIterator JS2Object::addRoot(RootKeeper *t)
|
||||
{
|
||||
return rootList.insert(rootList.end(), t);
|
||||
}
|
||||
#else
|
||||
JS2Object::RootIterator JS2Object::addRoot(void *t)
|
||||
{
|
||||
PondScum **p = (PondScum **)t;
|
||||
ASSERT(p);
|
||||
return rootList.insert(rootList.end(), p);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remove a root pointer
|
||||
void JS2Object::removeRoot(RootIterator ri)
|
||||
|
@ -4348,26 +4354,44 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
uint32 JS2Object::gc()
|
||||
{
|
||||
pond.resetMarks();
|
||||
// Anything on the root list is a pointer to a JS2Object.
|
||||
for (std::list<PondScum **>::iterator i = rootList.begin(), end = rootList.end(); (i != end); i++) {
|
||||
// Anything on the root list may also be a pointer to a JS2Object.
|
||||
for (RootIterator i = rootList.begin(), end = rootList.end(); (i != end); i++) {
|
||||
#ifdef DEBUG
|
||||
RootKeeper *r = *i;
|
||||
if (*(r->p)) {
|
||||
PondScum *p = (*(r->p) - 1);
|
||||
ASSERT(p->owner && (p->getSize() >= sizeof(PondScum)) && (p->owner->sanity == POND_SANITY));
|
||||
if (p->isJS2Object()) {
|
||||
JS2Object *obj = (JS2Object *)(p + 1);
|
||||
GCMARKOBJECT(obj)
|
||||
}
|
||||
else
|
||||
mark(p);
|
||||
}
|
||||
#else
|
||||
if (**i) {
|
||||
PondScum *p = (**i) - 1;
|
||||
ASSERT(p->owner && (p->getSize() >= sizeof(PondScum)) && (p->owner->sanity == POND_SANITY));
|
||||
JS2Object *obj = (JS2Object *)(p + 1);
|
||||
GCMARKOBJECT(obj)
|
||||
if (p->isJS2Object()) {
|
||||
JS2Object *obj = (JS2Object *)(p + 1);
|
||||
GCMARKOBJECT(obj)
|
||||
}
|
||||
else
|
||||
mark(p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return pond.moveUnmarkedToFreeList();
|
||||
}
|
||||
|
||||
// Allocate a chunk of size s
|
||||
void *JS2Object::alloc(size_t s)
|
||||
void *JS2Object::alloc(size_t s, bool isJS2Object)
|
||||
{
|
||||
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);
|
||||
void *p = pond.allocFromPond(s, isJS2Object);
|
||||
ASSERT(((ptrdiff_t)p & 0xF) == 0);
|
||||
return p;
|
||||
}
|
||||
|
@ -4429,7 +4453,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)
|
||||
void *Pond::allocFromPond(size_t sz, bool isJS2Object)
|
||||
{
|
||||
|
||||
// See if there's room left...
|
||||
|
@ -4459,15 +4483,16 @@ 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));
|
||||
return JS2Object::alloc(sz - sizeof(PondScum), isJS2Object);
|
||||
nextPond = new Pond(sz, nextPond);
|
||||
}
|
||||
return nextPond->allocFromPond(sz);
|
||||
return nextPond->allocFromPond(sz, isJS2Object);
|
||||
}
|
||||
// there was room, so acquire it
|
||||
PondScum *p = (PondScum *)pondTop;
|
||||
p->owner = this;
|
||||
p->setSize(sz);
|
||||
if (isJS2Object) p->setIsJS2Object();
|
||||
pondTop += sz;
|
||||
pondSize -= sz;
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -147,16 +147,22 @@ enum Hint { NoHint, NumberHint, StringHint };
|
|||
|
||||
class PondScum {
|
||||
public:
|
||||
|
||||
void resetMark() { size &= 0x7FFFFFFF; }
|
||||
void mark() { size |= 0x80000000; }
|
||||
bool isMarked() { return ((size & 0x80000000) != 0); }
|
||||
uint32 getSize() { return size & 0x7FFFFFFF; }
|
||||
void setSize(uint32 sz) { ASSERT((sz & 0x8000000) == 0); size = (sz & 0x7FFFFFFF); }
|
||||
|
||||
void setIsJS2Object() { size |= 0x40000000; }
|
||||
bool isJS2Object() { return ((size & 0x40000000) != 0); }
|
||||
|
||||
uint32 getSize() { return size & 0x3FFFFFFF; }
|
||||
void setSize(uint32 sz) { ASSERT((sz & 0xC000000) == 0); size = (sz & 0x3FFFFFFF); }
|
||||
|
||||
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:
|
||||
uint32 size; // The high bit is used as the gc mark flag
|
||||
// The next high bit is the flag that mark JS2Objects (1) or generic pointers
|
||||
};
|
||||
|
||||
// A pond is a place to get chunks of PondScum from and to return them to
|
||||
|
@ -166,7 +172,7 @@ class Pond {
|
|||
public:
|
||||
Pond(size_t sz, Pond *nextPond);
|
||||
|
||||
void *allocFromPond(size_t sz);
|
||||
void *allocFromPond(size_t sz, bool isJS2Object);
|
||||
uint32 returnToPond(PondScum *p);
|
||||
|
||||
void resetMarks();
|
||||
|
@ -187,6 +193,8 @@ public:
|
|||
#define GCMARKOBJECT(n) if ((n) && !(n)->isMarked()) { (n)->markObject(); (n)->markChildren(); }
|
||||
#define GCMARKVALUE(v) JS2Object::markJS2Value(v)
|
||||
|
||||
class RootKeeper;
|
||||
|
||||
class JS2Object {
|
||||
// Every object is either undefined, null, a Boolean,
|
||||
// a number, a string, a namespace, a compound attribute, a class, a method closure,
|
||||
|
@ -198,18 +206,23 @@ public:
|
|||
ObjectKind kind;
|
||||
|
||||
static Pond pond;
|
||||
#ifdef DEBUG
|
||||
static std::list<RootKeeper *> rootList;
|
||||
typedef std::list<RootKeeper *>::iterator RootIterator;
|
||||
static RootIterator addRoot(RootKeeper *t);
|
||||
#else
|
||||
static std::list<PondScum **> rootList;
|
||||
typedef std::list<PondScum **>::iterator RootIterator;
|
||||
|
||||
static uint32 gc();
|
||||
static RootIterator addRoot(void *t); // pass the address of any JS2Object pointer
|
||||
// Note: Not the address of a JS2VAL!
|
||||
#endif
|
||||
static uint32 gc();
|
||||
static void removeRoot(RootIterator ri);
|
||||
|
||||
static void *alloc(size_t s);
|
||||
static void *alloc(size_t s, bool isJS2Object = false);
|
||||
static void unalloc(void *p);
|
||||
|
||||
void *operator new(size_t s) { return alloc(s); }
|
||||
void *operator new(size_t s) { return alloc(s, true); }
|
||||
void operator delete(void *p) { unalloc(p); }
|
||||
|
||||
virtual void markChildren() { } // XXX !!!! XXXX these are supposed to not have vtables !!!!
|
||||
|
@ -222,12 +235,33 @@ public:
|
|||
|
||||
class RootKeeper {
|
||||
public:
|
||||
RootKeeper(void *t) : ri(JS2Object::addRoot(t)) { }
|
||||
#ifdef DEBUG
|
||||
RootKeeper(void *p, int line, char *pfile) : p((PondScum **)p), line(line)
|
||||
{
|
||||
file = new char[strlen(pfile) + 1];
|
||||
strcpy(file, pfile);
|
||||
ri = JS2Object::addRoot(this);
|
||||
}
|
||||
#else
|
||||
RootKeeper(void *p) :{ ri = JS2Object::addRoot(p); }
|
||||
#endif
|
||||
~RootKeeper() { JS2Object::removeRoot(ri); }
|
||||
|
||||
JS2Object::RootIterator ri;
|
||||
|
||||
#ifdef DEBUG
|
||||
PondScum **p;
|
||||
int line;
|
||||
char *file;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEFINE_ROOTKEEPER(rk_var, obj) RootKeeper rk_var(&obj, __LINE__, __FILE__);
|
||||
#else
|
||||
#define DEFINE_ROOTKEEPER(rk_var, obj) RootKeeper rk_var(&obj);
|
||||
#endif
|
||||
|
||||
class Attribute : public JS2Object {
|
||||
public:
|
||||
enum AttributeKind { TrueAttr, FalseAttr, NamespaceAttr, CompoundAttr };
|
||||
|
@ -1248,8 +1282,6 @@ public:
|
|||
// The one and only 'public' namespace
|
||||
Namespace *publicNamespace;
|
||||
|
||||
Multiname *mn1, *mn2; // useful, gc-rooted multiname temps.
|
||||
|
||||
LocalMember *forbiddenMember; // just need one of these hanging around
|
||||
|
||||
// The base classes:
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace MetaData {
|
|||
// XXX Change constructors to take js2val pointer for the result (which would be an already
|
||||
// rooted pointer).
|
||||
RegExpInstance *thisInst = new RegExpInstance(meta, meta->regexpClass->prototype, meta->regexpClass);
|
||||
RootKeeper rk(&thisInst);
|
||||
DEFINE_ROOTKEEPER(rk, thisInst);
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(thisInst);
|
||||
REuint32 flags = 0;
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val
|
|||
{
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new StringInstance(meta, meta->stringClass->prototype, meta->stringClass));
|
||||
StringInstance *strInst = checked_cast<StringInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
RootKeeper rk(&strInst);
|
||||
DEFINE_ROOTKEEPER(rk, strInst);
|
||||
if (argc > 0)
|
||||
strInst->mValue = meta->engine->allocStringPtr(meta->toString(argv[0]));
|
||||
else
|
||||
|
@ -169,7 +169,7 @@ static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
}
|
||||
else {
|
||||
ArrayInstance *A = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass);
|
||||
RootKeeper rk(&A);
|
||||
DEFINE_ROOTKEEPER(rk, A);
|
||||
int32 index = 0;
|
||||
int32 lastIndex = 0;
|
||||
while (true) {
|
||||
|
@ -405,7 +405,7 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
RootKeeper rk(&A);
|
||||
DEFINE_ROOTKEEPER(rk, A);
|
||||
|
||||
uint32 lim;
|
||||
js2val separatorV = (argc > 0) ? argv[0] : JS2VAL_UNDEFINED;
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
#define js2value_h___
|
||||
|
||||
|
||||
#define JS2_BIT(n) ((uint32)1 << (n))
|
||||
#define JS2_BITMASK(n) (JS2_BIT(n) - 1)
|
||||
/*
|
||||
* Type tags stored in the low bits of a js2val.
|
||||
*/
|
||||
|
@ -67,11 +65,11 @@
|
|||
|
||||
/* Type tag bitfield length and derived macros. */
|
||||
#define JS2VAL_TAGBITS 4
|
||||
#define JS2VAL_TAGMASK JS2_BITMASK(JS2VAL_TAGBITS)
|
||||
#define JS2VAL_TAGMASK JS_BITMASK(JS2VAL_TAGBITS)
|
||||
#define JS2VAL_TAG(v) ((v) & JS2VAL_TAGMASK)
|
||||
#define JS2VAL_SETTAG(v,t) ((v) | (t))
|
||||
#define JS2VAL_CLRTAG(v) ((v) & ~(js2val)JS2VAL_TAGMASK)
|
||||
#define JS2VAL_ALIGN JS2_BIT(JS2VAL_TAGBITS)
|
||||
#define JS2VAL_ALIGN JS_BIT(JS2VAL_TAGBITS)
|
||||
|
||||
#define JS2VAL_INT_POW2(n) ((js2val)1 << (n))
|
||||
#define JS2VAL_INT_MAX (JS2VAL_INT_POW2(30) - 1)
|
||||
|
|
Загрузка…
Ссылка в новой задаче