Changes to arguments instance & class

This commit is contained in:
rogerl%netscape.com 2003-05-30 22:47:57 +00:00
Родитель 412f76b934
Коммит 42eba1cf23
3 изменённых файлов: 137 добавлений и 25 удалений

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

@ -853,6 +853,48 @@ namespace MetaData {
return Delete(meta, base, mn, NULL, result);
}
bool JS2ArgumentsClass::Read(JS2Metadata *meta, js2val *base, Multiname *multiname, Environment *env, Phase phase, js2val *rval)
{
ASSERT(JS2VAL_IS_OBJECT(*base));
JS2Object *obj = JS2VAL_TO_OBJECT(*base);
ArgumentsInstance *args = checked_cast<ArgumentsInstance *>(obj);
uint32 index;
if ((multiname->nsList->size() == 1)
&& (multiname->nsList->back() == meta->publicNamespace)
&& isValidIndex(multiname->name, index)
&& (index < args->mSlots->size())) {
*rval = (*args->mSlots)[index];
return true;
}
else
return JS2Class::Read(meta, base, multiname, env, phase, rval);
}
bool JS2ArgumentsClass::Write(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag)
{
ASSERT(JS2VAL_IS_OBJECT(base));
JS2Object *obj = JS2VAL_TO_OBJECT(base);
ArgumentsInstance *args = checked_cast<ArgumentsInstance *>(obj);
uint32 index;
if ((multiname->nsList->size() == 1)
&& (multiname->nsList->back() == meta->publicNamespace)
&& isValidIndex(multiname->name, index)
&& (index < args->mSlots->size())) {
(*args->mSlots)[index] = newValue;
return true;
}
else
return JS2Class::Write(meta, base, multiname, env, createIfMissing, newValue, false);
}
bool JS2ArgumentsClass::Delete(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool *result)
{
return JS2Class::Delete(meta, base, multiname, env, result);
}
bool JS2Class::Write(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag)
{
InstanceMember *mBase = meta->findBaseInstanceMember(this, multiname, WriteAccess);
@ -883,7 +925,7 @@ namespace MetaData {
DEFINE_ROOTKEEPER(rk, mn);
if ( (meta->findBaseInstanceMember(this, mn, ReadAccess) == NULL)
&& (meta->findCommonMember(&base, mn, ReadAccess, true) == NULL) ) {
meta->createDynamicProperty(baseObj, &qName, newValue, ReadWriteAccess, false, true);
meta->createDynamicProperty(baseObj, mn->name, newValue, ReadWriteAccess, false, true);
return true;
}
}

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

@ -3106,7 +3106,7 @@ doUnary:
}
// Clone the pluralFrame bindings into the singularFrame, instantiating new members for each binding
void Environment::instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame)
void Environment::instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame, bool buildSlots)
{
singularFrame->localBindings.clear();
@ -3118,7 +3118,7 @@ doUnary:
LocalBindingEntry *lbe = *bi2;
singularFrame->localBindings.insert(lbe->name, lbe->clone());
}
if (pluralFrame->slots) {
if (buildSlots && pluralFrame->slots) {
size_t count = pluralFrame->slots->size();
singularFrame->slots = new std::vector<js2val>(count);
for (size_t i = 0; i < count; i++)
@ -4008,6 +4008,7 @@ static const uint8 urlCharType[256] =
MAKEBUILTINCLASS(classClass, objectClass, false, true, engine->allocStringPtr(&world.identifiers["Class"]), JS2VAL_NULL);
MAKEBUILTINCLASS(functionClass, objectClass, true, true, engine->Function_StringAtom, JS2VAL_NULL);
MAKEBUILTINCLASS(packageClass, objectClass, true, true, engine->allocStringPtr(&world.identifiers["Package"]), JS2VAL_NULL);
MAKEBUILTINCLASS(argumentsClass, objectClass, true, true, engine->allocStringPtr(&world.identifiers["Arguments"]), JS2VAL_NULL);
@ -4581,22 +4582,34 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, const char *name, js2val initVal, Access access, bool sealed, bool enumerable)
{
QualifiedName qName(publicNamespace, &world.identifiers[widenCString(name)]);
return createDynamicProperty(obj, &qName, initVal, access, sealed, enumerable);
return createDynamicProperty(obj, &world.identifiers[widenCString(name)], initVal, access, sealed, enumerable);
}
/*
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable)
{
DEFINE_ROOTKEEPER(rk, name);
QualifiedName qName(publicNamespace, name);
return createDynamicProperty(obj, &qName, initVal, access, sealed, enumerable);
}
*/
void JS2Metadata::addPublicVariableToLocalMap(LocalBindingMap *lMap, const String *name, LocalMember *v, Access access, bool enumerable)
{
LocalBinding *new_b = new LocalBinding(access, v, enumerable);
LocalBindingEntry **lbeP = (*lMap)[*name];
LocalBindingEntry *lbe;
if (lbeP == NULL) {
lbe = new LocalBindingEntry(*name);
lMap->insert(*name, lbe);
}
else
lbe = *lbeP;
lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(publicNamespace, new_b));
}
// The caller must make sure that the created property does not already exist and does not conflict with any other property.
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable)
DynamicVariable *JS2Metadata::createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable)
{
DynamicVariable *dv = new DynamicVariable(initVal, sealed);
LocalBinding *new_b = new LocalBinding(access, dv, enumerable);
LocalBindingMap *lMap;
if (obj->kind == SimpleInstanceKind)
lMap = &checked_cast<SimpleInstance *>(obj)->localBindings;
@ -4605,7 +4618,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
lMap = &checked_cast<Package *>(obj)->localBindings;
else
ASSERT(false);
addPublicVariableToLocalMap(lMap, name, dv, access, enumerable);
/*
LocalBindingEntry **lbeP = (*lMap)[*qName->name];
LocalBindingEntry *lbe;
if (lbeP == NULL) {
@ -4615,6 +4629,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
else
lbe = *lbeP;
lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(qName->nameSpace, new_b));
*/
return dv;
}
@ -4662,6 +4677,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
GCMARKOBJECT(syntaxErrorClass);
GCMARKOBJECT(typeErrorClass);
GCMARKOBJECT(uriErrorClass);
GCMARKOBJECT(argumentsClass);
for (BConListIterator i = bConList.begin(), end = bConList.end(); (i != end); i++)
(*i)->mark();
@ -5039,6 +5055,28 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
delete fWrap;
}
/************************************************************************************
*
* ArgumentsInstance
*
************************************************************************************/
// gc-mark all contained JS2Objects and visit contained structures to do likewise
void ArgumentsInstance::markChildren()
{
SimpleInstance::markChildren();
if (mSlots) {
for (uint32 i = 0; i < mSlots->size(); i++)
GCMARKVALUE((*mSlots)[i]);
}
}
ArgumentsInstance::~ArgumentsInstance()
{
if (mSlots)
delete mSlots;
}
/************************************************************************************
*
* InstanceMethod
@ -5129,7 +5167,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
void ParameterFrame::instantiate(Environment *env)
{
env->instantiateFrame(pluralFrame, this);
env->instantiateFrame(pluralFrame, this, !buildArguments);
}
// Assume that instantiate has been called, the plural frame will contain
@ -5141,11 +5179,18 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
ASSERT(pluralFrame->kind == ParameterFrameKind);
ParameterFrame *plural = checked_cast<ParameterFrame *>(pluralFrame);
SimpleInstance *argsObj = NULL;
ArgumentsInstance *argsObj = NULL;
DEFINE_ROOTKEEPER(rk2, argsObj);
uint32 slotCount = (plural->slots) ? plural->slots->size() : 0;
if (plural->buildArguments) {
argsObj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass);
// If we're building an arguments object, the slots for the parameter frame are located
// there so that the arguments object itself can survive beyond the life of the function.
argsObj = new ArgumentsInstance(meta, meta->objectClass->prototype, meta->argumentsClass);
if (slotCount)
argsObj->mSlots = new std::vector<js2val>(slotCount);
slots = argsObj->mSlots;
// Add the 'arguments' property
String name(widenCString("arguments"));
ASSERT(localBindings[name] == NULL);
@ -5155,22 +5200,16 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
localBindings.insert(name, lbe);
}
uint32 slotCount = (plural->slots) ? plural->slots->size() : 0;
uint32 i;
for (i = 0; (i < argCount); i++) {
if (i < slotCount) {
(*slots)[i] = argBase[i];
}
if (plural->buildArguments)
meta->objectClass->WritePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->engine->numberToString(i), true, argBase[i]);
}
while (i++ < length) {
if (i < slotCount) {
(*slots)[i] = JS2VAL_UNDEFINED;
}
if (plural->buildArguments)
meta->objectClass->WritePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->engine->numberToString(i), true, JS2VAL_UNDEFINED);
}
if (plural->buildArguments) {
setLength(meta, argsObj, argCount);
@ -5188,6 +5227,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
ParameterFrame::~ParameterFrame()
{
if (buildArguments) {
slots = NULL; // the slots are in the arguments object, let it do the delete
}
}
/************************************************************************************
@ -5202,6 +5244,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
GCMARKOBJECT(type)
}
/************************************************************************************
*
* BlockFrame
@ -5211,7 +5254,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
void BlockFrame::instantiate(Environment *env)
{
if (pluralFrame)
env->instantiateFrame(pluralFrame, this);
env->instantiateFrame(pluralFrame, this, true);
}

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

@ -57,6 +57,7 @@ class FunctionInstance;
class ArrayInstance;
class RegExpInstance;
class Package;
class ArgumentsInstance;
typedef void (Invokable)();
typedef js2val (Callor)(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
@ -270,6 +271,7 @@ public:
ROOTKEEPER_CONSTRUCTOR(SimpleInstance)
ROOTKEEPER_CONSTRUCTOR(FunctionInstance)
ROOTKEEPER_CONSTRUCTOR(DateInstance)
ROOTKEEPER_CONSTRUCTOR(ArgumentsInstance)
#ifdef DEBUG
RootKeeper(js2val *p, int line, char *pfile) : is_js2val(true), js2val_count(0), p(p) { init(line, pfile); }
@ -528,8 +530,6 @@ public:
virtual void mark();
};
// A LOCALBINDING describes the member to which one qualified name is bound in a frame. Multiple
// qualified names may be bound to the same member in a frame, but a qualified name may not be
// bound to multiple members in a frame (except when one binding is for reading only and
@ -752,7 +752,7 @@ public:
void lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue);
bool lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase);
void instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame);
void instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame, bool buildSlots);
void markChildren();
@ -855,6 +855,16 @@ public:
virtual bool BracketDelete(JS2Metadata *meta, js2val base, js2val indexVal, bool *result) { return false; }
};
class JS2ArgumentsClass : public JS2Class {
public:
JS2ArgumentsClass(JS2Class *super, js2val proto, Namespace *privateNamespace, bool dynamic, bool final, const String *name)
: JS2Class(super, proto, privateNamespace, dynamic, final, name) { }
virtual bool Read(JS2Metadata *meta, js2val *base, Multiname *multiname, Environment *env, Phase phase, js2val *rval);
virtual bool Write(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool createIfMissing, js2val newValue, bool initFlag);
virtual bool Delete(JS2Metadata *meta, js2val base, Multiname *multiname, Environment *env, bool *result);
};
class Package : public NonWithFrame {
public:
typedef enum { InTransit, InHand } PackageStatus;
@ -1049,6 +1059,19 @@ public:
virtual ~RegExpInstance() { }
};
class ArgumentsInstance : public SimpleInstance {
public:
ArgumentsInstance(JS2Metadata *meta, js2val parent, JS2Class *type) : SimpleInstance(meta, parent, type), mSlots(NULL) { }
ValueList *mSlots;
virtual void markChildren();
virtual ~ArgumentsInstance();
};
// A helper class for 'for..in' statements
class ForIteratorObject : public JS2Object {
public:
@ -1076,6 +1099,7 @@ private:
// Base class for all references (lvalues)
// References are generated during the eval stage (bytecode generation), but shouldn't live beyond that
// so they're allocated from an arena carried in the metadata class and cleared after each bytecode gen pass.
class Reference : public ArenaObject {
public:
virtual ~Reference() { }
@ -1092,7 +1116,7 @@ public:
virtual void emitDeleteBytecode(BytecodeContainer *, size_t) { ASSERT(false); }
// indicate whether building the reference generate any stack deposits
// indicate whether building the reference generates any stack deposits
virtual int hasStackEffect() { ASSERT(false); return 0; }
};
@ -1329,7 +1353,8 @@ public:
// available because this function hasn't been called yet.
bool prototype; // true if this function is not an instance method but defines this anyway
bool buildArguments;
bool buildArguments; // true if the 'arguments' variable is referenced, it will be constructed
// by 'assignArguments' and contain the slots for this frame.
bool isConstructor;
bool isInstance;
bool callsSuperConstructor;
@ -1489,8 +1514,9 @@ public:
void invokeInit(JS2Class *c, js2val thisValue, js2val* argv, uint32 argc);
DynamicVariable *createDynamicProperty(JS2Object *obj, const char *name, js2val initVal, Access access, bool sealed, bool enumerable);
DynamicVariable *createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable);
// DynamicVariable *createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable);
DynamicVariable *createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable);
void addPublicVariableToLocalMap(LocalBindingMap *lMap, const String *name, LocalMember *v, Access access, bool enumerable);
FunctionInstance *createFunctionInstance(Environment *env, bool prototype, bool unchecked, NativeCode *code, uint32 length, DynamicVariable **lengthProperty);
@ -1582,6 +1608,7 @@ public:
JS2Class *syntaxErrorClass;
JS2Class *typeErrorClass;
JS2Class *uriErrorClass;
JS2Class *argumentsClass;
BytecodeContainer *bCon; // the current output container