Bug 1275038 - IonMonkey: Remove regexp clone analysis in favor of hoist analysis, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Thu, 02 Jun 2016 12:21:33 +0200
changeset 339165 539bcdf33f32803be87f4d60faf6864277c13cba
parent 339164 00b8895ad68cf172ca74cecd822a2203b5d2e0a7
child 339166 67b41b80d37cf367ef746f2370c9ff947dead5f0
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1275038
milestone49.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 1275038 - IonMonkey: Remove regexp clone analysis in favor of hoist analysis, r=jandem
js/src/jit/IonAnalysis.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/Lowering.cpp
js/src/jit/MIR.h
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2045,23 +2045,23 @@ jit::MakeMRegExpHoistable(MIRGraph& grap
             if (!IsRegExpHoistable(regexp, worklist, &hoistable))
                 return false;
 
             if (!hoistable)
                 continue;
 
             // Make MRegExp hoistable
             regexp->setMovable();
+            regexp->setDoNotClone();
 
             // That would be incorrect for global/sticky, because lastIndex
             // could be wrong.  Therefore setting the lastIndex to 0. That is
             // faster than a not movable regexp.
             RegExpObject* source = regexp->source();
             if (source->sticky() || source->global()) {
-                MOZ_ASSERT(regexp->mustClone());
                 MConstant* zero = MConstant::New(graph.alloc(), Int32Value(0));
                 regexp->block()->insertAfter(regexp, zero);
 
                 MStoreFixedSlot* lastIndex =
                     MStoreFixedSlot::New(graph.alloc(), regexp, RegExpObject::lastIndexSlot(), zero);
                 regexp->block()->insertAfter(zero, lastIndex);
             }
         }
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -13143,30 +13143,17 @@ IonBuilder::jsop_delelem()
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_regexp(RegExpObject* reobj)
 {
-    // JS semantics require regular expression literals to create different
-    // objects every time they execute. We only need to do this cloning if the
-    // script could actually observe the effect of such cloning, for instance
-    // by getting or setting properties on it.
-    //
-    // First, make sure the regex is one we can safely optimize. Lowering can
-    // then check if this regex object only flows into known natives and can
-    // avoid cloning in this case.
-
-    bool mustClone = true;
-    if (!reobj->global() && !reobj->sticky())
-        mustClone = false;
-
-    MRegExp* regexp = MRegExp::New(alloc(), constraints(), reobj, mustClone);
+    MRegExp* regexp = MRegExp::New(alloc(), constraints(), reobj);
     current->add(regexp);
     current->push(regexp);
 
     return true;
 }
 
 bool
 IonBuilder::jsop_object(JSObject* obj)
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2236,87 +2236,26 @@ LIRGenerator::visitToObjectOrNull(MToObj
 {
     MOZ_ASSERT(ins->input()->type() == MIRType::Value);
 
     LValueToObjectOrNull* lir = new(alloc()) LValueToObjectOrNull(useBox(ins->input()));
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
-static bool
-MustCloneRegExpForCall(MCall* call, uint32_t useIndex)
-{
-    // We have a regex literal flowing into a call. Return |false| iff
-    // this is a native call that does not let the regex escape.
-
-    JSFunction* target = call->getSingleTarget();
-    if (!target || !target->isNative())
-        return true;
-
-    return true;
-}
-
-
-static bool
-MustCloneRegExp(MRegExp* regexp)
-{
-    if (regexp->mustClone())
-        return true;
-
-    // If this regex literal only flows into known natives that don't let
-    // it escape, we don't have to clone it.
-
-    for (MUseIterator iter(regexp->usesBegin()); iter != regexp->usesEnd(); iter++) {
-        MNode* node = iter->consumer();
-        if (!node->isDefinition())
-            return true;
-
-        MDefinition* def = node->toDefinition();
-        if (def->isRegExpMatcher()) {
-            MRegExpMatcher* test = def->toRegExpMatcher();
-            if (test->indexOf(*iter) == 1) {
-                // Optimized RegExp.prototype.exec.
-                MOZ_ASSERT(test->regexp() == regexp);
-                continue;
-            }
-        } else if (def->isRegExpSearcher()) {
-            MRegExpSearcher* test = def->toRegExpSearcher();
-            if (test->indexOf(*iter) == 1) {
-                // Optimized RegExp.prototype.exec.
-                MOZ_ASSERT(test->regexp() == regexp);
-                continue;
-            }
-        } else if (def->isRegExpTester()) {
-            MRegExpTester* test = def->toRegExpTester();
-            if (test->indexOf(*iter) == 1) {
-                // Optimized RegExp.prototype.test.
-                MOZ_ASSERT(test->regexp() == regexp);
-                continue;
-            }
-        } else if (def->isCall()) {
-            MCall* call = def->toCall();
-            if (!MustCloneRegExpForCall(call, call->indexOf(*iter)))
-                continue;
-        }
-
-        return true;
-    }
-    return false;
-}
-
 void
 LIRGenerator::visitRegExp(MRegExp* ins)
 {
-    if (!MustCloneRegExp(ins)) {
-        RegExpObject* source = ins->source();
-        define(new(alloc()) LPointer(source), ins);
-    } else {
+    if (ins->mustClone()) {
         LRegExp* lir = new(alloc()) LRegExp();
         defineReturn(lir, ins);
         assignSafepoint(lir, ins);
+    } else {
+        RegExpObject* source = ins->source();
+        define(new(alloc()) LPointer(source), ins);
     }
 }
 
 void
 LIRGenerator::visitRegExpMatcher(MRegExpMatcher* ins)
 {
     MOZ_ASSERT(ins->regexp()->type() == MIRType::Object);
     MOZ_ASSERT(ins->string()->type() == MIRType::String);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -8085,33 +8085,36 @@ class MDefFun
     }
 };
 
 class MRegExp : public MNullaryInstruction
 {
     CompilerGCPointer<RegExpObject*> source_;
     bool mustClone_;
 
-    MRegExp(CompilerConstraintList* constraints, RegExpObject* source, bool mustClone)
+    MRegExp(CompilerConstraintList* constraints, RegExpObject* source)
       : source_(source),
-        mustClone_(mustClone)
+        mustClone_(true)
     {
         setResultType(MIRType::Object);
         setResultTypeSet(MakeSingletonTypeSet(constraints, source));
     }
 
   public:
     INSTRUCTION_HEADER(RegExp)
 
     static MRegExp* New(TempAllocator& alloc, CompilerConstraintList* constraints,
-                        RegExpObject* source, bool mustClone)
-    {
-        return new(alloc) MRegExp(constraints, source, mustClone);
-    }
-
+                        RegExpObject* source)
+    {
+        return new(alloc) MRegExp(constraints, source);
+    }
+
+    void setDoNotClone() {
+        mustClone_ = false;
+    }
     bool mustClone() const {
         return mustClone_;
     }
     RegExpObject* source() const {
         return source_;
     }
     AliasSet getAliasSet() const override {
         return AliasSet::None();