diff --git a/js2/src/bytecodecontainer.cpp b/js2/src/bytecodecontainer.cpp index 70d8a7e36367..78cfced1d0ba 100644 --- a/js2/src/bytecodecontainer.cpp +++ b/js2/src/bytecodecontainer.cpp @@ -64,11 +64,17 @@ namespace MetaData { BytecodeContainer::~BytecodeContainer() { - delete mBuffer; for (std::vector::iterator i = mMultinameList.begin(), end = mMultinameList.end(); (i != end); i++) delete *i; } + size_t BytecodeContainer::getPosition(uint16 pc) + { + for (std::vector::iterator i = pcMap.begin(), end = pcMap.end(); (i != end); i++) + if (i->first >= pc) + return i->second; + return 0; + } } } diff --git a/js2/src/bytecodecontainer.h b/js2/src/bytecodecontainer.h index 86a232fcf329..673487b0e8ff 100644 --- a/js2/src/bytecodecontainer.h +++ b/js2/src/bytecodecontainer.h @@ -52,45 +52,50 @@ class Multiname; class BytecodeContainer { public: - BytecodeContainer() : mBuffer(new CodeBuffer), mStackTop(0), mStackMax(0) { } + BytecodeContainer() : mStackTop(0), mStackMax(0) { } BytecodeContainer::~BytecodeContainer() ; - uint8 *getCodeStart() { return mBuffer->begin(); } + uint8 *getCodeStart() { return mBuffer.begin(); } + typedef std::pair MapEntry; + std::vector pcMap; - void emitOp(JS2Op op) { adjustStack(op); addByte((uint8)op); } - void emitOp(JS2Op op, int32 effect) { adjustStack(op, effect); addByte((uint8)op); } + size_t getPosition(uint16 pc); + + void emitOp(JS2Op op, size_t pos) { adjustStack(op); addByte((uint8)op); pcMap.push_back(MapEntry(mBuffer.size(), pos)); } + void emitOp(JS2Op op, size_t pos, int32 effect) + { adjustStack(op, effect); addByte((uint8)op); pcMap.push_back(std::pair(mBuffer.size(), pos)); } 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 addByte(uint8 v) { mBuffer.push_back(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)); } + void addFloat64(float64 v) { mBuffer.insert(mBuffer.end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(float64)); } static float64 getFloat64(void *pc) { return *((float64 *)pc); } - void addLong(const 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 addShort(uint16 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(uint16)); } + 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); } + void addString(const StringAtom &x, size_t pos) { emitOp(eString, pos); addPointer(&x); } + void addString(String &x, size_t pos) { emitOp(eString, pos); addPointer(&x); } + void addString(String *x, size_t pos) { emitOp(eString, pos); 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 CodeBuffer; - CodeBuffer *mBuffer; + CodeBuffer mBuffer; std::vector mMultinameList; // gc tracking int32 mStackTop; // keep these as signed so as to diff --git a/js2/src/js2engine.cpp b/js2/src/js2engine.cpp index ae3863670514..adabea7ba8e5 100644 --- a/js2/src/js2engine.cpp +++ b/js2/src/js2engine.cpp @@ -240,7 +240,6 @@ int JS2Engine::getStackEffect(JS2Op op) return 0; case eMultiname: - case eQMultiname: return 1; // push the multiname object case eUse: @@ -252,5 +251,10 @@ int JS2Engine::getStackEffect(JS2Op op) return 0; } +size_t JS2Engine::errorPos() +{ + return bCon->getPosition(pc - bCon->getCodeStart()); +} + } } \ No newline at end of file diff --git a/js2/src/js2engine.h b/js2/src/js2engine.h index b65fab8a3f59..fa1e20ac2f25 100644 --- a/js2/src/js2engine.h +++ b/js2/src/js2engine.h @@ -61,7 +61,6 @@ enum JS2Op { eReturnVoid, eNewObject, // eMultiname, // - eQMultiname, // eUse, }; @@ -81,6 +80,8 @@ public: void *gc_alloc_8(); float64 *newDoubleValue(float64 x); + size_t errorPos(); + void pushNumber(float64 x); #define MAX_EXEC_STACK (20) diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index 47f01797e833..296aa516b077 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -191,11 +191,13 @@ namespace MetaData { { BytecodeContainer *saveBacon = bCon; bCon = new BytecodeContainer(); + size_t lastPos = p->pos; while (p) { EvalStmt(&env, phase, p); + lastPos = p->pos; p = p->next; } - bCon->emitOp(eReturnVoid); + bCon->emitOp(eReturnVoid, lastPos); js2val retval = engine->interpret(this, phase, bCon); bCon = saveBacon; return retval; @@ -242,7 +244,7 @@ namespace MetaData { { ExprStmtNode *e = checked_cast(p); Reference *r = EvalExprNode(env, phase, e->expr); - if (r) r->emitReadBytecode(bCon); + if (r) r->emitReadBytecode(bCon, p->pos); } break; case StmtNode::Namespace: @@ -255,8 +257,8 @@ namespace MetaData { ExprList *eList = u->namespaces; while (eList) { Reference *r = EvalExprNode(env, phase, eList->expr); - if (r) r->emitReadBytecode(bCon); - bCon->emitOp(eUse); + if (r) r->emitReadBytecode(bCon, p->pos); + bCon->emitOp(eUse, p->pos); eList = eList->next; } } @@ -549,8 +551,8 @@ namespace MetaData { BytecodeContainer *saveBacon = bCon; bCon = new BytecodeContainer(); Reference *r = EvalExprNode(env, phase, p); - if (r) r->emitReadBytecode(bCon); - bCon->emitOp(eReturn); + if (r) r->emitReadBytecode(bCon, p->pos); + bCon->emitOp(eReturn, p->pos); js2val retval = engine->interpret(this, phase, bCon); bCon = saveBacon; return retval; @@ -572,8 +574,8 @@ namespace MetaData { Reference *lVal = EvalExprNode(env, phase, b->op1); if (lVal) { Reference *rVal = EvalExprNode(env, phase, b->op2); - if (rVal) rVal->emitReadBytecode(bCon); - lVal->emitWriteBytecode(bCon); + if (rVal) rVal->emitReadBytecode(bCon, p->pos); + lVal->emitWriteBytecode(bCon, p->pos); } else reportError(Exception::semanticError, "Assignment needs an lValue", p->pos); @@ -584,9 +586,9 @@ namespace MetaData { BinaryExprNode *b = checked_cast(p); Reference *lVal = EvalExprNode(env, phase, b->op1); Reference *rVal = EvalExprNode(env, phase, b->op2); - if (lVal) lVal->emitReadBytecode(bCon); - if (rVal) rVal->emitReadBytecode(bCon); - bCon->emitOp(ePlus); + if (lVal) lVal->emitReadBytecode(bCon, p->pos); + if (rVal) rVal->emitReadBytecode(bCon, p->pos); + bCon->emitOp(ePlus, p->pos); } break; @@ -601,7 +603,7 @@ namespace MetaData { case ExprNode::number: { - bCon->emitOp(eNumber); + bCon->emitOp(eNumber, p->pos); bCon->addFloat64(checked_cast(p)->value); } break; @@ -609,24 +611,31 @@ namespace MetaData { { QualifyExprNode *qe = checked_cast(p); const StringAtom &name = checked_cast(p)->name; - Reference *rVal = EvalExprNode(env, phase, qe->qualifier); - if (rVal) rVal->emitReadBytecode(bCon); - returnRef = new LexicalReference(name, cxt.strict, true); - ((LexicalReference *)returnRef)->emitBindBytecode(bCon); + + js2val av = EvalExpression(env, CompilePhase, qe->qualifier); + if (JS2VAL_IS_NULL(av) || !JS2VAL_IS_OBJECT(av)) + reportError(Exception::badValueError, "Namespace expected in qualifier", p->pos); + JS2Object *obj = JS2VAL_TO_OBJECT(av); + if ((obj->kind != AttributeObjectKind) || (checked_cast(obj)->attrKind != Attribute::NamespaceAttr)) + reportError(Exception::badValueError, "Namespace expected in qualifier", p->pos); + Namespace *ns = checked_cast(obj); + + returnRef = new LexicalReference(name, ns, cxt.strict); + ((LexicalReference *)returnRef)->emitBindBytecode(bCon, p->pos); } break; case ExprNode::identifier: { IdentifierExprNode *i = checked_cast(p); returnRef = new LexicalReference(i->name, cxt.strict); - ((LexicalReference *)returnRef)->emitBindBytecode(bCon); + ((LexicalReference *)returnRef)->emitBindBytecode(bCon, p->pos); } break; case ExprNode::boolean: if (checked_cast(p)->value) - bCon->emitOp(eTrue); + bCon->emitOp(eTrue, p->pos); else - bCon->emitOp(eFalse); + bCon->emitOp(eFalse, p->pos); break; case ExprNode::objectLiteral: { @@ -636,16 +645,16 @@ namespace MetaData { while (e) { ASSERT(e->field && e->value); Reference *rVal = EvalExprNode(env, phase, e->value); - if (rVal) rVal->emitReadBytecode(bCon); + if (rVal) rVal->emitReadBytecode(bCon, p->pos); switch (e->field->getKind()) { case ExprNode::identifier: - bCon->addString(checked_cast(e->field)->name); + bCon->addString(checked_cast(e->field)->name, p->pos); break; case ExprNode::string: - bCon->addString(checked_cast(e->field)->str); + bCon->addString(checked_cast(e->field)->str, p->pos); break; case ExprNode::number: - bCon->addString(numberToString(&(checked_cast(e->field))->value)); + bCon->addString(numberToString(&(checked_cast(e->field))->value), p->pos); break; default: NOT_REACHED("bad field name"); @@ -742,14 +751,12 @@ namespace MetaData { Frame *pf = firstFrame; while (pf) { js2val rval; - // have to wrap the frame in a Monkey object in order - // to have readProperty handle it... if (meta->readProperty(pf, multiname, &lookup, phase, &rval)) return rval; pf = pf->nextFrame; } - meta->reportError(Exception::referenceError, "{0} is undefined", meta->errorPos, multiname->name); + meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name); return JS2VAL_VOID; } @@ -758,8 +765,6 @@ namespace MetaData { LookupKind lookup(true, findThis(false)); Frame *pf = firstFrame; while (pf) { - // have to wrap the frame in a Monkey object in order - // to have readProperty handle it... if (meta->writeProperty(pf, multiname, &lookup, false, newValue, phase)) return; pf = pf->nextFrame; @@ -771,7 +776,7 @@ namespace MetaData { return; } } - meta->reportError(Exception::referenceError, "{0} is undefined", meta->errorPos, multiname->name); + meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name); } @@ -842,10 +847,9 @@ namespace MetaData { publicNamespaceList.push_back(publicNamespace); namespaces = &publicNamespaceList; } - Multiname *mn = new Multiname(id, true); + Multiname *mn = new Multiname(id); mn->addNamespace(namespaces); - for (StaticBindingIterator b = localFrame->staticReadBindings.lower_bound(id), end = localFrame->staticReadBindings.upper_bound(id); (b != end); b++) { if (mn->matches(b->second->qname)) @@ -1003,7 +1007,8 @@ namespace MetaData { if (!multiname->onList(publicNamespace)) return false; const StringAtom &name = multiname->name; - if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", errorPos); + if (phase == CompilePhase) + reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos()); DynamicPropertyMap *dMap = NULL; bool isPrototypeInstance = false; if (container->kind == DynamicInstanceKind) @@ -1093,7 +1098,7 @@ namespace MetaData { return false; // 'None' switch (m->kind) { case StaticMember::Forbidden: - reportError(Exception::propertyAccessError, "Forbidden access", errorPos); + reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos()); break; case StaticMember::Variable: *rval = (checked_cast(m))->value; @@ -1117,7 +1122,7 @@ namespace MetaData { switch (m->kind) { case StaticMember::Forbidden: case StaticMember::ConstructorMethod: - reportError(Exception::propertyAccessError, "Forbidden access", errorPos); + reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos()); break; case StaticMember::Variable: (checked_cast(m))->value = newValue; @@ -1187,7 +1192,7 @@ namespace MetaData { } if (multiname->matches(b->second->qname)) { if (found && (b->second->content != found)) - reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", errorPos, multiname->name); + reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name); else found = b->second->content; } @@ -1229,7 +1234,7 @@ namespace MetaData { } if (multiname->matches(b->second->qname)) { if (result && (b->second->content != result->content)) - reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", errorPos, multiname->name); + reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name); else result = b->second; } diff --git a/js2/src/js2metadata.h b/js2/src/js2metadata.h index 1d52c0dcb8e7..3c45e06d413d 100644 --- a/js2/src/js2metadata.h +++ b/js2/src/js2metadata.h @@ -145,9 +145,7 @@ public: virtual CompoundAttribute *toCompoundAttribute() { ASSERT(false); return NULL; } - AttributeKind attrKind; - }; // A Namespace (is also an attribute) @@ -179,12 +177,10 @@ typedef std::vector NamespaceList; typedef NamespaceList::iterator NamespaceListIterator; class Multiname : public JS2Object { public: + Multiname(const StringAtom &name) : JS2Object(MultinameKind), name(name) { } + Multiname(const StringAtom &name, Namespace *ns) : JS2Object(MultinameKind), name(name) { addNamespace(ns); } - Multiname(const StringAtom &name) : JS2Object(MultinameKind), name(name), qualified(false) { } - Multiname(const StringAtom &name, bool qualified) : JS2Object(MultinameKind), name(name), qualified(qualified) { } - - - void emitBytecode(BytecodeContainer *bCon) { bCon->emitOp(qualified ? eQMultiname : eMultiname); bCon->addMultiname(this); } + void emitBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eMultiname, pos); bCon->addMultiname(this); } void addNamespace(Namespace *ns) { nsList.push_back(ns); } void addNamespace(NamespaceList *ns); @@ -195,7 +191,6 @@ public: NamespaceList nsList; const StringAtom &name; - bool qualified; // true for q::a, otherwise false }; @@ -446,10 +441,10 @@ public: // References are generated during the eval stage (bytecode generation) class Reference { public: - virtual void emitReadBytecode(BytecodeContainer *bCon) { ASSERT(false); } - virtual void emitWriteBytecode(BytecodeContainer *bCon) { ASSERT(false); } - virtual void emitDeleteBytecode(BytecodeContainer *bCon) { ASSERT(false); }; - virtual void emitReadForInvokeBytecode(BytecodeContainer *bCon) { ASSERT(false); } + virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); } + virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); } + virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }; + virtual void emitReadForInvokeBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); } }; class LexicalReference : public Reference { @@ -458,7 +453,7 @@ class LexicalReference : public Reference { // q::a. public: LexicalReference(const StringAtom &name, bool strict) : variableMultiname(new Multiname(name)), env(NULL), strict(strict) { } - LexicalReference(const StringAtom &name, bool strict, bool qualified) : variableMultiname(new Multiname(name, qualified)), env(NULL), strict(strict) { } + LexicalReference(const StringAtom &name, Namespace *nameSpace, bool strict) : variableMultiname(new Multiname(name, nameSpace)), env(NULL), strict(strict) { } Multiname *variableMultiname; // A nonempty set of qualified names to which this reference can refer @@ -466,9 +461,9 @@ public: bool strict; // The strict setting from the context in effect at the point where the reference was created - void emitBindBytecode(BytecodeContainer *bCon) { variableMultiname->emitBytecode(bCon); } - virtual void emitReadBytecode(BytecodeContainer *bCon) { bCon->emitOp(eLexicalRead); } - virtual void emitWriteBytecode(BytecodeContainer *bCon) { bCon->emitOp(eLexicalWrite); } + void emitBindBytecode(BytecodeContainer *bCon, size_t pos) { variableMultiname->emitBytecode(bCon, pos); } + virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eLexicalRead, pos); } + virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eLexicalWrite, pos); } }; class DotReference : public Reference { @@ -687,7 +682,6 @@ public: JS2Class *namespaceClass; Parser *mParser; // used for error reporting - size_t errorPos; BytecodeContainer *bCon; // the current output container diff --git a/js2/src/js2op_access.cpp b/js2/src/js2op_access.cpp index 7a48734cd8ae..4994844a8509 100644 --- a/js2/src/js2op_access.cpp +++ b/js2/src/js2op_access.cpp @@ -40,7 +40,7 @@ push(OBJECT_TO_JS2VAL(mn)); } break; - +#if 0 // Get a multiname literal and pop a namespace value to add to it // Push the resulting multiname object case eQMultiname: { @@ -56,7 +56,7 @@ push(OBJECT_TO_JS2VAL(mn)); } break; - +#endif // Pop a multiname object and read it's value from the environment on to the stack. case eLexicalRead: { js2val mnVal = pop(); @@ -85,10 +85,10 @@ case eUse: { js2val nsVal = pop(); if (!JS2VAL_IS_OBJECT(nsVal)) - meta->reportError(Exception::badValueError, "Expected a namespace", meta->errorPos); + meta->reportError(Exception::badValueError, "Expected a namespace", meta->engine->errorPos()); JS2Object *obj = JS2VAL_TO_OBJECT(nsVal); if ((obj->kind != AttributeObjectKind) || ((checked_cast(obj))->attrKind != Attribute::NamespaceAttr)) - meta->reportError(Exception::badValueError, "Expected a namespace", meta->errorPos); + meta->reportError(Exception::badValueError, "Expected a namespace", meta->engine->errorPos()); } break; \ No newline at end of file