Adding FrameVariable for slotted access.

This commit is contained in:
rogerl%netscape.com 2003-04-14 07:22:21 +00:00
Родитель 4b0d94c93a
Коммит ddecbfe981
7 изменённых файлов: 226 добавлений и 120 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -98,7 +98,13 @@ enum JS2Op {
eForValue,
eFrameSlotRead, // <slot index:u16>
eFrameSlotRef, // <slot index:u16>
eFrameSlotWrite, // <slot index:u16>
eFrameSlotDelete, // <slot index:u16>
eFrameSlotPostInc, // <slot index:u16>
eFrameSlotPostDec, // <slot index:u16>
eFrameSlotPreInc, // <slot index:u16>
eFrameSlotPreDec, // <slot index:u16>
eLexicalRead, // <multiname index:u16>
eLexicalWrite, // <multiname index:u16>

Просмотреть файл

@ -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<LocalMember *>(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<LocalMember *>(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<FrameVariable *>(m)->sealed) {
*result = false;
return true;
}
goto VariableMemberCommon;
}
case Member::DynamicVariableMember:
{
if (checked_cast<DynamicVariable *>(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;

Просмотреть файл

@ -878,7 +878,7 @@ namespace MetaData {
*/
{
SwitchStmtNode *sw = checked_cast<SwitchStmtNode *>(p);
uint16 swVarIndex = (checked_cast<NonWithFrame *>(env->getTopFrame()))->allocateTemp();
uint16 swVarIndex = (checked_cast<NonWithFrame *>(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<Variable *>(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<InstanceVariable *>(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<NonWithFrame *>(*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<DynamicVariable *>(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<InstanceVariable *>(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<InstanceVariable *>(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<Variable *>(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<DynamicVariable *>(m))->value;
return true;
case LocalMember::ConstructorMethod:
{
if (phase == CompilePhase)
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
*rval = (checked_cast<ConstructorMethod *>(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<ConstructorMethod *>(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<Variable *>(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<DynamicVariable *>(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<js2val>;
uint16 result = (uint16)(temps->size());
temps->push_back(JS2VAL_VOID);
if (slots == NULL)
slots = new std::vector<js2val>;
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<js2val>::iterator i = temps->begin(), end = temps->end(); (i != end); i++)
if (slots) {
for (std::vector<js2val>::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<Variable *>(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<Variable *>(plural->positional[i]->cloneContent))->value = JS2VAL_UNDEFINED;
}
meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->arrayClass, meta->engine->numberToString(i), true, JS2VAL_UNDEFINED);

Просмотреть файл

@ -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<js2val> *temps; // temporaries allocted in this frame
uint16 allocateTemp();
std::vector<js2val> *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();

Просмотреть файл

@ -263,7 +263,16 @@
pc += sizeof(short);
NonWithFrame *f = checked_cast<NonWithFrame *>(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<NonWithFrame *>(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<NonWithFrame *>(meta->env->getTopFrame());
push((*f->temps)[slotIndex]);
push((*f->slots)[slotIndex]);
}
break;

Просмотреть файл

@ -1149,3 +1149,48 @@
baseVal = JS2VAL_VOID;
}
break;
case eFrameSlotPostInc:
{
uint16 slotIndex = BytecodeContainer::getShort(pc);
pc += sizeof(short);
NonWithFrame *f = checked_cast<NonWithFrame *>(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<NonWithFrame *>(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<NonWithFrame *>(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<NonWithFrame *>(meta->env->getTopFrame());
a = (*f->slots)[slotIndex];
float64 num = meta->toFloat64(a);
a = pushNumber(num - 1.0);
(*f->slots)[slotIndex] = a;
}
break;