Bug 1359952 - Add HasPropIRGenerator draft
authorTed Campbell <tcampbell@mozilla.com>
Thu, 27 Apr 2017 12:11:17 -0400
changeset 571971 71c705ec8eaa7feb8e77a5f79cf57e25f94870b2
parent 571929 2f0b5fb1b8172f75734a3040db5343a631fe3e54
child 626933 1437d8ec2afb5df4c09ea6c37eee32c05204538b
push id56976
push userbmo:tcampbell@mozilla.com
push dateWed, 03 May 2017 16:09:46 +0000
bugs1359952
milestone55.0a1
Bug 1359952 - Add HasPropIRGenerator This combines InIRGenerator with HasOwnIRGenerator. MozReview-Commit-ID: 7FQX5YmVrM7
js/src/jit/BaselineIC.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/IonIC.cpp
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1203,38 +1203,37 @@ DoInFallback(JSContext* cx, BaselineFram
 
     FallbackICSpew(cx, stub, "In");
 
     if (!objValue.isObject()) {
         ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, objValue, nullptr);
         return false;
     }
 
-    RootedObject obj(cx, &objValue.toObject());
-
     if (stub->state().maybeTransition())
         stub->discardStubs(cx);
 
     if (stub->state().canAttachStub()) {
         RootedScript script(cx, frame->script());
         jsbytecode* pc = stub->icEntry()->pc(script);
 
         ICStubEngine engine = ICStubEngine::Baseline;
-        InIRGenerator gen(cx, script, pc, stub->state().mode(), key, obj);
+        HasPropIRGenerator gen(cx, script, pc, CacheKind::In, stub->state().mode(), key, objValue);
         bool attached = false;
         if (gen.tryAttachStub()) {
             ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
                                                         engine, script, stub, &attached);
             if (newStub)
                 JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
         }
         if (!attached)
             stub->state().trackNotAttached();
     }
 
+    RootedObject obj(cx, &objValue.toObject());
     bool cond = false;
     if (!OperatorIn(cx, key, obj, &cond))
         return false;
     res.setBoolean(cond);
 
     return true;
 }
 
@@ -1279,17 +1278,18 @@ DoHasOwnFallback(JSContext* cx, Baseline
     if (stub->state().maybeTransition())
         stub->discardStubs(cx);
 
     if (stub->state().canAttachStub()) {
         RootedScript script(cx, frame->script());
         jsbytecode* pc = stub->icEntry()->pc(script);
 
         ICStubEngine engine = ICStubEngine::Baseline;
-        HasOwnIRGenerator gen(cx, script, pc, stub->state().mode(), keyValue, objValue);
+        HasPropIRGenerator gen(cx, script, pc, CacheKind::HasOwn,
+                               stub->state().mode(), keyValue, objValue);
         bool attached = false;
         if (gen.tryAttachStub()) {
             ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
                                                         engine, script, stub, &attached);
             if (newStub)
                 JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
         }
         if (!attached)
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -435,17 +435,17 @@ EmitReadSlotGuard(CacheIRWriter& writer,
             ObjOperandId lastObjId = objId;
             while (proto) {
                 ObjOperandId protoId = writer.loadProto(lastObjId);
                 writer.guardShape(protoId, proto->as<NativeObject>().lastProperty());
                 proto = proto->staticPrototype();
                 lastObjId = protoId;
             }
         }
-    } else if (obj->is<UnboxedPlainObject>()) {
+    } else if (obj->is<UnboxedPlainObject>() && expandoId.isSome()) {
         holderId->emplace(*expandoId);
     } else {
         holderId->emplace(objId);
     }
 }
 
 static void
 EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
@@ -2051,348 +2051,249 @@ BindNameIRGenerator::trackNotAttached()
         sp.beginCache(guard, *this);
         sp.valueProperty(guard, "base", ObjectValue(*env_));
         sp.valueProperty(guard, "property", StringValue(name_));
         sp.endCache(guard);
     }
 #endif
 }
 
