[INFER] Trace IDs and objects which inference depends on, bug 613221.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 18 Nov 2010 11:23:22 -0800
changeset 74621 f098b0cf0761728736441a7489ab9d32bda06b51
parent 74620 633c888a78ca3fb094de04baef8d0626ef0c0d4e
child 74622 42b0294bf1e55637b6125573c00d5667880cac35
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs613221
milestone2.0b8pre
[INFER] Trace IDs and objects which inference depends on, bug 613221.
js/src/jsanalyze.h
js/src/jsapi.cpp
js/src/jscntxt.cpp
js/src/jsgc.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsscript.cpp
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -377,16 +377,18 @@ class Script
 
     /* Get the type set to use for a stack slot at a fixed stack depth. */
     inline types::TypeSet *getStackTypes(unsigned index, types::TypeStack *stack);
 
     /* Get any known type tag for an argument or local variable. */
     inline JSValueType knownArgumentTypeTag(JSContext *cx, JSScript *script, unsigned arg);
     inline JSValueType knownLocalTypeTag(JSContext *cx, JSScript *script, unsigned local);
 
+    void trace(JSTracer *trc);
+
 #endif /* JS_TYPE_INFERENCE */
 
 };
 
 static inline unsigned
 GetBytecodeLength(jsbytecode *pc)
 {
     JSOp op = (JSOp)*pc;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5098,16 +5098,22 @@ JS_EvaluateUCScriptForPrincipals(JSConte
                                      : TCF_COMPILE_N_GO,
                                      chars, length, NULL, filename, lineno);
     if (!script) {
         LAST_FRAME_CHECKS(cx, script);
         return JS_FALSE;
     }
     ok = Execute(cx, obj, script, NULL, 0, Valueify(rval));
     LAST_FRAME_CHECKS(cx, ok);
+
+#ifdef JS_TYPE_INFERENCE
+    // Don't destroy the script yet :FIXME: bug 613221
+    return ok;
+#endif
+
     js_DestroyScript(cx, script);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_EvaluateUCScript(JSContext *cx, JSObject *obj, const jschar *chars, uintN length,
                     const char *filename, uintN lineno, jsval *rval)
 {
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -513,22 +513,20 @@ JSThreadData::allocMathCache(JSContext *
     if (!mathCache)
         js_ReportOutOfMemory(cx);
     return mathCache;
 }
 
 void
 JSThreadData::finish()
 {
-#ifndef JS_TYPE_INFERENCE /* :FIXME: GC disabled during type inference */
 #ifdef DEBUG
     for (size_t i = 0; i != JS_ARRAY_LENGTH(scriptsToGC); ++i)
         JS_ASSERT(!scriptsToGC[i]);
 #endif
-#endif
 
     if (dtoaState)
         js_DestroyDtoaState(dtoaState);
 
     js_FinishGSNCache(&gsnCache);
     propertyCache.~PropertyCache();
 #if defined JS_TRACER
     FinishJIT(&traceMonitor);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1727,16 +1727,35 @@ MarkRuntime(JSTracer *trc)
             HM &h = (k == 0) ? rt->methodReadBarrierCountMap : rt->unjoinedFunctionCountMap;
             for (HM::Range r = h.all(); !r.empty(); r.popFront()) {
                 JSFunction *fun = r.front().key;
                 JS_CALL_OBJECT_TRACER(trc, fun, "FunctionCountMap key");
             }
         }
     }
 #endif
+
+#ifdef JS_TYPE_INFERENCE
+    /* Mark all scripts which have analysis information. :FIXME: bug 613221 */
+    JSCompartment **read = rt->compartments.begin();
+    JSCompartment **end = rt->compartments.end();
+    while (read < end) {
+        JSCompartment *compartment = (*read++);
+        if (compartment->marked) {
+            for (JSCList *cursor = compartment->scripts.next;
+                 cursor != &compartment->scripts;
+                 cursor = cursor->next) {
+                JSScript *script = reinterpret_cast<JSScript *>(cursor);
+                if (script->analysis)
+                    js_TraceScript(trc, script);
+            }
+            compartment->types.trace(trc);
+        }
+    }
+#endif
 }
 
 void
 TriggerGC(JSRuntime *rt)
 {
     JS_ASSERT(!rt->gcRunning);
     if (rt->gcIsNeeded)
         return;
@@ -1756,16 +1775,22 @@ js_DestroyScriptsToGC(JSContext *cx, JST
 {
     JSScript **listp, *script;
 
     for (size_t i = 0; i != JS_ARRAY_LENGTH(data->scriptsToGC); ++i) {
         listp = &data->scriptsToGC[i];
         while ((script = *listp) != NULL) {
             *listp = script->u.nextToGC;
             script->u.nextToGC = NULL;
+
+#ifdef JS_TYPE_INFERENCE
+            // :FIXME: bug 613221
+            continue;
+#endif
+
             js_DestroyScript(cx, script);
         }
     }
 }
 
 intN
 js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
                                  JSStringFinalizeOp newop)
@@ -2528,24 +2553,16 @@ GCUntilDone(JSContext *cx, JSGCInvocatio
     rt->gcMarkAndSweep = false;
     rt->gcRegenShapes = false;
     rt->setGCLastBytes(rt->gcBytes);
 }
 
 void
 js_GC(JSContext *cx, JSGCInvocationKind gckind)
 {
-#ifdef JS_TYPE_INFERENCE
-    /*
-     * GC is disabled if type inference is active, as type objects do not currently
-     * root the atoms they refer to.
-     */
-    return;
-#endif
-
     JSRuntime *rt = cx->runtime;
 
     /*
      * Don't collect garbage if the runtime isn't up, and cx is not the last
      * context in the runtime.  The last context must force a GC, and nothing
      * should suppress that final collection or there may be shutdown leaks,
      * or runtime bloat until the next context is created.
      */
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "jsapi.h"
 #include "jsautooplen.h"
 #include "jsbit.h"
 #include "jsbool.h"
 #include "jsdate.h"
 #include "jsexn.h"
+#include "jsgc.h"
 #include "jsinfer.h"
 #include "jsmath.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsscript.h"
 #include "jscntxt.h"
 #include "jsscan.h"
 #include "jsscope.h"
@@ -3472,8 +3473,64 @@ Script::print(JSContext *cx)
     TypeObject *object = objects;
     while (object) {
         object->print(cx, out);
         object = object->next;
     }
 }
 
 } } /* namespace js::analyze */
