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 328526 b4bc05f80383f464349cdba8f9ca34236767b333
parent 328525 1e155739b693921263efab6738e4ae3457d61d4c
child 328527 953bb49f3aafaea044051d11d501df0980c3d2e2
push id85462
push userhv1989@gmail.com
push dateMon, 09 Jan 2017 14:07:57 +0000
treeherdermozilla-inbound@953bb49f3aaf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1328228
milestone53.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 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();
     }