diff --git a/mozilla/js2/src/epimetheus.cpp b/mozilla/js2/src/epimetheus.cpp index d572469b370..91156b1083d 100644 --- a/mozilla/js2/src/epimetheus.cpp +++ b/mozilla/js2/src/epimetheus.cpp @@ -378,8 +378,10 @@ int main(int argc, char **argv) stdOut << "Welcome to Epimetheus.\n"; #endif - JS2Object::addRoot(&metadata); - metadata = new MetaData::JS2Metadata(world); + JS2Object::addRoot(&metadata); + + metadata = new MetaData::JS2Metadata(world); + metadata->addGlobalObjectFunction("print", print, 1); metadata->addGlobalObjectFunction("load", load, 1); #ifdef DEBUG diff --git a/mozilla/js2/src/js2array.cpp b/mozilla/js2/src/js2array.cpp index bce390fdfde..3aab4dfc9ba 100644 --- a/mozilla/js2/src/js2array.cpp +++ b/mozilla/js2/src/js2array.cpp @@ -94,6 +94,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(JS2VAL_TO_OBJECT(thatValue)); + JS2Object::RootIterator ri = JS2Object::addRoot(&arrInst); if (argc > 0) { if (argc == 1) { if (JS2VAL_IS_NUMBER(argv[0])) { @@ -118,6 +119,7 @@ js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val * } } } + JS2Object::removeRoot(ri); return thatValue; } diff --git a/mozilla/js2/src/js2boolean.cpp b/mozilla/js2/src/js2boolean.cpp index f2459b99106..9b3e2ef2b81 100644 --- a/mozilla/js2/src/js2boolean.cpp +++ b/mozilla/js2/src/js2boolean.cpp @@ -59,11 +59,13 @@ namespace MetaData { { js2val thatValue = OBJECT_TO_JS2VAL(new BooleanInstance(meta->booleanClass->prototype, meta->booleanClass)); BooleanInstance *boolInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); + JS2Object::RootIterator ri = JS2Object::addRoot(&boolInst); if (argc > 0) boolInst->mValue = meta->toBoolean(argv[0]); else boolInst->mValue = false; + JS2Object::removeRoot(ri); return thatValue; } diff --git a/mozilla/js2/src/js2date.cpp b/mozilla/js2/src/js2date.cpp index 65125fd0e1d..a49a6b6b0a0 100644 --- a/mozilla/js2/src/js2date.cpp +++ b/mozilla/js2/src/js2date.cpp @@ -856,6 +856,7 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val /* thisValue */, js2val { js2val thatValue = OBJECT_TO_JS2VAL(new DateInstance(meta->dateClass->prototype, meta->dateClass)); DateInstance *thisInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); + JS2Object::RootIterator ri = JS2Object::addRoot(&thisInst); /* Date called as constructor */ if (argc == 0) { @@ -895,6 +896,7 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val /* thisValue */, js2val and return */ if (!JSDOUBLE_IS_FINITE(double_arg)) { thisInst->ms = nan; + JS2Object::removeRoot(ri); return thatValue; } array[loop] = meta->engine->allocNumber(JS2Engine::float64toInt32(double_arg)); @@ -917,6 +919,7 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val /* thisValue */, js2val thisInst->ms = TIMECLIP(msec_time); } } + JS2Object::removeRoot(ri); return thatValue; } diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index e1b148a31dc..2b8a1b2a688 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -66,7 +66,7 @@ namespace MetaData { // Begin execution of a bytecodeContainer js2val JS2Engine::interpret(Phase execPhase, BytecodeContainer *targetbCon) { - jsr(execPhase, targetbCon, sp, JS2VAL_VOID); + jsr(execPhase, targetbCon, sp - execStack, JS2VAL_VOID); ActivationFrame *f = activationStackTop; js2val result; try { @@ -87,8 +87,8 @@ namespace MetaData { { retval = JS2VAL_VOID; baseVal = JS2VAL_VOID; - indexVal = JS2VAL_VOID; - pFrame = NULL; + indexVal = JS2VAL_VOID; + pFrame = NULL; int i = 0; while (true) { try { @@ -168,7 +168,7 @@ namespace MetaData { break; } } - sp = hndlr->mStackTop; + sp = execStack + hndlr->mStackTop; pc = hndlr->mPC; meta->env->setTopFrame(hndlr->mFrame); push(x); @@ -366,12 +366,12 @@ namespace MetaData { : meta(NULL), pc(NULL), bCon(NULL), - retval(JS2VAL_VOID), - a(JS2VAL_VOID), - b(JS2VAL_VOID), - baseVal(JS2VAL_VOID), - indexVal(JS2VAL_VOID), - pFrame(NULL), + retval(JS2VAL_VOID), + a(JS2VAL_VOID), + b(JS2VAL_VOID), + baseVal(JS2VAL_VOID), + indexVal(JS2VAL_VOID), + pFrame(NULL), INIT_STRINGATOM(true), INIT_STRINGATOM(false), INIT_STRINGATOM(null), @@ -794,7 +794,7 @@ namespace MetaData { // Save current engine state (pc, environment top) and // jump to start of new bytecodeContainer - void JS2Engine::jsr(Phase execPhase, BytecodeContainer *new_bCon, js2val *stackBase, js2val returnVal) + void JS2Engine::jsr(Phase execPhase, BytecodeContainer *new_bCon, uint32 stackBase, js2val returnVal) { ASSERT(activationStackTop < (activationStack + MAX_ACTIVATION_STACK)); activationStackTop->bCon = bCon; @@ -805,7 +805,15 @@ namespace MetaData { activationStackTop->retval = returnVal; activationStackTop++; bCon = new_bCon; - ASSERT((int32)bCon->getMaxStack() <= (execStackLimit - sp)); // XXX realloc if insufficient + if ((int32)bCon->getMaxStack() >= (execStackLimit - sp)) { + uint32 curDepth = execStackLimit - sp; + uint32 newDepth = curDepth + bCon->getMaxStack(); + js2val *newStack = new js2val[newDepth]; + ::memcpy(newStack, execStack, curDepth * sizeof(js2val)); + execStack = newStack; + sp = execStack + curDepth; + execStackLimit = execStack + newDepth; + } pc = new_bCon->getCodeStart(); phase = execPhase; @@ -822,7 +830,7 @@ namespace MetaData { phase = activationStackTop->phase; while (meta->env->getTopFrame() != activationStackTop->topFrame) meta->env->removeTopFrame(); - sp = activationStackTop->execStackBase; + sp = execStack + activationStackTop->execStackBase; if (!JS2VAL_IS_VOID(activationStackTop->retval)) // XXX might need an actual 'returnValue' flag instead retval = activationStackTop->retval; } @@ -853,7 +861,8 @@ namespace MetaData { GCMARKVALUE(b); GCMARKVALUE(baseVal); GCMARKVALUE(indexVal); - GCMARKOBJECT(pFrame); + GCMARKOBJECT(pFrame); + JS2Object::mark(true_StringAtom); JS2Object::mark(false_StringAtom); JS2Object::mark(null_StringAtom); @@ -873,7 +882,7 @@ namespace MetaData { void JS2Engine::pushHandler(uint8 *pc) { ActivationFrame *curAct = (activationStackEmpty()) ? NULL : (activationStackTop - 1); - mTryStack.push(new HandlerData(pc, sp, curAct, meta->env->getTopFrame())); + mTryStack.push(new HandlerData(pc, sp - execStack, curAct, meta->env->getTopFrame())); } void JS2Engine::popHandler() diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index ce1ac5d9ad3..9cd3bd4e895 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -158,8 +158,10 @@ enum JS2Op { }; -class Frame; -class ParameterFrame; +class Frame; + +class ParameterFrame; + class JS2Object; class JS2Metadata; class BytecodeContainer; @@ -226,7 +228,8 @@ private: js2val retval; js2val a,b; - js2val baseVal,indexVal; + js2val baseVal,indexVal; + ParameterFrame *pFrame; @@ -259,9 +262,9 @@ public: Frame *topFrame; Phase phase; js2val retval; - js2val *execStackBase; + uint32 execStackBase; }; - void jsr(Phase execPhase, BytecodeContainer *bCon, js2val *stackBase, js2val returnVal); + void jsr(Phase execPhase, BytecodeContainer *bCon, uint32 stackBase, js2val returnVal); bool activationStackEmpty() { return (activationStackTop == activationStack); } void rts(); ActivationFrame *activationStack; @@ -295,11 +298,11 @@ public: void insert(js2val x, int count); struct HandlerData { - HandlerData(uint8 *pc, js2val *stackTop, ActivationFrame *curAct, Frame *frame) + HandlerData(uint8 *pc, uint32 stackTop, ActivationFrame *curAct, Frame *frame) : mPC(pc), mStackTop(stackTop), mActivation(curAct), mFrame(frame) { } uint8 *mPC; - js2val *mStackTop; + uint32 mStackTop; ActivationFrame *mActivation; Frame *mFrame; }; diff --git a/mozilla/js2/src/js2math.cpp b/mozilla/js2/src/js2math.cpp index 0ac4ad851a4..ed01ecdf545 100644 --- a/mozilla/js2/src/js2math.cpp +++ b/mozilla/js2/src/js2math.cpp @@ -346,10 +346,14 @@ void initMathObject(JS2Metadata *meta) meta->env->addFrame(meta->mathClass); PrototypeFunction *pf = &prototypeFunctions[0]; while (pf->name) { - SimpleInstance *fInst = new SimpleInstance(meta->functionClass); - fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); - Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(fInst), true); + SimpleInstance *callInst = new SimpleInstance(meta->functionClass); + callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); + Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(callInst), true); meta->defineLocalMember(meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + + // XXX add 'length' as a dynamic property of the method + meta->writeDynamicProperty(callInst, new Multiname(meta->engine->length_StringAtom, meta->publicNamespace), true, INT_TO_JS2VAL(pf->length), RunPhase); + pf++; } meta->env->removeTopFrame(); diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index d3558e86520..28a4bf2184e 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -2565,7 +2565,7 @@ doUnary: Multiname *mn = new Multiname(id); mn->addNamespace(namespaces); // Search the local frame for an overlapping definition - LocalBindingIterator b, end; + LocalBindingIterator b, end; if (access & ReadAccess) { for (b = localFrame->localReadBindings.lower_bound(*id), end = localFrame->localReadBindings.upper_bound(*id); (b != end); b++) { @@ -2966,6 +2966,47 @@ doUnary: return meta->readEvalString(*meta->toString(argv[0]), widenCString("Eval Source")); } +#define JS7_ISHEX(c) ((c) < 128 && isxdigit(c)) +#define JS7_UNHEX(c) (uint32)(isdigit(c) ? (c) - '0' : 10 + tolower(c) - 'a') + + static js2val GlobalObject_unescape(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc) + { + const String *str = meta->toString(argv[0]); + const char16 *chars = str->data(); + uint32 length = str->length(); + + /* Don't bother allocating less space for the new string. */ + char16 *newchars = new char16[length + 1]; + + uint32 ni = 0; + uint32 i = 0; + char16 ch; + while (i < length) { + ch = chars[i++]; + if (ch == '%') { + if (i + 1 < length && + JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1])) + { + ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]); + i += 2; + } else if (i + 4 < length && chars[i] == 'u' && + JS7_ISHEX(chars[i + 1]) && JS7_ISHEX(chars[i + 2]) && + JS7_ISHEX(chars[i + 3]) && JS7_ISHEX(chars[i + 4])) + { + ch = (((((JS7_UNHEX(chars[i + 1]) << 4) + + JS7_UNHEX(chars[i + 2])) << 4) + + JS7_UNHEX(chars[i + 3])) << 4) + + JS7_UNHEX(chars[i + 4]); + i += 5; + } + } + newchars[ni++] = ch; + } + newchars[ni] = 0; + + return STRING_TO_JS2VAL(meta->engine->allocStringPtr(&meta->world.identifiers[newchars])); + } + void JS2Metadata::addGlobalObjectFunction(char *name, NativeCode *code, uint32 length) { SimpleInstance *fInst = new SimpleInstance(functionClass); @@ -2983,7 +3024,8 @@ doUnary: bCon(new BytecodeContainer()), glob(new GlobalObject(world)), env(new Environment(new MetaData::SystemFrame(), glob)), - showTrees(false) + showTrees(false), + flags(JS1) { engine->meta = this; @@ -3001,7 +3043,7 @@ doUnary: 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(functionClass, objectClass, true, true, true, engine->Function_StringAtom, 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); @@ -3039,6 +3081,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... addGlobalObjectFunction("isNaN", GlobalObject_isNaN, 1); addGlobalObjectFunction("eval", GlobalObject_eval, 1); addGlobalObjectFunction("toString", GlobalObject_toString, 0); + addGlobalObjectFunction("unescape", GlobalObject_unescape, 0); /*** ECMA 3 Object Class ***/ @@ -3437,7 +3480,10 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... if (!initFlag && (JS2VAL_IS_INACCESSIBLE(v->value) || (v->immutable && !JS2VAL_IS_UNINITIALIZED(v->value)))) - reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos()); + if (flags == JS2) + reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos()); + else // quietly ignore the write for JS1 compatibility + return true; v->value = v->type->implicitCoerce(this, newValue); } return true; @@ -4065,38 +4111,38 @@ deleteClassProperty: // XXX here we ignore the bound this, can that be right? MethodClosure *mc = checked_cast(fnObj); fWrap = mc->method->fInst->fWrap; - } + } if (fWrap) { if (fWrap->code) { result = (fWrap->code)(this, thisValue, NULL, 0); return true; } - else { - uint8 *savePC = NULL; - BytecodeContainer *bCon = fWrap->bCon; + else { + uint8 *savePC = NULL; + BytecodeContainer *bCon = fWrap->bCon; - CompilationData *oldData = startCompilationUnit(bCon, bCon->mSource, bCon->mSourceLocation); - ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame); - runtimeFrame->instantiate(env); - runtimeFrame->thisObject = thisValue; - Frame *oldTopFrame = env->getTopFrame(); - env->addFrame(runtimeFrame); - try { - savePC = engine->pc; - engine->pc = NULL; - result = engine->interpret(RunPhase, bCon); - } - catch (Exception &x) { - engine->pc = savePC; - restoreCompilationUnit(oldData); - env->setTopFrame(oldTopFrame); - throw x; - } - engine->pc = savePC; - restoreCompilationUnit(oldData); - env->setTopFrame(oldTopFrame); - return true; - } + CompilationData *oldData = startCompilationUnit(bCon, bCon->mSource, bCon->mSourceLocation); + ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame); + runtimeFrame->instantiate(env); + runtimeFrame->thisObject = thisValue; + Frame *oldTopFrame = env->getTopFrame(); + env->addFrame(runtimeFrame); + try { + savePC = engine->pc; + engine->pc = NULL; + result = engine->interpret(RunPhase, bCon); + } + catch (Exception &x) { + engine->pc = savePC; + restoreCompilationUnit(oldData); + env->setTopFrame(oldTopFrame); + throw x; + } + engine->pc = savePC; + restoreCompilationUnit(oldData); + env->setTopFrame(oldTopFrame); + return true; + } } } } @@ -4649,8 +4695,15 @@ deleteClassProperty: ParameterFrame *plural = checked_cast(pluralFrame); ASSERT((plural->positionalCount == 0) || (plural->positional != NULL)); - js2val argumentsVal = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); - ArrayInstance *arrInst = checked_cast(JS2VAL_TO_OBJECT(argumentsVal)); + ArrayInstance *arrInst = new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass); + js2val argumentsVal = OBJECT_TO_JS2VAL(arrInst); + + // Add the 'arguments' property + QualifiedName qn(meta->publicNamespace, &meta->world.identifiers["arguments"]); + LocalBinding *sb = new LocalBinding(qn, new Variable(meta->arrayClass, argumentsVal, true)); + const LocalBindingMap::value_type e(*qn.id, sb); + localReadBindings.insert(e); + uint32 i; for (i = 0; ((i < argCount) && (i < plural->positionalCount)); i++) { ASSERT(plural->positional[i]->cloneContent); @@ -4661,12 +4714,6 @@ deleteClassProperty: meta->writeDynamicProperty(arrInst, &mn, true, argBase[i], RunPhase); } setLength(meta, arrInst, i); - - // Add the 'arguments' property - QualifiedName qn(meta->publicNamespace, &meta->world.identifiers["arguments"]); - LocalBinding *sb = new LocalBinding(qn, new Variable(meta->arrayClass, argumentsVal, true)); - const LocalBindingMap::value_type e(*qn.id, sb); - localReadBindings.insert(e); } @@ -4845,7 +4892,8 @@ deleteClassProperty: // Allocate from this or the next Pond (make a new one if necessary) void *Pond::allocFromPond(size_t sz) - { + { + // See if there's room left... if (sz > pondSize) { // If not, try the free list... @@ -4870,11 +4918,10 @@ deleteClassProperty: } // 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)); - + // there isn't one; run the gc + uint32 released = JS2Object::gc(); + if (released > sz) + return JS2Object::alloc(sz - sizeof(PondScum)); nextPond = new Pond(sz, nextPond); } return nextPond->allocFromPond(sz); @@ -4899,8 +4946,8 @@ deleteClassProperty: #ifdef DEBUG memset(t, 0xB3, p->getSize() - sizeof(PondScum)); #endif - freeHeader = p; - return p->getSize() - sizeof(PondScum); + freeHeader = p; + return p->getSize() - sizeof(PondScum); } // Clear the mark bit from all PondScums @@ -4918,18 +4965,18 @@ deleteClassProperty: // Anything left unmarked is now moved to the free list uint32 Pond::moveUnmarkedToFreeList() - { - uint32 released = 0; + { + uint32 released = 0; uint8 *t = pondBottom; while (t != pondTop) { PondScum *p = (PondScum *)t; if (!p->isMarked() && (p->owner == this)) // (owner != this) ==> already on free list released += returnToPond(p); - t += p->getSize(); + t += p->getSize(); } if (nextPond) - released += nextPond->moveUnmarkedToFreeList(); - return released; + released += nextPond->moveUnmarkedToFreeList(); + return released; } diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 8cd191668d3..9660dc18fe2 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -129,7 +129,7 @@ private: }; // A pond is a place to get chunks of PondScum from and to return them to -#define POND_SIZE (32000) +#define POND_SIZE (64000) #define POND_SANITY (0xFADE2BAD) class Pond { public: @@ -232,14 +232,16 @@ public: // A MULTINAME is the semantic domain of sets of qualified names. Multinames are used internally in property lookup. // We keep Multinames as a basename and a list of namespace qualifiers (XXX is that right - would the basename -// ever be different for the same multiname?) +// ever be different for the same multiname?) + // XXX can nsList ever be null, or could allow null nsList to indicate public? typedef std::vector NamespaceList; typedef NamespaceList::iterator NamespaceListIterator; class Multiname : public JS2Object { public: Multiname(const String *name) : JS2Object(MultinameKind), name(name), nsList(new NamespaceList) { } - Multiname(const String *name, Namespace *ns) : JS2Object(MultinameKind), name(name), nsList(new NamespaceList) { addNamespace(ns); } + Multiname(const String *name, Namespace *ns) : JS2Object(MultinameKind), name(name), nsList(new NamespaceList) { addNamespace(ns); } + Multiname(const Multiname& m) : JS2Object(MultinameKind), name(m.name), nsList(m.nsList) { } void addNamespace(Namespace *ns) { nsList->push_back(ns); } @@ -1180,6 +1182,9 @@ public: Environment *env; Context cxt; + enum Flag { JS1, JS2 }; + Flag flags; + TargetList targetList; // stack of potential break/continue targets virtual void markChildren(); diff --git a/mozilla/js2/src/js2op_invocation.cpp b/mozilla/js2/src/js2op_invocation.cpp index 73c3ec721db..ad4c45d6f36 100644 --- a/mozilla/js2/src/js2op_invocation.cpp +++ b/mozilla/js2/src/js2op_invocation.cpp @@ -91,9 +91,9 @@ baseVal = OBJECT_TO_JS2VAL(pInst); pFrame->thisObject = baseVal; pFrame->assignArguments(meta, base(argCount), argCount); - jsr(phase, fWrap->bCon, base(argCount + 1), baseVal); // seems out of order, but we need to catch the current top frame - meta->env->addFrame(pFrame); - pFrame = NULL; + jsr(phase, fWrap->bCon, base(argCount + 1) - execStack, baseVal); // seems out of order, but we need to catch the current top frame + meta->env->addFrame(pFrame); + pFrame = NULL; } } else @@ -146,9 +146,9 @@ // assignArguments(runtimeFrame, fWrap->compileFrame->signature); // XXX pFrame->assignArguments(meta, base(argCount), argCount); - jsr(phase, fWrap->bCon, base(argCount + 2), JS2VAL_VOID); // seems out of order, but we need to catch the current top frame - meta->env->addFrame(pFrame); - pFrame = NULL; + jsr(phase, fWrap->bCon, base(argCount + 2) - execStack, JS2VAL_VOID); // seems out of order, but we need to catch the current top frame + meta->env->addFrame(pFrame); + pFrame = NULL; } } else @@ -167,12 +167,11 @@ pFrame->instantiate(meta->env); pFrame->thisObject = mc->thisObject; // assignArguments(runtimeFrame, fWrap->compileFrame->signature); - jsr(phase, fWrap->bCon, base(argCount + 2), JS2VAL_VOID); // seems out of order, but we need to catch the current top frame + jsr(phase, fWrap->bCon, base(argCount + 2) - execStack, JS2VAL_VOID); // seems out of order, but we need to catch the current top frame meta->env->addFrame(meta->objectType(mc->thisObject)); - meta->env->addFrame(pFrame); - pFrame = NULL; + meta->env->addFrame(pFrame); + pFrame = NULL; } - } else if (fObj->kind == ClassKind) { diff --git a/mozilla/js2/src/js2string.cpp b/mozilla/js2/src/js2string.cpp index 5d6ef8fcf09..1c692f0b2ba 100644 --- a/mozilla/js2/src/js2string.cpp +++ b/mozilla/js2/src/js2string.cpp @@ -60,16 +60,15 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val // XXX GC might happen after the new StringInstance, but before the // object gets rooted somewhere - this is a general problem... js2val thatValue = OBJECT_TO_JS2VAL(new StringInstance(meta->stringClass->prototype, meta->stringClass)); - StringInstance *strInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); - JS2Object::RootIterator ri = JS2Object::addRoot(&strInst); - + StringInstance *strInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); + JS2Object::RootIterator ri = JS2Object::addRoot(&strInst); if (argc > 0) strInst->mValue = meta->engine->allocStringPtr(meta->toString(argv[0])); else strInst->mValue = meta->engine->allocStringPtr(""); Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace); - meta->writeDynamicProperty(JS2VAL_TO_OBJECT(thatValue), &mn, true, meta->engine->allocNumber(strInst->mValue->length()), RunPhase); - JS2Object::removeRoot(ri); + meta->writeDynamicProperty(JS2VAL_TO_OBJECT(thatValue), &mn, true, meta->engine->allocNumber(strInst->mValue->length()), RunPhase); + JS2Object::removeRoot(ri); return thatValue; }