-InIRGenerator::InIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc,
-                             ICState::Mode mode, HandleValue key, HandleObject obj)
-  : IRGenerator(cx, script, pc, CacheKind::In, mode),
-    key_(key), obj_(obj)
+HasPropIRGenerator::HasPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc,
+                                       CacheKind cacheKind, ICState::Mode mode,
+                                       HandleValue idVal, HandleValue val)
+  : IRGenerator(cx, script, pc, cacheKind, mode),
+    val_(val),
+    idVal_(idVal)
 { }
 
 bool
-InIRGenerator::tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
-                                HandleObject obj, ObjOperandId objId)
+HasPropIRGenerator::tryAttachDense(HandleObject obj, ObjOperandId objId,
+                                   uint32_t index, Int32OperandId indexId)
 {
     if (!obj->isNative())
         return false;
     if (!obj->as<NativeObject>().containsDenseElement(index))
         return false;
 
+    // Guard shape to ensure object class is NativeObject.
     writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
+
     writer.loadDenseElementExistsResult(objId, indexId);
     writer.returnFromIC();
 
-    trackAttached("DenseIn");
+    trackAttached("DenseHasProp");
     return true;
 }
 
 bool
-InIRGenerator::tryAttachDenseInHole(uint32_t index, Int32OperandId indexId,
-                                    HandleObject obj, ObjOperandId objId)
+HasPropIRGenerator::tryAttachDenseHole(HandleObject obj, ObjOperandId objId,
+                                       uint32_t index, Int32OperandId indexId)
 {
+    bool hasOwn = (cacheKind_ == CacheKind::HasOwn);
+
     if (!obj->isNative())
         return false;
-
     if (obj->as<NativeObject>().containsDenseElement(index))
         return false;
-
-    if (!CanAttachDenseElementHole(obj, false))
+    if (!CanAttachDenseElementHole(obj, hasOwn))
         return false;
 
-    // Guard on the shape, to prevent non-dense elements from appearing.
+    // Guard shape to ensure class is NativeObject and to prevent non-dense
+    // elements being added. Also ensures prototype doesn't change if dynamic
+    // checks aren't emitted.
     writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
 
-    GeneratePrototypeHoleGuards(writer, obj, objId);
+    // Generate prototype guards if needed. This includes monitoring that
+    // properties were not added in the chain.
+    if (!hasOwn)
+        GeneratePrototypeHoleGuards(writer, obj, objId);
+
     writer.loadDenseElementHoleExistsResult(objId, indexId);
     writer.returnFromIC();
 
-    trackAttached("DenseInHole");
+    trackAttached("DenseHasPropHole");
+    return true;
+}
+
+bool
+HasPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId,
+                                    HandleId key, ValOperandId keyId)
+{
+    bool hasOwn = (cacheKind_ == CacheKind::HasOwn);
+
+    JSObject* holder = nullptr;
+    PropertyResult prop;
+
+    if (hasOwn) {
+        if (!LookupOwnPropertyPure(cx_, obj, key, &prop))
+            return false;
+
+        holder = obj;
+    } else {
+        if (!LookupPropertyPure(cx_, obj, key, &holder, &prop))
+            return false;
+    }
+    if (!prop.isFound())
+        return false;
+
+    // Use MegamorphicHasOwnResult if applicable
+    if (hasOwn && mode_ == ICState::Mode::Megamorphic) {
+        writer.megamorphicHasOwnResult(objId, keyId);
+        writer.returnFromIC();
+        trackAttached("MegamorphicHasProp");
+        return true;
+    }
+
+    Maybe<ObjOperandId> tempId;
+    emitIdGuard(keyId, key);
+    EmitReadSlotGuard(writer, obj, holder, objId, &tempId);
+    writer.loadBooleanResult(true);
+    writer.returnFromIC();
+
+    trackAttached("NativeHasProp");
     return true;
 }
 
 bool
