зеркало из https://github.com/mozilla/gecko-dev.git
Switching to frame & package slot mechanism.
This commit is contained in:
Родитель
4dba4eaf22
Коммит
1b01f15f8e
|
@ -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;
|
||||
|
@ -509,7 +510,22 @@ namespace MetaData {
|
|||
{ eForValue, "ForValue", 0 },
|
||||
|
||||
{ eFrameSlotRead, "FrameSlotRead", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotRef, "FrameSlotRef", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotWrite, "FrameSlotWrite", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotDelete, "FrameSlotDelete", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotPostInc, "FrameSlotPostInc", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotPostDec, "FrameSlotPostDec", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotPreInc, "FrameSlotPreInc", U16 }, // <slot index:u16>
|
||||
{ eFrameSlotPreDec, "FrameSlotPreDec", U16 }, // <slot index:u16>
|
||||
|
||||
{ ePackageSlotRead, "PackageSlotRead", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotRef, "PackageSlotRef", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotWrite, "PackageSlotWrite", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotDelete, "PackageSlotDelete", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotPostInc, "PackageSlotPostInc", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotPostDec, "PackageSlotPostDec", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotPreInc, "PackageSlotPreInc", U16 }, // <slot index:u16>
|
||||
{ ePackageSlotPreDec, "PackageSlotPreDec", U16 }, // <slot index:u16>
|
||||
|
||||
{ eLexicalRead, "LexicalRead", NAME_INDEX }, // <multiname index:u16>
|
||||
{ eLexicalWrite, "LexicalWrite", NAME_INDEX }, // <multiname index:u16>
|
||||
|
@ -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,10 +851,15 @@ 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:
|
||||
|
@ -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<NonWithFrame *>(activationStackTop->topFrame);
|
||||
activationStackTop++;
|
||||
if (new_bCon) {
|
||||
bCon = new_bCon;
|
||||
|
|
|
@ -106,6 +106,15 @@ enum JS2Op {
|
|||
eFrameSlotPreInc, // <slot index:u16>
|
||||
eFrameSlotPreDec, // <slot index:u16>
|
||||
|
||||
ePackageSlotRead, // <slot index:u16>
|
||||
ePackageSlotRef, // <slot index:u16>
|
||||
ePackageSlotWrite, // <slot index:u16>
|
||||
ePackageSlotDelete, // <slot index:u16>
|
||||
ePackageSlotPostInc, // <slot index:u16>
|
||||
ePackageSlotPostDec, // <slot index:u16>
|
||||
ePackageSlotPreInc, // <slot index:u16>
|
||||
ePackageSlotPreDec, // <slot index:u16>
|
||||
|
||||
eLexicalRead, // <multiname index:u16>
|
||||
eLexicalWrite, // <multiname index:u16>
|
||||
eLexicalInit, // <multiname index:u16>
|
||||
|
@ -170,6 +179,7 @@ enum JS2Op {
|
|||
|
||||
|
||||
class Frame;
|
||||
class NonWithFrame;
|
||||
class ParameterFrame;
|
||||
class Environment;
|
||||
|
||||
|
@ -332,6 +342,10 @@ public:
|
|||
std::stack<HandlerData *> mTryStack;
|
||||
std::stack<uint8 *> finallyStack;
|
||||
|
||||
// For frame slot references:
|
||||
NonWithFrame *packageFrame;
|
||||
NonWithFrame *localFrame;
|
||||
|
||||
void pushHandler(uint8 *pc);
|
||||
void popHandler();
|
||||
|
||||
|
|
|
@ -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<NonWithFrame *>(*fi);
|
||||
if (pf->kind != ClassKind) {
|
||||
LocalMember *m = findFlatMember(pf, multiname, ReadAccess, CompilePhase);
|
||||
if (m && m->kind == Member::Variable) {
|
||||
NonWithFrame *pf = checked_cast<NonWithFrame *>(fr);
|
||||
switch (pf->kind) {
|
||||
default:
|
||||
keepLooking = false;
|
||||
break;
|
||||
case BlockFrameKind:
|
||||
{
|
||||
LocalMember *m = findLocalMember(pf, multiname, ReadAccess);
|
||||
if (m) {
|
||||
switch (checked_cast<LocalMember *>(m)->memberKind) {
|
||||
case LocalMember::VariableMember:
|
||||
*exprType = checked_cast<Variable *>(m)->type;
|
||||
break;
|
||||
}
|
||||
if (pf->kind == PackageKind)
|
||||
case LocalMember::FrameVariableMember:
|
||||
ASSERT(!checked_cast<FrameVariable *>(m)->packageSlot);
|
||||
returnRef = new (*referenceArena) FrameSlotReference(checked_cast<FrameVariable *>(m)->frameSlot);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
keepLooking = false;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
JS2Class *c = checked_cast<JS2Class *>(pf);
|
||||
MemberDescriptor m2;
|
||||
if (findLocalMember(c, multiname, ReadAccess, CompilePhase, &m2)
|
||||
&& m2.localMember) {
|
||||
if (m2.localMember->kind == LocalMember::Variable)
|
||||
*exprType = checked_cast<Variable *>(m2.localMember)->type;
|
||||
break;
|
||||
}
|
||||
if (m2.ns) { // an instance member
|
||||
QualifiedName qname(m2.ns, multiname->name);
|
||||
InstanceMember *m = findInstanceMember(c, &qname, ReadAccess);
|
||||
js2val base = OBJECT_TO_JS2VAL(pf);
|
||||
Member *m = findCommonMember(&base, multiname, ReadAccess, false);
|
||||
if (m) {
|
||||
if (m->kind == InstanceMember::InstanceVariableKind)
|
||||
*exprType = checked_cast<InstanceVariable *>(m)->type;
|
||||
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<LocalMember *>(m)->memberKind) {
|
||||
case LocalMember::VariableMember:
|
||||
*exprType = checked_cast<Variable *>(m)->type;
|
||||
break;
|
||||
case LocalMember::FrameVariableMember:
|
||||
ASSERT(checked_cast<FrameVariable *>(m)->packageSlot);
|
||||
returnRef = new (*referenceArena) PackageSlotReference(checked_cast<FrameVariable *>(m)->frameSlot);
|
||||
break;
|
||||
}
|
||||
else
|
||||
break; // XXX Shouldn't findLocalMember guarantee this not possible?
|
||||
}
|
||||
else
|
||||
break;
|
||||
// XXX ok to keep going? Suppose the class allows dynamic properties?
|
||||
case Member::InstanceVariableMember:
|
||||
case Member::InstanceMethodMember:
|
||||
case Member::InstanceGetterMember:
|
||||
case Member::InstanceSetterMember:
|
||||
// XXX checked_cast<InstanceMember *>(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<js2val>(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<NonWithFrame *>(*regionalFrameEnd);
|
||||
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<FrameVariable *>(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);
|
||||
|
||||
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<FrameVariable *>(m);
|
||||
if (f->packageSlot)
|
||||
*rval = (*env->getPackageFrame()->slots)[f->frameSlot];
|
||||
else {
|
||||
FrameListIterator fi = env->getRegionalFrame();
|
||||
ASSERT((*fi)->kind == ParameterKind);
|
||||
*rval = (*checked_cast<NonWithFrame *>(*(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<FrameVariable *>(m);
|
||||
if (f->packageSlot)
|
||||
(*env->getPackageFrame()->slots)[f->frameSlot] = newValue;
|
||||
else {
|
||||
FrameListIterator fi = env->getRegionalFrame();
|
||||
ASSERT((*fi)->kind == ParameterKind);
|
||||
(*checked_cast<NonWithFrame *>(*(fi - 1))->slots)[f->frameSlot] = newValue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case LocalMember::DynamicVariableMember:
|
||||
(checked_cast<DynamicVariable *>(m))->value = newValue;
|
||||
return true;
|
||||
|
|
|
@ -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<js2val> *slots; // temporaries allocted in this frame
|
||||
std::vector<js2val> *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,
|
||||
|
|
|
@ -261,9 +261,8 @@
|
|||
{
|
||||
uint16 slotIndex = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(short);
|
||||
NonWithFrame *f = checked_cast<NonWithFrame *>(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<NonWithFrame *>(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<NonWithFrame *>(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;
|
||||
|
||||
|
|
|
@ -1154,10 +1154,9 @@
|
|||
{
|
||||
uint16 slotIndex = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(short);
|
||||
NonWithFrame *f = checked_cast<NonWithFrame *>(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<NonWithFrame *>(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<NonWithFrame *>(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<NonWithFrame *>(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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче