Bug 880330 - Refactor the shell to use the new options API; r=bholley
authorEddy Bruel <ejpbruel@mozilla.com>
Mon, 14 Oct 2013 13:31:03 +0200
changeset 164482 e437294a2dbeb0a10d84fafd6fb2085355f4b505
parent 164481 0b6f43cbb7ddaea2bbc357847bb2e7fc331d8f09
child 164483 a15782f2e779a5eac15570b661d07baaf40e7b68
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs880330
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 880330 - Refactor the shell to use the new options API; r=bholley
js/src/NamespaceImports.h
js/src/shell/js.cpp
--- a/js/src/NamespaceImports.h
+++ b/js/src/NamespaceImports.h
@@ -38,16 +38,21 @@ template <typename T> class AutoVectorRo
 template<typename K, typename V> class AutoHashMapRooter;
 template<typename T> class AutoHashSetRooter;
 
 class JS_PUBLIC_API(ContextOptions);
 class JS_PUBLIC_API(AutoSaveContextOptions);
 
 JS_PUBLIC_API(ContextOptions &) ContextOptionsRef(JSContext *cx);
 
+class ContextOptions;
+class AutoSaveContextOptions;
+
+ContextOptions &ContextOptionsRef(JSContext *cx);
+
 }
 
 // Do the importing.
 namespace js {
 
 using JS::Value;
 using JS::BooleanValue;
 using JS::DoubleValue;
@@ -112,11 +117,15 @@ using JS::MutableHandleFunction;
 using JS::MutableHandleId;
 using JS::MutableHandleObject;
 using JS::MutableHandleScript;
 using JS::MutableHandleString;
 using JS::MutableHandleValue;
 
 using JS::Zone;
 
+using JS::ContextOptions;
+using JS::ContextOptionsRef;
+using JS::AutoSaveContextOptions;
+
 } /* namespace js */
 
 #endif /* NamespaceImports_h */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -406,33 +406,36 @@ RunFile(JSContext *cx, Handle<JSObject*>
         while ((ch = fgetc(file)) != EOF) {
             if (ch == '\n' || ch == '\r')
                 break;
         }
     }
     ungetc(ch, file);
 
     int64_t t1 = PRMJ_Now();
-    uint32_t oldopts = JS_GetOptions(cx);
-    gGotError = false;
-    JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-    CompileOptions options(cx);
-    options.setUTF8(true)
-        .setFileAndLine(filename, 1);
-
     RootedScript script(cx);
-    script = JS::Compile(cx, obj, options, file);
-
-#ifdef DEBUG
-    if (dumpEntrainedVariables)
-        AnalyzeEntrainedVariables(cx, script);
-#endif
-
-    JS_SetOptions(cx, oldopts);
-    JS_ASSERT_IF(!script, gGotError);
+
+    {
+        AutoSaveContextOptions asco(cx);
+        ContextOptionsRef(cx).setCompileAndGo(true)
+                             .setNoScriptRval(true);
+
+        CompileOptions options(cx);
+        options.setUTF8(true)
+               .setFileAndLine(filename, 1);
+
+        gGotError = false;
+        script = JS::Compile(cx, obj, options, file);
+        JS_ASSERT_IF(!script, gGotError);
+    }
+
+    #ifdef DEBUG
+        if (dumpEntrainedVariables)
+            AnalyzeEntrainedVariables(cx, script);
+    #endif
     if (script && !compileOnly) {
         if (!JS_ExecuteScript(cx, obj, script, nullptr)) {
             if (!gQuitting && !gTimedOut)
                 gExitCode = EXITCODE_RUNTIME_ERROR;
         }
         int64_t t2 = PRMJ_Now() - t1;
         if (printTiming)
             printf("runtime = %.3f ms\n", double(t2) / PRMJ_USEC_PER_MSEC);
@@ -565,60 +568,16 @@ Process(JSContext *cx, JSObject *obj_, c
         // It's not interactive - just execute it.
         RunFile(cx, obj, filename, file, compileOnly);
     } else {
         // It's an interactive filehandle; drop into read-eval-print loop.
         ReadEvalPrintLoop(cx, obj, file, gOutFile, compileOnly);
     }
 }
 