-InIRGenerator::tryAttachNativeIn(HandleId key, ValOperandId keyId,
-                                 HandleObject obj, ObjOperandId objId)
+HasPropIRGenerator::tryAttachNativeDoesNotExist(HandleObject obj, ObjOperandId objId,
+                                                HandleId key, ValOperandId keyId)
 {
-    PropertyResult prop;
-    JSObject* holder;
-    if (!LookupPropertyPure(cx_, obj, key, &holder, &prop))
-        return false;
-
-    if (!prop.isNativeProperty())
-        return false;
-
-    Maybe<ObjOperandId> holderId;
+    bool hasOwn = (cacheKind_ == CacheKind::HasOwn);
+
+    if (hasOwn) {
+        if (!CheckHasNoSuchOwnProperty(cx_, obj, key))
+            return false;
+    } else {
+        if (!CheckHasNoSuchProperty(cx_, obj, key))
+            return false;
+    }
+
+    // Use MegamorphicHasOwnResult if applicable
+    if (hasOwn && mode_ == ICState::Mode::Megamorphic) {
+        writer.megamorphicHasOwnResult(objId, keyId);
+        writer.returnFromIC();
+        trackAttached("MegamorphicHasOwn");
+        return true;
+    }
+
+    Maybe<ObjOperandId> tempId;
     emitIdGuard(keyId, key);
-    EmitReadSlotGuard(writer, obj, holder, objId, &holderId);
-    writer.loadBooleanResult(true);
+    if (hasOwn) {
+        TestMatchingReceiver(writer, obj, objId, &tempId);
+    } else {
+        EmitReadSlotGuard(writer, obj, nullptr, objId, &tempId);
+    }
+    writer.loadBooleanResult(false);
     writer.returnFromIC();
 
-    trackAttached("NativeIn");
+    trackAttached("NativeDoesNotExist");
     return true;
 }
 
 bool
-InIRGenerator::tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,
-                                             HandleObject obj, ObjOperandId objId)
+HasPropIRGenerator::tryAttachProxyElement(HandleObject obj, ObjOperandId objId,
+                                          ValOperandId keyId)
 {
-    if (!CheckHasNoSuchProperty(cx_, obj, key))
+    MOZ_ASSERT(cacheKind_ == CacheKind::HasOwn);
+
+    if (!obj->is<ProxyObject>())
         return false;
 
-    Maybe<ObjOperandId> holderId;
-    emitIdGuard(keyId, key);
-    EmitReadSlotGuard(writer, obj, nullptr, objId, &holderId);
-    writer.loadBooleanResult(false);
+    writer.guardIsProxy(objId);
+    writer.callProxyHasOwnResult(objId, keyId);
     writer.returnFromIC();
 
-    trackAttached("NativeInDoesNotExist");
+    trackAttached("ProxyHasProp");
     return true;
 }
 
 bool
