Bug 669786: JSCodeGenerator::upvarMap should be a js::Vector. (r=njn)
authorChris Leary <cdleary@mozilla.com>
Wed, 06 Jul 2011 18:00:17 -0700
changeset 75182 1013f4be025f77ff1badf1ac121c56f232527b48
parent 75181 8570f783088c6797cdbdfc58870c20dad8e54abf
child 75183 b5ebe47700ce19a7ee2227a7c5a1134efa3fb17d
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersnjn
bugs669786
milestone8.0a1
Bug 669786: JSCodeGenerator::upvarMap should be a js::Vector. (r=njn)
js/src/jsemit.cpp
js/src/jsemit.h
js/src/jsprvtd.h
js/src/jsscript.cpp
--- 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())