Bug 669786: JSCodeGenerator::upvarMap should be a js::Vector. (r=njn)
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -116,30 +116,30 @@ JSCodeGenerator::JSCodeGenerator(Parser
ntrynotes(0), lastTryNode(NULL),
spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL),
numSpanDeps(0), numJumpTargets(0), spanDepTodo(0),
arrayCompDepth(0),
emitLevel(0),
constMap(parser->context),
constList(parser->context),
upvarIndices(parser->context),
+ upvarMap(parser->context),
globalUses(parser->context),
globalMap(parser->context),
closedArgs(parser->context),
closedVars(parser->context),
traceIndex(0),
typesetIndex(0)
{
flags = TCF_COMPILING;
memset(&prolog, 0, sizeof prolog);
memset(&main, 0, sizeof main);
current = &main;
firstLine = prolog.currentLine = main.currentLine = lineno;
prolog.noteMask = main.noteMask = SRCNOTE_CHUNK - 1;
- memset(&upvarMap, 0, sizeof upvarMap);
}
bool
JSCodeGenerator::init(JSContext *cx, JSTreeContext::InitBehavior ib)
{
roLexdeps.init();
return JSTreeContext::init(cx, ib) && constMap.init() && atomIndices.ensureMap(cx);
}
@@ -149,19 +149,16 @@ JSCodeGenerator::~JSCodeGenerator()
JS_ARENA_RELEASE(codePool, codeMark);
JS_ARENA_RELEASE(notePool, noteMark);
JSContext *cx = parser->context;
/* NB: non-null only after OOM. */
if (spanDeps)
cx->free_(spanDeps);
-
- if (upvarMap.vector)
- cx->free_(upvarMap.vector);
}
static ptrdiff_t
EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
{
jsbytecode *base, *limit, *next;
ptrdiff_t offset, length;
size_t incr, size;
@@ -2334,40 +2331,36 @@ BindNameToSlot(JSContext *cx, JSCodeGene
} else {
if (!cg->bindings.addUpvar(cx, atom))
return JS_FALSE;
index = cg->upvarIndices->count();
if (!cg->upvarIndices->add(p, atom, index))
return JS_FALSE;
- UpvarCookie *vector = cg->upvarMap.vector;
- uint32 length = cg->roLexdeps->count();
- if (!vector || cg->upvarMap.length != length) {
- vector = (UpvarCookie *) cx->realloc_(vector, length * sizeof *vector);
- if (!vector) {
- JS_ReportOutOfMemory(cx);
- return JS_FALSE;
- }
- cg->upvarMap.vector = vector;
- cg->upvarMap.length = length;
- }
+ UpvarCookies &upvarMap = cg->upvarMap;
+ /* upvarMap should have the same number of UpvarCookies as there are lexdeps. */
+ size_t lexdepCount = cg->roLexdeps->count();
+
+ JS_ASSERT_IF(!upvarMap.empty(), lexdepCount == upvarMap.length());
+ if (upvarMap.empty() && !upvarMap.appendN(UpvarCookie(), lexdepCount))
+ return JS_FALSE;
uintN slot = cookie.slot();
if (slot != UpvarCookie::CALLEE_SLOT && dn_kind != JSDefinition::ARG) {
JSTreeContext *tc = cg;
do {
tc = tc->parent;
} while (tc->staticLevel != level);
if (tc->inFunction())
slot += tc->fun()->nargs;
}
- JS_ASSERT(index < cg->upvarMap.length);
- vector[index].set(skip, slot);
+ JS_ASSERT(index < upvarMap.length());
+ upvarMap[index].set(skip, slot);
}
pn->pn_op = JSOP_GETFCSLOT;
JS_ASSERT((index & JS_BITMASK(16)) == index);
pn->pn_cookie.set(0, index);
pn->pn_dflags |= PND_BOUND;
return JS_TRUE;
}
--- a/js/src/jsemit.h
+++ b/js/src/jsemit.h
@@ -639,17 +639,18 @@ struct JSCodeGenerator : public JSTreeCo
JSGCConstList constList; /* constants to be included with the script */
JSCGObjectList objectList; /* list of emitted objects */
JSCGObjectList regexpList; /* list of emitted regexp that will be
cloned during execution */
js::OwnedAtomIndexMapPtr upvarIndices; /* map of atoms to upvar indexes */
- JSUpvarArray upvarMap; /* indexed upvar pairs (JS_realloc'ed) */
+
+ js::UpvarCookies upvarMap; /* indexed upvar slot locations */
typedef js::Vector<js::GlobalSlotArray::Entry, 16> GlobalUseVector;
GlobalUseVector globalUses; /* per-script global uses */
js::OwnedAtomIndexMapPtr globalMap; /* per-script map of global name to globalUses vector */
/* Vectors of pn_cookie slot values. */
typedef js::Vector<uint32, 8> SlotVector;
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -150,16 +150,17 @@ class CallReceiver;
class CallArgs;
struct Compiler;
struct Parser;
class TokenStream;
struct Token;
struct TokenPos;
struct TokenPtr;
+class UpvarCookie;
class TempAllocPolicy;
template <class T,
size_t MinInlineCapacity = 0,
class AllocPolicy = TempAllocPolicy>
class Vector;
@@ -187,19 +188,20 @@ struct PropertyCacheEntry;
struct Shape;
struct EmptyShape;
class Bindings;
class MultiDeclRange;
class ParseMapPool;
class DefnOrHeader;
-typedef js::InlineMap<JSAtom *, JSDefinition *, 24> AtomDefnMap;
-typedef js::InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
-typedef js::InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
+typedef InlineMap<JSAtom *, JSDefinition *, 24> AtomDefnMap;
+typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
+typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
+typedef Vector<UpvarCookie> UpvarCookies;
} /* namespace js */
} /* export "C++" */
#else
typedef struct JSAtom JSAtom;
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1307,22 +1307,21 @@ JSScript::NewScriptFromCG(JSContext *cx,
if (cg->callsEval())
script->usesEval = true;
if (cg->flags & TCF_FUN_USES_ARGUMENTS)
script->usesArguments = true;
if (cg->flags & TCF_HAS_SINGLETONS)
script->hasSingletons = true;
if (cg->hasUpvarIndices()) {
- JS_ASSERT(cg->upvarIndices->count() <= cg->upvarMap.length);
- memcpy(script->upvars()->vector, cg->upvarMap.vector,
- cg->upvarIndices->count() * sizeof(uint32));
+ JS_ASSERT(cg->upvarIndices->count() <= cg->upvarMap.length());
+ memcpy(script->upvars()->vector, cg->upvarMap.begin(),
+ cg->upvarIndices->count() * sizeof(cg->upvarMap[0]));
cg->upvarIndices->clear();
- cx->free_(cg->upvarMap.vector);
- cg->upvarMap.vector = NULL;
+ cg->upvarMap.clear();
}
/* Set global for compileAndGo scripts. */
if (script->compileAndGo) {
GlobalScope *globalScope = cg->compiler()->globalScope;
if (globalScope->globalObj && globalScope->globalObj->isGlobal())
script->global_ = globalScope->globalObj->asGlobal();
else if (cx->globalObject->isGlobal())