-InIRGenerator::tryAttachStub()
+HasPropIRGenerator::tryAttachStub()
 {
-    MOZ_ASSERT(cacheKind_ == CacheKind::In);
+    MOZ_ASSERT(cacheKind_ == CacheKind::In ||
+               cacheKind_ == CacheKind::HasOwn);
 
     AutoAssertNoPendingException aanpe(cx_);
 
+    // NOTE: Argument order is PROPERTY, OBJECT
     ValOperandId keyId(writer.setInputOperandId(0));
     ValOperandId valId(writer.setInputOperandId(1));
+
+    if (!val_.isObject()) {
+        trackNotAttached();
+        return false;
+    }
+    RootedObject obj(cx_, &val_.toObject());
     ObjOperandId objId = writer.guardIsObject(valId);
 
+    // Optimize DOM Proxies for JSOP_HASOWN
+    if (cacheKind_ == CacheKind::HasOwn) {
+        if (tryAttachProxyElement(obj, objId, keyId))
+            return true;
+    }
+
     RootedId id(cx_);
     bool nameOrSymbol;
-    if (!ValueToNameOrSymbolId(cx_, key_, &id, &nameOrSymbol)) {
+    if (!ValueToNameOrSymbolId(cx_, idVal_, &id, &nameOrSymbol)) {
         cx_->clearPendingException();
         return false;
     }
 
     if (nameOrSymbol) {
-        if (tryAttachNativeIn(id, keyId, obj_, objId))
+        if (tryAttachNative(obj, objId, id, keyId))
             return true;
-        if (tryAttachNativeInDoesNotExist(id, keyId, obj_, objId))
+        if (tryAttachNativeDoesNotExist(obj, objId, id, keyId))
             return true;
 
         trackNotAttached();
         return false;
     }
 
     uint32_t index;
     Int32OperandId indexId;
-    if (maybeGuardInt32Index(key_, keyId, &index, &indexId)) {
-        if (tryAttachDenseIn(index, indexId, obj_, objId))
+    if (maybeGuardInt32Index(idVal_, keyId, &index, &indexId)) {
+        if (tryAttachDense(obj, objId, index, indexId))
             return true;
-        if (tryAttachDenseInHole(index, indexId, obj_, objId))
+        if (tryAttachDenseHole(obj, objId, index, indexId))
             return true;
 
         trackNotAttached();
         return false;
     }
 
     trackNotAttached();
     return false;
 }
 
 void
-InIRGenerator::trackAttached(const char* name)
+HasPropIRGenerator::trackAttached(const char* name)
 {
 #ifdef JS_CACHEIR_SPEW
     CacheIRSpewer& sp = CacheIRSpewer::singleton();
     if (sp.enabled()) {
         LockGuard<Mutex> guard(sp.lock());
         sp.beginCache(guard, *this);
-        sp.valueProperty(guard, "base", ObjectValue(*obj_));
-        sp.valueProperty(guard, "property", key_);
+        sp.valueProperty(guard, "base", val_);
+        sp.valueProperty(guard, "property", idVal_);
         sp.attached(guard, name);
         sp.endCache(guard);
     }
 #endif
 }
 
 void
-InIRGenerator::trackNotAttached()
-{
-#ifdef JS_CACHEIR_SPEW
-    CacheIRSpewer& sp = CacheIRSpewer::singleton();
-    if (sp.enabled()) {
-        LockGuard<Mutex> guard(sp.lock());
-        sp.beginCache(guard, *this);
-        sp.valueProperty(guard, "base", ObjectValue(*obj_));
-        sp.valueProperty(guard, "property", key_);
-        sp.endCache(guard);
-    }
-#endif
-}
-
-HasOwnIRGenerator::HasOwnIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc,
-                                     ICState::Mode mode, HandleValue key, HandleValue value)
-  : IRGenerator(cx, script, pc, CacheKind::HasOwn, mode),
-    key_(key), val_(value)
-{ }
-
-
-bool
-HasOwnIRGenerator::tryAttachNativeHasOwn(HandleId key, ValOperandId keyId,
-                                         HandleObject obj, ObjOperandId objId)
-{
-    PropertyResult prop;
-    if (!LookupOwnPropertyPure(cx_, obj, key, &prop))
-        return false;
-
-    if (!prop.isFound())
-        return false;
-
-    if (!obj->isNative() && !obj->is<UnboxedPlainObject>())
-        return false;
-
-    if (mode_ == ICState::Mode::Megamorphic) {
-        writer.megamorphicHasOwnResult(objId, keyId);
-        writer.returnFromIC();
-        trackAttached("MegamorphicHasOwn");
-        return true;
-    }
-
-    Maybe<ObjOperandId> expandoId;
-    emitIdGuard(keyId, key);
-    TestMatchingReceiver(writer, obj, objId, &expandoId);
-    writer.loadBooleanResult(true);
-    writer.returnFromIC();
-
-    trackAttached("NativeHasOwn");
-    return true;
-}
-
-bool
-HasOwnIRGenerator::tryAttachNativeHasOwnDoesNotExist(HandleId key, ValOperandId keyId,
-                                                     HandleObject obj, ObjOperandId objId)
-{
-    if (!CheckHasNoSuchOwnProperty(cx_, obj, key))
-        return false;
-
-    if (mode_ == ICState::Mode::Megamorphic) {
-        writer.megamorphicHasOwnResult(objId, keyId);
-        writer.returnFromIC();
-        trackAttached("MegamorphicHasOwn");
-        return true;
-    }
-
-    Maybe<ObjOperandId> expandoId;
-    emitIdGuard(keyId, key);
-    TestMatchingReceiver(writer, obj, objId, &expandoId);
-    writer.loadBooleanResult(false);
-    writer.returnFromIC();
-
-    trackAttached("NativeHasOwnDoesNotExist");
-    return true;
-}
-
-bool
-HasOwnIRGenerator::tryAttachProxyElement(ValOperandId keyId, HandleObject obj, ObjOperandId objId)
-{
-    if (!obj->is<ProxyObject>())
-        return false;
-
-    writer.guardIsProxy(objId);
-    writer.callProxyHasOwnResult(objId, keyId);
-    writer.returnFromIC();
-
-    trackAttached("ProxyHasOwn");
-    return true;
-}
-
-bool
-HasOwnIRGenerator::tryAttachDenseHasOwn(uint32_t index, Int32OperandId indexId,
-                                        HandleObject obj, ObjOperandId objId)
-{
-    if (!obj->isNative())
-        return false;
-    if (!obj->as<NativeObject>().containsDenseElement(index))
-        return false;
-
-    writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
-    writer.loadDenseElementExistsResult(objId, indexId);
-    writer.returnFromIC();
-
-    trackAttached("DenseHasOwn");
-    return true;
-}
-
-bool
-HasOwnIRGenerator::tryAttachStub()
-{
-    MOZ_ASSERT(cacheKind_ == CacheKind::HasOwn);
-
-    AutoAssertNoPendingException aanpe(cx_);
-
-    ValOperandId keyId(writer.setInputOperandId(0));
-    ValOperandId valId(writer.setInputOperandId(1));
-
-    if (!val_.isObject()) {
-        trackNotAttached();
-        return false;
-    }
-    RootedObject obj(cx_, &val_.toObject());
-
-    ObjOperandId objId = writer.guardIsObject(valId);
-
-    if (tryAttachProxyElement(keyId, obj, objId))
-        return true;
-
-    RootedId id(cx_);
-    bool nameOrSymbol;
-    if (!ValueToNameOrSymbolId(cx_, key_, &id, &nameOrSymbol)) {
-        cx_->clearPendingException();
-        return false;
-    }
-
-    if (nameOrSymbol) {
-        if (tryAttachNativeHasOwn(id, keyId, obj, objId))
-            return true;
-        if (tryAttachNativeHasOwnDoesNotExist(id, keyId, obj, objId))
-            return true;
-
-        trackNotAttached();
-        return false;
-    }
-
-    uint32_t index;
-    Int32OperandId indexId;
-    if (maybeGuardInt32Index(key_, keyId, &index, &indexId)) {
-        if (tryAttachDenseHasOwn(index, indexId, obj, objId))
-            return true;
-
-        trackNotAttached();
-        return false;
-    }
-
-    trackNotAttached();
-    return false;
-}
-
-void
-HasOwnIRGenerator::trackAttached(const char* name)
+HasPropIRGenerator::trackNotAttached()
 {
 #ifdef JS_CACHEIR_SPEW
     CacheIRSpewer& sp = CacheIRSpewer::singleton();
     if (sp.enabled()) {
         LockGuard<Mutex> guard(sp.lock());
         sp.beginCache(guard, *this);
         sp.valueProperty(guard, "base", val_);
-        sp.valueProperty(guard, "property", key_);
-        sp.attached(guard, name);
-        sp.endCache(guard);
-    }
-#endif
-}
-
-void
-HasOwnIRGenerator::trackNotAttached()
-{
-#ifdef JS_CACHEIR_SPEW
-    CacheIRSpewer& sp = CacheIRSpewer::singleton();
-    if (sp.enabled()) {
-        LockGuard<Mutex> guard(sp.lock());
-        sp.beginCache(guard, *this);
-        sp.valueProperty(guard, "base", val_);
-        sp.valueProperty(guard, "property", key_);
+        sp.valueProperty(guard, "property", idVal_);
         sp.endCache(guard);
     }
 #endif
 }
 
 bool
 IRGenerator::maybeGuardInt32Index(const Value& index, ValOperandId indexId,
                                   uint32_t* int32Index, Int32OperandId* int32IndexId)
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -1271,61 +1271,41 @@ class MOZ_RAII SetPropIRGenerator : publ
         return &typeCheckInfo_;
     }
 
     bool attachedTypedArrayOOBStub() const {
         return attachedTypedArrayOOBStub_;
     }
 };
 
