diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index eef1dc7bce6..cacef76b65c 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -742,8 +742,12 @@ namespace MetaData { case eSlotWrite: return -1; // write the value, don't preserve it - case eSlotRead: // push the value - return 1; + case eSlotRead: + return 1; // push the value + case eSlotDelete: + return 1; // push boolean result + case eSlotRef: + return 2; // push base & value case eLexicalInit: return -1; // pop the value diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 3f63938cfb9..6f125cb323b 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -98,7 +98,13 @@ enum JS2Op { eForValue, eFrameSlotRead, // + eFrameSlotRef, // eFrameSlotWrite, // + eFrameSlotDelete, // + eFrameSlotPostInc, // + eFrameSlotPostDec, // + eFrameSlotPreInc, // + eFrameSlotPreDec, // eLexicalRead, // eLexicalWrite, // diff --git a/mozilla/js2/src/js2eval.cpp b/mozilla/js2/src/js2eval.cpp index 4ce9831293e..76e40cc22f7 100644 --- a/mozilla/js2/src/js2eval.cpp +++ b/mozilla/js2/src/js2eval.cpp @@ -579,18 +579,19 @@ namespace MetaData { else return false; } - switch (m->kind) { - case Member::Forbidden: - case Member::DynamicVariableKind: - case Member::Variable: - case Member::ConstructorMethod: - case Member::Setter: - case Member::Getter: + switch (m->memberKind) { + case Member::ForbiddenMember: + case Member::DynamicVariableMember: + case Member::FrameVariableMember: + case Member::VariableMember: + case Member::ConstructorMethodMember: + case Member::SetterMember: + case Member::GetterMember: return meta->readLocalMember(checked_cast(m), phase, rval); - case Member::InstanceVariableKind: - case Member::InstanceMethodKind: - case Member::InstanceGetterKind: - case Member::InstanceSetterKind: + case Member::InstanceVariableMember: + case Member::InstanceMethodMember: + case Member::InstanceGetterMember: + case Member::InstanceSetterMember: if ( (JS2VAL_IS_OBJECT(*base) && (JS2VAL_TO_OBJECT(*base)->kind != ClassKind)) || lookupKind->isPropertyLookup()) meta->reportError(Exception::propertyAccessError, "Illegal access to instance member", meta->engine->errorPos()); @@ -712,18 +713,19 @@ namespace MetaData { } return false; } - switch (m->kind) { - case Member::Forbidden: - case Member::DynamicVariableKind: - case Member::Variable: - case Member::ConstructorMethod: - case Member::Setter: - case Member::Getter: + switch (m->memberKind) { + case Member::ForbiddenMember: + case Member::DynamicVariableMember: + case Member::FrameVariableMember: + case Member::VariableMember: + case Member::ConstructorMethodMember: + case Member::SetterMember: + case Member::GetterMember: return meta->writeLocalMember(checked_cast(m), newValue, false); - case Member::InstanceVariableKind: - case Member::InstanceMethodKind: - case Member::InstanceGetterKind: - case Member::InstanceSetterKind: + case Member::InstanceVariableMember: + case Member::InstanceMethodMember: + case Member::InstanceGetterMember: + case Member::InstanceSetterMember: if ( (JS2VAL_IS_OBJECT(base) && (JS2VAL_TO_OBJECT(base)->kind != ClassKind)) || lookupKind->isPropertyLookup()) meta->reportError(Exception::propertyAccessError, "Illegal access to instance member", meta->engine->errorPos()); @@ -756,16 +758,25 @@ namespace MetaData { Member *m = meta->findCommonMember(&base, multiname, WriteAccess, false); if (m == NULL) return false; - switch (m->kind) { - case Member::Forbidden: + switch (m->memberKind) { + case Member::ForbiddenMember: meta->reportError(Exception::propertyAccessError, "It is forbidden", meta->engine->errorPos()); return false; - case Member::DynamicVariableKind: + case Member::FrameVariableMember: + { + if (checked_cast(m)->sealed) { + *result = false; + return true; + } + goto VariableMemberCommon; + } + case Member::DynamicVariableMember: { if (checked_cast(m)->sealed) { *result = false; return true; } +VariableMemberCommon: // XXX if findCommonMember returned the Binding instead, we wouldn't have to rediscover it here... JS2Object *container = JS2VAL_TO_OBJECT(meta->toObject(base)); LocalBindingMap *lMap; @@ -793,16 +804,16 @@ namespace MetaData { *result = true; return true; } - case Member::Variable: - case Member::ConstructorMethod: - case Member::Setter: - case Member::Getter: + case Member::VariableMember: + case Member::ConstructorMethodMember: + case Member::SetterMember: + case Member::GetterMember: *result = false; return true; - case Member::InstanceVariableKind: - case Member::InstanceMethodKind: - case Member::InstanceGetterKind: - case Member::InstanceSetterKind: + case Member::InstanceVariableMember: + case Member::InstanceMethodMember: + case Member::InstanceGetterMember: + case Member::InstanceSetterMember: if ( (JS2VAL_IS_OBJECT(base) && (JS2VAL_TO_OBJECT(base)->kind != ClassKind)) || lookupKind->isPropertyLookup()) { *result = false; return true; diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index f0b782d0833..8d15c1e290f 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -878,7 +878,7 @@ namespace MetaData { */ { SwitchStmtNode *sw = checked_cast(p); - uint16 swVarIndex = (checked_cast(env->getTopFrame()))->allocateTemp(); + uint16 swVarIndex = (checked_cast(env->getTopFrame()))->allocateSlot(); BytecodeContainer::LabelID defaultLabel = NotALabel; Reference *r = SetupExprNode(env, phase, sw->expr, &exprType); @@ -1125,7 +1125,7 @@ namespace MetaData { VariableBinding *vb = vs->bindings; while (vb) { if (vb->member) { // static or instance variable - if (vb->member->kind == Member::Variable) { + if (vb->member->memberKind == Member::VariableMember) { Variable *v = checked_cast(vb->member); JS2Class *type = getVariableType(v, CompilePhase, p->pos); if (JS2VAL_IS_FUTURE(v->value)) { // it's a const, execute the initializer @@ -1176,7 +1176,7 @@ namespace MetaData { } } else { - ASSERT(vb->member->kind == Member::InstanceVariableKind); + ASSERT(vb->member->memberKind == Member::InstanceVariableMember); InstanceVariable *v = checked_cast(vb->member); JS2Class *t; if (vb->type) @@ -2777,7 +2777,7 @@ doUnary: for (LocalBindingEntry::NS_Iterator i = (*rbeP)->begin(), end = (*rbeP)->end(); (i != end); i++) { LocalBindingEntry::NamespaceBinding &ns = *i; if ((ns.second->accesses & access) - && (ns.second->content->kind != LocalMember::Forbidden) + && (ns.second->content->memberKind != LocalMember::ForbiddenMember) && multiname->listContains(ns.first)) reportError(Exception::definitionError, "Duplicate definition {0}", pos, id); } @@ -2817,7 +2817,7 @@ doUnary: for (LocalBindingEntry::NS_Iterator i = (*rbeP)->begin(), end = (*rbeP)->end(); (i != end); i++) { LocalBindingEntry::NamespaceBinding &ns = *i; if ((ns.second->accesses & access) && (ns.first == *nli)) { - ASSERT(ns.second->content->kind == LocalMember::Forbidden); + ASSERT(ns.second->content->memberKind == LocalMember::ForbiddenMember); foundEntry = true; break; } @@ -2907,20 +2907,20 @@ doUnary: if (!requestedMultiname.subsetOf(definedMultiname)) reportError(Exception::definitionError, "Illegal definition", pos); bool goodKind; - switch (m->kind) { - case Member::InstanceVariableKind: - goodKind = (mOverridden->kind == Member::InstanceVariableKind); + switch (m->memberKind) { + case Member::InstanceVariableMember: + goodKind = (mOverridden->memberKind == Member::InstanceVariableMember); break; - case Member::InstanceGetterKind: - goodKind = ((mOverridden->kind == Member::InstanceVariableKind) - || (mOverridden->kind == Member::InstanceGetterKind)); + case Member::InstanceGetterMember: + goodKind = ((mOverridden->memberKind == Member::InstanceVariableMember) + || (mOverridden->memberKind == Member::InstanceGetterMember)); break; - case Member::InstanceSetterKind: - goodKind = ((mOverridden->kind == Member::InstanceVariableKind) - || (mOverridden->kind == Member::InstanceSetterKind)); + case Member::InstanceSetterMember: + goodKind = ((mOverridden->memberKind == Member::InstanceVariableMember) + || (mOverridden->memberKind == Member::InstanceSetterMember)); break; - case Member::InstanceMethodKind: - goodKind = (mOverridden->kind == Member::InstanceMethodKind); + case Member::InstanceMethodMember: + goodKind = (mOverridden->memberKind == Member::InstanceMethodMember); break; } if (mOverridden->final || !goodKind) @@ -2978,9 +2978,9 @@ doUnary: // will shadow a parameter with the same name for compatibility with ECMAScript Edition 3. // If there are multiple function definitions, the initial value is the last function definition. - DynamicVariable *JS2Metadata::defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar) + LocalMember *JS2Metadata::defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar) { - DynamicVariable *result; + LocalMember *result; FrameListIterator regionalFrameEnd = env->getRegionalEnvironment(); NonWithFrame *regionalFrame = checked_cast(*regionalFrameEnd); ASSERT((regionalFrame->kind == PackageKind) || (regionalFrame->kind == ParameterKind)); @@ -3019,7 +3019,7 @@ rescan: } else lbe = *lbeP; - result = new DynamicVariable(); + result = new FrameVariable(regionalFrame->allocateSlot()); LocalBinding *sb = new LocalBinding(ReadWriteAccess, result, true); lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(publicNamespace, sb)); } @@ -3028,9 +3028,11 @@ rescan: reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id); else { if ((bindingResult->accesses != ReadWriteAccess) - || (bindingResult->content->kind != LocalMember::DynamicVariableKind)) + || ((bindingResult->content->memberKind != LocalMember::DynamicVariableMember) + && (bindingResult->content->memberKind != LocalMember::FrameVariableMember)) reportError(Exception::definitionError, "Illegal redefinition of {0}", p->pos, id); - result = checked_cast(bindingResult->content); + + result = bindingResult->content; } // At this point a hoisted binding of the same var already exists, so there is no need to create another one } @@ -3329,7 +3331,7 @@ bool nullClass_BracketDelete(JS2Metadata *meta, js2val base, JS2Class *limit, Mu // A 'forbidden' member, used to mark hidden bindings - forbiddenMember = new LocalMember(Member::Forbidden, true); + forbiddenMember = new LocalMember(Member::ForbiddenMember, true); // needed for class instance variables etc... NamespaceList publicNamespaceList; @@ -3645,7 +3647,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... js2val superVal = getSuperObject(baseObj); if (!JS2VAL_IS_NULL(superVal) && !JS2VAL_IS_UNDEFINED(superVal)) { m = findCommonMember(&superVal, multiname, access, flat); - if ((m != NULL) && flat && (m->kind == Member::DynamicVariableKind)) + if ((m != NULL) && flat + && ((m->memberKind == Member::DynamicVariableMember) + || (m->memberKind == Member::FrameVariableMember))) m = NULL; } return m; @@ -3654,8 +3658,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... bool JS2Metadata::readInstanceMember(js2val containerVal, JS2Class *c, InstanceMember *mBase, Phase phase, js2val *rval) { InstanceMember *m = getDerivedInstanceMember(c, mBase, ReadAccess); - switch (m->kind) { - case Member::InstanceVariableKind: + switch (m->memberKind) { + case Member::InstanceVariableMember: { InstanceVariable *mv = checked_cast(m); if ((phase == CompilePhase) && !mv->immutable) @@ -3675,8 +3679,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... bool JS2Metadata::writeInstanceMember(js2val containerVal, JS2Class *c, InstanceMember *mBase, js2val newValue) { InstanceMember *m = getDerivedInstanceMember(c, mBase, WriteAccess); - switch (m->kind) { - case Member::InstanceVariableKind: + switch (m->memberKind) { + case Member::InstanceVariableMember: { InstanceVariable *mv = checked_cast(m); Slot *s = findSlot(containerVal, mv); @@ -3693,11 +3697,11 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... bool JS2Metadata::readLocalMember(LocalMember *m, Phase phase, js2val *rval) { - switch (m->kind) { - case LocalMember::Forbidden: + switch (m->memberKind) { + case LocalMember::ForbiddenMember: reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos()); break; - case LocalMember::Variable: + case LocalMember::VariableMember: { Variable *v = checked_cast(m); if ((phase == CompilePhase) && !v->immutable) @@ -3705,20 +3709,18 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... *rval = v->value; return true; } - case LocalMember::DynamicVariableKind: + case LocalMember::DynamicVariableMember: if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos()); *rval = (checked_cast(m))->value; return true; - case LocalMember::ConstructorMethod: - { - if (phase == CompilePhase) - reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos()); - *rval = (checked_cast(m))->value; - return true; - } - case LocalMember::Getter: - case LocalMember::Setter: + case LocalMember::ConstructorMethodMember: + if (phase == CompilePhase) + reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos()); + *rval = (checked_cast(m))->value; + return true; + case LocalMember::GetterMember: + case LocalMember::SetterMember: break; } NOT_REACHED("Bad member kind"); @@ -3728,12 +3730,12 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... // Write a value to the local member bool JS2Metadata::writeLocalMember(LocalMember *m, js2val newValue, bool initFlag) // phase not used? { - switch (m->kind) { - case LocalMember::Forbidden: - case LocalMember::ConstructorMethod: + switch (m->memberKind) { + case LocalMember::ForbiddenMember: + case LocalMember::ConstructorMethodMember: reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos()); break; - case LocalMember::Variable: + case LocalMember::VariableMember: { Variable *v = checked_cast(m); if (!initFlag @@ -3746,11 +3748,11 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... v->value = v->type->implicitCoerce(this, newValue); } return true; - case LocalMember::DynamicVariableKind: + case LocalMember::DynamicVariableMember: (checked_cast(m))->value = newValue; return true; - case LocalMember::Getter: - case LocalMember::Setter: + case LocalMember::GetterMember: + case LocalMember::SetterMember: break; } NOT_REACHED("Bad member kind"); @@ -4272,14 +4274,14 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... * ************************************************************************************/ - // Allocate a new temporary variable in this frame and stick it + // Allocate a new value slot in this frame and stick it // on the list (which may need to be created) for gc tracking. - uint16 NonWithFrame::allocateTemp() + uint16 NonWithFrame::allocateSlot() { - if (temps == NULL) - temps = new std::vector; - uint16 result = (uint16)(temps->size()); - temps->push_back(JS2VAL_VOID); + if (slots == NULL) + slots = new std::vector; + uint16 result = (uint16)(slots->size()); + slots->push_back(JS2VAL_VOID); return result; } @@ -4293,6 +4295,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... } delete lbe; } + if (slots) + delete slots; } // gc-mark all contained JS2Objects and visit contained structures to do likewise @@ -4306,8 +4310,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... ns.second->content->mark(); } } - if (temps) { - for (std::vector::iterator i = temps->begin(), end = temps->end(); (i != end); i++) + if (slots) { + for (std::vector::iterator i = slots->begin(), end = slots->end(); (i != end); i++) GCMARKVALUE(*i); } } @@ -4374,7 +4378,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... for (i = 0; (i < argCount); i++) { if (i < plural->positionalCount) { ASSERT(plural->positional[i]->cloneContent); - ASSERT(plural->positional[i]->cloneContent->kind == Member::Variable); + ASSERT(plural->positional[i]->cloneContent->memberKind == Member::VariableMember); (checked_cast(plural->positional[i]->cloneContent))->value = argBase[i]; } meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->arrayClass, meta->engine->numberToString(i), true, argBase[i]); @@ -4382,7 +4386,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... while (i++ < length) { if (i < plural->positionalCount) { ASSERT(plural->positional[i]->cloneContent); - ASSERT(plural->positional[i]->cloneContent->kind == Member::Variable); + ASSERT(plural->positional[i]->cloneContent->memberKind == Member::VariableMember); (checked_cast(plural->positional[i]->cloneContent))->value = JS2VAL_UNDEFINED; } meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->arrayClass, meta->engine->numberToString(i), true, JS2VAL_UNDEFINED); diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 62483eb7b61..7c32fd38ee6 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -380,11 +380,22 @@ class Signature { // A base class for Instance and Local members for convenience. class Member { public: - enum MemberKind { Forbidden, DynamicVariableKind, Variable, ConstructorMethod, Setter, Getter, InstanceVariableKind, InstanceMethodKind, InstanceGetterKind, InstanceSetterKind }; + enum MemberKind { + ForbiddenMember, + DynamicVariableMember, + FrameVariableMember, + VariableMember, + ConstructorMethodMember, + SetterMember, + GetterMember, + InstanceVariableMember, + InstanceMethodMember, + InstanceGetterMember, + InstanceSetterMember }; - Member(MemberKind kind) : kind(kind) { } + Member(MemberKind kind) : memberKind(kind) { } virtual ~Member() { } - MemberKind kind; + MemberKind memberKind; virtual void mark() { } @@ -412,8 +423,9 @@ public: class Variable : public LocalMember { public: - Variable() : LocalMember(Member::Variable), type(NULL), value(JS2VAL_VOID), immutable(false), vb(NULL) { } - Variable(JS2Class *type, js2val value, bool immutable) : LocalMember(LocalMember::Variable), type(type), value(value), immutable(immutable), vb(NULL) { } + Variable() : LocalMember(Member::VariableMember), type(NULL), value(JS2VAL_VOID), immutable(false), vb(NULL) { } + Variable(JS2Class *type, js2val value, bool immutable) + : LocalMember(LocalMember::VariableMember), type(type), value(value), immutable(immutable), vb(NULL) { } virtual LocalMember *clone() { return new Variable(type, value, immutable); } @@ -430,8 +442,8 @@ public: class DynamicVariable : public LocalMember { public: - DynamicVariable() : LocalMember(Member::DynamicVariableKind), value(JS2VAL_UNDEFINED), sealed(false) { } - DynamicVariable(js2val value, bool sealed) : LocalMember(Member::DynamicVariableKind), value(value), sealed(sealed) { } + DynamicVariable() : LocalMember(Member::DynamicVariableMember), value(JS2VAL_UNDEFINED), sealed(false) { } + DynamicVariable(js2val value, bool sealed) : LocalMember(Member::DynamicVariableMember), value(value), sealed(sealed) { } js2val value; // This variable's current value // XXX may be an uninstantiated function at compile time @@ -441,10 +453,20 @@ public: virtual void mark() { GCMARKVALUE(value); } }; +class FrameVariable : public LocalMember { +public: + FrameVariable(uint16 frameSlot) : LocalMember(Member::FrameVariableMember), frameSlot(frameSlot), sealed(false) { } + + uint16 frameSlot; + + bool sealed; // true if this variable cannot be deleted using the delete operator + virtual LocalMember *clone() { return new FrameVariable(frameSlot); } +}; + class ConstructorMethod : public LocalMember { public: - ConstructorMethod() : LocalMember(Member::ConstructorMethod), value(JS2VAL_VOID) { } - ConstructorMethod(js2val value) : LocalMember(Member::ConstructorMethod), value(value) { } + ConstructorMethod() : LocalMember(Member::ConstructorMethodMember), value(JS2VAL_VOID) { } + ConstructorMethod(js2val value) : LocalMember(Member::ConstructorMethodMember), value(value) { } js2val value; // This constructor itself (a callable object) @@ -453,7 +475,7 @@ public: class Getter : public LocalMember { public: - Getter() : LocalMember(Member::Getter), type(NULL), code(NULL) { } + Getter() : LocalMember(Member::GetterMember), type(NULL), code(NULL) { } JS2Class *type; // The type of the value read from this getter Invokable *code; // calling this object does the read @@ -463,7 +485,7 @@ public: class Setter : public LocalMember { public: - Setter() : LocalMember(Member::Setter), type(NULL), code(NULL) { } + Setter() : LocalMember(Member::SetterMember), type(NULL), code(NULL) { } JS2Class *type; // The type of the value written into the setter Invokable *code; // calling this object does the write @@ -494,7 +516,8 @@ public: class InstanceMember : public Member { public: - InstanceMember(MemberKind kind, Multiname *multiname, bool final, bool enumerable) : Member(kind), multiname(multiname), final(final), enumerable(enumerable) { } + InstanceMember(MemberKind kind, Multiname *multiname, bool final, bool enumerable) + : Member(kind), multiname(multiname), final(final), enumerable(enumerable) { } virtual ~InstanceMember() { } @@ -508,7 +531,8 @@ public: class InstanceVariable : public InstanceMember { public: - InstanceVariable(Multiname *multiname, JS2Class *type, bool immutable, bool final, bool enumerable, uint32 slotIndex) : InstanceMember(InstanceVariableKind, multiname, final, enumerable), type(type), immutable(immutable), slotIndex(slotIndex) { } + InstanceVariable(Multiname *multiname, JS2Class *type, bool immutable, bool final, bool enumerable, uint32 slotIndex) + : InstanceMember(InstanceVariableMember, multiname, final, enumerable), type(type), immutable(immutable), slotIndex(slotIndex) { } Invokable *evalInitialValue; // A function that computes this variable's initial value JS2Class *type; // Type of values that may be stored in this variable bool immutable; // true if this variable's value may not be changed once set @@ -519,7 +543,8 @@ public: class InstanceMethod : public InstanceMember { public: - InstanceMethod(Multiname *multiname, SimpleInstance *fInst, bool final, bool enumerable) : InstanceMember(InstanceMethodKind, multiname, final, enumerable), fInst(fInst) { } + InstanceMethod(Multiname *multiname, SimpleInstance *fInst, bool final, bool enumerable) + : InstanceMember(InstanceMethodMember, multiname, final, enumerable), fInst(fInst) { } Signature type; // This method's signature // Invokable *code; // This method itself (a callable object); null if this method is abstract SimpleInstance *fInst; @@ -530,7 +555,8 @@ public: class InstanceGetter : public InstanceMember { public: - InstanceGetter(Multiname *multiname, Invokable *code, JS2Class *type, bool final, bool enumerable) : InstanceMember(InstanceGetterKind, multiname, final, enumerable), code(code), type(type) { } + InstanceGetter(Multiname *multiname, Invokable *code, JS2Class *type, bool final, bool enumerable) + : InstanceMember(InstanceGetterMember, multiname, final, enumerable), code(code), type(type) { } Invokable *code; // A callable object which does the read or write; null if this method is abstract JS2Class *type; // Type of values that may be stored in this variable @@ -539,7 +565,8 @@ public: class InstanceSetter : public InstanceMember { public: - InstanceSetter(Multiname *multiname, Invokable *code, JS2Class *type, bool final, bool enumerable) : InstanceMember(InstanceSetterKind, multiname, final, enumerable), code(code), type(type) { } + InstanceSetter(Multiname *multiname, Invokable *code, JS2Class *type, bool final, bool enumerable) + : InstanceMember(InstanceSetterMember, multiname, final, enumerable), code(code), type(type) { } Invokable *code; // A callable object which does the read or write; null if this method is abstract JS2Class *type; // Type of values that may be stored in this variable @@ -619,17 +646,17 @@ public: class NonWithFrame : public Frame { public: - NonWithFrame(ObjectKind kind) : Frame(kind), temps(NULL), pluralFrame(NULL) { } - NonWithFrame(ObjectKind kind, NonWithFrame *pluralFrame) : Frame(kind), temps(NULL), pluralFrame(pluralFrame) { } + NonWithFrame(ObjectKind kind) : Frame(kind), slots(NULL), pluralFrame(NULL) { } + NonWithFrame(ObjectKind kind, NonWithFrame *pluralFrame) : Frame(kind), slots(NULL), pluralFrame(pluralFrame) { } - LocalBindingMap localBindings; // Map of qualified names to members defined in this frame + LocalBindingMap localBindings; // Map of qualified names to members defined in this frame - std::vector *temps; // temporaries allocted in this frame - uint16 allocateTemp(); + std::vector *slots; // temporaries allocted in this frame + uint16 allocateSlot(); virtual void instantiate(Environment * /*env*/) { ASSERT(false); } - NonWithFrame *pluralFrame; // for a singular frame, this is the plural frame from which it will be instantiated + NonWithFrame *pluralFrame; // for a singular frame, this is the plural frame from which it will be instantiated virtual void markChildren(); virtual ~NonWithFrame(); @@ -769,7 +796,7 @@ public: BytecodeContainer *bCon; NativeCode *code; - bool unchecked; // true if the function is untyped, non-method, normal + bool unchecked; // true if the function is untyped, non-method, normal ParameterFrame *compileFrame; Environment *env; }; @@ -780,13 +807,13 @@ class SimpleInstance : public JS2Object { public: SimpleInstance(JS2Metadata *meta, js2val parent, JS2Class *type); - LocalBindingMap localBindings; + LocalBindingMap localBindings; // Map of qualified names to local properties (including dynamic properties, if any) js2val super; // Optional link to the next object in this instance's prototype chain - bool sealed; + bool sealed; // If true, no more local properties may be added to this instance JS2Class *type; // This instance's type Slot *slots; // A set of slots that hold this instance's fixed property values - FunctionWrapper *fWrap; + FunctionWrapper *fWrap; virtual void markChildren(); virtual ~SimpleInstance(); diff --git a/mozilla/js2/src/js2op_access.cpp b/mozilla/js2/src/js2op_access.cpp index ead642609a3..1a650fd767a 100644 --- a/mozilla/js2/src/js2op_access.cpp +++ b/mozilla/js2/src/js2op_access.cpp @@ -263,7 +263,16 @@ pc += sizeof(short); NonWithFrame *f = checked_cast(meta->env->getTopFrame()); a = pop(); - (*f->temps)[slotIndex] = a; + (*f->slots)[slotIndex] = a; + } + break; + + case eFrameSlotDelete: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + NonWithFrame *f = checked_cast(meta->env->getTopFrame()); + // XXX some kind of code here? } break; @@ -272,7 +281,7 @@ uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); NonWithFrame *f = checked_cast(meta->env->getTopFrame()); - push((*f->temps)[slotIndex]); + push((*f->slots)[slotIndex]); } break; diff --git a/mozilla/js2/src/js2op_arithmetic.cpp b/mozilla/js2/src/js2op_arithmetic.cpp index c13ac76f4fd..414f3b67e91 100644 --- a/mozilla/js2/src/js2op_arithmetic.cpp +++ b/mozilla/js2/src/js2op_arithmetic.cpp @@ -1149,3 +1149,48 @@ baseVal = JS2VAL_VOID; } break; + + case eFrameSlotPostInc: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + NonWithFrame *f = checked_cast(meta->env->getTopFrame()); + a = (*f->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + (*f->slots)[slotIndex] = allocNumber(num + 1.0); + pushNumber(num); + } + break; + case eFrameSlotPostDec: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + NonWithFrame *f = checked_cast(meta->env->getTopFrame()); + a = (*f->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + (*f->slots)[slotIndex] = allocNumber(num - 1.0); + pushNumber(num); + } + break; + case eFrameSlotPreInc: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + NonWithFrame *f = checked_cast(meta->env->getTopFrame()); + a = (*f->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + a = pushNumber(num + 1.0); + (*f->slots)[slotIndex] = a; + } + break; + case eFrameSlotPreDec: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + NonWithFrame *f = checked_cast(meta->env->getTopFrame()); + a = (*f->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + a = pushNumber(num - 1.0); + (*f->slots)[slotIndex] = a; + } + break;