This commit is contained in:
rogerl%netscape.com 2002-08-24 04:10:42 +00:00
Родитель 7ef02807ad
Коммит 36ebbbe9b2
9 изменённых файлов: 327 добавлений и 62 удалений

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

@ -32,6 +32,14 @@
* file under either the NPL or the GPL.
*/
#ifdef _WIN32
// Turn off warnings about identifiers too long in browser information
#pragma warning(disable: 4786)
#pragma warning(disable: 4711)
#pragma warning(disable: 4710)
#endif
#include <algorithm>
#include <assert.h>

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

@ -60,20 +60,33 @@ public:
void emitOp(JS2Op op) { adjustStack(op); addByte((uint8)op); }
void adjustStack(JS2Op op) { mStackTop += JS2Engine::getStackEffect(op); if (mStackTop > mStackMax) mStackMax = mStackTop; ASSERT(mStackTop >= 0); }
void emitOp(JS2Op op, int32 effect) { adjustStack(op, effect); addByte((uint8)op); }
void adjustStack(JS2Op op) { adjustStack(op, JS2Engine::getStackEffect(op)); }
void adjustStack(JS2Op op, int32 effect){ mStackTop += effect; if (mStackTop > mStackMax) mStackMax = mStackTop; ASSERT(mStackTop >= 0); }
void addByte(uint8 v) { mBuffer->push_back(v); }
void addPointer(void *v) { ASSERT(sizeof(void *) == sizeof(uint32)); addLong((uint32)(v)); }
void addPointer(const void *v) { ASSERT(sizeof(void *) == sizeof(uint32)); addLong((uint32)(v)); }
static void *getPointer(void *pc) { return (void *)getLong(pc); }
void addFloat64(float64 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(float64)); }
static float64 getFloat64(void *pc) { return *((float64 *)pc); }
void addLong(uint32 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(uint32)); }
void addLong(const uint32 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(uint32)); }
static uint32 getLong(void *pc) { return *((uint32 *)pc); }
void addMultiname(Multiname *mn) { mMultinameList.push_back(mn); addPointer(mn); }
void addShort(uint16 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(uint16)); }
static uint16 getShort(void *pc) { return *((uint16 *)pc); }
void addMultiname(Multiname *mn) { mMultinameList.push_back(mn); addShort(mMultinameList.size() - 1); }
static Multiname *getMultiname(void *pc){ return (Multiname *)getLong(pc); }
void addString(const StringAtom &x) { emitOp(eString); addPointer(&x); }
void addString(String &x) { emitOp(eString); addPointer(&x); }
void addString(String *x) { emitOp(eString); addPointer(x); }
static String *getString(void *pc) { return (String *)getPointer(pc); }
// XXX We lose StringAtom here - is there anyway of stashing these in a bytecodecontainer?
typedef std::vector<uint8> CodeBuffer;

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

