diff --git a/mozilla/js2/src/bytecodecontainer.cpp b/mozilla/js2/src/bytecodecontainer.cpp index 528cadb489b..e864be66dcd 100644 --- a/mozilla/js2/src/bytecodecontainer.cpp +++ b/mozilla/js2/src/bytecodecontainer.cpp @@ -42,6 +42,7 @@ #include #include +#include #include "world.h" #include "utilities.h" diff --git a/mozilla/js2/src/epimetheus.cpp b/mozilla/js2/src/epimetheus.cpp index 18f620639c2..0f33e7d8ce2 100644 --- a/mozilla/js2/src/epimetheus.cpp +++ b/mozilla/js2/src/epimetheus.cpp @@ -37,6 +37,7 @@ #include #include +#include #include "reader.h" #include "parser.h" diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 2ef2a34b4aa..7cc797d8b82 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -43,6 +43,7 @@ #include #include +#include #include "world.h" #include "utilities.h" @@ -363,6 +364,7 @@ namespace MetaData { ASSERT(activationStackTop < (activationStack + MAX_ACTIVATION_STACK)); activationStackTop->bCon = bCon; activationStackTop->pc = pc; + activationStackTop->topFrame = meta->env.getTopFrame(); activationStackTop++; bCon = new_bCon; @@ -377,6 +379,9 @@ namespace MetaData { bCon = activationStackTop->bCon; pc = activationStackTop->pc; + while (meta->env.getTopFrame() != activationStackTop->topFrame) + meta->env.removeTopFrame(); + } void JS2Engine::mark() diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 7c7070291c9..653abb52bb6 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -103,6 +103,7 @@ enum JS2Op { int getStackEffect(JS2Op op); +class Frame; class JS2Object; class JS2Metadata; class BytecodeContainer; @@ -168,6 +169,7 @@ public: struct ActivationFrame { uint8 *pc; BytecodeContainer *bCon; + Frame *topFrame; }; void jsr(BytecodeContainer *bCon); bool activationStackEmpty() { return (activationStackTop == activationStack); } diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 561c5c509bd..047739fe0ce 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -49,6 +49,7 @@ #include #include +#include #include "reader.h" #include "parser.h" @@ -89,7 +90,11 @@ namespace MetaData { /* * Validate an individual statement 'p', including it's children */ - void JS2Metadata::ValidateStmt(Context *cxt, Environment *env, StmtNode *p) { + void JS2Metadata::ValidateStmt(Context *cxt, Environment *env, StmtNode *p) + { + CompoundAttribute *a = NULL; + JS2Object::RootIterator ri = JS2Object::addRoot(&a); + switch (p->getKind()) { case StmtNode::block: case StmtNode::group: @@ -274,7 +279,7 @@ namespace MetaData { ValidateAttributeExpression(cxt, env, f->attributes); attr = EvalAttributeExpression(env, CompilePhase, f->attributes); } - CompoundAttribute *a = Attribute::toCompoundAttribute(attr); + a = Attribute::toCompoundAttribute(attr); if (a->dynamic) reportError(Exception::definitionError, "Illegal attribute", p->pos); VariableBinding *vb = f->function.parameters; @@ -323,17 +328,25 @@ namespace MetaData { defineHoistedVar(env, *f->function.name, p); } else { + FixedInstance *fInst = new FixedInstance(functionClass); + fInst->fWrap = new FunctionWrapper(unchecked, compileFrame); + f->fWrap = fInst->fWrap; switch (memberMod) { case Attribute::NoModifier: case Attribute::Static: { - FixedInstance *fInst = new FixedInstance(functionClass); - fInst->fWrap = new FunctionWrapper(unchecked, compileFrame); - f->fWrap = fInst->fWrap; Variable *v = new Variable(functionClass, OBJECT_TO_JS2VAL(fInst), true); defineStaticMember(env, *f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); } break; + case Attribute::Virtual: + case Attribute::Final: + { + JS2Class *c = checked_cast(env->getTopFrame()); + InstanceMember *m = new InstanceMethod(fInst); + defineInstanceMember(c, cxt, *f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, m, p->pos); + } + break; } } } @@ -366,7 +379,7 @@ namespace MetaData { defineHoistedVar(env, *name, p); } else { - CompoundAttribute *a = Attribute::toCompoundAttribute(attr); + a = Attribute::toCompoundAttribute(attr); if (a->dynamic || a->prototype) reportError(Exception::definitionError, "Illegal attribute", p->pos); Attribute::MemberModifier memberMod = a->memberMod; @@ -418,7 +431,7 @@ namespace MetaData { ValidateAttributeExpression(cxt, env, ns->attributes); attr = EvalAttributeExpression(env, CompilePhase, ns->attributes); } - CompoundAttribute *a = Attribute::toCompoundAttribute(attr); + a = Attribute::toCompoundAttribute(attr); if (a->dynamic || a->prototype) reportError(Exception::definitionError, "Illegal attribute", p->pos); if ( ! ((a->memberMod == Attribute::NoModifier) || ((a->memberMod == Attribute::Static) && (env->getTopFrame()->kind == ClassKind))) ) @@ -462,7 +475,7 @@ namespace MetaData { ValidateAttributeExpression(cxt, env, classStmt->attributes); attr = EvalAttributeExpression(env, CompilePhase, classStmt->attributes); } - CompoundAttribute *a = Attribute::toCompoundAttribute(attr); + a = Attribute::toCompoundAttribute(attr); if (!superClass->complete || superClass->final) reportError(Exception::definitionError, "Illegal inheritance", p->pos); JS2Object *proto = NULL; @@ -496,6 +509,8 @@ namespace MetaData { c->complete = true; } } // switch (p->getKind()) + + JS2Object::removeRoot(ri); } @@ -678,7 +693,8 @@ namespace MetaData { { ExprStmtNode *e = checked_cast(p); if (e->expr) { - EvalExprNode(env, phase, e->expr); + Reference *r = EvalExprNode(env, phase, e->expr); + if (r) r->emitReadBytecode(bCon, p->pos); bCon->emitOp(eReturn, p->pos); } } @@ -1974,6 +1990,9 @@ doBinary: case PackageKind: return packageClass; + case MethodClosureKind: + return functionClass; + case SystemKind: case ParameterKind: case BlockKind: @@ -2146,6 +2165,7 @@ readClassProperty: case AttributeObjectKind: case MultinameKind: case FixedInstanceKind: + case MethodClosureKind: goto readClassProperty; case DynamicInstanceKind: isDynamicInstance = true; @@ -2156,35 +2176,8 @@ readClassProperty: case PackageKind: case ParameterKind: case BlockKind: - return readProperty(checked_cast(container), multiname, lookupKind, phase, rval); - case ClassKind: - { - // this: - // JS2VAL_UNINITIALIZED --> generic - // JS2VAL_NULL --> none - // JS2VAL_VOID --> inaccessible - // - js2val thisObject; - if (lookupKind->isPropertyLookup()) - thisObject = JS2VAL_UNINITIALIZED; - else - thisObject = lookupKind->thisObject; - MemberDescriptor m2; - if (findStaticMember(checked_cast(container), multiname, ReadAccess, phase, &m2) && m2.staticMember) - return readStaticMember(m2.staticMember, phase, rval); - else { - if (JS2VAL_IS_NULL(thisObject)) - reportError(Exception::propertyAccessError, "Null 'this' object", engine->errorPos()); - if (JS2VAL_IS_VOID(thisObject)) - reportError(Exception::compileExpressionError, "Undefined 'this' object", engine->errorPos()); - if (JS2VAL_IS_UNINITIALIZED(thisObject)) { - // 'this' is {generic} - // XXX is ??? in spec. - } - return readInstanceMember(thisObject, objectType(thisObject), m2.qname, phase, rval); - } - } + return readProperty(checked_cast(container), multiname, lookupKind, phase, rval); case PrototypeInstanceKind: return readDynamicProperty(container, multiname, lookupKind, phase, rval); @@ -2228,6 +2221,12 @@ readClassProperty: break; case InstanceMember::InstanceMethodKind: + { + *rval = OBJECT_TO_JS2VAL(new MethodClosure(containerVal, checked_cast(m))); + return true; + } + break; + case InstanceMember::InstanceAccessorKind: break; } @@ -2239,11 +2238,36 @@ readClassProperty: // the property or not. If it does, return it's value bool JS2Metadata::readProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval) { - StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase); - if (!m && (container->kind == GlobalObjectKind)) - return readDynamicProperty(container, multiname, lookupKind, phase, rval); - else - return readStaticMember(m, phase, rval); + if (container->kind != ClassKind) { + // Must be System, Global, Package, Parameter or Block + StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase); + if (!m && (container->kind == GlobalObjectKind)) + return readDynamicProperty(container, multiname, lookupKind, phase, rval); + else + return readStaticMember(m, phase, rval); + } + else { + // XXX using JS2VAL_UNINITIALIZED to signal generic 'this' + js2val thisObject; + if (lookupKind->isPropertyLookup()) + thisObject = JS2VAL_UNINITIALIZED; + else + thisObject = lookupKind->thisObject; + MemberDescriptor m2; + if (findStaticMember(checked_cast(container), multiname, ReadAccess, phase, &m2) && m2.staticMember) + return readStaticMember(m2.staticMember, phase, rval); + else { + if (JS2VAL_IS_NULL(thisObject)) + reportError(Exception::propertyAccessError, "Null 'this' object", engine->errorPos()); + if (JS2VAL_IS_INACCESSIBLE(thisObject)) + reportError(Exception::compileExpressionError, "Inaccesible 'this' object", engine->errorPos()); + if (JS2VAL_IS_UNINITIALIZED(thisObject)) { + // 'this' is {generic} + // XXX is ??? in spec. + } + return readInstanceMember(thisObject, objectType(thisObject), m2.qname, phase, rval); + } + } } // Write the value of a property in the container. Return true/false if that container has @@ -2257,6 +2281,7 @@ readClassProperty: switch (container->kind) { case AttributeObjectKind: case MultinameKind: + case MethodClosureKind: return false; case FixedInstanceKind: @@ -2279,36 +2304,8 @@ readClassProperty: case PackageKind: case ParameterKind: case BlockKind: - return writeProperty(checked_cast(container), multiname, lookupKind, createIfMissing, newValue, phase); - case ClassKind: - { - // this: - // JS2VAL_UNINITIALIZED --> generic - // JS2VAL_NULL --> none - // JS2VAL_VOID --> inaccessible - // - js2val thisObject; - if (lookupKind->isPropertyLookup()) - thisObject = JS2VAL_UNINITIALIZED; - else - thisObject = lookupKind->thisObject; - MemberDescriptor m2; - if (findStaticMember(checked_cast(container), multiname, WriteAccess, phase, &m2) && m2.staticMember) - return writeStaticMember(m2.staticMember, newValue, phase); - else { - if (JS2VAL_IS_NULL(thisObject)) - reportError(Exception::propertyAccessError, "Null 'this' object", engine->errorPos()); - if (JS2VAL_IS_VOID(thisObject)) - reportError(Exception::compileExpressionError, "Undefined 'this' object", engine->errorPos()); - if (JS2VAL_IS_UNINITIALIZED(thisObject)) { - // 'this' is {generic} - // XXX is ??? in spec. - } - return writeInstanceMember(thisObject, objectType(thisObject), m2.qname, newValue, phase); - } - } - break; + return writeProperty(checked_cast(container), multiname, lookupKind, createIfMissing, newValue, phase); case PrototypeInstanceKind: return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase); @@ -2351,11 +2348,36 @@ readClassProperty: // the property or not. bool JS2Metadata::writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase) { - StaticMember *m = findFlatMember(container, multiname, WriteAccess, phase); - if (!m && (container->kind == GlobalObjectKind)) - return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase); - else - return writeStaticMember(m, newValue, phase); + if (container->kind != ClassKind) { + // Must be System, Global, Package, Parameter or Block + StaticMember *m = findFlatMember(container, multiname, WriteAccess, phase); + if (!m && (container->kind == GlobalObjectKind)) + return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase); + else + return writeStaticMember(m, newValue, phase); + } + else { + // XXX using JS2VAL_UNINITIALIZED to signal generic 'this' + js2val thisObject; + if (lookupKind->isPropertyLookup()) + thisObject = JS2VAL_UNINITIALIZED; + else + thisObject = lookupKind->thisObject; + MemberDescriptor m2; + if (findStaticMember(checked_cast(container), multiname, WriteAccess, phase, &m2) && m2.staticMember) + return writeStaticMember(m2.staticMember, newValue, phase); + else { + if (JS2VAL_IS_NULL(thisObject)) + reportError(Exception::propertyAccessError, "Null 'this' object", engine->errorPos()); + if (JS2VAL_IS_VOID(thisObject)) + reportError(Exception::compileExpressionError, "Undefined 'this' object", engine->errorPos()); + if (JS2VAL_IS_UNINITIALIZED(thisObject)) { + // 'this' is {generic} + // XXX is ??? in spec. + } + return writeInstanceMember(thisObject, objectType(thisObject), m2.qname, newValue, phase); + } + } } // Find a binding in the frame that matches the multiname and access @@ -2441,7 +2463,7 @@ readClassProperty: else iFound = ib->second; } - b++; + ib++; } if (iFound) { result->staticMember = NULL; @@ -2620,7 +2642,7 @@ readClassProperty: p->owner = (Pond *)freeHeader; uint8 *t = (uint8 *)(p + 1); #ifdef DEBUG - memset(t, 0xB7, p->getSize() - sizeof(PondScum)); + memset(t, 0xB3, p->getSize() - sizeof(PondScum)); #endif freeHeader = p; } @@ -2683,6 +2705,13 @@ readClassProperty: GCMARKOBJECT(super) GCMARKOBJECT(prototype) GCMARKOBJECT(privateNamespace) + InstanceBindingIterator ib, iend; + for (ib = instanceReadBindings.begin(), iend = instanceReadBindings.end(); (ib != iend); ib++) { + GCMARKOBJECT(ib->second->content) + } + for (ib = instanceWriteBindings.begin(), iend = instanceWriteBindings.end(); (ib != iend); ib++) { + GCMARKOBJECT(ib->second->content) + } } /************************************************************************************ @@ -2738,6 +2767,7 @@ readClassProperty: FixedInstance::FixedInstance(JS2Class *type) : JS2Object(FixedInstanceKind), type(type), + fWrap(NULL), call(NULL), construct(NULL), env(NULL), @@ -2752,6 +2782,10 @@ readClassProperty: void FixedInstance::markChildren() { GCMARKOBJECT(type) + if (fWrap) { + GCMARKOBJECT(fWrap->compileFrame); + fWrap->bCon->mark(); + } if (slots) { ASSERT(type); for (uint32 i = 0; (i < type->slotCount); i++) { @@ -2782,6 +2816,22 @@ readClassProperty: } } + +/************************************************************************************ + * + * Frame + * + ************************************************************************************/ + + void MethodClosure::markChildren() + { + if (JS2VAL_IS_OBJECT(thisObject)) { + JS2Object *obj = JS2VAL_TO_OBJECT(thisObject); + GCMARKOBJECT(obj) + } + GCMARKOBJECT(method->fInst) + } + /************************************************************************************ * * Frame @@ -2855,6 +2905,77 @@ readClassProperty: } + /************************************************************************************ + * + * InstanceMember + * + ************************************************************************************/ + + bool InstanceMember::isMarked() + { + return type->isMarked(); + } + + void InstanceMember::mark() + { + type->mark(); + } + + void InstanceMember::markChildren() + { + type->markChildren(); + } + + + /************************************************************************************ + * + * InstanceVariable + * + ************************************************************************************/ + + bool InstanceVariable::isMarked() + { + if (type != FUTURE_TYPE) + return type->isMarked(); + else + return false; + } + + void InstanceVariable::mark() + { + if (type != FUTURE_TYPE) + type->mark(); + } + + void InstanceVariable::markChildren() + { + if (type != FUTURE_TYPE) + type->markChildren(); + } + + + /************************************************************************************ + * + * InstanceMethod + * + ************************************************************************************/ + + bool InstanceMethod::isMarked() + { + return fInst->isMarked(); + } + + void InstanceMethod::mark() + { + fInst->mark(); + } + + void InstanceMethod::markChildren() + { + fInst->markChildren(); + } + + /************************************************************************************ * * JS2Object @@ -2862,27 +2983,33 @@ readClassProperty: ************************************************************************************/ Pond JS2Object::pond(POND_SIZE, NULL); - std::vector JS2Object::rootList; + std::list JS2Object::rootList; - void JS2Object::addRoot(void *t) + JS2Object::RootIterator JS2Object::addRoot(void *t) { PondScum **p = (PondScum **)t; ASSERT(p); - rootList.push_back(p); + return rootList.insert(rootList.end(), p); + } + + void JS2Object::removeRoot(RootIterator ri) + { + rootList.erase(ri); } void JS2Object::gc(JS2Metadata *meta) { pond.resetMarks(); - for (std::vector::iterator i = rootList.begin(), end = rootList.end(); (i != end); i++) { - PondScum *p = **i; - if (p) { + for (std::list::iterator i = rootList.begin(), end = rootList.end(); (i != end); i++) { + if (**i) { + PondScum *p = (**i) - 1; ASSERT(p->owner && (p->getSize() >= sizeof(PondScum)) && (p->owner->sanity == POND_SANITY)); - p->mark(); if (p->isJS2Object()) { JS2Object *obj = (JS2Object *)(p + 1); GCMARKOBJECT(obj) } + else + p->mark(); } } meta->mark(); diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 97c838b6983..da7bc29053a 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -50,6 +50,7 @@ class Context; class CompoundAttribute; class BytecodeContainer; class Pond; +class FixedInstance; typedef void (Invokable)(); @@ -67,7 +68,8 @@ enum ObjectKind { PrototypeInstanceKind, FixedInstanceKind, DynamicInstanceKind, - MultinameKind + MultinameKind, + MethodClosureKind }; class PondScum { @@ -126,9 +128,12 @@ public: ObjectKind kind; static Pond pond; - static std::vector rootList; + static std::list rootList; + typedef std::list::iterator RootIterator; + static void gc(JS2Metadata *meta); - static void addRoot(void *t); // pass the address of any JS2Object pointer + static RootIterator addRoot(void *t); // pass the address of any JS2Object pointer + static void removeRoot(RootIterator ri); static void *alloc(size_t s, bool isJS2Object = false); static void unalloc(void *p); @@ -243,9 +248,9 @@ public: MemberKind kind; -#ifdef DEBUG - virtual void uselessVirtual() { } // want the checked_cast stuff to work, so need a virtual function -#endif + virtual bool isMarked() { return true; } + virtual void mark() { } + virtual void markChildren() { } }; // A static member is either forbidden, a variable, a hoisted variable, a constructor method, or an accessor: @@ -258,9 +263,6 @@ public: // bindings that refer to this member.) virtual StaticMember *clone() { ASSERT(false); return NULL; } - virtual bool isMarked() { return true; } - virtual void mark() { } - virtual void markChildren() { } }; #define FUTURE_TYPE ((JS2Class *)(-1)) @@ -347,9 +349,9 @@ public: JS2Class *type; // Type of values that may be stored in this variable bool final; // true if this member may not be overridden in subclasses -#ifdef DEBUG - virtual void uselessVirtual() { } // want the checked_cast stuff to work, so need a virtual function -#endif + virtual bool isMarked(); + virtual void mark(); + virtual void markChildren(); }; class InstanceVariable : public InstanceMember { @@ -358,13 +360,22 @@ public: Invokable *evalInitialValue; // A function that computes this variable's initial value bool immutable; // true if this variable's value may not be changed once set uint32 slotIndex; // The index into an instance's slot array in which this variable is stored + + virtual bool isMarked(); + virtual void mark(); + virtual void markChildren(); }; class InstanceMethod : public InstanceMember { public: - InstanceMethod() : InstanceMember(InstanceMethodKind, NULL, false) { } + InstanceMethod(FixedInstance *fInst) : InstanceMember(InstanceMethodKind, NULL, false), fInst(fInst) { } Signature type; // This method's signature Invokable *code; // This method itself (a callable object); null if this method is abstract + FixedInstance *fInst; + + virtual bool isMarked(); + virtual void mark(); + virtual void markChildren(); }; class InstanceAccessor : public InstanceMember { @@ -523,7 +534,15 @@ public: virtual void markChildren(); }; +// A METHODCLOSURE tuple describes an instance method with a bound this value. +class MethodClosure : public JS2Object { +public: + MethodClosure(js2val thisObject, InstanceMethod *method) : JS2Object(MethodClosureKind), thisObject(thisObject), method(method) { } + js2val thisObject; // The bound this value + InstanceMethod *method; // The bound method + virtual void markChildren(); +}; // Base class for all references (lvalues) @@ -641,7 +660,7 @@ public: class ParameterFrame : public Frame { public: ParameterFrame(js2val thisObject, bool prototype) : Frame(ParameterKind), thisObject(thisObject), prototype(prototype) { } - ParameterFrame(ParameterFrame *pluralFrame) : Frame(ParameterKind, pluralFrame) { } + ParameterFrame(ParameterFrame *pluralFrame) : Frame(ParameterKind, pluralFrame), thisObject(JS2VAL_UNDEFINED), prototype(pluralFrame->prototype) { } Plurality plurality; js2val thisObject; // The value of this; none if this function doesn't define this; diff --git a/mozilla/js2/src/js2op_access.cpp b/mozilla/js2/src/js2op_access.cpp index b35503d4e43..5bc16ce6494 100644 --- a/mozilla/js2/src/js2op_access.cpp +++ b/mozilla/js2/src/js2op_access.cpp @@ -104,22 +104,6 @@ } break; - case ePushFrame: - { - Frame *f = bCon->mFrameList[BytecodeContainer::getShort(pc)]; - pc += sizeof(short); - meta->env.addFrame(f); - f->instantiate(&meta->env); - } - break; - - case ePopFrame: - { - meta->env.removeTopFrame(); - } - break; - - // Read an index property from a base object, push the value onto the stack case eBracketRead: { diff --git a/mozilla/js2/src/js2op_invocation.cpp b/mozilla/js2/src/js2op_invocation.cpp index b333c465920..313133a8283 100644 --- a/mozilla/js2/src/js2op_invocation.cpp +++ b/mozilla/js2/src/js2op_invocation.cpp @@ -97,16 +97,27 @@ runtimeThis = OBJECT_TO_JS2VAL(g); } } - Frame *runtimeFrame = new ParameterFrame(fWrap->compileFrame); - meta->env.addFrame(runtimeFrame); + ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame); runtimeFrame->instantiate(&meta->env); + runtimeFrame->thisObject = runtimeThis; // assignArguments(runtimeFrame, fWrap->compileFrame->signature); - - jsr(fWrap->bCon); + jsr(fWrap->bCon); // seems out of order, but we need to catch the current top frame + meta->env.addFrame(runtimeFrame); } else - ASSERT(false); + if (fObj->kind == MethodClosureKind) { + MethodClosure *mc = checked_cast(fObj); + FixedInstance *fInst = mc->method->fInst; + FunctionWrapper *fWrap = fInst->fWrap; + ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame); + runtimeFrame->instantiate(&meta->env); + runtimeFrame->thisObject = mc->thisObject; +// assignArguments(runtimeFrame, fWrap->compileFrame->signature); + jsr(fWrap->bCon); // seems out of order, but we need to catch the current top frame + meta->env.addFrame(meta->objectType(mc->thisObject)); + meta->env.addFrame(runtimeFrame); + } } break; @@ -118,9 +129,9 @@ case eReturn: { - retval = pop(); +// retval = pop(); if (activationStackEmpty()) - return retval; + return pop(); else rts(); } @@ -135,3 +146,18 @@ } break; + case ePushFrame: + { + Frame *f = bCon->mFrameList[BytecodeContainer::getShort(pc)]; + pc += sizeof(short); + meta->env.addFrame(f); + f->instantiate(&meta->env); + } + break; + + case ePopFrame: + { + meta->env.removeTopFrame(); + } + break; + diff --git a/mozilla/js2/src/js2value.h b/mozilla/js2/src/js2value.h index d07ec0dff04..15dd27ac9b4 100644 --- a/mozilla/js2/src/js2value.h +++ b/mozilla/js2/src/js2value.h @@ -60,6 +60,7 @@ that a variable has to have it's initializer run */ #define JS2VAL_IS_FUTURE(v) (v == JS2VAL_FUTUREVALUE) +#define JS2VAL_IS_SPECIALREF(v) ( (v & ~0xF0) == 0 ) /* Type tag bitfield length and derived macros. */ #define JS2VAL_TAGBITS 3 @@ -81,7 +82,7 @@ #define JS2VAL_TRUE BOOLEAN_TO_JS2VAL(true) /* Predicates for type testing. */ -#define JS2VAL_IS_OBJECT(v) (JS2VAL_TAG(v) == JS2VAL_OBJECT) +#define JS2VAL_IS_OBJECT(v) ((JS2VAL_TAG(v) == JS2VAL_OBJECT) && !JS2VAL_IS_SPECIALREF(v)) #define JS2VAL_IS_NUMBER(v) (JS2VAL_IS_INT(v) || JS2VAL_IS_DOUBLE(v)) #define JS2VAL_IS_INT(v) (((v) & JS2VAL_INT) && (v) != JS2VAL_VOID) #define JS2VAL_IS_DOUBLE(v) (JS2VAL_TAG(v) == JS2VAL_DOUBLE)