Bug 1344469 - Part 6 - Port not defined property optimzation to HasOwn. r=jandem
authorTom Schuster <evilpies@gmail.com>
Fri, 14 Apr 2017 00:47:31 +0200
changeset 353020 2ca1453ae574e7cbbffe09facf99a31773fe460c
parent 353019 1e4d5a3704d00366a598687552dec52f5f7de64c
child 353021 e295801c2da9403ec103978ff362506c69752e41
push id31655
push userihsiao@mozilla.com
push dateFri, 14 Apr 2017 09:07:09 +0000
treeherdermozilla-central@8f806306fb83 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1344469
milestone55.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 1344469 - Part 6 - Port not defined property optimzation to HasOwn. r=jandem
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -6977,17 +6977,17 @@ IonBuilder::testSingletonPropertyTypes(M
     JSObject* proto = GetBuiltinPrototypePure(&script()->global(), key);
     if (proto)
         return testSingletonProperty(proto, id);
 
     return nullptr;
 }
 
 AbortReasonOr<bool>
-IonBuilder::testNotDefinedProperty(MDefinition* obj, jsid id)
+IonBuilder::testNotDefinedProperty(MDefinition* obj, jsid id, bool ownProperty /* = false */)
 {
     TemporaryTypeSet* types = obj->resultTypeSet();
     if (!types || types->unknownObject() || types->getKnownMIRType() != MIRType::Object)
         return false;
 
     for (unsigned i = 0, count = types->getObjectCount(); i < count; i++) {
         TypeSet::ObjectKey* key = types->getObject(i);
         if (!key)
@@ -7013,16 +7013,20 @@ IonBuilder::testNotDefinedProperty(MDefi
             {
                 return false;
             }
 
             HeapTypeSetKey property = key->property(id);
             if (property.isOwnProperty(constraints()))
                 return false;
 
+            // If we only care about own properties don't check the proto.
+            if (ownProperty)
+                break;
+
             JSObject* proto = checkNurseryObject(key->proto().toObjectOrNull());
             if (!proto)
                 break;
             key = TypeSet::ObjectKey::get(proto);
         }
     }
 
     return true;
@@ -12599,17 +12603,17 @@ IonBuilder::jsop_in()
     MDefinition* id = current->pop();
 
     bool emitted = false;
 
     MOZ_TRY(inTryDense(&emitted, obj, id));
     if (emitted)
         return Ok();
 
-    MOZ_TRY(inTryFold(&emitted, obj, id));
+    MOZ_TRY(hasTryNotDefined(&emitted, obj, id, /* ownProperty = */ false));
     if (emitted)
         return Ok();
 
     MIn* ins = MIn::New(alloc(), id, obj);
 
     current->add(ins);
     current->push(ins);
 
@@ -12663,33 +12667,33 @@ IonBuilder::inTryDense(bool* emitted, MD
 
     current->add(ins);
     current->push(ins);
 
     return Ok();
 }
 
 AbortReasonOr<Ok>
-IonBuilder::inTryFold(bool* emitted, MDefinition* obj, MDefinition* id)
+IonBuilder::hasTryNotDefined(bool* emitted, MDefinition* obj, MDefinition* id, bool ownProperty)
 {
     // Fold |id in obj| to |false|, if we know the object (or an object on its
     // prototype chain) does not have this property.
 
     MOZ_ASSERT(!*emitted);
 
     MConstant* idConst = id->maybeConstantValue();
     jsid propId;
     if (!idConst || !ValueToIdPure(idConst->toJSValue(), &propId))
         return Ok();
 
     if (propId != IdToTypeId(propId))
         return Ok();
 
     bool res;
-    MOZ_TRY_VAR(res, testNotDefinedProperty(obj, propId));
+    MOZ_TRY_VAR(res, testNotDefinedProperty(obj, propId, ownProperty));
     if (!res)
         return Ok();
 
     *emitted = true;
 
     pushConstant(BooleanValue(false));
     obj->setImplicitlyUsedUnchecked();
     id->setImplicitlyUsedUnchecked();
@@ -12697,16 +12701,23 @@ IonBuilder::inTryFold(bool* emitted, MDe
 }
 
 AbortReasonOr<Ok>
 IonBuilder::jsop_hasown()
 {
     MDefinition* obj = convertUnboxedObjects(current->pop());
     MDefinition* id = current->pop();
 
+    if (!forceInlineCaches()) {
+        bool emitted = false;
+        MOZ_TRY(hasTryNotDefined(&emitted, obj, id, /* ownProperty = */ true));
+        if (emitted)
+            return Ok();
+    }
+
     MHasOwnCache* ins = MHasOwnCache::New(alloc(), obj, id);
     current->add(ins);
     current->push(ins);
 
     MOZ_TRY(resumeAfter(ins));
     return Ok();
 }
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -330,19 +330,19 @@ class IonBuilder
                                                 uint32_t length);
     AbortReasonOr<Ok> newArrayTryVM(bool* emitted, JSObject* templateObject, uint32_t length);
 
     // jsop_newobject helpers.
     AbortReasonOr<Ok> newObjectTrySharedStub(bool* emitted);
     AbortReasonOr<Ok> newObjectTryTemplateObject(bool* emitted, JSObject* templateObject);
     AbortReasonOr<Ok> newObjectTryVM(bool* emitted, JSObject* templateObject);
 
-    // jsop_in helpers.
+    // jsop_in/jsop_hasown helpers.
     AbortReasonOr<Ok> inTryDense(bool* emitted, MDefinition* obj, MDefinition* id);
-    AbortReasonOr<Ok> inTryFold(bool* emitted, MDefinition* obj, MDefinition* id);
+    AbortReasonOr<Ok> hasTryNotDefined(bool* emitted, MDefinition* obj, MDefinition* id, bool ownProperty);
 
     // binary data lookup helpers.
     TypedObjectPrediction typedObjectPrediction(MDefinition* typedObj);
     TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet* types);
     bool typedObjectHasField(MDefinition* typedObj,
                              PropertyName* name,
                              size_t* fieldOffset,
                              TypedObjectPrediction* fieldTypeReprs,
@@ -852,17 +852,17 @@ class IonBuilder
 
     MGetPropertyCache* getInlineableGetPropertyCache(CallInfo& callInfo);
 
     JSObject* testGlobalLexicalBinding(PropertyName* name);
 
     JSObject* testSingletonProperty(JSObject* obj, jsid id);
     JSObject* testSingletonPropertyTypes(MDefinition* obj, jsid id);
 
-    AbortReasonOr<bool> testNotDefinedProperty(MDefinition* obj, jsid id);
+    AbortReasonOr<bool> testNotDefinedProperty(MDefinition* obj, jsid id, bool ownProperty = false);
 
     uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
     MDefinition* convertUnboxedObjects(MDefinition* obj);
     MDefinition* convertUnboxedObjects(MDefinition* obj,
                                        const BaselineInspector::ObjectGroupVector& list);
     uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
                               JSValueType* punboxedType);
     MInstruction* loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,