Merge backout.
authorDavid Anderson <danderson@mozilla.com>
Wed, 27 Jun 2012 13:05:57 -0700
changeset 106476 62c180773b87fd633d8013f7d77e0e3633d3b0df
parent 106475 839a7e46762087aca46c2c016fc32c9898b79441
child 106477 c47c09bf5775598666faa7e975525ef539d731bd
push id23447
push userdanderson@mozilla.com
push dateTue, 11 Sep 2012 17:34:27 +0000
treeherdermozilla-central@fdfaef738a00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone16.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
Merge backout.
js/src/Makefile.in
js/src/ion/EdgeCaseAnalysis.cpp
js/src/ion/EdgeCaseAnalysis.h
js/src/ion/Ion.cpp
js/src/ion/Ion.h
js/src/ion/MIR.cpp
js/src/ion/MIR.h
js/src/ion/RangeAnalysis.cpp
js/src/ion/RangeAnalysis.h
js/src/shell/js.cpp
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -272,17 +272,17 @@ CPPSRCS +=	MIR.cpp \
 		LICM.cpp \
 		LinearScan.cpp \
 		LIR.cpp \
 		Lowering.cpp \
 		Lowering-shared.cpp \
 		MCallOptimize.cpp \
 		MIRGraph.cpp \
 		MoveResolver.cpp \
-		EdgeCaseAnalysis.cpp \
+		RangeAnalysis.cpp \
 		Snapshots.cpp \
 		Safepoints.cpp \
 		TypeOracle.cpp \
 		TypePolicy.cpp \
 		ValueNumbering.cpp \
 		VMFunctions.cpp \
 		AliasAnalysis.cpp \
 		$(NULL)
deleted file mode 100644
--- a/js/src/ion/EdgeCaseAnalysis.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set ts=4 sw=4 et tw=79: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stdio.h>
-
-#include "Ion.h"
-#include "IonSpewer.h"
-#include "EdgeCaseAnalysis.h"
-#include "MIR.h"
-#include "MIRGraph.h"
-
-using namespace js;
-using namespace js::ion;
-
-EdgeCaseAnalysis::EdgeCaseAnalysis(MIRGraph &graph)
-  : graph(graph)
-{
-}
-
-bool
-EdgeCaseAnalysis::analyzeLate()
-{
-    for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
-        for (MDefinitionIterator iter(*block); iter; iter++)
-            iter->analyzeEdgeCasesForward();
-    }
-
-    for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
-        for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
-            riter->analyzeEdgeCasesBackward();
-    }
-
-    return true;
-}
-
-bool
-EdgeCaseAnalysis::analyzeEarly()
-{
-
-    for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
-        for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
-            riter->analyzeTruncateBackward();
-    }
-
-    return true;
-}
-
-bool
-EdgeCaseAnalysis::AllUsesTruncate(MInstruction *m)
-{
-    for (MUseIterator use = m->usesBegin(); use != m->usesEnd(); use++) {
-        if (use->node()->isResumePoint())
-            return false;
-
-        MDefinition *def = use->node()->toDefinition();
-        if (def->isTruncateToInt32())
-            continue;
-        if (def->isBitAnd())
-            continue;
-        if (def->isBitOr())
-            continue;
-        if (def->isBitXor())
-            continue;
-        if (def->isLsh())
-            continue;
-        if (def->isRsh())
-            continue;
-        if (def->isBitNot())
-            continue;
-        if (def->isAdd() && def->toAdd()->isTruncated())
-            continue;
-        if (def->isSub() && def->toSub()->isTruncated())
-            continue;
-        // cannot use divide, since |truncate(int32(x/y) + int32(a/b)) != truncate(x/y+a/b)|
-        return false;
-    }
-    return true;
-}
deleted file mode 100644
--- a/js/src/ion/EdgeCaseAnalysis.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set ts=4 sw=4 et tw=79: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef jsion_ion_edge_case_analysis_h__
-#define jsion_ion_edge_case_analysis_h__
-
-namespace js {
-namespace ion {
-
-class MIRGraph;
-
-class EdgeCaseAnalysis
-{
-    MIRGraph &graph;
-
-  public:
-    EdgeCaseAnalysis(MIRGraph &graph);
-    bool analyzeEarly();
-    bool analyzeLate();
-    static bool AllUsesTruncate(MInstruction *m);
-};
-
-
-} // namespace ion
-} // namespace js
-
-#endif // jsion_ion_edge_case_analysis_h__
-
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -43,17 +43,17 @@
 #include "IonAnalysis.h"
 #include "IonBuilder.h"
 #include "IonSpewer.h"
 #include "LIR.h"
 #include "AliasAnalysis.h"
 #include "GreedyAllocator.h"
 #include "LICM.h"
 #include "ValueNumbering.h"