-/*
- * JSContext option name to flag map. The option names are in alphabetical
- * order for better reporting.
- */
-static const struct JSOption {
-    const char  *name;
-    uint32_t    flag;
-} js_options[] = {
-    {"strict",          JSOPTION_EXTRA_WARNINGS},
-    {"typeinfer",       JSOPTION_TYPE_INFERENCE},
-    {"werror",          JSOPTION_WERROR},
-    {"strict_mode",     JSOPTION_STRICT_MODE},
-};
-
-static uint32_t
-MapContextOptionNameToFlag(JSContext* cx, const char* name)
-{
-    for (size_t i = 0; i < ArrayLength(js_options); ++i) {
-        if (strcmp(name, js_options[i].name) == 0)
-            return js_options[i].flag;
-    }
-
-    char* msg = JS_sprintf_append(nullptr,
-                                  "unknown option name '%s'."
-                                  " The valid names are ", name);
-    for (size_t i = 0; i < ArrayLength(js_options); ++i) {
-        if (!msg)
-            break;
-        msg = JS_sprintf_append(msg, "%s%s", js_options[i].name,
-                                (i + 2 < ArrayLength(js_options)
-                                 ? ", "
-                                 : i + 2 == ArrayLength(js_options)
-                                 ? " and "
-                                 : "."));
-    }
-    if (!msg) {
-        JS_ReportOutOfMemory(cx);
-    } else {
-        JS_ReportError(cx, msg);
-        free(msg);
-    }
-    return 0;
-}
-
 static bool
 Version(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JSVersion origVersion = JS_GetVersion(cx);
     if (args.length() == 0 || JSVAL_IS_VOID(args[0])) {
         /* Get version. */
         args.rval().setInt32(origVersion);
@@ -717,55 +676,76 @@ ResolvePath(JSContext *cx, HandleString 
     return JS_NewStringCopyZ(cx, buffer);
 }
 
 static bool
 Options(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    uint32_t flag;
-    JSString *str;
-    char *names;
-    bool found;
-
-    uint32_t optset = 0;
+    ContextOptions oldOptions = ContextOptionsRef(cx);
     for (unsigned i = 0; i < args.length(); i++) {
-        str = JS_ValueToString(cx, args[i]);
+        JSString *str = JS_ValueToString(cx, args[i]);
         if (!str)
             return false;
         args[i].setString(str);
+
         JSAutoByteString opt(cx, str);
         if (!opt)
             return false;
-        flag = MapContextOptionNameToFlag(cx, opt.ptr());
-        if (!flag)
+
+        if (strcmp(opt.ptr(), "strict") == 0)
+            ContextOptionsRef(cx).toggleExtraWarnings();
+        else if (strcmp(opt.ptr(), "typeinfer") == 0)
+            ContextOptionsRef(cx).toggleTypeInference();
+        else if (strcmp(opt.ptr(), "werror") == 0)
+            ContextOptionsRef(cx).toggleWerror();
+        else if (strcmp(opt.ptr(), "strict_mode") == 0)
+            ContextOptionsRef(cx).toggleStrictMode();
+        else {
+            char* msg = JS_sprintf_append(NULL,
+                                          "unknown option name '%s'."
+                                          " The valid names are strict,"
+                                          " typeinfer, werror, and strict_mode.",
+                                          opt.ptr());
+            if (!msg) {
+                JS_ReportOutOfMemory(cx);
+                return false;
+            }
+
+            JS_ReportError(cx, msg);
+            free(msg);
             return false;
-        optset |= flag;
-    }
-    optset = JS_ToggleOptions(cx, optset);
-
-    names = nullptr;
-    found = false;
-    for (size_t i = 0; i < ArrayLength(js_options); i++) {
-        if (js_options[i].flag & optset) {
-            found = true;
-            names = JS_sprintf_append(names, "%s%s",
-                                      names ? "," : "", js_options[i].name);
-            if (!names)
-                break;
         }
     }
-    if (!found)
-        names = strdup("");
+
+    char *names = strdup("");
+    bool found = false;
+    if (!names && oldOptions.extraWarnings()) {
+        names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict");
+        found = true;
+    }
+    if (!names && oldOptions.typeInference()) {
+        names = JS_sprintf_append(names, "%s%s", found ? "," : "", "typeinfer");
+        found = true;
+    }
+    if (!names && oldOptions.werror()) {
+        names = JS_sprintf_append(names, "%s%s", found ? "," : "", "werror");
+        found = true;
+    }
+    if (!names && oldOptions.strictMode()) {
+        names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict_mode");
+        found = true;
+    }
     if (!names) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
-    str = JS_NewStringCopyZ(cx, names);
+
+    JSString *str = JS_NewStringCopyZ(cx, names);
     free(names);
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
 static bool
@@ -831,17 +811,17 @@ class AutoNewContext
     AutoNewContext() : oldcx(nullptr), newcx(nullptr) {}
 
     bool enter(JSContext *cx) {
         JS_ASSERT(!JS_IsExceptionPending(cx));
         oldcx = cx;
         newcx = NewContext(JS_GetRuntime(cx));
         if (!newcx)
             return false;
-        JS_SetOptions(newcx, JS_GetOptions(newcx) | JSOPTION_DONT_REPORT_UNCAUGHT);
+        ContextOptionsRef(newcx).setDontReportUncaught(true);
         js::SetDefaultObjectForContext(newcx, JS::CurrentGlobalOrNull(cx));
 
         newRequest.construct(newcx);
         newCompartment.construct(newcx, JS::CurrentGlobalOrNull(cx));
         return true;
     }
 
     JSContext *get() { return newcx; }
@@ -1066,32 +1046,32 @@ Evaluate(JSContext *cx, unsigned argc, j
     }
 
     {
         AutoSaveFrameChain asfc(cx);
         if (saveFrameChain && !asfc.save())
             return false;
 
         JSAutoCompartment ac(cx, global);
-        uint32_t oldopts = JS_GetOptions(cx);
-        uint32_t opts = oldopts & ~(JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-        if (compileAndGo)
-            opts |= JSOPTION_COMPILE_N_GO;
-        if (noScriptRval)
-            opts |= JSOPTION_NO_SCRIPT_RVAL;
-
-        JS_SetOptions(cx, opts);
-        CompileOptions options(cx);
-        options.setFileAndLine(fileName, lineNumber);
-        options.setElement(element);
-        options.setSourcePolicy(sourcePolicy);
-        RootedScript script(cx, JS::Compile(cx, global, options, codeChars, codeLength));
-        JS_SetOptions(cx, oldopts);
-        if (!script)
-            return false;
+        RootedScript script(cx);
+
+        {
+            AutoSaveContextOptions asco(cx);
+            ContextOptionsRef(cx).setCompileAndGo(compileAndGo)
+                                 .setNoScriptRval(noScriptRval);
+
+            CompileOptions options(cx);
+            options.setFileAndLine(fileName, lineNumber)
+                   .setElement(element)
+                   .setSourcePolicy(sourcePolicy);
+
+            script = JS::Compile(cx, global, options, codeChars, codeLength);
+            if (!script)
+                return false;
+        }
 
         if (sourceURL && !script->scriptSource()->hasSourceURL()) {
             const jschar *surl = JS_GetStringCharsZ(cx, sourceURL);
             if (!surl)
                 return false;
             if (!script->scriptSource()->setSourceURL(cx, surl))
                 return false;
         }
@@ -1228,26 +1208,34 @@ Run(JSContext *cx, unsigned argc, jsval 
     size_t buflen;
     str = FileAsString(cx, filename.ptr());
     if (str)
         ucbuf = JS_GetStringCharsAndLength(cx, str, &buflen);
     if (!ucbuf)
         return false;
 
     JS::Anchor<JSString *> a_str(str);
-    uint32_t oldopts = JS_GetOptions(cx);
-    JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-
+
+    RootedScript script(cx);
     int64_t startClock = PRMJ_Now();
-    RootedScript script(cx, JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1));
-    JS_SetOptions(cx, oldopts);
-    if (!script || !JS_ExecuteScript(cx, thisobj, script, nullptr))
+    {
+        AutoSaveContextOptions asco(cx);
+        ContextOptionsRef(cx).setCompileAndGo(true)
+                             .setNoScriptRval(true);
+
+        script = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1);
+        if (!script)
+            return false;
+    }
+
+    if (!JS_ExecuteScript(cx, thisobj, script, NULL))
         return false;
 
     int64_t endClock = PRMJ_Now();
+
     args.rval().setDouble((endClock - startClock) / double(PRMJ_USEC_PER_MSEC));
     return true;
 }
 
 /*
  * function readline()
  * Provides a hook for scripts to read a line from stdin.
  */
@@ -2058,26 +2046,31 @@ DisassFile(JSContext *cx, unsigned argc,
         return false;
 
     JSString *str = JS_ValueToString(cx, p.argv[0]);
     if (!str)
         return false;
     JSAutoByteString filename(cx, str);
     if (!filename)
         return false;
-
-    uint32_t oldopts = JS_GetOptions(cx);
-    JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-    CompileOptions options(cx);
-    options.setUTF8(true)
-           .setFileAndLine(filename.ptr(), 1);
-    RootedScript script (cx, JS::Compile(cx, thisobj, options, filename.ptr()));
-    JS_SetOptions(cx, oldopts);
-    if (!script)
-        return false;
+    RootedScript script(cx);
+
+    {
+        AutoSaveContextOptions asco(cx);
+        ContextOptionsRef(cx).setCompileAndGo(true)
+                             .setNoScriptRval(true);
+
+        CompileOptions options(cx);
+        options.setUTF8(true)
+               .setFileAndLine(filename.ptr(), 1);
+
+        script = JS::Compile(cx, thisobj, options, filename.ptr());
+        if (!script)
+            return false;
+    }
 
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return false;
     bool ok = DisassembleScript(cx, script, NullPtr(), p.lines, p.recursive, &sprinter);
     if (ok)
         fprintf(stdout, "%s\n", sprinter.string());
     if (!ok)
@@ -3172,22 +3165,21 @@ Compile(JSContext *cx, unsigned argc, js
     if (!JSVAL_IS_STRING(arg0)) {
         const char *typeName = JS_GetTypeName(cx, JS_TypeOfValue(cx, arg0));
         JS_ReportError(cx, "expected string to compile, got %s", typeName);
         return false;
     }
 
     RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
     JSString *scriptContents = JSVAL_TO_STRING(arg0);
-    unsigned oldopts = JS_GetOptions(cx);
-    JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+    AutoSaveContextOptions asco(cx);
+    ContextOptionsRef(cx).setCompileAndGo(true)
+                         .setNoScriptRval(true);
     bool ok = JS_CompileUCScript(cx, global, JS_GetStringCharsZ(cx, scriptContents),
                                  JS_GetStringLength(scriptContents), "<string>", 1);
-    JS_SetOptions(cx, oldopts);
-
     JS_SET_RVAL(cx, vp, UndefinedValue());
     return ok;
 }
 
 static bool
 Parse(JSContext *cx, unsigned argc, jsval *vp)
 {
     using namespace js::frontend;
@@ -4935,23 +4927,23 @@ NewContext(JSRuntime *rt)
     if (!data) {
         DestroyContext(cx, false);
         return nullptr;
     }
 
     JS_SetContextPrivate(cx, data);
     JS_SetErrorReporter(cx, my_ErrorReporter);
     if (enableTypeInference)
-        JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
+        ContextOptionsRef(cx).toggleTypeInference();
     if (enableIon)
-        JS_ToggleOptions(cx, JSOPTION_ION);
+        ContextOptionsRef(cx).toggleIon();
     if (enableBaseline)
-        JS_ToggleOptions(cx, JSOPTION_BASELINE);
+        ContextOptionsRef(cx).toggleBaseline();
     if (enableAsmJS)
-        JS_ToggleOptions(cx, JSOPTION_ASMJS);
+        ContextOptionsRef(cx).toggleAsmJS();
     return cx;
 }
 
 static void
 DestroyContext(JSContext *cx, bool withGC)
 {
     JSShellContextData *data = GetContextData(cx);
     JS_SetContextPrivate(cx, nullptr);
@@ -5065,17 +5057,17 @@ ProcessArgs(JSContext *cx, JSObject *obj
         compileOnly = true;
 
     if (op->getBoolOption('w'))
         reportWarnings = true;
     else if (op->getBoolOption('W'))
         reportWarnings = false;
 
     if (op->getBoolOption('s'))
-        JS_ToggleOptions(cx, JSOPTION_EXTRA_WARNINGS);
+        ContextOptionsRef(cx).toggleExtraWarnings();
 
     if (op->getBoolOption('d')) {
         JS_SetRuntimeDebugMode(JS_GetRuntime(cx), true);
         JS_SetDebugMode(cx, true);
     }
 
     if (op->getBoolOption('b'))
         printTiming = true;
@@ -5089,26 +5081,26 @@ ProcessArgs(JSContext *cx, JSObject *obj
     int32_t threadCount = op->getIntOption("thread-count");
     if (threadCount >= 0)
         cx->runtime()->requestHelperThreadCount(threadCount);
 #endif /* JS_THREADSAFE */
 
 #if defined(JS_ION)
     if (op->getBoolOption("no-ion")) {
         enableIon = false;
-        JS_ToggleOptions(cx, JSOPTION_ION);
+        ContextOptionsRef(cx).toggleIon();
     }
     if (op->getBoolOption("no-asmjs")) {
         enableAsmJS = false;
-        JS_ToggleOptions(cx, JSOPTION_ASMJS);
+        ContextOptionsRef(cx).toggleAsmJS();
     }
 
     if (op->getBoolOption("no-baseline")) {
         enableBaseline = false;
-        JS_ToggleOptions(cx, JSOPTION_BASELINE);
+        ContextOptionsRef(cx).toggleBaseline();
     }
 
     if (const char *str = op->getStringOption("ion-gvn")) {
         if (strcmp(str, "off") == 0)
             jit::js_IonOptions.gvn = false;
         else if (strcmp(str, "pessimistic") == 0)
             jit::js_IonOptions.gvnIsOptimistic = false;
         else if (strcmp(str, "optimistic") == 0)
@@ -5278,17 +5270,17 @@ Shell(JSContext *cx, OptionParser *op, c
     JSAutoRequest ar(cx);
 
     /*
      * First check to see if type inference is enabled. These flags
      * must be set on the compartment when it is constructed.
      */
     if (op->getBoolOption("no-ti")) {
         enableTypeInference = false;
-        JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
+        ContextOptionsRef(cx).toggleTypeInference();
     }
 
     if (op->getBoolOption("fuzzing-safe"))
         fuzzingSafe = true;
 
     RootedObject glob(cx);
     JS::CompartmentOptions options;
     options.setVersion(JSVERSION_LATEST);