diff --git a/js2/src/js2engine.cpp b/js2/src/js2engine.cpp index cacef76b65c5..4626111e4dd8 100644 --- a/js2/src/js2engine.cpp +++ b/js2/src/js2engine.cpp @@ -66,6 +66,7 @@ namespace MetaData { // Begin execution of a bytecodeContainer js2val JS2Engine::interpret(Phase execPhase, BytecodeContainer *targetbCon, Environment *env) { + packageFrame = env->getPackageFrame(); jsr(execPhase, targetbCon, sp - execStack, JS2VAL_VOID, env); ActivationFrame *f = activationStackTop; js2val result; @@ -508,18 +509,33 @@ namespace MetaData { { eNext, "Next", 0 }, { eForValue, "ForValue", 0 }, - { eFrameSlotRead, "FrameSlotRead", U16 }, // - { eFrameSlotWrite, "FrameSlotWrite", U16 }, // + { eFrameSlotRead, "FrameSlotRead", U16 }, // + { eFrameSlotRef, "FrameSlotRef", U16 }, // + { eFrameSlotWrite, "FrameSlotWrite", U16 }, // + { eFrameSlotDelete, "FrameSlotDelete", U16 }, // + { eFrameSlotPostInc, "FrameSlotPostInc", U16 }, // + { eFrameSlotPostDec, "FrameSlotPostDec", U16 }, // + { eFrameSlotPreInc, "FrameSlotPreInc", U16 }, // + { eFrameSlotPreDec, "FrameSlotPreDec", U16 }, // + + { ePackageSlotRead, "PackageSlotRead", U16 }, // + { ePackageSlotRef, "PackageSlotRef", U16 }, // + { ePackageSlotWrite, "PackageSlotWrite", U16 }, // + { ePackageSlotDelete, "PackageSlotDelete", U16 }, // + { ePackageSlotPostInc, "PackageSlotPostInc", U16 }, // + { ePackageSlotPostDec, "PackageSlotPostDec", U16 }, // + { ePackageSlotPreInc, "PackageSlotPreInc", U16 }, // + { ePackageSlotPreDec, "PackageSlotPreDec", U16 }, // { eLexicalRead, "LexicalRead", NAME_INDEX }, // - { eLexicalWrite, "LexicalWrite", NAME_INDEX }, // - { eLexicalInit, "LexicalInit", NAME_INDEX }, // - { eLexicalRef, "LexicalRef", NAME_INDEX }, // - { eLexicalDelete, "LexicalDelete", NAME_INDEX }, // - { eDotRead, "DotRead", NAME_INDEX }, // - { eDotWrite, "DotWrite", NAME_INDEX }, // - { eDotRef, "DotRef", NAME_INDEX }, // - { eDotDelete, "DotDelete", NAME_INDEX }, // + { eLexicalWrite, "LexicalWrite", NAME_INDEX }, // + { eLexicalInit, "LexicalInit", NAME_INDEX }, // + { eLexicalRef, "LexicalRef", NAME_INDEX }, // + { eLexicalDelete, "LexicalDelete", NAME_INDEX }, // + { eDotRead, "DotRead", NAME_INDEX }, // + { eDotWrite, "DotWrite", NAME_INDEX }, // + { eDotRef, "DotRef", NAME_INDEX }, // + { eDotDelete, "DotDelete", NAME_INDEX }, // { eBracketRead, "BracketRead", 0 }, { eBracketWrite, "BracketWrite", 0 }, { eBracketRef, "BracketRef", 0 }, @@ -760,6 +776,19 @@ namespace MetaData { case eLexicalDelete: return 1; // push boolean result + case eFrameSlotRead: + case ePackageSlotRead: + return 1; // push value + case eFrameSlotWrite: + case ePackageSlotWrite: + return 0; // leaves value on stack + case eFrameSlotRef: + case ePackageSlotRef: + return 2; // push base and value + case eFrameSlotDelete: + case ePackageSlotDelete: + return 1; // push boolean result; + case eDotRead: return 0; // pop a base, push the value case eDotWrite: @@ -822,16 +851,21 @@ namespace MetaData { case eForValue: // leave the iterator helper return 1; // and push iteration value - case eFrameSlotRead: - return 1; // push value - case eFrameSlotWrite: - return -1; // doesn't leave value on stack + case eFrameSlotPostInc: + case eFrameSlotPostDec: + case eFrameSlotPreInc: + case eFrameSlotPreDec: + case ePackageSlotPostInc: + case ePackageSlotPostDec: + case ePackageSlotPreInc: + case ePackageSlotPreDec: + return 1; // push the new/old value case eLexicalPostInc: case eLexicalPostDec: case eLexicalPreInc: case eLexicalPreDec: - return 1; // push the new/old value + return 1; // push the new/old value case eDotPostInc: case eDotPostDec: @@ -887,6 +921,7 @@ namespace MetaData { activationStackTop->env = meta->env; // save current environment, to be restored on rts activationStackTop->newEnv = env; // and save the new environment, if an exception occurs, we can't depend on meta->env activationStackTop->topFrame = env->getTopFrame(); // remember how big the new env. is supposed to be so that local frames don't accumulate + localFrame = checked_cast(activationStackTop->topFrame); activationStackTop++; if (new_bCon) { bCon = new_bCon; diff --git a/js2/src/js2engine.h b/js2/src/js2engine.h index 6f125cb323bb..499c14fb2891 100644 --- a/js2/src/js2engine.h +++ b/js2/src/js2engine.h @@ -106,6 +106,15 @@ enum JS2Op { eFrameSlotPreInc, // eFrameSlotPreDec, // + ePackageSlotRead, // + ePackageSlotRef, // + ePackageSlotWrite, // + ePackageSlotDelete, // + ePackageSlotPostInc, // + ePackageSlotPostDec, // + ePackageSlotPreInc, // + ePackageSlotPreDec, // + eLexicalRead, // eLexicalWrite, // eLexicalInit, // @@ -170,6 +179,7 @@ enum JS2Op { class Frame; +class NonWithFrame; class ParameterFrame; class Environment; @@ -332,6 +342,10 @@ public: std::stack mTryStack; std::stack finallyStack; + // For frame slot references: + NonWithFrame *packageFrame; + NonWithFrame *localFrame; + void pushHandler(uint8 *pc); void popHandler(); diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index 8d15c1e290fd..7926f081125a 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -439,8 +439,7 @@ namespace MetaData { && ((topFrame->kind == PackageKind) || (topFrame->kind == BlockFrameKind) || (topFrame->kind == ParameterKind)) ) { - DynamicVariable *v = defineHoistedVar(env, f->function.name, p, false); - v->value = OBJECT_TO_JS2VAL(fObj); + LocalMember *v = defineHoistedVar(env, f->function.name, p, false, OBJECT_TO_JS2VAL(fObj)); } else { Variable *v = new Variable(functionClass, OBJECT_TO_JS2VAL(fObj), true); @@ -500,7 +499,7 @@ namespace MetaData { && !immutable && (vs->attributes == NULL) && (vb->type == NULL)) { - defineHoistedVar(env, name, p, true); + defineHoistedVar(env, name, p, true, JS2VAL_UNDEFINED); } else { a = Attribute::toCompoundAttribute(attr); @@ -517,7 +516,7 @@ namespace MetaData { // Set type to FUTURE_TYPE - it will be resolved during 'Setup'. The value is either FUTURE_VALUE // for 'const' - in which case the expression is compile time evaluated (or attempted) or set // to INACCESSIBLE until run time initialization occurs. - Variable *v = new Variable(FUTURE_TYPE, immutable ? JS2VAL_FUTUREVALUE : JS2VAL_INACCESSIBLE, immutable); + Variable *v = new Variable(FUTURE_TYPE, immutable ? JS2VAL_FUTUREVALUE : JS2VAL_FUTUREVALUE, immutable); vb->member = v; v->vb = vb; vb->mn = defineLocalMember(env, name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos, true); @@ -2058,54 +2057,97 @@ doUnary: returnRef = new (*referenceArena) LexicalReference(&i->name, cxt.strict); referenceArena->registerDestructor(returnRef); ((LexicalReference *)returnRef)->variableMultiname.addNamespace(cxt); -#if 0 // Try to find this identifier at compile time, we have to stop if we reach // a frame that supports dynamic properties - the identifier could be // created at runtime without us finding it here. + // We're looking to find both the type of the reference (to store into exprType) + // and to see if we can change the reference to a FrameSlot or Slot (for member + // functions) Multiname *multiname = &((LexicalReference *)returnRef)->variableMultiname; FrameListIterator fi = env->getBegin(); - while (fi != env->getEnd()) { + bool keepLooking = true; + while (fi != env->getEnd() && keepLooking) { Frame *fr = *fi; if (fr->kind == WithFrameKind) // XXX unless it's provably not a dynamic object that been with'd?? break; - NonWithFrame *pf = checked_cast(*fi); - if (pf->kind != ClassKind) { - LocalMember *m = findFlatMember(pf, multiname, ReadAccess, CompilePhase); - if (m && m->kind == Member::Variable) { - *exprType = checked_cast(m)->type; - break; - } - if (pf->kind == PackageKind) - break; - } - else { - JS2Class *c = checked_cast(pf); - MemberDescriptor m2; - if (findLocalMember(c, multiname, ReadAccess, CompilePhase, &m2) - && m2.localMember) { - if (m2.localMember->kind == LocalMember::Variable) - *exprType = checked_cast(m2.localMember)->type; - break; - } - if (m2.ns) { // an instance member - QualifiedName qname(m2.ns, multiname->name); - InstanceMember *m = findInstanceMember(c, &qname, ReadAccess); + NonWithFrame *pf = checked_cast(fr); + switch (pf->kind) { + default: + keepLooking = false; + break; + case BlockFrameKind: + { + LocalMember *m = findLocalMember(pf, multiname, ReadAccess); if (m) { - if (m->kind == InstanceMember::InstanceVariableKind) - *exprType = checked_cast(m)->type; + switch (checked_cast(m)->memberKind) { + case LocalMember::VariableMember: + *exprType = checked_cast(m)->type; + break; + case LocalMember::FrameVariableMember: + ASSERT(!checked_cast(m)->packageSlot); + returnRef = new (*referenceArena) FrameSlotReference(checked_cast(m)->frameSlot); + break; + } break; + keepLooking = false; } - else - break; // XXX Shouldn't findLocalMember guarantee this not possible? } - else - break; - // XXX ok to keep going? Suppose the class allows dynamic properties? + break; + case ClassKind: + { + // look for this identifier in the static members + // (do we have a this?) + // If the class allows dynamic members, have to stop the search here + keepLooking = false; + } + break; + case PackageKind: + { + JS2Class *limit = objectType(pf); + InstanceMember *mBase = findBaseInstanceMember(limit, multiname, ReadAccess); + if (mBase) + // XXX *exprType = mBase->... + keepLooking = false; + else { + js2val base = OBJECT_TO_JS2VAL(pf); + Member *m = findCommonMember(&base, multiname, ReadAccess, false); + if (m) { + switch (m->memberKind) { + case Member::ForbiddenMember: + case Member::DynamicVariableMember: + case Member::FrameVariableMember: + case Member::VariableMember: + case Member::ConstructorMethodMember: + case Member::SetterMember: + case Member::GetterMember: + switch (checked_cast(m)->memberKind) { + case LocalMember::VariableMember: + *exprType = checked_cast(m)->type; + break; + case LocalMember::FrameVariableMember: + ASSERT(checked_cast(m)->packageSlot); + returnRef = new (*referenceArena) PackageSlotReference(checked_cast(m)->frameSlot); + break; + } + break; + case Member::InstanceVariableMember: + case Member::InstanceMethodMember: + case Member::InstanceGetterMember: + case Member::InstanceSetterMember: + // XXX checked_cast(m) + break; + } + keepLooking = false; + } + } + // XXX if package allows dynamic members, stop looking + keepLooking = false; + } + break; } fi++; } -#endif } break; case ExprNode::Delete: @@ -2630,7 +2672,12 @@ doUnary: LocalBindingEntry *lbe = *bi2; singularFrame->localBindings.insert(lbe->name, lbe->clone()); } - + if (pluralFrame->slots) { + size_t count = pluralFrame->slots->size(); + singularFrame->slots = new std::vector(count); + for (size_t i = 0; i < count; i++) + (*singularFrame->slots)[i] = (*pluralFrame->slots)[i]; + } } // need to mark all the frames in the environment - otherwise a marked frame that @@ -2978,13 +3025,12 @@ 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. - LocalMember *JS2Metadata::defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar) + LocalMember *JS2Metadata::defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar, js2val initVal) { - LocalMember *result; + LocalMember *result = NULL; FrameListIterator regionalFrameEnd = env->getRegionalEnvironment(); NonWithFrame *regionalFrame = checked_cast(*regionalFrameEnd); - ASSERT((regionalFrame->kind == PackageKind) || (regionalFrame->kind == ParameterKind)); - + ASSERT((regionalFrame->kind == PackageKind) || (regionalFrame->kind == ParameterKind)); rescan: // run through all the existing bindings, to see if this variable already exists. LocalBinding *bindingResult = NULL; @@ -3019,7 +3065,8 @@ rescan: } else lbe = *lbeP; - result = new FrameVariable(regionalFrame->allocateSlot()); + result = new FrameVariable(regionalFrame->allocateSlot(), (regionalFrame->kind == PackageKind)); + (*regionalFrame->slots)[checked_cast(result)->frameSlot] = initVal; LocalBinding *sb = new LocalBinding(ReadWriteAccess, result, true); lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(publicNamespace, sb)); } @@ -3029,14 +3076,15 @@ rescan: else { if ((bindingResult->accesses != ReadWriteAccess) || ((bindingResult->content->memberKind != LocalMember::DynamicVariableMember) - && (bindingResult->content->memberKind != LocalMember::FrameVariableMember)) + && (bindingResult->content->memberKind != LocalMember::FrameVariableMember))) reportError(Exception::definitionError, "Illegal redefinition of {0}", p->pos, id); - - result = bindingResult->content; + else { + result = bindingResult->content; + writeLocalMember(result, initVal, true); + } } // At this point a hoisted binding of the same var already exists, so there is no need to create another one } - return result; } @@ -3551,14 +3599,15 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... return result; } - InstanceMember *JS2Metadata::findBaseInstanceMember(JS2Class *limit, Multiname *multiname, Access access) + // Start from the root class (Object) and proceed through more specific classes that are ancestors of c + InstanceMember *JS2Metadata::findBaseInstanceMember(JS2Class *c, Multiname *multiname, Access access) { InstanceMember *result = NULL; - if (limit->super) { - result = findBaseInstanceMember(limit->super, multiname, access); + if (c->super) { + result = findBaseInstanceMember(c->super, multiname, access); if (result) return result; } - return findLocalInstanceMember(limit, multiname, access); + return findLocalInstanceMember(c, multiname, access); } // getDerivedInstanceMember returns the most derived instance member whose name includes that of mBase and @@ -3709,6 +3758,20 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... *rval = v->value; return true; } + case LocalMember::FrameVariableMember: + { + if (phase == CompilePhase) + reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos()); + FrameVariable *f = checked_cast(m); + if (f->packageSlot) + *rval = (*env->getPackageFrame()->slots)[f->frameSlot]; + else { + FrameListIterator fi = env->getRegionalFrame(); + ASSERT((*fi)->kind == ParameterKind); + *rval = (*checked_cast(*(fi - 1))->slots)[f->frameSlot]; + } + } + return true; case LocalMember::DynamicVariableMember: if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos()); @@ -3741,13 +3804,25 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... if (!initFlag && (JS2VAL_IS_INACCESSIBLE(v->value) || (v->immutable && !JS2VAL_IS_UNINITIALIZED(v->value)))) - if (flags == JS2) + if (!cxt.E3compatibility) 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; + case LocalMember::FrameVariableMember: + { + FrameVariable *f = checked_cast(m); + if (f->packageSlot) + (*env->getPackageFrame()->slots)[f->frameSlot] = newValue; + else { + FrameListIterator fi = env->getRegionalFrame(); + ASSERT((*fi)->kind == ParameterKind); + (*checked_cast(*(fi - 1))->slots)[f->frameSlot] = newValue; + } + } + return true; case LocalMember::DynamicVariableMember: (checked_cast(m))->value = newValue; return true; diff --git a/js2/src/js2metadata.h b/js2/src/js2metadata.h index 7c32fd38ee6b..b4b1f5fdb143 100644 --- a/js2/src/js2metadata.h +++ b/js2/src/js2metadata.h @@ -455,12 +455,13 @@ public: class FrameVariable : public LocalMember { public: - FrameVariable(uint16 frameSlot) : LocalMember(Member::FrameVariableMember), frameSlot(frameSlot), sealed(false) { } + FrameVariable(uint16 frameSlot, bool packageSlot) : LocalMember(Member::FrameVariableMember), frameSlot(frameSlot), packageSlot(packageSlot), sealed(false) { } uint16 frameSlot; + bool packageSlot; // true if the variable is in a package frame bool sealed; // true if this variable cannot be deleted using the delete operator - virtual LocalMember *clone() { return new FrameVariable(frameSlot); } + virtual LocalMember *clone() { return new FrameVariable(frameSlot, packageSlot); } }; class ConstructorMethod : public LocalMember { @@ -651,7 +652,7 @@ public: LocalBindingMap localBindings; // Map of qualified names to members defined in this frame - std::vector *slots; // temporaries allocted in this frame + std::vector *slots; // temporaries or frame variables allocted in this frame uint16 allocateSlot(); virtual void instantiate(Environment * /*env*/) { ASSERT(false); } @@ -1067,6 +1068,52 @@ public: virtual int hasStackEffect() { return 1; } }; +class FrameSlotReference : public Reference { +// A special case of a DotReference with an FrameSl instead of a D +public: + FrameSlotReference(uint32 slotIndex) : slotIndex(slotIndex) { } + virtual ~FrameSlotReference() { } + + virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotRead, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotWrite, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitReadForInvokeBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotRef, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitReadForWriteBackBytecode(BytecodeContainer *bCon, size_t pos) { emitReadForInvokeBytecode(bCon, pos); } + virtual void emitWriteBackBytecode(BytecodeContainer *bCon, size_t pos) { emitWriteBytecode(bCon, pos); } + + virtual void emitPostIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotPostInc, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitPostDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotPostDec, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitPreIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotPreInc, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitPreDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFrameSlotPreDec, pos); bCon->addShort((uint16)slotIndex); } + + virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFalse, pos); /* bCon->emitOp(eFrameSlotDelete, pos); bCon->addShort((uint16)slotIndex); */ } + + uint32 slotIndex; + virtual int hasStackEffect() { return 0; } +}; + +class PackageSlotReference : public Reference { +// A special case of a DotReference with an PackageSl instead of a D +public: + PackageSlotReference(uint32 slotIndex) : slotIndex(slotIndex) { } + virtual ~PackageSlotReference() { } + + virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotRead, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotWrite, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitReadForInvokeBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotRef, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitReadForWriteBackBytecode(BytecodeContainer *bCon, size_t pos) { emitReadForInvokeBytecode(bCon, pos); } + virtual void emitWriteBackBytecode(BytecodeContainer *bCon, size_t pos) { emitWriteBytecode(bCon, pos); } + + virtual void emitPostIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotPostInc, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitPostDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotPostDec, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitPreIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotPreInc, pos); bCon->addShort((uint16)slotIndex); } + virtual void emitPreDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(ePackageSlotPreDec, pos); bCon->addShort((uint16)slotIndex); } + + virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eFalse, pos); /* bCon->emitOp(ePackageSlotDelete, pos); bCon->addShort((uint16)slotIndex); */ } + + uint32 slotIndex; + virtual int hasStackEffect() { return 0; } +}; + class NamedArgument { public: @@ -1260,7 +1307,7 @@ public: LocalMember *findFlatMember(NonWithFrame *container, Multiname *multiname, Access access, Phase phase); InstanceBinding *resolveInstanceMemberName(JS2Class *js2class, Multiname *multiname, Access access, Phase phase, QualifiedName *qname); - DynamicVariable *defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar); + LocalMember *defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar, js2val initVal); Multiname *defineLocalMember(Environment *env, const String *id, NamespaceList &namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, LocalMember *m, size_t pos, bool enumerable); InstanceMember *defineInstanceMember(JS2Class *c, Context *cxt, const String *id, NamespaceList &namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, diff --git a/js2/src/js2op_access.cpp b/js2/src/js2op_access.cpp index 1a650fd767a3..ecaa06ef7892 100644 --- a/js2/src/js2op_access.cpp +++ b/js2/src/js2op_access.cpp @@ -261,9 +261,8 @@ { uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); - NonWithFrame *f = checked_cast(meta->env->getTopFrame()); - a = pop(); - (*f->slots)[slotIndex] = a; + a = top(); + (*localFrame->slots)[slotIndex] = a; } break; @@ -271,7 +270,6 @@ { uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); - NonWithFrame *f = checked_cast(meta->env->getTopFrame()); // XXX some kind of code here? } break; @@ -280,8 +278,32 @@ { uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); - NonWithFrame *f = checked_cast(meta->env->getTopFrame()); - push((*f->slots)[slotIndex]); + push((*localFrame->slots)[slotIndex]); + } + break; + + case ePackageSlotWrite: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + a = top(); + (*packageFrame->slots)[slotIndex] = a; + } + break; + + case ePackageSlotDelete: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + // XXX some kind of code here? + } + break; + + case ePackageSlotRead: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + push((*packageFrame->slots)[slotIndex]); } break; diff --git a/js2/src/js2op_arithmetic.cpp b/js2/src/js2op_arithmetic.cpp index 414f3b67e91c..84196ed7beb0 100644 --- a/js2/src/js2op_arithmetic.cpp +++ b/js2/src/js2op_arithmetic.cpp @@ -1154,10 +1154,9 @@ { uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); - NonWithFrame *f = checked_cast(meta->env->getTopFrame()); - a = (*f->slots)[slotIndex]; + a = (*localFrame->slots)[slotIndex]; float64 num = meta->toFloat64(a); - (*f->slots)[slotIndex] = allocNumber(num + 1.0); + (*localFrame->slots)[slotIndex] = allocNumber(num + 1.0); pushNumber(num); } break; @@ -1165,10 +1164,9 @@ { uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); - NonWithFrame *f = checked_cast(meta->env->getTopFrame()); - a = (*f->slots)[slotIndex]; + a = (*localFrame->slots)[slotIndex]; float64 num = meta->toFloat64(a); - (*f->slots)[slotIndex] = allocNumber(num - 1.0); + (*localFrame->slots)[slotIndex] = allocNumber(num - 1.0); pushNumber(num); } break; @@ -1176,21 +1174,60 @@ { uint16 slotIndex = BytecodeContainer::getShort(pc); pc += sizeof(short); - NonWithFrame *f = checked_cast(meta->env->getTopFrame()); - a = (*f->slots)[slotIndex]; + a = (*localFrame->slots)[slotIndex]; float64 num = meta->toFloat64(a); a = pushNumber(num + 1.0); - (*f->slots)[slotIndex] = a; + (*localFrame->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]; + a = (*localFrame->slots)[slotIndex]; float64 num = meta->toFloat64(a); a = pushNumber(num - 1.0); - (*f->slots)[slotIndex] = a; + (*localFrame->slots)[slotIndex] = a; + } + break; + + case ePackageSlotPostInc: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + a = (*packageFrame->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + (*packageFrame->slots)[slotIndex] = allocNumber(num + 1.0); + pushNumber(num); + } + break; + case ePackageSlotPostDec: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + a = (*packageFrame->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + (*packageFrame->slots)[slotIndex] = allocNumber(num - 1.0); + pushNumber(num); + } + break; + case ePackageSlotPreInc: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + a = (*packageFrame->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + a = pushNumber(num + 1.0); + (*packageFrame->slots)[slotIndex] = a; + } + break; + case ePackageSlotPreDec: + { + uint16 slotIndex = BytecodeContainer::getShort(pc); + pc += sizeof(short); + a = (*packageFrame->slots)[slotIndex]; + float64 num = meta->toFloat64(a); + a = pushNumber(num - 1.0); + (*packageFrame->slots)[slotIndex] = a; } break;