[INFER] Fixes for OOM handling, bug 657633.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 18 May 2011 13:15:38 -0700
changeset 75077 4dff743ec04d8058507115006bb93a35c990fa1a
parent 75076 9aeb58c8c43f71c13418f2e377e3a9e832e01153
child 75078 00a1518d640a25d505c27dc121e341345394415f
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs657633
milestone6.0a1
[INFER] Fixes for OOM handling, bug 657633.
js/src/jsanalyze.cpp
js/src/jsinfer.cpp
js/src/jsscript.cpp
js/src/methodjit/FrameState.cpp
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -1735,17 +1735,17 @@ ScriptAnalysis::removeBranchTarget(Vecto
 {
     for (unsigned i = 0; i < branchTargets.length(); i++) {
         if (branchTargets[i] == offset) {
             branchTargets[i] = branchTargets.back();
             branchTargets.popBack();
             return;
         }
     }
-    JS_NOT_REACHED("Missing target");
+    JS_ASSERT(OOM());
 }
 
 void
 ScriptAnalysis::freezeNewValues(JSContext *cx, uint32 offset)
 {
     Bytecode &code = getCode(offset);
 
     Vector<SlotValue> *pending = code.pendingValues;
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -302,26 +302,27 @@ TypeSet::addTypeSet(JSContext *cx, Clone
     } else if (types->objectCount == 1) {
         addType(cx, (jstype) types->objectSet);
     }
 }
 
 inline void
 TypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExisting)
 {
+    if (!constraint) {
+        /* OOM failure while constructing the constraint. */
+        cx->compartment->types.setPendingNukeTypes(cx);
+        return;
+    }
+
     JS_ASSERT_IF(!constraint->condensed() && !constraint->persistentObject(),
                  constraint->script->compartment == cx->compartment);
     JS_ASSERT_IF(!constraint->condensed(), cx->compartment->activeInference);
     JS_ASSERT_IF(intermediate(), !constraint->persistentObject() && !constraint->condensed());
 
-    if (!constraint) {
-        /* OOM failure while constructing the constraint. */
-        cx->compartment->types.setPendingNukeTypes(cx);
-    }
-
     InferSpew(ISpewOps, "addConstraint: T%p C%p %s",
               this, constraint, constraint->kind());
 
     JS_ASSERT(constraint->next == NULL);
     constraint->next = constraintList;
     constraintList = constraint;
 
     if (!callExisting)
@@ -2031,17 +2032,17 @@ TypeCompartment::nukeTypes(JSContext *cx
     /*
      * We may or may not be under the GC. In either case don't allocate, and
      * acquire the GC lock so we can update inferenceEnabled for all contexts.
      */
 
 #ifdef JS_THREADSAFE
     Maybe<AutoLockGC> maybeLock;
     if (!cx->runtime->gcMarkAndSweep)
-        maybeLock.construct(info.runtime);
+        maybeLock.construct(cx->runtime);
 #endif
 
     inferenceEnabled = false;
 
     /* Update the cached inferenceEnabled bit in all contexts. */
     for (JSCList *cl = cx->runtime->contextList.next;
          cl != &cx->runtime->contextList;
          cl = cl->next) {
@@ -3719,17 +3720,22 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
     }
 
     return true;
 }
 
 void
 ScriptAnalysis::analyzeTypes(JSContext *cx)
 {
-    JS_ASSERT(!ranInference() && !failed());
+    JS_ASSERT(!ranInference());
+
+    if (OOM()) {
+        cx->compartment->types.setPendingNukeTypes(cx);
+        return;
+    }
 
     /*
      * Refuse to analyze the types in a script which is compileAndGo but is
      * running against a global with a cleared scope. Per GlobalObject::clear,
      * we won't be running anymore compileAndGo code against the global
      * (moreover, after clearing our analysis results will be wrong for the
      * script and trying to reanalyze here can cause reentrance problems if we
      * try to reinitialize standard classes that were cleared).
@@ -4422,23 +4428,23 @@ JSScript::typeSetFunction(JSContext *cx,
     if (!cx->typeInferenceEnabled())
         return true;
 
     char *name = NULL;
 #ifdef DEBUG
     name = (char *) alloca(10);
     JS_snprintf(name, 10, "#%u", id());
 #endif
-    TypeFunction *type = cx->newTypeFunction(name, fun->getProto())->asFunction();
+    TypeObject *type = cx->newTypeFunction(name, fun->getProto());
     if (!type)
         return false;
 
     if (!fun->setTypeAndUniqueShape(cx, type))
         return false;
-    type->script = this;
+    type->asFunction()->script = this;
     this->fun = fun;
 
     return true;
 }
 
 #ifdef DEBUG
 
 void
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1367,31 +1367,32 @@ JSScript::NewScriptFromCG(JSContext *cx,
         JS_ASSERT(fun->isInterpreted());
         JS_ASSERT(!fun->script());
 #ifdef DEBUG
         if (JSScript::isValidOffset(script->upvarsOffset))
             JS_ASSERT(script->upvars()->length == script->bindings.countUpvars());
         else
             JS_ASSERT(script->bindings.countUpvars() == 0);
 #endif
-        fun->u.i.script = script;
 
 #ifdef CHECK_SCRIPT_OWNER
         script->owner = NULL;
 #endif
         if (cg->flags & TCF_FUN_HEAVYWEIGHT)
             fun->flags |= JSFUN_HEAVYWEIGHT;
         if (!script->typeSetFunction(cx, fun))
             goto bad;
 
         /* Watch for scripts whose functions will not be cloned. These are singletons. */
         if (cx->typeInferenceEnabled() && cg->parent && cg->parent->compiling() &&
             cg->parent->asCodeGenerator()->checkSingletonContext()) {
             fun->getType()->singleton = fun;
         }
+
+        fun->u.i.script = script;
     }
 
     /* Tell the debugger about this compiled script. */
     js_CallNewScriptHook(cx, script, fun);
 #ifdef DEBUG
     {
         jsrefcount newEmptyLive, newLive, newTotal;
         if (script->isEmpty()) {
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -105,29 +105,30 @@ FrameState::pushActiveFrame(JSScript *sc
         cursor += sizeof(FrameEntry *) * nentries;
 
         this->extraArray = (StackEntryExtra *)cursor;
         cursor += sizeof(StackEntryExtra) * nentries;
 
         JS_ASSERT(reinterpret_cast<uint8 *>(this->entries) + totalBytes == cursor);
 
 #if defined JS_NUNBOX32
-        if (!reifier.init(cx, *this, nentries)) {
-            cx->free_(this->entries);
+        if (!reifier.init(cx, *this, nentries))
             return false;
-        }
 #endif
 
         this->temporaries = this->temporariesTop = this->entries + nentries - TEMPORARY_LIMIT;
     }
 
     /* We should have already checked that argc == nargs */
     JS_ASSERT_IF(a, argc == script->fun->nargs);
 
     ActiveFrame *newa = cx->new_<ActiveFrame>();
+    if (!newa)
+        return false;
+
     newa->parent = a;
     newa->depth = a ? (totalDepth() + VALUES_PER_STACK_FRAME) : 0;
 
     newa->script = script;
     newa->PC = script->code;
     newa->analysis = script->analysis(cx);
 
     /*