Bug 1028675 - Implement RInstruction for StringSplit. r=nbp
authorDavid Moreira <david.moreira.fr@gmail.com>
Fri, 11 Jul 2014 03:04:45 -0700
changeset 214369 1f27562e4159b152eeaab50fbde42019d07ce16e
parent 214368 037da8d9b3c941c11f9cd7624d4b949efc94f0e7
child 214370 c4a56f872991965536a23d3a639441e415e6aab2
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1028675
milestone33.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 1028675 - Implement RInstruction for StringSplit. r=nbp
js/src/jit-test/tests/ion/dce-with-rinstructions.js
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.h
js/src/jit/Recover.cpp
js/src/jit/Recover.h
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -532,16 +532,25 @@ function rsqrt_object(i) {
     var o = { valueOf: function () { return t; } };
     var x = Math.sqrt(o); /* computed with t == i, not 1.5 */
     t = 1.5;
     if (uceFault_sqrt_object(i) || uceFault_sqrt_object(i))
         assertEq(x, Math.sqrt(99));
     return i;
 }
 
+var uceFault_str_split = eval(uneval(uceFault).replace('uceFault', 'uceFault_str_split'))
+function rstr_split(i) {
+    var x = "str01234567899876543210rts".split("" + i);
+    if (uceFault_str_split(i) || uceFault_str_split(i)) {
+        assertEq(x[0], "str012345678");
+    }
+    return i;
+}
+
 for (i = 0; i < 100; i++) {
     rbitnot_number(i);
     rbitnot_object(i);
     rbitand_number(i);
     rbitand_object(i);
     rbitor_number(i);
     rbitor_object(i);
     rbitxor_number(i);
@@ -590,16 +599,17 @@ for (i = 0; i < 100; i++) {
     rmin_object(i);
     rmax_number(i);
     rmax_object(i);
     rabs_number(i);
     rabs_object(i);
     rsqrt_number(i);
     rsqrt_float(i);
     rsqrt_object(i);
+    rstr_split(i);
 }
 
 // Test that we can refer multiple time to the same recover instruction, as well
 // as chaining recover instructions.
 
 function alignedAlloc($size, $alignment) {
     var $1 = $size + 4 | 0;
     var $2 = $alignment - 1 | 0;
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -1152,19 +1152,21 @@ IonBuilder::inlineStringSplit(CallInfo &
         return InliningStatus_NotInlined;
 
     if (!key.maybeTypes()->hasType(types::Type::StringType())) {
         key.freeze(constraints());
         return InliningStatus_NotInlined;
     }
 
     callInfo.setImplicitlyUsedUnchecked();
+    MConstant *templateObjectDef = MConstant::New(alloc(), ObjectValue(*templateObject), constraints());
+    current->add(templateObjectDef);
 
     MStringSplit *ins = MStringSplit::New(alloc(), constraints(), callInfo.thisArg(),
-                                          callInfo.getArg(0), templateObject);
+                                          callInfo.getArg(0), templateObjectDef);
     current->add(ins);
     current->push(ins);
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineStrCharCodeAt(CallInfo &callInfo)
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -4845,59 +4845,63 @@ class MFromCharCode
 
     bool writeRecoverData(CompactBufferWriter &writer) const;
     bool canRecoverOnBailout() const {
         return true;
     }
 };
 
 class MStringSplit
-  : public MBinaryInstruction,
+  : public MTernaryInstruction,
     public MixPolicy<StringPolicy<0>, StringPolicy<1> >
 {
-    types::TypeObject *typeObject_;
-
     MStringSplit(types::CompilerConstraintList *constraints, MDefinition *string, MDefinition *sep,
-                 JSObject *templateObject)
-      : MBinaryInstruction(string, sep),
-        typeObject_(templateObject->type())
+                 MConstant *templateObject)
+      : MTernaryInstruction(string, sep, templateObject)
     {
         setResultType(MIRType_Object);
-        setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject));
+        setResultTypeSet(templateObject->resultTypeSet());
     }
 
   public:
     INSTRUCTION_HEADER(StringSplit)
 
     static MStringSplit *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
                              MDefinition *string, MDefinition *sep,
-                             JSObject *templateObject)
+                             MConstant *templateObject)
     {
         return new(alloc) MStringSplit(constraints, string, sep, templateObject);
     }
-    types::TypeObject *typeObject() const {
-        return typeObject_;
-    }
     MDefinition *string() const {
         return getOperand(0);
     }
     MDefinition *separator() const {
         return getOperand(1);
     }
+    JSObject *templateObject() const {
+        return &getOperand(2)->toConstant()->value().toObject();
+    }
+    types::TypeObject *typeObject() const {
+        return templateObject()->type();
+    }
     TypePolicy *typePolicy() {
         return this;
     }
     bool possiblyCalls() const {
         return true;
     }
     virtual AliasSet getAliasSet() const {
         // Although this instruction returns a new array, we don't have to mark
         // it as store instruction, see also MNewArray.
         return AliasSet::None();
     }
+    bool writeRecoverData(CompactBufferWriter &writer) const;
+    bool canRecoverOnBailout() const {
+        return true;
+    }
 };
 
 // Returns an object to use as |this| value. See also ComputeThis and
 // BoxNonStrictThis in Interpreter.h.
 class MComputeThis
   : public MUnaryInstruction,
     public BoxPolicy<0>
 {
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -824,16 +824,45 @@ MMathFunction::writeRecoverData(CompactB
         writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
         return true;
       default:
         MOZ_CRASH("Unknown math function.");
     }
 }
 
 bool
+MStringSplit::writeRecoverData(CompactBufferWriter &writer) const
+{
+    MOZ_ASSERT(canRecoverOnBailout());
+    writer.writeUnsigned(uint32_t(RInstruction::Recover_StringSplit));
+    return true;
+}
+
+RStringSplit::RStringSplit(CompactBufferReader &reader)
+{}
+
+bool
+RStringSplit::recover(JSContext *cx, SnapshotIterator &iter) const
+{
+    RootedString str(cx, iter.read().toString());
+    RootedString sep(cx, iter.read().toString());
+    RootedTypeObject typeObj(cx, iter.read().toObject().type());
+
+    RootedValue result(cx);
+
+    JSObject *res = str_split_string(cx, typeObj, str, sep);
+    if (!res)
+        return false;
+
+    result.setObject(*res);
+    iter.storeInstructionResult(result);
+    return true;
+}
+
+bool
 MNewObject::writeRecoverData(CompactBufferWriter &writer) const
 {
     MOZ_ASSERT(canRecoverOnBailout());
     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewObject));
     writer.writeByte(templateObjectIsClassPrototype_);
     return true;
 }
 
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -38,16 +38,17 @@ namespace jit {
     _(Round)                                    \
     _(CharCodeAt)                               \
     _(FromCharCode)                             \
     _(Pow)                                      \
     _(PowHalf)                                  \
     _(MinMax)                                   \
     _(Abs)                                      \
     _(Sqrt)                                     \
+    _(StringSplit)                              \
     _(NewObject)                                \
     _(NewDerivedTypedObject)
 
 class RResumePoint;
 class SnapshotIterator;
 
 class RInstruction
 {
@@ -426,16 +427,28 @@ class RSqrt MOZ_FINAL : public RInstruct
 
     virtual uint32_t numOperands() const {
         return 1;
     }
 
     bool recover(JSContext *cx, SnapshotIterator &iter) const;
 };
 
+class RStringSplit MOZ_FINAL : public RInstruction
+{
+  public:
+    RINSTRUCTION_HEADER_(StringSplit)
+
+    virtual uint32_t numOperands() const {
+        return 3;
+    }
+
+    bool recover(JSContext *cx, SnapshotIterator &iter) const;
+};
+
 class RNewObject MOZ_FINAL : public RInstruction
 {
   private:
     bool templateObjectIsClassPrototype_;
 
   public:
     RINSTRUCTION_HEADER_(NewObject)