-#include "EdgeCaseAnalysis.h"
+#include "RangeAnalysis.h"
 #include "LinearScan.h"
 #include "jscompartment.h"
 #include "IonCompartment.h"
 #include "CodeGenerator.h"
 
 #if defined(JS_CPU_X86)
 # include "x86/Lowering-x86.h"
 #elif defined(JS_CPU_X64)
@@ -756,21 +756,21 @@ TestCompiler(IonBuilder &builder, MIRGra
     if (js_IonOptions.licm || js_IonOptions.gvn) {
         AliasAnalysis analysis(graph);
         if (!analysis.analyze())
             return false;
         IonSpewPass("Alias analysis");
         AssertGraphCoherency(graph);
     }
 
-    if (js_IonOptions.edgeCaseAnalysis) {
-        EdgeCaseAnalysis edgeCaseAnalysis(graph);
-        if (!edgeCaseAnalysis.analyzeEarly())
+    if (js_IonOptions.rangeAnalysis) {
+        RangeAnalysis rangeAnalysis(graph);
+        if (!rangeAnalysis.analyzeEarly())
             return false;
-        IonSpewPass("Edge Case Analysis (Early)");
+        IonSpewPass("Range Analysis (Early)");
         AssertGraphCoherency(graph);
     }
 
     if (js_IonOptions.gvn) {
         ValueNumberer gvn(graph, js_IonOptions.gvnIsOptimistic);
         if (!gvn.analyze())
             return false;
         IonSpewPass("GVN");
@@ -785,21 +785,21 @@ TestCompiler(IonBuilder &builder, MIRGra
     if (js_IonOptions.licm) {
         LICM licm(graph);
         if (!licm.analyze())
             return false;
         IonSpewPass("LICM");
         AssertGraphCoherency(graph);
     }
 
-    if (js_IonOptions.edgeCaseAnalysis) {
-        EdgeCaseAnalysis edgeCaseAnalysis(graph);
-        if (!edgeCaseAnalysis.analyzeLate())
+    if (js_IonOptions.rangeAnalysis) {
+        RangeAnalysis rangeAnalysis(graph);
+        if (!rangeAnalysis.analyzeLate())
             return false;
-        IonSpewPass("Edge Case Analysis (Late)");
+        IonSpewPass("Range Analysis (Late)");
         AssertGraphCoherency(graph);
     }
 
     LIRGraph lir(graph);
     LIRGenerator lirgen(&builder, graph, lir);
     if (!lirgen.generate())
         return false;
     IonSpewPass("Generate LIR");
--- a/js/src/ion/Ion.h
+++ b/js/src/ion/Ion.h
@@ -86,20 +86,20 @@ struct IonOptions
     // Default: true
     bool lsra;
 
     // Toggles whether inlining is performed.
     //
     // Default: true
     bool inlining;
 
-    // Toggles whether Edge Case Analysis is used.
+    // Toggles whether Range Analysis is used.
     //
     // Default: true
-    bool edgeCaseAnalysis;
+    bool rangeAnalysis;
 
     // How many invocations or loop iterations are needed before functions
     // are compiled.
     //
     // Default: 10,240
     uint32 usesBeforeCompile;
 
     // How many invocations or loop iterations are needed before functions
@@ -147,17 +147,17 @@ struct IonOptions
     IonOptions()
       : gvn(true),
         gvnIsOptimistic(true),
         licm(true),
         osr(true),
         limitScriptSize(true),
         lsra(true),
         inlining(true),
-        edgeCaseAnalysis(true),
+        rangeAnalysis(true),
         usesBeforeCompile(10240),
         usesBeforeCompileNoJaeger(40),
         usesBeforeInlining(usesBeforeCompile),
         maxStackArgs(4096),
         smallFunctionMaxBytecodeLength(100),
         smallFunctionUsesBeforeInlining(usesBeforeInlining / 4)
     { }
 };
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -38,17 +38,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "IonBuilder.h"
 #include "LICM.h" // For LinearSum
 #include "MIR.h"
 #include "MIRGraph.h"
-#include "EdgeCaseAnalysis.h"
+#include "RangeAnalysis.h"
 #include "jsnum.h"
 #include "jstypedarrayinlines.h" // For ClampIntForUint8Array
 
 using namespace js;
 using namespace js::ion;
 
 void
 MDefinition::PrintOpcodeName(FILE *fp, MDefinition::Opcode op)
@@ -181,23 +181,23 @@ MDefinition::congruentIfOperandsEqual(MD
 MDefinition *
 MDefinition::foldsTo(bool useValueNumbers)
 {
     // In the default case, there are no constants to fold.
     return this;
 }
 
 void
-MDefinition::analyzeEdgeCasesForward()
+MDefinition::analyzeRangeForward()
 {
     return;
 }
 
 void
-MDefinition::analyzeEdgeCasesBackward()
+MDefinition::analyzeRangeBackward()
 {
     return;
 }
 void
 MDefinition::analyzeTruncateBackward()
 {
     return;
 }
@@ -690,17 +690,17 @@ MDiv::foldsTo(bool useValueNumbers)
     // x / 1 -> x
     if (IsConstant(lhs(), 0) || IsConstant(rhs(), 1))
         return lhs();
 
     return this;
 }
 
 void
-MDiv::analyzeEdgeCasesForward()
+MDiv::analyzeRangeForward()
 {
     // This is only meaningful when doing integer division.
     if (specialization_ != MIRType_Int32)
         return;
 
     // Try removing divide by zero check
     if (rhs()->isConstant() && !rhs()->toConstant()->value().isInt32(0))
         canBeDivideByZero_ =  false;
@@ -722,35 +722,35 @@ MDiv::analyzeEdgeCasesForward()
     if (rhs()->isConstant()) {
         const js::Value &val = rhs()->toConstant()->value();
         if (val.isInt32() && val.toInt32() >= 0)
             canBeNegativeZero_ = false;
     }
 }
 
 void
-MDiv::analyzeEdgeCasesBackward()
+MDiv::analyzeRangeBackward()
 {
     if (canBeNegativeZero_)
         canBeNegativeZero_ = NeedNegativeZeroCheck(this);
 }
 
 void
 MDiv::analyzeTruncateBackward()
 {
     if (!isTruncated())
-        setTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
+        setTruncated(js::ion::RangeAnalysis::AllUsesTruncate(this));
 }
 
 bool
 MDiv::updateForReplacement(MDefinition *ins_)
 {
     JS_ASSERT(ins_->isDiv());
     MDiv *ins = ins_->toDiv();
-    // Since EdgeCaseAnalysis is not being run before GVN, its information does
+    // Since RangeAnalysis is not being run before GVN, its information does
     // not need to be merged here.
     if (isTruncated())
         setTruncated(ins->isTruncated());
     return true;
 }
 
 static inline MDefinition *
 TryFold(MDefinition *original, MDefinition *replacement)
@@ -808,34 +808,34 @@ MMod::foldsTo(bool useValueNumbers)
 
     return this;
 }
 
 void
 MAdd::analyzeTruncateBackward()
 {
     if (!isTruncated())
-        setTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
+        setTruncated(js::ion::RangeAnalysis::AllUsesTruncate(this));
 }
 
 bool
 MAdd::updateForReplacement(MDefinition *ins_)
 {
     JS_ASSERT(ins_->isAdd());
     MAdd *ins = ins_->toAdd();
     if (isTruncated())
         setTruncated(ins->isTruncated());
     return true;
 }
 
 void
 MSub::analyzeTruncateBackward()
 {
     if (!isTruncated())
-        setTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
+        setTruncated(js::ion::RangeAnalysis::AllUsesTruncate(this));
 }
 
 bool
 MSub::updateForReplacement(MDefinition *ins_)
 {
     JS_ASSERT(ins_->isSub());
     MSub *ins = ins_->toSub();
     if (isTruncated())
@@ -855,17 +855,17 @@ MMul::foldsTo(bool useValueNumbers)
 
     if (lhs()->congruentTo(rhs()))
         canBeNegativeZero_ = false;
 
     return this;
 }
 
 void
-MMul::analyzeEdgeCasesForward()
+MMul::analyzeRangeForward()
 {
     // Try to remove the check for negative zero
     // This only makes sense when using the integer multiplication
     if (specialization() != MIRType_Int32)
         return;
 
     // If lhs is > 0, no need for negative zero check.
     if (lhs()->isConstant()) {
@@ -879,17 +879,17 @@ MMul::analyzeEdgeCasesForward()
         const js::Value &val = rhs()->toConstant()->value();
         if (val.isInt32() && val.toInt32() > 0)
             canBeNegativeZero_ = false;
     }
 
 }
 
 void
-MMul::analyzeEdgeCasesBackward()
+MMul::analyzeRangeBackward()
 {
     if (canBeNegativeZero_)
         canBeNegativeZero_ = NeedNegativeZeroCheck(this);
 }
 
 bool
 MMul::updateForReplacement(MDefinition *ins)
 {
@@ -1159,17 +1159,17 @@ MToInt32::foldsTo(bool useValueNumbers)
 {
     MDefinition *input = getOperand(0);
     if (input->type() == MIRType_Int32)
         return input;
     return this;
 }
 
 void
-MToInt32::analyzeEdgeCasesBackward()
+MToInt32::analyzeRangeBackward()
 {
     canBeNegativeZero_ = NeedNegativeZeroCheck(this);
 }
 
 MDefinition *
 MTruncateToInt32::foldsTo(bool useValueNumbers)
 {
     MDefinition *input = getOperand(0);
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -323,18 +323,18 @@ class MDefinition : public MNode
     virtual void printOpcode(FILE *fp);
 
     virtual HashNumber valueHash() const;
     virtual bool congruentTo(MDefinition* const &ins) const {
         return false;
     }
     bool congruentIfOperandsEqual(MDefinition * const &ins) const;
     virtual MDefinition *foldsTo(bool useValueNumbers);
-    virtual void analyzeEdgeCasesForward();
-    virtual void analyzeEdgeCasesBackward();
+    virtual void analyzeRangeForward();
+    virtual void analyzeRangeBackward();
     virtual void analyzeTruncateBackward();
 
     MNode::Kind kind() const {
         return MNode::Definition;
     }
 
     uint32 id() const {
         JS_ASSERT(block_);
@@ -1625,17 +1625,17 @@ class MToInt32 : public MUnaryInstructio
 
     MDefinition *input() const {
         return getOperand(0);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
 
     // this only has backwards information flow.
-    void analyzeEdgeCasesBackward();
+    void analyzeRangeBackward();
 
     bool canBeNegativeZero() {
         return canBeNegativeZero_;
     }
 
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
@@ -2213,18 +2213,18 @@ class MMul : public MBinaryArithInstruct
 
   public:
     INSTRUCTION_HEADER(Mul);
     static MMul *New(MDefinition *left, MDefinition *right) {
         return new MMul(left, right);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
-    void analyzeEdgeCasesForward();
-    void analyzeEdgeCasesBackward();
+    void analyzeRangeForward();
+    void analyzeRangeBackward();
 
     double getIdentity() {
         return 1;
     }
 
     bool canOverflow() {
         return canOverflow_;
     }
@@ -2258,18 +2258,18 @@ class MDiv : public MBinaryArithInstruct
 
   public:
     INSTRUCTION_HEADER(Div);
     static MDiv *New(MDefinition *left, MDefinition *right) {
         return new MDiv(left, right);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
-    void analyzeEdgeCasesForward();
-    void analyzeEdgeCasesBackward();
+    void analyzeRangeForward();
+    void analyzeRangeBackward();
     void analyzeTruncateBackward();
 
     double getIdentity() {
         JS_NOT_REACHED("not used");
         return 1;
     }
 
     bool isTruncated() const {
new file mode 100644
--- /dev/null
+++ b/js/src/ion/RangeAnalysis.cpp
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 sw=4 et tw=79: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+
+#include "Ion.h"
+#include "IonSpewer.h"
+#include "RangeAnalysis.h"
+#include "MIR.h"
+#include "MIRGraph.h"
+
+using namespace js;
+using namespace js::ion;
+
+RangeAnalysis::RangeAnalysis(MIRGraph &graph)
+  : graph(graph)
+{
+}
+
+bool
+RangeAnalysis::analyzeLate()
+{
+    for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
+        for (MDefinitionIterator iter(*block); iter; iter++)
+            iter->analyzeRangeForward();
+    }
+
+    for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
+        for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
+            riter->analyzeRangeBackward();
+    }
+
+    return true;
+}
+
+bool
+RangeAnalysis::analyzeEarly()
+{
+
+    for (PostorderIterator block(graph.poBegin()); block != graph.poEnd(); block++) {
+        for (MInstructionReverseIterator riter(block->rbegin()); riter != block->rend(); riter++)
+            riter->analyzeTruncateBackward();
+    }
+
+    return true;
+}
+
+bool
+RangeAnalysis::AllUsesTruncate(MInstruction *m)
+{
+    for (MUseIterator use = m->usesBegin(); use != m->usesEnd(); use++) {
+        if (use->node()->isResumePoint())
+            return false;
+
+        MDefinition *def = use->node()->toDefinition();
+        if (def->isTruncateToInt32())
+            continue;
+        if (def->isBitAnd())
+            continue;
+        if (def->isBitOr())
+            continue;
+        if (def->isBitXor())
+            continue;
+        if (def->isLsh())
+            continue;
+        if (def->isRsh())
+            continue;
+        if (def->isBitNot())
+            continue;
+        if (def->isAdd() && def->toAdd()->isTruncated())
+            continue;
+        if (def->isSub() && def->toSub()->isTruncated())
+            continue;
+        // cannot use divide, since |truncate(int32(x/y) + int32(a/b)) != truncate(x/y+a/b)|
+        return false;
+    }
+    return true;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/ion/RangeAnalysis.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 sw=4 et tw=79: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jsion_ion_range_analysis_h__
+#define jsion_ion_range_analysis_h__
+
+namespace js {
+namespace ion {
+
+class MIRGraph;
+
+class RangeAnalysis
+{
+    MIRGraph &graph;
+
+  public:
+    RangeAnalysis(MIRGraph &graph);
+    bool analyzeEarly();
+    bool analyzeLate();
+    static bool AllUsesTruncate(MInstruction *m);
+};
+
+
+} // namespace ion
+} // namespace js
+
+#endif // jsion_ion_range_analysis_h__
+
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4706,23 +4706,23 @@ ProcessArgs(JSContext *cx, JSObject *obj
         if (strcmp(str, "on") == 0)
             ion::js_IonOptions.licm = true;
         else if (strcmp(str, "off") == 0)
             ion::js_IonOptions.licm = false;
         else
             return OptionFailure("ion-licm", str);
     }
 
-    if (const char *str = op->getStringOption("ion-edgecase-analysis")) {
+    if (const char *str = op->getStringOption("ion-range-analysis")) {
         if (strcmp(str, "on") == 0)
-            ion::js_IonOptions.edgeCaseAnalysis = true;
+            ion::js_IonOptions.rangeAnalysis = true;
         else if (strcmp(str, "off") == 0)
-            ion::js_IonOptions.edgeCaseAnalysis = false;
+            ion::js_IonOptions.rangeAnalysis = false;
         else
-            return OptionFailure("ion-edgecase-analysis", str);
+            return OptionFailure("ion-range-analysis", str);
     }
 
     if (const char *str = op->getStringOption("ion-inlining")) {
         if (strcmp(str, "on") == 0)
             ion::js_IonOptions.inlining = true;
         else if (strcmp(str, "off") == 0)
             ion::js_IonOptions.inlining = false;
         else
@@ -4966,18 +4966,18 @@ main(int argc, char **argv, char **envp)
         || !op.addBoolOption('\0', "no-ion", "Disable IonMonkey")
         || !op.addStringOption('\0', "ion-gvn", "[mode]",
                                "Specify Ion global value numbering:\n"
                                "  off: disable GVN\n"
                                "  pessimistic: (default) use pessimistic GVN\n"
                                "  optimistic: use optimistic GVN")
         || !op.addStringOption('\0', "ion-licm", "on/off",
                                "Loop invariant code motion (default: on, off to disable)")
-        || !op.addStringOption('\0', "ion-edgecase-analysis", "on/off",
-                               "Find edge cases where Ion can avoid bailouts (default: on, off to disable)")
+        || !op.addStringOption('\0', "ion-range-analysis", "on/off",
+                               "Range Analysis (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-inlining", "on/off",
                                "Inline methods where possible (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-osr", "on/off",
                                "On-Stack Replacement (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-limit-script-size", "on/off",
                                "Don't compile very large scripts (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-regalloc", "[mode]",
                                "Specify Ion register allocation:\n"