+
+/////////////////////////////////////////////////////////////////////
+// Tracing
+/////////////////////////////////////////////////////////////////////
+
+namespace js {
+
+static inline void
+TraceVariableSet(JSTracer *trc, const types::VariableSet &vars)
+{
+    types::Variable *var = vars.variables;
+    while (var) {
+        if (!JSID_IS_VOID(var->id))
+            gc::MarkString(trc, JSID_TO_STRING(var->id), "type_property");
+        var = var->next;
+    }
+}
+
+static inline void
+TraceObjectList(JSTracer *trc, types::TypeObject *objects)
+{
+    types::TypeObject *object = objects;
+    while (object) {
+        gc::MarkString(trc, JSID_TO_STRING(object->name), "type_object_name");
+        TraceVariableSet(trc, object->propertySet);
+        object = object->next;
+    }
+}
+
+void
+analyze::Script::trace(JSTracer *trc)
+{
+    if (fun) {
+        JS_SET_TRACING_NAME(trc, "type_script");
+        gc::Mark(trc, fun);
+    }
+
+    TraceObjectList(trc, objects);
+    TraceVariableSet(trc, localTypes);
+
+    unsigned nameCount = script->nfixed + argCount();
+    for (unsigned i = 0; i < nameCount; i++) {
+        if (localNames[i]) {
+            JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[i]);
+            gc::MarkString(trc, ATOM_TO_STRING(atom), "type_script_local");
+        }
+    }
+}
+
+void
+types::TypeCompartment::trace(JSTracer *trc)
+{
+    TraceObjectList(trc, objects);
+}
+
+} /* namespace js */
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -811,16 +811,18 @@ struct TypeCompartment
     void dynamicAssign(JSContext *cx, JSObject *obj, jsid id, const Value &rval);
 
     inline bool hasPendingRecompiles() { return pendingRecompiles != NULL; }
     void processPendingRecompiles(JSContext *cx);
     void addPendingRecompile(JSContext *cx, JSScript *script);
 
     /* Monitor future effects on a bytecode. */
     void monitorBytecode(JSContext *cx, analyze::Bytecode *code);
+
+    void trace(JSTracer *trc);
 };
 
 } /* namespace types */
 } /* namespace js */
 
 static JS_ALWAYS_INLINE js::types::TypeObject *
 Valueify(JSTypeObject *jstype) { return (js::types::TypeObject*) jstype; }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1437,16 +1437,21 @@ js_TraceScript(JSTracer *trc, JSScript *
 
     if (script->u.object) {
         JS_SET_TRACING_NAME(trc, "object");
         Mark(trc, script->u.object);
     }
 
     if (IS_GC_MARKING_TRACER(trc) && script->filename)
         js_MarkScriptFilename(script->filename);
+
+#ifdef JS_TYPE_INFERENCE
+    if (script->analysis)
+        script->analysis->trace(trc);
+#endif
 }
 
 JSBool
 js_NewScriptObject(JSContext *cx, JSScript *script)
 {
     AutoScriptRooter root(cx, script);
 
     JS_ASSERT(!script->u.object);