@ -61,9 +61,10 @@
namespace JavaScript {
namespace MetaData {
js2val JS2Engine::interpret(JS2Metadata *metadata, Phase execPhase, uint8 *start)
js2val JS2Engine::interpret(JS2Metadata *metadata, Phase execPhase, BytecodeContainer *targetbCon)
{
pc = start;
bCon = targetbCon;
pc = bCon->getCodeStart();
meta = metadata;
phase = execPhase;
return interpreterLoop();
@ -171,6 +172,9 @@ js2val JS2Engine::convertValueToPrimitive(js2val x)
// return [[DefaultValue]] --> get property 'toString' and invoke it,
// if not available or result is not primitive then try property 'valueOf'
// if that's not available or returns a non primitive, throw a TypeError
return STRING_TO_JS2VAL(&object_StringAtom);
ASSERT(false);
return JS2VAL_VOID;
}
@ -196,11 +200,13 @@ float64 JS2Engine::convertValueToDouble(js2val x)
#define INIT_STRINGATOM(n) n##_StringAtom(world.identifiers[#n])
JS2Engine::JS2Engine(World &world)
: INIT_STRINGATOM(true),
: world(world),
INIT_STRINGATOM(true),
INIT_STRINGATOM(false),
INIT_STRINGATOM(null),
INIT_STRINGATOM(undefined),
INIT_STRINGATOM(public)
INIT_STRINGATOM(public),
INIT_STRINGATOM(object)
{
nanValue = (float64 *)gc_alloc_8();
*nanValue = nan;
@ -218,6 +224,7 @@ int JS2Engine::getStackEffect(JS2Op op)
case eReturn:
case ePlus:
return -1;
case eString:
case eTrue:
case eFalse:
case eNumber:

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

@ -53,22 +53,25 @@ enum JS2Op {
eTrue,
eFalse,
eNumber,
eString, // <string pointer>
eObject, // <named argument count>
eLexicalRead, // <multiname index>
eLexicalWrite, // <multiname index>
eReturn,
eReturnVoid
eReturnVoid,
eNewObject // <argCount:16>
};
class JS2Metadata;
class BytecodeContainer;
class JS2Engine {
public:
JS2Engine(World &world);
js2val interpret(JS2Metadata *metadata, Phase execPhase, uint8 *start);
js2val interpret(JS2Metadata *metadata, Phase execPhase, BytecodeContainer *targetbCon);
js2val interpreterLoop();
@ -91,8 +94,10 @@ public:
float64 toNumber(js2val x) { if (JS2VAL_IS_INT(x)) return JS2VAL_TO_INT(x); else if (JS2VAL_IS_DOUBLE(x)) return *JS2VAL_TO_DOUBLE(x); else return convertValueToDouble(x); }
uint8 *pc;
BytecodeContainer *bCon;
JS2Metadata *meta;
Phase phase;
World &world;
float64 *nanValue;
float64 *float64Table[256];
@ -102,6 +107,7 @@ public:
StringAtom &null_StringAtom;
StringAtom &undefined_StringAtom;
StringAtom &public_StringAtom;
StringAtom &object_StringAtom;
js2val *execStack;
js2val *sp;
@ -113,6 +119,7 @@ public:
};
String *numberToString(float64 *number);

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

@ -120,8 +120,8 @@ namespace MetaData {
while (v) {
ValidateTypeExpression(v->type);
if (cxt->strict && ((regionalFrame->kind == Frame::GlobalObject)
|| (regionalFrame->kind == Frame::Function))
if (cxt->strict && ((regionalFrame->kind == GlobalObjectKind)
|| (regionalFrame->kind == FunctionKind))
&& (p->getKind() == StmtNode::Var) // !immutable
&& (vs->attributes == NULL)
&& (v->type == NULL)) {
@ -132,7 +132,7 @@ namespace MetaData {
if (a->dynamic || a->prototype)
reportError(Exception::definitionError, "Illegal attribute", p->pos);
Attribute::MemberModifier memberMod = a->memberMod;
if ((env->getTopFrame()->kind == Frame::Class)
if ((env->getTopFrame()->kind == ClassKind)
&& (memberMod == Attribute::NoModifier))
memberMod = Attribute::Final;
switch (memberMod) {
@ -168,7 +168,7 @@ namespace MetaData {
p = p->next;
}
bCon->emitOp(eReturnVoid);
return engine->interpret(this, phase, bCon->getCodeStart());
return engine->interpret(this, phase, bCon);
}
/*
@ -458,6 +458,16 @@ namespace MetaData {
void JS2Metadata::ValidateExpression(Context *cxt, Environment *env, ExprNode *p)
{
switch (p->getKind()) {
case ExprNode::number:
case ExprNode::boolean:
break;
case ExprNode::objectLiteral:
break;
case ExprNode::dot:
{
}
break;
case ExprNode::assignment:
case ExprNode::add:
{
@ -471,6 +481,8 @@ namespace MetaData {
// IdentifierExprNode *i = checked_cast<IdentifierExprNode *>(p);
}
break;
default:
NOT_REACHED("Not Yet Implemented");
} // switch (p->getKind())
}
@ -483,7 +495,7 @@ namespace MetaData {
{
EvalExprNode(env, phase, p);
bCon->emitOp(eReturnVoid);
return engine->interpret(this, phase, bCon->getCodeStart());
return engine->interpret(this, phase, bCon);
}
/*
@ -494,10 +506,6 @@ namespace MetaData {
Reference *returnRef = NULL;
switch (p->getKind()) {
case ExprNode::index:
{
}
break;
case ExprNode::assignment:
{
@ -542,7 +550,7 @@ namespace MetaData {
case ExprNode::identifier:
{
IdentifierExprNode *i = checked_cast<IdentifierExprNode *>(p);
returnRef = new LexicalReference(new Multiname(i->name, cxt), env, cxt.strict);
returnRef = new LexicalReference(i->name, cxt.strict);
}
break;
case ExprNode::boolean:
@ -552,6 +560,38 @@ namespace MetaData {
bCon->emitOp(eFalse);
break;
case ExprNode::objectLiteral:
{
uint32 argCount = 0;
PairListExprNode *plen = checked_cast<PairListExprNode *>(p);
ExprPairList *e = plen->pairs;
while (e) {
ASSERT(e->field && e->value);
Reference *rVal = EvalExprNode(env, phase, e->value);
if (rVal) rVal->emitReadBytecode(bCon);
switch (e->field->getKind()) {
case ExprNode::identifier:
bCon->addString(checked_cast<IdentifierExprNode *>(e->field)->name);
break;
case ExprNode::string:
bCon->addString(checked_cast<StringExprNode *>(e->field)->str);
break;
case ExprNode::number:
bCon->addString(numberToString(&(checked_cast<NumberExprNode *>(e->field))->value));
break;
default:
NOT_REACHED("bad field name");
}
argCount++;
e = e->next;
}
bCon->emitOp(eNewObject, -argCount + 1);
bCon->addShort(argCount);
}
break;
case ExprNode::dot:
{
BinaryExprNode *b = checked_cast<BinaryExprNode *>(p);
}
break;
default:
NOT_REACHED("Not Yet Implemented");
@ -574,7 +614,7 @@ namespace MetaData {
JS2Class *Environment::getEnclosingClass()
{
Frame *pf = firstFrame;
while (pf && (pf->kind != Frame::Class))
while (pf && (pf->kind != ClassKind))
pf = pf->nextFrame;
return checked_cast<JS2Class *>(pf);
}
@ -584,11 +624,11 @@ namespace MetaData {
{
Frame *pf = firstFrame;
Frame *prev = NULL;
while (pf->kind == Frame::Block) {
while (pf->kind == BlockKind) {
prev = pf;
pf = pf->nextFrame;
}
if (pf->nextFrame && (pf->kind == Frame::Class))
if (pf->nextFrame && (pf->kind == ClassKind))
pf = prev;
return pf;
}
@ -610,7 +650,7 @@ namespace MetaData {
{
Frame *pf = firstFrame;
while (pf) {
if ((pf->kind == Frame::Function)
if ((pf->kind == FunctionKind)
&& !JS2VAL_IS_NULL(checked_cast<FunctionFrame *>(pf)->thisObject))
if (allowPrototypeThis || !checked_cast<FunctionFrame *>(pf)->prototype)
return checked_cast<FunctionFrame *>(pf)->thisObject;
@ -651,7 +691,7 @@ namespace MetaData {
}
if (createIfMissing) {
pf = getPackageOrGlobalFrame();
if (pf->kind == Frame::GlobalObject) {
if (pf->kind == GlobalObjectKind) {
if (meta->writeProperty(pf, multiname, &lookup, true, newValue, phase))
return;
}
@ -705,7 +745,7 @@ namespace MetaData {
{
QualifiedName qName(publicNamespace, id);
Frame *regionalFrame = env->getRegionalFrame();
ASSERT((env->getTopFrame()->kind == Frame::GlobalObject) || (env->getTopFrame()->kind == Frame::Function));
ASSERT((env->getTopFrame()->kind == GlobalObjectKind) || (env->getTopFrame()->kind == FunctionKind));
// run through all the existing bindings, both read and write, to see if this
// variable already exists.
@ -734,7 +774,7 @@ namespace MetaData {
}
}
if (!existing) {
if (regionalFrame->kind == Frame::GlobalObject) {
if (regionalFrame->kind == GlobalObjectKind) {
GlobalObject *gObj = checked_cast<GlobalObject *>(regionalFrame);
DynamicPropertyIterator dp = gObj->dynamicProperties.find(id);
if (dp != gObj->dynamicProperties.end())
@ -791,14 +831,98 @@ namespace MetaData {
*/
}
bool JS2Metadata::readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
// Read the property from the container given by the public id in multiname - if that exists
//
bool JS2Metadata::readDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
{
return true;
ASSERT(container && ((container->kind == DynamicInstanceKind)
|| (container->kind == GlobalObjectKind)
|| (container->kind == PrototypeInstanceKind)));
if (!multiname->onList(publicNamespace))
return false;
const StringAtom &name = multiname->name;
if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", errorPos);
DynamicPropertyMap *dMap = NULL;
bool isPrototypeInstance = false;
if (container->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(container))->dynamicProperties;
else
if (container->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
else {
isPrototypeInstance = true;
dMap = &(checked_cast<PrototypeInstance *>(container))->dynamicProperties;
}
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
if (i->first == name) {
*rval = i->second;
return true;
}
}
if (isPrototypeInstance) {
PrototypeInstance *pInst = (checked_cast<PrototypeInstance *>(container))->parent;
while (pInst) {
for (DynamicPropertyIterator i = pInst->dynamicProperties.begin(), end = pInst->dynamicProperties.end(); (i != end); i++) {
if (i->first == name) {
*rval = i->second;
return true;
}
}
pInst = pInst->parent;
}
}
if (lookupKind->isPropertyLookup()) {
*rval = JS2VAL_UNDEFINED;
return true;
}
return false; // 'None'
}
bool JS2Metadata::writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase)
{
return true;
ASSERT(container && ((container->kind == DynamicInstanceKind)
|| (container->kind == GlobalObjectKind)
|| (container->kind == PrototypeInstanceKind)));
if (!multiname->onList(publicNamespace))
return false;
const StringAtom &name = multiname->name;
DynamicPropertyMap *dMap = NULL;
if (container->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(container))->dynamicProperties;
else
if (container->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
else
dMap = &(checked_cast<PrototypeInstance *>(container))->dynamicProperties;
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
if (i->first == name) {
i->second = newValue;
return true;
}
}
if (!createIfMissing)
return false;
if (container->kind == DynamicInstanceKind) {
DynamicInstance *dynInst = checked_cast<DynamicInstance *>(container);
InstanceBinding *ib = resolveInstanceMemberName(dynInst->type, multiname, ReadAccess, phase);
if (ib == NULL) {
const DynamicPropertyMap::value_type e(name, newValue);
dynInst->dynamicProperties.insert(e);
return true;
}
}
else {
if (container->kind == GlobalObjectKind) {
GlobalObject *glob = checked_cast<GlobalObject *>(container);
StaticMember *m = findFlatMember(glob, multiname, ReadAccess, phase);
if (m == NULL) {
const DynamicPropertyMap::value_type e(name, newValue);
glob->dynamicProperties.insert(e);
return true;
}
}
}
return false; // 'None'
}
bool JS2Metadata::readStaticMember(StaticMember *m, Phase phase, js2val *rval)
@ -856,7 +980,7 @@ namespace MetaData {
bool JS2Metadata::readProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
{
StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase);
if (!m && (container->kind == Frame::GlobalObject))
if (!m && (container->kind == GlobalObjectKind))
return readDynamicProperty(container, multiname, lookupKind, phase, rval);
else
return readStaticMember(m, phase, rval);
@ -867,7 +991,7 @@ namespace MetaData {
bool JS2Metadata::writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase)
{
StaticMember *m = findFlatMember(container, multiname, WriteAccess, phase);
if (!m && (container->kind == Frame::GlobalObject))
if (!m && (container->kind == GlobalObjectKind))
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase);
else
return writeStaticMember(m, newValue, phase);
@ -898,7 +1022,7 @@ namespace MetaData {
break;
}
if (multiname->matches(b->second->qname)) {
if (found)
if (found && (b->second->content != found))
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", errorPos, multiname->name);
else
found = b->second->content;
@ -908,6 +1032,48 @@ namespace MetaData {
return found;
}
/*
* Start from the root class (Object) and proceed through more specific classes that are ancestors of c.
* Find the binding that matches the given access and multiname, it's an error if more than one such exists.
*
*/
InstanceBinding *JS2Metadata::resolveInstanceMemberName(JS2Class *c, Multiname *multiname, Access access, Phase phase)
{
InstanceBinding *result = NULL;
if (c->super) {
result = resolveInstanceMemberName(c->super, multiname, access, phase);
if (result) return result;
}
InstanceBindingIterator b, end;
if ((access == ReadAccess) || (access == ReadWriteAccess)) {
b = c->instanceReadBindings.lower_bound(multiname->name);
end = c->instanceReadBindings.upper_bound(multiname->name);
}
else {
b = c->instanceWriteBindings.lower_bound(multiname->name);
end = c->instanceWriteBindings.upper_bound(multiname->name);
}
while (true) {
if (b == end) {
if (access == ReadWriteAccess) {
access = WriteAccess;
b = c->instanceWriteBindings.lower_bound(multiname->name);
end = c->instanceWriteBindings.upper_bound(multiname->name);
}
else
break;
}
if (multiname->matches(b->second->qname)) {
if (result && (b->second->content != result->content))
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", errorPos, multiname->name);
else
result = b->second;
}
b++;
}
return result;
}
/*
* Throw an exception of the specified kind, indicating the position 'pos' and
* attaching the given message. If 'arg' is specified, replace {0} in the message

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

@ -54,14 +54,35 @@ typedef void (Invokable)();
typedef Invokable Callor;
typedef JS2Object *(Constructor)();
enum ObjectKind {
AttributeObjectKind,
SystemKind,
GlobalObjectKind,
PackageKind,
FunctionKind,
ClassKind,
BlockKind,
PrototypeInstanceKind,
FixedInstanceKind,
DynamicInstanceKind };
class JS2Object {
// Every object is either undefined, null, a Boolean,
// a number, a string, a namespace, a compound attribute, a class, a method closure,
// a prototype instance, a class instance, a package object, or the global object.
public:
JS2Object(ObjectKind kind) : kind(kind) { }
ObjectKind kind;
void *operator new(size_t s);
#ifdef DEBUG
virtual void uselessVirtual() { } // want the checked_cast stuff to work, so need a virtual function
#endif
};
class Attribute : public JS2Object {
@ -71,7 +92,7 @@ public:
enum OverrideModifier { NoOverride, DoOverride, DontOverride, OverrideUndefined };
Attribute(AttributeKind kind) : kind(kind) { }
Attribute(AttributeKind kind) : JS2Object(AttributeObjectKind), kind(kind) { }
static Attribute *combineAttributes(Attribute *a, Attribute *b);
static CompoundAttribute *toCompoundAttribute(Attribute *a);
@ -102,7 +123,9 @@ public:
};
// MULTINAME is the semantic domain of sets of qualified names. Multinames are used internally in property lookup.
// We keep Multinames as a basename and a list of namespace qualifiers
// We keep Multinames as a basename and a list of namespace qualifiers (XXX is that right - would the basename
// ever be different for the same multiname?)
// Pointers to Multiname instances get embedded in the bytecode.
typedef std::vector<Namespace *> NamespaceList;
typedef NamespaceList::iterator NamespaceListIterator;
class Multiname {
@ -257,33 +280,28 @@ public:
typedef std::multimap<String, StaticBinding *> StaticBindingMap;
typedef StaticBindingMap::iterator StaticBindingIterator;
class InstanceBindingMap {
public:
};
typedef std::multimap<String, InstanceBinding *> InstanceBindingMap;
typedef InstanceBindingMap::iterator InstanceBindingIterator;
// A frame contains bindings defined at a particular scope in a program. A frame is either the top-level system frame,
// a global object, a package, a function frame, a class, or a block frame
class Frame {
class Frame : public JS2Object {
public:
enum Plurality { Singular, Plural };
enum FrameKind { System, GlobalObject, Package, Function, Class, Block };
Frame(FrameKind kind) : kind(kind), nextFrame(NULL) { }
Frame(ObjectKind kind) : JS2Object(kind), nextFrame(NULL) { }
StaticBindingMap staticReadBindings; // Map of qualified names to readable static members defined in this frame
StaticBindingMap staticWriteBindings; // Map of qualified names to writable static members defined in this frame
FrameKind kind; // [rather than use RTTI (in general)]
Frame *nextFrame;
#ifdef DEBUG
virtual void uselessVirtual() { } // want the checked_cast stuff to work, so need a virtual function
#endif
};
class JS2Class : public Frame {
public:
JS2Class() : Frame(Class) { }
JS2Class() : Frame(ClassKind) { }
StringAtom &getName();
@ -310,7 +328,7 @@ public:
class GlobalObject : public Frame {
public:
GlobalObject(World &world) : Frame(Frame::GlobalObject), internalNamespace(new Namespace(world.identifiers["internal"])) { }
GlobalObject(World &world) : Frame(GlobalObjectKind), internalNamespace(new Namespace(world.identifiers["internal"])) { }
Namespace *internalNamespace; // This global object's internal namespace
DynamicPropertyMap dynamicProperties; // A set of this global object's dynamic properties
@ -325,8 +343,10 @@ public:
};
// Instances of non-dynamic classes are represented as FIXEDINSTANCE records. These instances can contain only fixed properties.
class FixedInstance {
class FixedInstance : public JS2Object {
public:
FixedInstance() : JS2Object(FixedInstanceKind), typeofString(type->getName()) { }
JS2Class *type; // This instance's type
Invokable *call; // A procedure to call when this instance is used in a call expression
Invokable *construct; // A procedure to call when this instance is used in a new expression
@ -336,9 +356,9 @@ public:
};
// Instances of dynamic classes are represented as DYNAMICINSTANCE records. These instances can contain fixed and dynamic properties.
class DynamicInstance {
class DynamicInstance : public JS2Object {
public:
DynamicInstance(JS2Class *type) : type(type), call(NULL), construct(NULL), env(NULL), typeofString(type->getName()) { }
DynamicInstance(JS2Class *type) : JS2Object(DynamicInstanceKind), type(type), call(NULL), construct(NULL), env(NULL), typeofString(type->getName()) { }
JS2Class *type; // This instance's type
Invokable *call; // A procedure to call when this instance is used in a call expression
@ -349,7 +369,24 @@ public:
DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties
};
// Prototype instances are represented as PROTOTYPE records. Prototype instances
// contain no fixed properties.
class PrototypeInstance : public JS2Object {
public:
PrototypeInstance(PrototypeInstance *parent) : JS2Object(PrototypeInstanceKind), parent(parent) { }
PrototypeInstance *parent; // If this instance was created by calling new on a prototype function,
// the value of the functions prototype property at the time of the call;
// none otherwise.
DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties
};
// Base class for all references (lvalues)
// References are generated during the eval stage (bytecode generation)
class Reference {
public:
virtual void emitReadBytecode(BytecodeContainer *bCon) { ASSERT(false); }
@ -363,6 +400,7 @@ class LexicalReference : public Reference {
// of a given set of qualified names. LEXICALREFERENCE tuples arise from evaluating identifiers a and qualified identifiers
// q::a.
public:
LexicalReference(const StringAtom &name, bool strict) : variableMultiname(new Multiname(name)), env(NULL), strict(strict) { }
LexicalReference(Multiname *vm, Environment *env, bool strict) : variableMultiname(vm), env(env), strict(strict) { }
Multiname *variableMultiname; // A nonempty set of qualified names to which this reference can refer
@ -419,13 +457,13 @@ public:
// The top-level frame containing predefined constants, functions, and classes.
class SystemFrame : public Frame {
public:
SystemFrame() : Frame(System) { }
SystemFrame() : Frame(SystemKind) { }
};
// Frames holding bindings for invoked functions
class FunctionFrame : public Frame {
public:
FunctionFrame() : Frame(Function) { }
FunctionFrame() : Frame(FunctionKind) { }
Plurality plurality;
js2val thisObject; // The value of this; none if this function doesn't define this;
@ -439,7 +477,7 @@ public:
class BlockFrame : public Frame {
public:
BlockFrame() : Frame(Block) { }
BlockFrame() : Frame(BlockKind) { }
Plurality plurality;
};
@ -448,6 +486,9 @@ public:
class LookupKind {
public:
LookupKind(bool isLexical, js2val thisObject) : isLexical(isLexical), thisObject(thisObject) { }
bool isPropertyLookup() { return !isLexical; }
bool isLexical; // if isLexical, use the 'this' below. Otherwise it's a propertyLookup
js2val thisObject;
};
@ -547,11 +588,12 @@ public:
JS2Class *objectType(js2val obj);
StaticMember *findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase);
InstanceBinding *resolveInstanceMemberName(JS2Class *js2class, Multiname *multiname, Access access, Phase phase);
bool readProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);
bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);
bool readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);
bool readDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);
bool readStaticMember(StaticMember *m, Phase phase, js2val *rval);
@ -594,7 +636,6 @@ public:
};
}; // namespace MetaData
}; // namespace Javascript

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

@ -33,15 +33,17 @@
case eLexicalRead: {
Multiname *mn = BytecodeContainer::getMultiname(pc);
pc += sizeof(Multiname *);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
meta->env.lexicalRead(meta, mn, phase);
}
break;
case eLexicalWrite: {
Multiname *mn = BytecodeContainer::getMultiname(pc);
pc += sizeof(Multiname *);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
mn->addNamespace(meta->cxt);
retval = pop();
meta->env.lexicalWrite(meta, mn, retval, true, phase);
}

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

@ -44,4 +44,19 @@
}
break;
case eNewObject: {
uint16 argCount = BytecodeContainer::getShort(pc);
pc += sizeof(uint16);
PrototypeInstance *pInst = new PrototypeInstance(NULL); // XXX Object prototype object
for (uint16 i = 0; i < argCount; i++) {
js2val nameVal = pop();
ASSERT(JS2VAL_IS_STRING(nameVal));
String *name = JS2VAL_TO_STRING(nameVal);
const StringAtom &nameAtom = world.identifiers[*name];
js2val fieldVal = pop();
const DynamicPropertyMap::value_type e(nameAtom, fieldVal);
pInst->dynamicProperties.insert(e);
}
push(OBJECT_TO_JS2VAL(pInst));
}
break;

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

@ -48,3 +48,9 @@
push(JS2VAL_TRUE);
}
break;
case eString: {
push(STRING_TO_JS2VAL(BytecodeContainer::getString(pc)));
pc += sizeof(String *);
}
break;