-// InIRGenerator generates CacheIR for a In IC.
-class MOZ_RAII InIRGenerator : public IRGenerator
+// HasPropIRGenerator generates CacheIR for a HasProp IC. Used for
+// CacheKind::In / CacheKind::HasOwn.
+class MOZ_RAII HasPropIRGenerator : public IRGenerator
 {
-    HandleValue key_;
-    HandleObject obj_;
+    HandleValue val_;
+    HandleValue idVal_;
 
-    bool tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
-                          HandleObject obj, ObjOperandId objId);
-    bool tryAttachDenseInHole(uint32_t index, Int32OperandId indexId,
-                              HandleObject obj, ObjOperandId objId);
-    bool tryAttachNativeIn(HandleId key, ValOperandId keyId,
-                           HandleObject obj, ObjOperandId objId);
-    bool tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,
-                                       HandleObject obj, ObjOperandId objId);
+    bool tryAttachDense(HandleObject obj, ObjOperandId objId,
+                        uint32_t index, Int32OperandId indexId);
+    bool tryAttachDenseHole(HandleObject obj, ObjOperandId objId,
+                            uint32_t index, Int32OperandId indexId);
+    bool tryAttachNative(HandleObject obj, ObjOperandId objId,
+                         HandleId key, ValOperandId keyId);
+    bool tryAttachNativeDoesNotExist(HandleObject obj, ObjOperandId objId,
+                                     HandleId key, ValOperandId keyId);
+    bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId,
+                               ValOperandId keyId);
 
     void trackAttached(const char* name);
     void trackNotAttached();
 
   public:
-    InIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode, HandleValue key,
-                  HandleObject obj);
-
-    bool tryAttachStub();
-};
-
-// HasOwnIRGenerator generates CacheIR for a HasOwn IC.
-class MOZ_RAII HasOwnIRGenerator : public IRGenerator
-{
-    HandleValue key_;
-    HandleValue val_;
-
-    bool tryAttachProxyElement(ValOperandId keyId, HandleObject obj, ObjOperandId objId);
-    bool tryAttachDenseHasOwn(uint32_t index, Int32OperandId indexId,
-                              HandleObject obj, ObjOperandId objId);
-    bool tryAttachNativeHasOwn(HandleId key, ValOperandId keyId,
-                           HandleObject obj, ObjOperandId objId);
-    bool tryAttachNativeHasOwnDoesNotExist(HandleId key, ValOperandId keyId,
-                                           HandleObject obj, ObjOperandId objId);
-
-    void trackAttached(const char* name);
-    void trackNotAttached();
-
-  public:
-    HasOwnIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode, HandleValue key,
-                      HandleValue value);
+    // NOTE: Argument order is PROPERTY, OBJECT
+    HasPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
+                       ICState::Mode mode, HandleValue idVal, HandleValue val);
 
     bool tryAttachStub();
 };
 
 class MOZ_RAII TypeOfIRGenerator : public IRGenerator
 {
     HandleValue val_;
 
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -350,17 +350,17 @@ IonHasOwnIC::update(JSContext* cx, Handl
     if (ic->state().maybeTransition())
         ic->discardStubs(cx->zone());
 
     jsbytecode* pc = ic->pc();
 
     if (ic->state().canAttachStub()) {
         bool attached = false;
         RootedScript script(cx, ic->script());
-        HasOwnIRGenerator gen(cx, script, pc, ic->state().mode(), idVal, val);
+        HasPropIRGenerator gen(cx, script, pc, CacheKind::HasOwn, ic->state().mode(), idVal, val);
         if (gen.tryAttachStub())
             ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
 
         if (!attached)
             ic->state().trackNotAttached();
     }
 
     bool found;