зеркало из https://github.com/mozilla/gecko-dev.git
Adding FrameVariable for slotted access.
This commit is contained in:
Родитель
4b0d94c93a
Коммит
ddecbfe981
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче