Back out 104ba36f44c0 (bug 845596) for jsreftest assertions

CLOSED TREE
This commit is contained in:
Phil Ringnalda 2013-04-13 19:15:33 -07:00
parent d5678418dc
commit 398123c900
9 changed files with 290 additions and 359 deletions

View File

@ -48,7 +48,7 @@ class FullParseHandler
foldConstants(foldConstants)
{}
static ParseNode *null() { return NULL; }
static Definition *null() { return NULL; }
ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
@ -62,16 +62,6 @@ class FullParseHandler
pn->setOp(JSOP_NAME);
return pn;
}
Definition *newPlaceholder(ParseNode *pn, ParseContext<FullParseHandler> *pc) {
Definition *dn = (Definition *) NameNode::create(PNK_NAME, pn->pn_atom, this, pc);
if (!dn)
return NULL;
dn->setOp(JSOP_NOP);
dn->setDefn(true);
dn->pn_dflags |= PND_PLACEHOLDER;
return dn;
}
ParseNode *newAtom(ParseNodeKind kind, JSAtom *atom, JSOp op = JSOP_NOP) {
ParseNode *pn = NullaryNode::create(kind, this);
if (!pn)
@ -178,9 +168,6 @@ class FullParseHandler
void setFunctionBox(ParseNode *pn, FunctionBox *funbox) {
pn->pn_funbox = funbox;
}
void addFunctionArgument(ParseNode *pn, ParseNode *argpn) {
pn->pn_body->append(argpn);
}
inline ParseNode *newLexicalScope(ObjectBox *blockbox);
bool isOperationWithoutParens(ParseNode *pn, ParseNodeKind kind) {
return pn->isKind(kind) && !pn->isInParens();
@ -205,9 +192,6 @@ class FullParseHandler
JS_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
}
void setPosition(ParseNode *pn, const TokenPos &pos) {
pn->pn_pos = pos;
}
TokenPos getPosition(ParseNode *pn) {
return pn->pn_pos;
}
@ -270,50 +254,6 @@ class FullParseHandler
}
inline ParseNode *makeAssignment(ParseNode *pn, ParseNode *rhs);
static Definition *getDefinitionNode(Definition *dn) {
return dn;
}
static Definition::Kind getDefinitionKind(Definition *dn) {
return dn->kind();
}
void linkUseToDef(ParseNode *pn, Definition *dn)
{
JS_ASSERT(!pn->isUsed());
JS_ASSERT(!pn->isDefn());
JS_ASSERT(pn != dn->dn_uses);
JS_ASSERT(dn->isDefn());
pn->pn_link = dn->dn_uses;
dn->dn_uses = pn;
dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
pn->setUsed(true);
pn->pn_lexdef = dn;
}
Definition *resolve(Definition *dn) {
return dn->resolve();
}
void deoptimizeUsesWithin(Definition *dn, const TokenPos &pos)
{
for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
JS_ASSERT(pnu->isUsed());
JS_ASSERT(!pnu->isDefn());
if (pnu->pn_pos.begin >= pos.begin && pnu->pn_pos.end <= pos.end)
pnu->pn_dflags |= PND_DEOPTIMIZED;
}
}
bool dependencyCovered(ParseNode *pn, unsigned blockid, bool functionScope) {
return pn->pn_blockid >= blockid;
}
static uintptr_t definitionToBits(Definition *dn) {
return uintptr_t(dn);
}
static Definition *definitionFromBits(uintptr_t bits) {
return (Definition *) bits;
}
static Definition *nullDefinition() {
return NULL;
}
};
inline bool

View File

@ -48,20 +48,18 @@ ParseMapPool::allocate()
return map;
}
template <typename ParseHandler>
inline typename ParseHandler::DefinitionNode
AtomDecls<ParseHandler>::lookupFirst(JSAtom *atom) const
inline Definition *
AtomDecls::lookupFirst(JSAtom *atom) const
{
JS_ASSERT(map);
AtomDefnListPtr p = map->lookup(atom);
if (!p)
return ParseHandler::nullDefinition();
return p.value().front<ParseHandler>();
return NULL;
return p.value().front();
}
template <typename ParseHandler>
inline DefinitionList::Range
AtomDecls<ParseHandler>::lookupMulti(JSAtom *atom) const
AtomDecls::lookupMulti(JSAtom *atom) const
{
JS_ASSERT(map);
if (AtomDefnListPtr p = map->lookup(atom))
@ -69,16 +67,15 @@ AtomDecls<ParseHandler>::lookupMulti(JSAtom *atom) const
return DefinitionList::Range();
}
template <typename ParseHandler>
inline bool
AtomDecls<ParseHandler>::addUnique(JSAtom *atom, DefinitionNode defn)
AtomDecls::addUnique(JSAtom *atom, Definition *defn)
{
JS_ASSERT(map);
AtomDefnListAddPtr p = map->lookupForAdd(atom);
if (!p)
return map->add(p, atom, DefinitionList(ParseHandler::definitionToBits(defn)));
return map->add(p, atom, DefinitionList(defn));
JS_ASSERT(!p.value().isMultiple());
p.value() = DefinitionList(ParseHandler::definitionToBits(defn));
p.value() = DefinitionList(defn);
return true;
}
@ -102,17 +99,15 @@ AtomThingMapPtr<Map>::releaseMap(JSContext *cx)
map_ = NULL;
}
template <typename ParseHandler>
inline bool
AtomDecls<ParseHandler>::init()
AtomDecls::init()
{
map = cx->parseMapPool().acquire<AtomDefnListMap>();
return map;
}
template <typename ParseHandler>
inline
AtomDecls<ParseHandler>::~AtomDecls()
AtomDecls::~AtomDecls()
{
if (map)
cx->parseMapPool().release(map);

View File

@ -5,12 +5,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ParseMaps-inl.h"
#include "jscntxt.h"
#include "jscompartment.h"
#include "FullParseHandler.h"
#include "SyntaxParseHandler.h"
#include "ParseMaps-inl.h"
#include "vm/String-inl.h"
using namespace js;
@ -60,7 +58,7 @@ ParseMapPool::allocateFresh()
}
DefinitionList::Node *
DefinitionList::allocNode(JSContext *cx, uintptr_t head, Node *tail)
DefinitionList::allocNode(JSContext *cx, Definition *head, Node *tail)
{
Node *result = cx->tempLifoAlloc().new_<Node>(head, tail);
if (!result)
@ -68,17 +66,58 @@ DefinitionList::allocNode(JSContext *cx, uintptr_t head, Node *tail)
return result;
}
bool
DefinitionList::pushFront(JSContext *cx, Definition *val)
{
Node *tail;
if (isMultiple()) {
tail = firstNode();
} else {
tail = allocNode(cx, defn(), NULL);
if (!tail)
return false;
}
Node *node = allocNode(cx, val, tail);
if (!node)
return false;
*this = DefinitionList(node);
return true;
}
bool
DefinitionList::pushBack(JSContext *cx, Definition *val)
{
Node *last;
if (isMultiple()) {
last = firstNode();
while (last->next)
last = last->next;
} else {
last = allocNode(cx, defn(), NULL);
if (!last)
return false;
}
Node *node = allocNode(cx, val, NULL);
if (!node)
return false;
last->next = node;
if (!isMultiple())
*this = DefinitionList(last);
return true;
}
#ifdef DEBUG
template <typename ParseHandler>
void
AtomDecls<ParseHandler>::dump()
AtomDecls::dump()
{
for (AtomDefnListRange r = map->all(); !r.empty(); r.popFront()) {
fprintf(stderr, "atom: ");
js_DumpAtom(r.front().key());
const DefinitionList &dlist = r.front().value();
for (DefinitionList::Range dr = dlist.all(); !dr.empty(); dr.popFront()) {
fprintf(stderr, " defn: %p\n", (void *) dr.front<ParseHandler>());
fprintf(stderr, " defn: %p\n", (void *) dr.front());
}
}
}
@ -94,20 +133,19 @@ DumpAtomDefnMap(const AtomDefnMapPtr &map)
for (AtomDefnRange r = map->all(); !r.empty(); r.popFront()) {
fprintf(stderr, "atom: ");
js_DumpAtom(r.front().key());
fprintf(stderr, "defn: %p\n", (void *) r.front().value().get<FullParseHandler>());
fprintf(stderr, "defn: %p\n", (void *) r.front().value());
}
}
#endif
template <typename ParseHandler>
bool
AtomDecls<ParseHandler>::addShadow(JSAtom *atom, typename ParseHandler::DefinitionNode defn)
AtomDecls::addShadow(JSAtom *atom, Definition *defn)
{
AtomDefnListAddPtr p = map->lookupForAdd(atom);
if (!p)
return map->add(p, atom, DefinitionList(ParseHandler::definitionToBits(defn)));
return map->add(p, atom, DefinitionList(defn));
return p.value().pushFront<ParseHandler>(cx, defn);
return p.value().pushFront(cx, defn);
}
void
@ -133,6 +171,3 @@ frontend::InitAtomMap(JSContext *cx, frontend::AtomIndexMap *indices, HeapPtrAto
}
}
}
template class AtomDecls<FullParseHandler>;
template class AtomDecls<SyntaxParseHandler>;

View File

@ -18,11 +18,11 @@
namespace js {
namespace frontend {
class DefinitionSingle;
struct Definition;
class DefinitionList;
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
typedef InlineMap<JSAtom *, DefinitionSingle, 24> AtomDefnMap;
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
typedef InlineMap<JSAtom *, DefinitionList, 24> AtomDefnListMap;
/*
@ -135,6 +135,15 @@ struct AtomThingMapPtr
Map &operator*() const { return *map_; }
};
struct AtomDefnMapPtr : public AtomThingMapPtr<AtomDefnMap>
{
JS_ALWAYS_INLINE
Definition *lookupDefn(JSAtom *atom) {
AtomDefnMap::Ptr p = map_->lookup(atom);
return p ? p.value() : NULL;
}
};
typedef AtomThingMapPtr<AtomIndexMap> AtomIndexMapPtr;
/*
@ -156,48 +165,8 @@ class OwnedAtomThingMapPtr : public AtomThingMapPtrT
}
};
typedef OwnedAtomThingMapPtr<AtomIndexMapPtr> OwnedAtomIndexMapPtr;
/*
* DefinitionSingle and DefinitionList represent either a single definition
* or a list of them. The representation of definitions varies between
* parse handlers, being either a Definition* (FullParseHandler) or a
* Definition::Kind (SyntaxParseHandler). Methods on the below classes are
* templated to distinguish the kind of value wrapped by the class.
*/
/* Wrapper for a single definition. */
class DefinitionSingle
{
uintptr_t bits;
public:
template <typename ParseHandler>
static DefinitionSingle new_(typename ParseHandler::DefinitionNode defn)
{
DefinitionSingle res;
res.bits = ParseHandler::definitionToBits(defn);
return res;
}
template <typename ParseHandler>
typename ParseHandler::DefinitionNode get() {
return ParseHandler::definitionFromBits(bits);
}
};
struct AtomDefnMapPtr : public AtomThingMapPtr<AtomDefnMap>
{
template <typename ParseHandler>
JS_ALWAYS_INLINE
typename ParseHandler::DefinitionNode lookupDefn(JSAtom *atom) {
AtomDefnMap::Ptr p = map_->lookup(atom);
return p ? p.value().get<ParseHandler>() : ParseHandler::nullDefinition();
}
};
typedef OwnedAtomThingMapPtr<AtomDefnMapPtr> OwnedAtomDefnMapPtr;
typedef OwnedAtomThingMapPtr<AtomIndexMapPtr> OwnedAtomIndexMapPtr;
/*
* A nonempty list containing one or more pointers to Definitions.
@ -222,24 +191,30 @@ class DefinitionList
/* A node in a linked list of Definitions. */
struct Node
{
uintptr_t bits;
Definition *defn;
Node *next;
Node(uintptr_t bits, Node *next) : bits(bits), next(next) {}
Node(Definition *defn, Node *next) : defn(defn), next(next) {}
};
union {
uintptr_t bits;
Definition *defn;
Node *head;
uintptr_t bits;
} u;
Definition *defn() const {
JS_ASSERT(!isMultiple());
return u.defn;
}
Node *firstNode() const {
JS_ASSERT(isMultiple());
return (Node *) (u.bits & ~0x1);
}
static Node *
allocNode(JSContext *cx, uintptr_t bits, Node *tail);
allocNode(JSContext *cx, Definition *head, Node *tail);
public:
class Range
@ -247,41 +222,40 @@ class DefinitionList
friend class DefinitionList;
Node *node;
uintptr_t bits;
Definition *defn;
explicit Range(const DefinitionList &list) {
if (list.isMultiple()) {
node = list.firstNode();
bits = node->bits;
defn = node->defn;
} else {
node = NULL;
bits = list.u.bits;
defn = list.defn();
}
}
public:
/* An empty Range. */
Range() : node(NULL), bits(0) {}
Range() : node(NULL), defn(NULL) {}
void popFront() {
JS_ASSERT(!empty());
if (!node) {
bits = 0;
defn = NULL;
return;
}
node = node->next;
bits = node ? node->bits : 0;
defn = node ? node->defn : NULL;
}
template <typename ParseHandler>
typename ParseHandler::DefinitionNode front() {
Definition *front() {
JS_ASSERT(!empty());
return ParseHandler::definitionFromBits(bits);
return defn;
}
bool empty() const {
JS_ASSERT_IF(!bits, !node);
return !bits;
JS_ASSERT_IF(!defn, !node);
return !defn;
}
};
@ -289,8 +263,8 @@ class DefinitionList
u.bits = 0;
}
explicit DefinitionList(uintptr_t bits) {
u.bits = bits;
explicit DefinitionList(Definition *defn) {
u.defn = defn;
JS_ASSERT(!isMultiple());
}
@ -302,9 +276,8 @@ class DefinitionList
bool isMultiple() const { return (u.bits & 0x1) != 0; }
template <typename ParseHandler>
typename ParseHandler::DefinitionNode front() {
return ParseHandler::definitionFromBits(isMultiple() ? firstNode()->bits : u.bits);
Definition *front() {
return isMultiple() ? firstNode()->defn : defn();
}
/*
@ -321,7 +294,7 @@ class DefinitionList
if (next->next)
*this = DefinitionList(next);
else
*this = DefinitionList(next->bits);
*this = DefinitionList(next->defn);
return true;
}
@ -330,31 +303,17 @@ class DefinitionList
*
* Return true on success. On OOM, report on cx and return false.
*/
template <typename ParseHandler>
bool pushFront(JSContext *cx, typename ParseHandler::DefinitionNode defn) {
Node *tail;
if (isMultiple()) {
tail = firstNode();
} else {
tail = allocNode(cx, u.bits, NULL);
if (!tail)
return false;
}
bool pushFront(JSContext *cx, Definition *val);
Node *node = allocNode(cx, ParseHandler::definitionToBits(defn), tail);
if (!node)
return false;
*this = DefinitionList(node);
return true;
}
/* Like pushFront, but add the given val to the end of the list. */
bool pushBack(JSContext *cx, Definition *val);
/* Overwrite the first Definition in the list. */
template <typename ParseHandler>
void setFront(typename ParseHandler::DefinitionNode defn) {
void setFront(Definition *val) {
if (isMultiple())
firstNode()->bits = ParseHandler::definitionToBits(defn);
firstNode()->defn = val;
else
*this = DefinitionList(ParseHandler::definitionToBits(defn));
*this = DefinitionList(val);
}
Range all() const { return Range(*this); }
@ -382,11 +341,8 @@ class DefinitionList
* method addShadow. When we leave the block associated with the let, the method
* remove is used to unshadow the declaration immediately preceding it.
*/
template <typename ParseHandler>
class AtomDecls
{
typedef typename ParseHandler::DefinitionNode DefinitionNode;
/* AtomDeclsIter needs to get at the DefnListMap directly. */
friend class AtomDeclsIter;
@ -408,21 +364,21 @@ class AtomDecls
}
/* Return the definition at the head of the chain for |atom|. */
inline DefinitionNode lookupFirst(JSAtom *atom) const;
inline Definition *lookupFirst(JSAtom *atom) const;
/* Perform a lookup that can iterate over the definitions associated with |atom|. */
inline DefinitionList::Range lookupMulti(JSAtom *atom) const;
/* Add-or-update a known-unique definition for |atom|. */
inline bool addUnique(JSAtom *atom, DefinitionNode defn);
bool addShadow(JSAtom *atom, DefinitionNode defn);
inline bool addUnique(JSAtom *atom, Definition *defn);
bool addShadow(JSAtom *atom, Definition *defn);
/* Updating the definition for an entry that is known to exist is infallible. */
void updateFirst(JSAtom *atom, DefinitionNode defn) {
void updateFirst(JSAtom *atom, Definition *defn) {
JS_ASSERT(map);
AtomDefnListMap::Ptr p = map->lookup(atom);
JS_ASSERT(p);
p.value().setFront<ParseHandler>(defn);
p.value().setFront(defn);
}
/* Remove the node at the head of the chain for |atom|. */
@ -464,9 +420,6 @@ typedef AtomDefnListMap::Range AtomDefnListRange;
namespace mozilla {
template <>
struct IsPod<js::frontend::DefinitionSingle> : TrueType {};
template <>
struct IsPod<js::frontend::DefinitionList> : TrueType {};

View File

@ -461,7 +461,7 @@ Parser<FullParseHandler>::cloneParseTree(ParseNode *opn)
*/
if (opn->isDefn()) {
opn->setDefn(false);
handler.linkUseToDef(opn, (Definition *) pn);
LinkUseToDef(opn, (Definition *) pn);
}
}
break;
@ -552,7 +552,7 @@ Parser<FullParseHandler>::cloneLeftHandSide(ParseNode *opn)
pn->pn_dflags &= ~PND_BOUND;
pn->setDefn(false);
handler.linkUseToDef(pn, (Definition *) opn);
LinkUseToDef(pn, (Definition *) opn);
}
}
return pn;

View File

@ -12,6 +12,7 @@
#include "jsscript.h"
#include "frontend/ParseMaps.h"
#include "frontend/TokenStream.h"
namespace js {
@ -1214,7 +1215,7 @@ struct Definition : public ParseNode
return pn_cookie.isFree();
}
enum Kind { MISSING = 0, VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
enum Kind { VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
bool canHaveInitializer() { return int(kind()) <= int(ARG); }
@ -1297,6 +1298,19 @@ ParseNode::isConstant()
}
}
inline void
LinkUseToDef(ParseNode *pn, Definition *dn)
{
JS_ASSERT(!pn->isUsed());
JS_ASSERT(!pn->isDefn());
JS_ASSERT(pn != dn->dn_uses);
pn->pn_link = dn->dn_uses;
dn->dn_uses = pn;
dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
pn->setUsed(true);
pn->pn_lexdef = dn;
}
class ObjectBox {
public:
JSObject *object;

View File

@ -125,7 +125,7 @@ ParseContext<FullParseHandler>::define(JSContext *cx, HandlePropertyName name,
JS_ASSERT(!decls_.lookupFirst(name));
if (!prevDef)
prevDef = lexdeps.lookupDefn<FullParseHandler>(name);
prevDef = lexdeps.lookupDefn(name);
if (prevDef) {
ParseNode **pnup = &prevDef->dn_uses;
@ -196,7 +196,8 @@ ParseContext<FullParseHandler>::define(JSContext *cx, HandlePropertyName name,
return false;
break;
default:
case Definition::PLACEHOLDER:
case Definition::NAMED_LAMBDA:
JS_NOT_REACHED("unexpected kind");
break;
}
@ -209,20 +210,17 @@ bool
ParseContext<SyntaxParseHandler>::define(JSContext *cx, HandlePropertyName name, Node pn,
Definition::Kind kind)
{
JS_ASSERT(!decls_.lookupFirst(name));
if (lexdeps.lookupDefn<SyntaxParseHandler>(name))
lexdeps->remove(name);
return decls_.addUnique(name, kind);
return true;
}
template <typename ParseHandler>
void
ParseContext<ParseHandler>::prepareToAddDuplicateArg(HandlePropertyName name, DefinitionNode prevDecl)
ParseContext<ParseHandler>::prepareToAddDuplicateArg(Definition *prevDecl)
{
JS_ASSERT(decls_.lookupFirst(name) == prevDecl);
decls_.remove(name);
JS_ASSERT(prevDecl->kind() == Definition::ARG);
JS_ASSERT(decls_.lookupFirst(prevDecl->name()) == prevDecl);
JS_ASSERT(!prevDecl->isClosed());
decls_.remove(prevDecl->name());
}
template <typename ParseHandler>
@ -260,7 +258,7 @@ template <typename ParseHandler>
void
ParseContext<ParseHandler>::popLetDecl(JSAtom *atom)
{
JS_ASSERT(ParseHandler::getDefinitionKind(decls_.lookupFirst(atom)) == Definition::LET);
JS_ASSERT(decls_.lookupFirst(atom)->isLet());
decls_.remove(atom);
}
@ -283,7 +281,9 @@ AppendPackedBindings(const ParseContext<ParseHandler> *pc, const DeclVector &vec
case Definition::ARG:
kind = ARGUMENT;
break;
default:
case Definition::LET:
case Definition::NAMED_LAMBDA:
case Definition::PLACEHOLDER:
JS_NOT_REACHED("unexpected dn->kind");
}
@ -821,6 +821,11 @@ Parser<ParseHandler>::checkStrictBinding(HandlePropertyName name, Node pn)
return true;
}
template <>
bool
Parser<FullParseHandler>::defineArg(ParseNode *funcpn, HandlePropertyName name,
bool disallowDuplicateArgs, Definition **duplicatedArg);
template <>
ParseNode *
Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
@ -870,21 +875,27 @@ template <>
bool
Parser<FullParseHandler>::checkFunctionArguments()
{
/* Time to implement the odd semantics of 'arguments'. */
HandlePropertyName arguments = context->names().arguments;
/*
* Non-top-level functions use JSOP_DEFFUN which is a dynamic scope
* operation which means it aliases any bindings with the same name.
* Due to the implicit declaration mechanism (below), 'arguments' will not
* have decls and, even if it did, they will not be noted as closed in the
* emitter. Thus, in the corner case of function-statement-overridding-
* arguments, flag the whole scope as dynamic.
*/
if (FuncStmtSet *set = pc->funcStmts) {
for (FuncStmtSet::Range r = set->all(); !r.empty(); r.popFront()) {
PropertyName *name = r.front()->asPropertyName();
if (Definition *dn = pc->decls().lookupFirst(name))
if (name == arguments)
pc->sc->setBindingsAccessedDynamically();
else if (Definition *dn = pc->decls().lookupFirst(name))
dn->pn_dflags |= PND_CLOSED;
}
}
/* Time to implement the odd semantics of 'arguments'. */
HandlePropertyName arguments = context->names().arguments;
/*
* As explained by the ContextFlags::funArgumentsHasLocalBinding comment,
* create a declaration for 'arguments' if there are any unbound uses in
@ -892,7 +903,7 @@ Parser<FullParseHandler>::checkFunctionArguments()
*/
for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
if (r.front().key() == arguments) {
Definition *dn = r.front().value().get<FullParseHandler>();
Definition *dn = r.front().value();
pc->lexdeps->remove(arguments);
dn->pn_dflags |= PND_IMPLICITARGUMENTS;
if (!pc->define(context, arguments, dn, Definition::VAR))
@ -968,7 +979,7 @@ Parser<FullParseHandler>::checkFunctionArguments()
for (AtomDefnListMap::Range r = pc->decls().all(); !r.empty(); r.popFront()) {
DefinitionList &dlist = r.front().value();
for (DefinitionList::Range dr = dlist.all(); !dr.empty(); dr.popFront()) {
Definition *dn = dr.front<FullParseHandler>();
Definition *dn = dr.front();
if (dn->kind() == Definition::ARG && dn->isAssigned())
funbox->setDefinitelyNeedsArgsObj();
}
@ -1034,6 +1045,23 @@ Parser<ParseHandler>::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ
return pn;
}
// Create a placeholder Definition node for |atom|.
// Nb: unlike most functions that are passed a Parser, this one gets a
// SharedContext passed in separately, because in this case |pc| may not equal
// |parser->pc|.
static Definition *
MakePlaceholder(ParseNode *pn, FullParseHandler *handler, ParseContext<FullParseHandler> *pc)
{
Definition *dn = (Definition *) NameNode::create(PNK_NAME, pn->pn_atom, handler, pc);
if (!dn)
return NULL;
dn->setOp(JSOP_NOP);
dn->setDefn(true);
dn->pn_dflags |= PND_PLACEHOLDER;
return dn;
}
static void
ForgetUse(ParseNode *pn)
{
@ -1225,6 +1253,23 @@ MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts)
return true;
}
static bool
DeoptimizeUsesWithin(Definition *dn, const TokenPos &pos)
{
unsigned ndeoptimized = 0;
for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
JS_ASSERT(pnu->isUsed());
JS_ASSERT(!pnu->isDefn());
if (pnu->pn_pos.begin >= pos.begin && pnu->pn_pos.end <= pos.end) {
pnu->pn_dflags |= PND_DEOPTIMIZED;
++ndeoptimized;
}
}
return ndeoptimized != 0;
}
/*
* Beware: this function is called for functions nested in other functions or
* global scripts but not for functions compiled through the Function
@ -1249,7 +1294,7 @@ Parser<FullParseHandler>::leaveFunction(ParseNode *fn, HandlePropertyName funNam
if (pc->lexdeps->count()) {
for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
JSAtom *atom = r.front().key();
Definition *dn = r.front().value().get<FullParseHandler>();
Definition *dn = r.front().value();
JS_ASSERT(dn->isPlaceholder());
if (atom == funName && kind == Expression) {
@ -1292,12 +1337,12 @@ Parser<FullParseHandler>::leaveFunction(ParseNode *fn, HandlePropertyName funNam
* having an extensible scope) or any enclosing 'with'.
*/
if (funbox->hasExtensibleScope() || outerpc->parsingWith)
handler.deoptimizeUsesWithin(dn, fn->pn_pos);
DeoptimizeUsesWithin(dn, fn->pn_pos);
if (!outer_dn) {
AtomDefnAddPtr p = outerpc->lexdeps->lookupForAdd(atom);
if (p) {
outer_dn = p.value().get<FullParseHandler>();
outer_dn = p.value();
} else {
/*
* Create a new placeholder for our outer lexdep. We could
@ -1320,11 +1365,8 @@ Parser<FullParseHandler>::leaveFunction(ParseNode *fn, HandlePropertyName funNam
* inherited lexdeps into uses of a new outer definition
* allows us to handle both these cases in a natural way.
*/
outer_dn = handler.newPlaceholder(dn, outerpc);
if (!outer_dn)
return false;
DefinitionSingle def = DefinitionSingle::new_<FullParseHandler>(outer_dn);
if (!outerpc->lexdeps->add(p, atom, def))
outer_dn = MakePlaceholder(dn, &handler, outerpc);
if (!outer_dn || !outerpc->lexdeps->add(p, atom, outer_dn))
return false;
}
}
@ -1396,28 +1438,26 @@ Parser<SyntaxParseHandler>::leaveFunction(Node fn, HandlePropertyName funName,
* argument with the same name. The caller may use this to report an error when
* one of the abovementioned features occurs after a duplicate.
*/
template <typename ParseHandler>
template <>
bool
Parser<ParseHandler>::defineArg(Node funcpn, HandlePropertyName name,
bool disallowDuplicateArgs, Node *duplicatedArg)
Parser<FullParseHandler>::defineArg(ParseNode *funcpn, HandlePropertyName name,
bool disallowDuplicateArgs, Definition **duplicatedArg)
{
SharedContext *sc = pc->sc;
/* Handle duplicate argument names. */
if (DefinitionNode prevDecl = pc->decls().lookupFirst(name)) {
Node pn = handler.getDefinitionNode(prevDecl);
if (Definition *prevDecl = pc->decls().lookupFirst(name)) {
/*
* Strict-mode disallows duplicate args. We may not know whether we are
* in strict mode or not (since the function body hasn't been parsed).
* In such cases, report will queue up the potential error and return
* 'true'.
* In such cases, reportStrictModeError will queue up the potential
* error and return 'true'.
*/
if (sc->needStrictChecks()) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(context, name, &bytes))
return false;
if (!report(ParseStrictError, pc->sc->strict, pn,
if (!report(ParseStrictError, pc->sc->strict, prevDecl,
JSMSG_DUPLICATE_FORMAL, bytes.ptr()))
{
return false;
@ -1425,29 +1465,36 @@ Parser<ParseHandler>::defineArg(Node funcpn, HandlePropertyName name,
}
if (disallowDuplicateArgs) {
report(ParseError, false, pn, JSMSG_BAD_DUP_ARGS);
report(ParseError, false, prevDecl, JSMSG_BAD_DUP_ARGS);
return false;
}
if (duplicatedArg)
*duplicatedArg = pn;
*duplicatedArg = prevDecl;
/* ParseContext::define assumes and asserts prevDecl is not in decls. */
JS_ASSERT(handler.getDefinitionKind(prevDecl) == Definition::ARG);
pc->prepareToAddDuplicateArg(name, prevDecl);
pc->prepareToAddDuplicateArg(prevDecl);
}
Node argpn = handler.newName(name, pc);
ParseNode *argpn = handler.newName(name, pc);
if (!argpn)
return false;
if (!checkStrictBinding(name, argpn))
return false;
handler.addFunctionArgument(funcpn, argpn);
funcpn->pn_body->append(argpn);
return pc->define(context, name, argpn, Definition::ARG);
}
template <>
bool
Parser<SyntaxParseHandler>::defineArg(Node funcpn, HandlePropertyName name,
bool disallowDuplicateArgs, DefinitionNode *duplicatedArg)
{
return true;
}
#if JS_HAS_DESTRUCTURING
template <typename ParseHandler>
/* static */ bool
@ -1500,7 +1547,7 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, Node *listp, No
if (parenFreeArrow || !tokenStream.matchToken(TOK_RP)) {
bool hasDefaults = false;
Node duplicatedArg = null();
DefinitionNode duplicatedArg = null();
bool destructuringArg = false;
#if JS_HAS_DESTRUCTURING
Node list = null();
@ -1690,7 +1737,7 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
* pre-created definition node for this function that primaryExpr
* put in pc->lexdeps on first forward reference, and recycle pn.
*/
if (Definition *fn = pc->lexdeps.lookupDefn<FullParseHandler>(funName)) {
if (Definition *fn = pc->lexdeps.lookupDefn(funName)) {
JS_ASSERT(fn->isDefn());
fn->setKind(PNK_FUNCTION);
fn->setArity(PN_CODE);
@ -1743,15 +1790,6 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
}
if (!pc->funcStmts->put(funName))
return false;
/*
* Due to the implicit declaration mechanism, 'arguments' will not
* have decls and, even if it did, they will not be noted as closed
* in the emitter. Thus, in the corner case of function statements
* overridding arguments, flag the whole scope as dynamic.
*/
if (funName == context->names().arguments)
pc->sc->setBindingsAccessedDynamically();
}
/* No further binding (in BindNameToSlot) is needed for functions. */
@ -1769,36 +1807,6 @@ bool
Parser<SyntaxParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
Node *pn, FunctionSyntaxKind kind)
{
/* Function statements add a binding to the enclosing scope. */
bool bodyLevel = pc->atBodyLevel();
if (kind == Statement) {
/*
* Handle redeclaration and optimize cases where we can statically bind the
* function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
*/
if (DefinitionNode dn = pc->decls().lookupFirst(funName)) {
if (dn == Definition::CONST) {
JSAutoByteString name;
if (!js_AtomToPrintableString(context, funName, &name) ||
!report(ParseError, false, null(), JSMSG_REDECLARED_VAR,
Definition::kindString(dn), name.ptr()))
{
return false;
}
}
} else if (bodyLevel) {
if (pc->lexdeps.lookupDefn<SyntaxParseHandler>(funName))
pc->lexdeps->remove(funName);
if (!pc->define(context, funName, *pn, Definition::VAR))
return false;
}
if (!bodyLevel && funName == context->names().arguments)
pc->sc->setBindingsAccessedDynamically();
}
return true;
}
@ -2466,17 +2474,17 @@ OuterLet(ParseContext<ParseHandler> *pc, StmtInfoPC *stmt, HandleAtom atom)
return false;
}
template <typename ParseHandler>
template <>
/* static */ bool
Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser)
Parser<FullParseHandler>::bindVarOrConst(JSContext *cx, BindData<FullParseHandler> *data,
HandlePropertyName name, Parser<FullParseHandler> *parser)
{
ParseContext<ParseHandler> *pc = parser->pc;
Node pn = data->pn;
ParseContext<FullParseHandler> *pc = parser->pc;
ParseNode *pn = data->pn;
bool isConstDecl = data->op == JSOP_DEFCONST;
/* Default best op for pn is JSOP_NAME; we'll try to improve below. */
parser->handler.setOp(pn, JSOP_NAME);
pn->setOp(JSOP_NAME);
if (!parser->checkStrictBinding(name, pn))
return false;
@ -2484,7 +2492,7 @@ Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data
StmtInfoPC *stmt = LexicalLookup(pc, name, NULL, (StmtInfoPC *)NULL);
if (stmt && stmt->type == STMT_WITH) {
parser->handler.setFlag(pn, PND_DEOPTIMIZED);
pn->pn_dflags |= PND_DEOPTIMIZED;
if (pc->sc->isFunctionBox()) {
FunctionBox *funbox = pc->sc->asFunctionBox();
funbox->setMightAliasLocals();
@ -2515,8 +2523,8 @@ Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data
* is not allowed which allows us to turn any non-error redeclaration
* into a use of the initial declaration.
*/
DefinitionNode dn = defs.front<ParseHandler>();
Definition::Kind dn_kind = parser->handler.getDefinitionKind(dn);
Definition *dn = defs.front();
Definition::Kind dn_kind = dn->kind();
if (dn_kind == Definition::ARG) {
JSAutoByteString bytes;
if (!js_AtomToPrintableString(cx, name, &bytes))
@ -2549,7 +2557,16 @@ Parser<ParseHandler>::bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data
}
}
parser->handler.linkUseToDef(pn, dn);
LinkUseToDef(pn, dn);
return true;
}
template <>
/* static */ bool
Parser<SyntaxParseHandler>::bindVarOrConst(JSContext *cx, BindData<SyntaxParseHandler> *data,
HandlePropertyName name,
Parser<SyntaxParseHandler> *parser)
{
return true;
}
@ -2572,20 +2589,21 @@ Parser<FullParseHandler>::makeSetCall(ParseNode *pn, unsigned msg)
return true;
}
template <typename ParseHandler>
template <>
bool
Parser<ParseHandler>::noteNameUse(HandlePropertyName name, Node pn)
Parser<FullParseHandler>::noteNameUse(ParseNode *pn)
{
RootedPropertyName name(context, pn->pn_atom->asPropertyName());
StmtInfoPC *stmt = LexicalLookup(pc, name, NULL, (StmtInfoPC *)NULL);
DefinitionList::Range defs = pc->decls().lookupMulti(name);
DefinitionNode dn;
Definition *dn;
if (!defs.empty()) {
dn = defs.front<ParseHandler>();
dn = defs.front();
} else {
if (AtomDefnAddPtr p = pc->lexdeps->lookupForAdd(name)) {
dn = p.value().get<ParseHandler>();
dn = p.value();
} else {
/*
* No definition before this use in any lexical scope.
@ -2595,23 +2613,28 @@ Parser<ParseHandler>::noteNameUse(HandlePropertyName name, Node pn)
* - Be left as a free variable definition if we never
* see the real definition.
*/
dn = handler.newPlaceholder(pn, pc);
if (!dn)
return false;
DefinitionSingle def = DefinitionSingle::new_<ParseHandler>(dn);
if (!pc->lexdeps->add(p, name, def))
dn = MakePlaceholder(pn, &handler, pc);
if (!dn || !pc->lexdeps->add(p, name, dn))
return false;
}
}
handler.linkUseToDef(pn, dn);
JS_ASSERT(dn->isDefn());
LinkUseToDef(pn, dn);
if (stmt && stmt->type == STMT_WITH)
handler.setFlag(pn, PND_DEOPTIMIZED);
pn->pn_dflags |= PND_DEOPTIMIZED;
return true;
}
template <>
bool
Parser<SyntaxParseHandler>::noteNameUse(Node pn)
{
return true;
}
#if JS_HAS_DESTRUCTURING
template <>
@ -2793,8 +2816,7 @@ Parser<FullParseHandler>::checkDestructuring(BindData<FullParseHandler> *data,
* officially linked to its def or registered in lexdeps. Do
* that now.
*/
RootedPropertyName name(context, pn->pn_atom->asPropertyName());
if (pair->pn_right == pair->pn_left && !noteNameUse(name, pn))
if (pair->pn_right == pair->pn_left && !noteNameUse(pn))
return false;
ok = bindDestructuringLHS(pn);
}
@ -3121,9 +3143,9 @@ PushBlocklikeStatement(StmtInfoPC *stmt, StmtType type, ParseContext<ParseHandle
return GenerateBlockId(pc, stmt->blockid);
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::newBindingNode(PropertyName *name, bool functionScope, VarContext varContext)
template <>
ParseNode *
Parser<FullParseHandler>::newBindingNode(PropertyName *name, VarContext varContext)
{
/*
* If this name is being injected into an existing block/function, see if
@ -3134,15 +3156,13 @@ Parser<ParseHandler>::newBindingNode(PropertyName *name, bool functionScope, Var
*/
if (varContext == HoistVars) {
if (AtomDefnPtr p = pc->lexdeps->lookup(name)) {
DefinitionNode lexdep = p.value().get<ParseHandler>();
JS_ASSERT(handler.getDefinitionKind(lexdep) == Definition::PLACEHOLDER);
Node pn = handler.getDefinitionNode(lexdep);
if (handler.dependencyCovered(pn, pc->blockid(), functionScope)) {
handler.setBlockId(pn, pc->blockid());
ParseNode *lexdep = p.value();
JS_ASSERT(lexdep->isPlaceholder());
if (lexdep->pn_blockid >= pc->blockid()) {
lexdep->pn_blockid = pc->blockid();
pc->lexdeps->remove(p);
handler.setPosition(pn, tokenStream.currentToken().pos);
return pn;
lexdep->pn_pos = tokenStream.currentToken().pos;
return lexdep;
}
}
}
@ -3152,6 +3172,13 @@ Parser<ParseHandler>::newBindingNode(PropertyName *name, bool functionScope, Var
return handler.newName(name, pc);
}
template <>
SyntaxParseHandler::Node
Parser<SyntaxParseHandler>::newBindingNode(PropertyName *name, VarContext varContext)
{
return SyntaxParseHandler::NodeGeneric;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::switchStatement()
@ -3877,7 +3904,7 @@ Parser<ParseHandler>::tryStatement()
case TOK_NAME:
{
RootedPropertyName label(context, tokenStream.currentToken().name());
catchName = newBindingNode(label, false);
catchName = newBindingNode(label);
if (!catchName)
return null();
data.pn = catchName;
@ -3993,10 +4020,9 @@ Parser<ParseHandler>::withStatement()
* to safely optimize binding globals (see bug 561923).
*/
for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
DefinitionNode defn = r.front().value().get<ParseHandler>();
DefinitionNode lexdep = handler.resolve(defn);
handler.deoptimizeUsesWithin(lexdep,
TokenPos::make(begin, tokenStream.currentToken().pos.begin));
Definition *defn = r.front().value();
Definition *lexdep = defn->resolve();
DeoptimizeUsesWithin(lexdep, TokenPos::make(begin, tokenStream.currentToken().pos.begin));
}
Node pn = handler.newBinary(PNK_WITH, objectExpr, innerBlock);
@ -4568,7 +4594,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool *psimple,
}
RootedPropertyName name(context, tokenStream.currentToken().name());
pn2 = newBindingNode(name, kind == PNK_VAR || kind == PNK_CONST, varContext);
pn2 = newBindingNode(name, varContext);
if (!pn2)
return null();
if (data.op == JSOP_DEFCONST)
@ -5419,7 +5445,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
* generator) a use of a new placeholder in the generator's
* lexdeps.
*/
Definition *dn2 = parser->handler.newPlaceholder(pn, parser->pc);
Definition *dn2 = MakePlaceholder(pn, &parser->handler, parser->pc);
if (!dn2)
return false;
dn2->pn_pos = root->pn_pos;
@ -5438,8 +5464,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
dn2->dn_uses = dn->dn_uses;
dn->dn_uses = *pnup;
*pnup = NULL;
DefinitionSingle def = DefinitionSingle::new_<FullParseHandler>(dn2);
if (!pc->lexdeps->put(atom, def))
if (!pc->lexdeps->put(atom, dn2))
return false;
if (dn->isClosed())
dn2->pn_dflags |= PND_CLOSED;
@ -5450,8 +5475,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
* from the parent's lexdeps into the generator's lexdeps.
*/
outerpc->lexdeps->remove(atom);
DefinitionSingle def = DefinitionSingle::new_<FullParseHandler>(dn);
if (!pc->lexdeps->put(atom, def))
if (!pc->lexdeps->put(atom, dn))
return false;
} else if (dn->isImplicitArguments()) {
/*
@ -5605,7 +5629,7 @@ Parser<FullParseHandler>::comprehensionTail(ParseNode *kid, unsigned blockid, bo
* and it tries to bind all names to slots, so we must let it do
* the deed.
*/
pn3 = newBindingNode(name, false);
pn3 = newBindingNode(name);
if (!pn3)
return null();
break;
@ -6121,12 +6145,12 @@ Parser<ParseHandler>::identifierName()
{
JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME));
RootedPropertyName name(context, tokenStream.currentToken().name());
PropertyName *name = tokenStream.currentToken().name();
Node pn = handler.newName(name, pc);
if (!pn)
return null();
if (!pc->inDeclDestructuring && !noteNameUse(name, pn))
if (!pc->inDeclDestructuring && !noteNameUse(pn))
return null();
return pn;

View File

@ -85,7 +85,6 @@ struct ParseContext : public GenericParseContext
{
typedef StmtInfoPC StmtInfo;
typedef typename ParseHandler::Node Node;
typedef typename ParseHandler::DefinitionNode DefinitionNode;
uint32_t bodyid; /* block number of program/function body */
uint32_t blockidGen; /* preincremented block number generator */
@ -104,12 +103,12 @@ struct ParseContext : public GenericParseContext
Node blockNode; /* parse node for a block with let declarations
(block with its own lexical scope) */
private:
AtomDecls<ParseHandler> decls_; /* function, const, and var declarations */
AtomDecls decls_; /* function, const, and var declarations */
DeclVector args_; /* argument definitions */
DeclVector vars_; /* var/const definitions */
public:
const AtomDecls<ParseHandler> &decls() const {
const AtomDecls &decls() const {
return decls_;
}
@ -162,7 +161,7 @@ struct ParseContext : public GenericParseContext
void popLetDecl(JSAtom *atom);
/* See the sad story in defineArg. */
void prepareToAddDuplicateArg(HandlePropertyName name, DefinitionNode prevDecl);
void prepareToAddDuplicateArg(Definition *prevDecl);
/* See the sad story in MakeDefIntoUse. */
void updateDecl(JSAtom *atom, Node newDecl);
@ -495,13 +494,13 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
bool checkStrictBinding(HandlePropertyName name, Node pn);
bool checkDeleteExpression(Node *pn);
bool defineArg(Node funcpn, HandlePropertyName name,
bool disallowDuplicateArgs = false, Node *duplicatedArg = NULL);
bool disallowDuplicateArgs = false, DefinitionNode *duplicatedArg = NULL);
Node pushLexicalScope(StmtInfoPC *stmt);
Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt);
Node pushLetScope(Handle<StaticBlockObject*> blockObj, StmtInfoPC *stmt);
bool noteNameUse(HandlePropertyName name, Node pn);
bool noteNameUse(Node pn);
Node newRegExp(const jschar *chars, size_t length, RegExpFlag flags);
Node newBindingNode(PropertyName *name, bool functionScope, VarContext varContext = HoistVars);
Node newBindingNode(PropertyName *name, VarContext varContext = HoistVars);
bool checkDestructuring(BindData<ParseHandler> *data, Node left, bool toplevel = true);
bool bindDestructuringVar(BindData<ParseHandler> *data, Node pn);
bool bindDestructuringLHS(Node pn);
@ -522,7 +521,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter
bindVarOrConst(JSContext *cx, BindData<ParseHandler> *data,
HandlePropertyName name, Parser<ParseHandler> *parser);
static Node null() { return ParseHandler::null(); }
static DefinitionNode null() { return ParseHandler::null(); }
bool reportRedeclaration(Node pn, bool isConst, JSAtom *atom);
bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum);

View File

@ -27,7 +27,7 @@ class SyntaxParseHandler
NodeStringExprStatement,
NodeLValue
};
typedef Definition::Kind DefinitionNode;
typedef Node DefinitionNode;
SyntaxParseHandler(JSContext *cx, TokenStream &tokenStream, bool foldConstants)
: lastAtom(NULL),
@ -43,9 +43,6 @@ class SyntaxParseHandler
lastAtom = name;
return NodeName;
}
DefinitionNode newPlaceholder(Node pn, ParseContext<SyntaxParseHandler> *pc) {
return Definition::PLACEHOLDER;
}
Node newAtom(ParseNodeKind kind, JSAtom *atom, JSOp op = JSOP_NOP) {
if (kind == PNK_STRING) {
lastAtom = atom;
@ -105,7 +102,6 @@ class SyntaxParseHandler
Node newFunctionDefinition() { return NodeGeneric; }
void setFunctionBody(Node pn, Node kid) {}
void setFunctionBox(Node pn, FunctionBox *funbox) {}
void addFunctionArgument(Node pn, Node argpn) {}
Node newLexicalScope(ObjectBox *blockbox) { return NodeGeneric; }
bool isOperationWithoutParens(Node pn, ParseNodeKind kind) {
// It is OK to return false here, callers should only use this method
@ -123,8 +119,6 @@ class SyntaxParseHandler
void setEndPosition(Node pn, Node oth) {}
void setEndPosition(Node pn, uint32_t end) {}
void setPosition(Node pn, const TokenPos &pos) {}
TokenPos getPosition(Node pn) {
return tokenStream.currentToken().pos;
}
@ -160,29 +154,6 @@ class SyntaxParseHandler
bool isEmptySemicolon(Node pn) { return false; }
Node makeAssignment(Node pn, Node rhs) { return NodeGeneric; }
static Node getDefinitionNode(DefinitionNode dn) { return NodeGeneric; }
static Definition::Kind getDefinitionKind(DefinitionNode dn) { return dn; }
void linkUseToDef(Node pn, DefinitionNode dn) {}
DefinitionNode resolve(DefinitionNode dn) { return dn; }
void deoptimizeUsesWithin(DefinitionNode dn, const TokenPos &pos) {}
bool dependencyCovered(Node pn, unsigned blockid, bool functionScope) {
// Only resolve lexical dependencies in cases where a definition covers
// the entire function. Not enough information is kept to compare the
// dependency location with blockid.
return functionScope;
}
static uintptr_t definitionToBits(DefinitionNode dn) {
// Use a shift, as DefinitionList tags the lower bit of its associated union.
return uintptr_t(dn << 1);
}
static DefinitionNode definitionFromBits(uintptr_t bits) {
return (DefinitionNode) (bits >> 1);
}
static DefinitionNode nullDefinition() {
return Definition::MISSING;
}
};
} // namespace frontend