Bug 1328228: IonMonkey - Track optimizations for newarray and newobject, r=shu
authorHannes Verschore <hv1989@gmail.com>
Mon, 09 Jan 2017 15:05:38 +0100
changeset 457713 b4bc05f80383f464349cdba8f9ca34236767b333
parent 457712 1e155739b693921263efab6738e4ae3457d61d4c
child 457714 953bb49f3aafaea044051d11d501df0980c3d2e2
push id40874
push userbmo:kmckinley@mozilla.com
push dateMon, 09 Jan 2017 19:01:26 +0000
reviewersshu
bugs1328228
milestone53.0a1
Bug 1328228: IonMonkey - Track optimizations for newarray and newobject, r=shu
js/public/TrackedOptimizationInfo.h
js/src/jit/IonBuilder.cpp
--- a/js/public/TrackedOptimizationInfo.h
+++ b/js/public/TrackedOptimizationInfo.h
@@ -55,16 +55,24 @@ namespace JS {
     _(BinaryArith_Concat)                               \
     _(BinaryArith_SpecializedTypes)                     \
     _(BinaryArith_SpecializedOnBaselineTypes)           \
     _(BinaryArith_SharedCache)                          \
     _(BinaryArith_Call)                                 \
                                                         \
     _(InlineCache_OptimizedStub)                        \
                                                         \
+    _(NewArray_TemplateObject)                          \
+    _(NewArray_SharedCache)                             \
+    _(NewArray_Call)                                    \
+                                                        \
+    _(NewObject_TemplateObject)                         \
+    _(NewObject_SharedCache)                            \
+    _(NewObject_Call)                                   \
+                                                        \
     _(Call_Inline)
 
 
 // Ordering is important below. All outcomes before GenericSuccess will be
 // considered failures, and all outcomes after GenericSuccess will be
 // considered successes.
 #define TRACKED_OUTCOME_LIST(_)                                         \
     _(GenericFailure)                                                   \
@@ -115,16 +123,20 @@ namespace JS {
     _(NonNativeReceiver)                                                \
     _(IndexType)                                                        \
     _(SetElemNonDenseNonTANotCached)                                    \
     _(NoSimdJitSupport)                                                 \
     _(SimdTypeNotOptimized)                                             \
     _(UnknownSimdProperty)                                              \
     _(NotModuleNamespace)                                               \
     _(UnknownProperty)                                                  \
+    _(NoTemplateObject)                                                 \
+    _(TemplateObjectIsUnboxedWithoutInlineElements)                     \
+    _(TemplateObjectIsPlainObjectWithDynamicSlots)                      \
+    _(LengthTooBig)                                                     \
                                                                         \
     _(ICOptStub_GenericSuccess)                                         \
                                                                         \
     _(ICGetPropStub_ReadSlot)                                           \
     _(ICGetPropStub_CallGetter)                                         \
     _(ICGetPropStub_ArrayLength)                                        \
     _(ICGetPropStub_UnboxedRead)                                        \
     _(ICGetPropStub_UnboxedReadExpando)                                 \
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5664,43 +5664,52 @@ IonBuilder::compareTrySharedStub(bool* e
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newArrayTryTemplateObject(bool* emitted, JSObject* templateObject, uint32_t length)
 {
     MOZ_ASSERT(*emitted == false);
 
-    if (!templateObject)
-        return Ok();
+    trackOptimizationAttempt(TrackedStrategy::NewArray_TemplateObject);
+
+    if (!templateObject) {
+        trackOptimizationOutcome(TrackedOutcome::NoTemplateObject);
+        return Ok();
+    }
 
     if (templateObject->is<UnboxedArrayObject>()) {
         MOZ_ASSERT(templateObject->as<UnboxedArrayObject>().capacity() >= length);
-        if (!templateObject->as<UnboxedArrayObject>().hasInlineElements())
-            return Ok();
+        if (!templateObject->as<UnboxedArrayObject>().hasInlineElements()) {
+            trackOptimizationOutcome(TrackedOutcome::TemplateObjectIsUnboxedWithoutInlineElements);
+            return Ok();
+        }
     }
 
     MOZ_ASSERT(length <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);
 
     size_t arraySlots =
         gc::GetGCKindSlots(templateObject->asTenured().getAllocKind()) - ObjectElements::VALUES_PER_HEADER;
 
-    if (length > arraySlots)
-        return Ok();
+    if (length > arraySlots) {
+        trackOptimizationOutcome(TrackedOutcome::LengthTooBig);
+        return Ok();
+    }
 
     // Emit fastpath.
 
     gc::InitialHeap heap = templateObject->group()->initialHeap(constraints());
     MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     current->add(templateConst);
 
     MNewArray* ins = MNewArray::New(alloc(), constraints(), length, templateConst, heap, pc);
     current->add(ins);
     current->push(ins);
 
+    trackOptimizationSuccess();
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newArrayTrySharedStub(bool* emitted)
 {
     MOZ_ASSERT(*emitted == false);
@@ -5708,51 +5717,57 @@ IonBuilder::newArrayTrySharedStub(bool* 
     // Try to emit a shared stub cache.
 
     if (JitOptions.disableSharedStubs)
         return Ok();
 
     if (*pc != JSOP_NEWINIT && *pc != JSOP_NEWARRAY)
         return Ok();
 
+    trackOptimizationAttempt(TrackedStrategy::NewArray_SharedCache);
+
     MInstruction* stub = MNullarySharedStub::New(alloc());
     current->add(stub);
     current->push(stub);
 
     MOZ_TRY(resumeAfter(stub));
 
     MUnbox* unbox = MUnbox::New(alloc(), current->pop(), MIRType::Object, MUnbox::Infallible);
     current->add(unbox);
     current->push(unbox);
 
+    trackOptimizationSuccess();
+
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length)
 {
     MOZ_ASSERT(*emitted == false);
 
     // Emit a VM call.
+    trackOptimizationAttempt(TrackedStrategy::NewArray_Call);
 
     gc::InitialHeap heap = gc::DefaultHeap;
     MConstant* templateConst = MConstant::New(alloc(), NullValue());
 
     if (templateObject) {
         heap = templateObject->group()->initialHeap(constraints());
         templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     }
 
     current->add(templateConst);
 
     MNewArray* ins = MNewArray::NewVM(alloc(), constraints(), length, templateConst, heap, pc);
     current->add(ins);
     current->push(ins);
 
+    trackOptimizationSuccess();
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::jsop_newarray(uint32_t length)
 {
     JSObject* templateObject = inspector->getTemplateObject(pc);
@@ -5767,16 +5782,17 @@ IonBuilder::jsop_newarray(uint32_t lengt
 
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::jsop_newarray(JSObject* templateObject, uint32_t length)
 {
     bool emitted = false;
+    startTrackingOptimizations();
 
     if (!forceInlineCaches()) {
         MOZ_TRY(newArrayTryTemplateObject(&emitted, templateObject, length));
         if (emitted)
             return Ok();
     }
 
     MOZ_TRY(newArrayTrySharedStub(&emitted));
@@ -5812,21 +5828,26 @@ IonBuilder::jsop_newarray_copyonwrite()
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newObjectTryTemplateObject(bool* emitted, JSObject* templateObject)
 {
     MOZ_ASSERT(*emitted == false);
 
-    if (!templateObject)
-        return Ok();
-
-    if (templateObject->is<PlainObject>() && templateObject->as<PlainObject>().hasDynamicSlots())
-        return Ok();
+    trackOptimizationAttempt(TrackedStrategy::NewObject_TemplateObject);
+    if (!templateObject) {
+        trackOptimizationOutcome(TrackedOutcome::NoTemplateObject);
+        return Ok();
+    }
+
+    if (templateObject->is<PlainObject>() && templateObject->as<PlainObject>().hasDynamicSlots()) {
+        trackOptimizationOutcome(TrackedOutcome::TemplateObjectIsPlainObjectWithDynamicSlots);
+        return Ok();
+    }
 
     // Emit fastpath.
 
     MNewObject::Mode mode;
     if (JSOp(*pc) == JSOP_NEWOBJECT || JSOp(*pc) == JSOP_NEWINIT)
         mode = MNewObject::ObjectLiteral;
     else
         mode = MNewObject::ObjectCreate;
@@ -5836,50 +5857,56 @@ IonBuilder::newObjectTryTemplateObject(b
     current->add(templateConst);
 
     MNewObject* ins = MNewObject::New(alloc(), constraints(), templateConst, heap, mode);
     current->add(ins);
     current->push(ins);
 
     MOZ_TRY(resumeAfter(ins));
 
+    trackOptimizationSuccess();
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newObjectTrySharedStub(bool* emitted)
 {
     MOZ_ASSERT(*emitted == false);
 
     // Try to emit a shared stub cache.
 
     if (JitOptions.disableSharedStubs)
         return Ok();
 
+    trackOptimizationAttempt(TrackedStrategy::NewObject_SharedCache);
+
     MInstruction* stub = MNullarySharedStub::New(alloc());
     current->add(stub);
     current->push(stub);
 
     MOZ_TRY(resumeAfter(stub));
 
     MUnbox* unbox = MUnbox::New(alloc(), current->pop(), MIRType::Object, MUnbox::Infallible);
     current->add(unbox);
     current->push(unbox);
 
+    trackOptimizationSuccess();
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::newObjectTryVM(bool* emitted, JSObject* templateObject)
 {
     // Emit a VM call.
     MOZ_ASSERT(JSOp(*pc) == JSOP_NEWOBJECT || JSOp(*pc) == JSOP_NEWINIT);
 
+    trackOptimizationAttempt(TrackedStrategy::NewObject_Call);
+
     gc::InitialHeap heap = gc::DefaultHeap;
     MConstant* templateConst = MConstant::New(alloc(), NullValue());
 
     if (templateObject) {
         heap = templateObject->group()->initialHeap(constraints());
         templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     }
 
@@ -5887,24 +5914,26 @@ IonBuilder::newObjectTryVM(bool* emitted
 
     MNewObject* ins = MNewObject::NewVM(alloc(), constraints(), templateConst, heap,
                                         MNewObject::ObjectLiteral);
     current->add(ins);
     current->push(ins);
 
     MOZ_TRY(resumeAfter(ins));
 
+    trackOptimizationSuccess();
     *emitted = true;
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::jsop_newobject()
 {
     bool emitted = false;
+    startTrackingOptimizations();
 
     JSObject* templateObject = inspector->getTemplateObject(pc);
 
     if (!forceInlineCaches()) {
         MOZ_TRY(newObjectTryTemplateObject(&emitted, templateObject));
         if (emitted)
             return Ok();
     }