Bug 852331 - immediately GC the Zone after JS::Evaluate on a very large script (r=bhackett)
authorLuke Wagner <luke@mozilla.com>
Mon, 18 Mar 2013 17:37:24 -0700
changeset 131894 b0b858d36b3d589f007b92eee27fba3c95f436bd
parent 131893 d54c51456af56a2215bd52ba6057cbac51bdc611
child 131895 34bf1e07b8d3ffdade95ea3e457eb7aa3c92e338
push idunknown
push userunknown
push dateunknown
reviewersbhackett
bugs852331
milestone22.0a1
Bug 852331 - immediately GC the Zone after JS::Evaluate on a very large script (r=bhackett)
js/public/GCAPI.h
js/src/jsapi.cpp
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -38,17 +38,18 @@ namespace JS {
     D(SET_NEW_DOCUMENT)                         \
     D(SET_DOC_SHELL)                            \
     D(DOM_UTILS)                                \
     D(DOM_IPC)                                  \
     D(DOM_WORKER)                               \
     D(INTER_SLICE_GC)                           \
     D(REFRESH_FRAME)                            \
     D(FULL_GC_TIMER)                            \
-    D(SHUTDOWN_CC)
+    D(SHUTDOWN_CC)                              \
+    D(FINISH_LARGE_EVALUTE)
 
 namespace gcreason {
 
 /* GCReasons will end up looking like JSGC_MAYBEGC */
 enum Reason {
 #define MAKE_REASON(name) name,
     GCREASONS(MAKE_REASON)
 #undef MAKE_REASON
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5529,16 +5529,18 @@ JS_PUBLIC_API(JSBool)
 JS_ExecuteScriptVersion(JSContext *cx, JSObject *objArg, JSScript *script, jsval *rval,
                         JSVersion version)
 {
     RootedObject obj(cx, objArg);
     AutoVersionAPI ava(cx, version);
     return JS_ExecuteScript(cx, obj, script, rval);
 }
 
+static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
+
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const jschar *chars, size_t length, jsval *rval)
 {
     Maybe<AutoVersionAPI> mava;
     if (options.versionSet) {
         mava.construct(cx, options.version);
         // AutoVersionAPI propagates some compilation flags through.
@@ -5561,16 +5563,28 @@ JS::Evaluate(JSContext *cx, HandleObject
     if (!script)
         return false;
 
     JS_ASSERT(script->getVersion() == options.version);
 
     bool result = Execute(cx, script, *obj, rval);
     if (!sct.complete())
         result = false;
+
+    // After evaluation, the compiled script will not be run again.
+    // script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode
+    // which for large scripts means significant memory. Perform a GC eagerly
+    // to clear out this analysis data before anything happens to inhibit the
+    // flushing of this memory (such as setting requestAnimationFrame).
+    if (script->length > LARGE_SCRIPT_LENGTH) {
+        script = NULL;
+        PrepareZoneForGC(cx->zone());
+        GC(cx->runtime, GC_NORMAL, gcreason::FINISH_LARGE_EVALUTE);
+    }
+
     return result;
 }
 
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const char *bytes, size_t length, jsval *rval)
 {
     jschar *chars;