diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index b43861eff17e..b3f57059c062 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -7483,7 +7483,8 @@ class CGMemberJITInfo(CGThing): return "" def defineJitInfo(self, infoName, opName, opType, infallible, movable, - aliasSet, hasSlot, slotIndex, returnTypes, args): + aliasSet, alwaysInSlot, lazilyInSlot, slotIndex, + returnTypes, args): """ aliasSet is a JSJitInfo::AliasSet value, without the "JSJitInfo::" bit. @@ -7492,7 +7493,7 @@ class CGMemberJITInfo(CGThing): otherwise an iterable of the arguments for this method. """ assert(not movable or aliasSet != "AliasEverything") # Can't move write-aliasing things - assert(not hasSlot or movable) # Things with slots had better be movable + assert(not alwaysInSlot or movable) # Things always in slots had better be movable def jitInfoInitializer(isTypedMethod): initializer = fill( @@ -7506,7 +7507,8 @@ class CGMemberJITInfo(CGThing): ${returnType}, /* returnType. Not relevant for setters. */ ${isInfallible}, /* isInfallible. False in setters. */ ${isMovable}, /* isMovable. Not relevant for setters. */ - ${isInSlot}, /* isInSlot. Only relevant for getters. */ + ${isAlwaysInSlot}, /* isAlwaysInSlot. Only relevant for getters. */ + ${isLazilyCachedInSlot}, /* isLazilyCachedInSlot. Only relevant for getters. */ ${isTypedMethod}, /* isTypedMethod. Only relevant for methods. */ ${slotIndex} /* Reserved slot index, if we're stored in a slot, else 0. */ } @@ -7519,7 +7521,8 @@ class CGMemberJITInfo(CGThing): ""), isInfallible=toStringBool(infallible), isMovable=toStringBool(movable), - isInSlot=toStringBool(hasSlot), + isAlwaysInSlot=toStringBool(alwaysInSlot), + isLazilyCachedInSlot=toStringBool(lazilyInSlot), isTypedMethod=toStringBool(isTypedMethod), slotIndex=slotIndex) return initializer.rstrip() @@ -7568,17 +7571,22 @@ class CGMemberJITInfo(CGThing): movable = getterpure and getterinfal getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor) - isInSlot = self.member.getExtendedAttribute("StoreInSlot") - if isInSlot: + isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot") + if self.member.slotIndex is not None: + assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached") + isLazilyCachedInSlot = not isAlwaysInSlot slotIndex = memberReservedSlot(self.member) # We'll statically assert that this is not too big in - # CGUpdateMemberSlotsMethod + # CGUpdateMemberSlotsMethod, in the case when + # isAlwaysInSlot is true. else: + isLazilyCachedInSlot = False slotIndex = "0" result = self.defineJitInfo(getterinfo, getter, "Getter", getterinfal, movable, aliasSet, - isInSlot, slotIndex, + isAlwaysInSlot, isLazilyCachedInSlot, + slotIndex, [self.member.type], None) if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None or @@ -7590,7 +7598,7 @@ class CGMemberJITInfo(CGThing): # Setters are always fallible, since they have to do a typed unwrap. result += self.defineJitInfo(setterinfo, setter, "Setter", False, False, "AliasEverything", - False, "0", + False, False, "0", [BuiltinTypes[IDLBuiltinType.Types.void]], None) return result @@ -7641,7 +7649,8 @@ class CGMemberJITInfo(CGThing): else: aliasSet = "AliasEverything" result = self.defineJitInfo(methodinfo, method, "Method", - methodInfal, movable, aliasSet, False, "0", + methodInfal, movable, aliasSet, + False, False, "0", [s[0] for s in sigs], args) return result raise TypeError("Illegal member type to CGPropertyJITInfo") diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index b8a293d76db9..348555fd9d80 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -8852,9 +8852,9 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName if (isDOM && testShouldDOMCall(objTypes, commonGetter, JSJitInfo::Getter)) { const JSJitInfo *jitinfo = commonGetter->jitInfo(); MInstruction *get; - if (jitinfo->isInSlot) { + if (jitinfo->isAlwaysInSlot) { // We can't use MLoadFixedSlot here because it might not have the - // right aliasing behavior; we want to alias DOM setters. + // right aliasing behavior; we want to alias DOM setters as needed. get = MGetDOMMember::New(alloc(), jitinfo, obj, guard); } else { get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard); diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 3ddffe786973..a87e1dc5ef40 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -8665,7 +8665,7 @@ class MGetDOMProperty return info_->aliasSet(); } size_t domMemberSlotIndex() const { - MOZ_ASSERT(info_->isInSlot); + MOZ_ASSERT(info_->isAlwaysInSlot || info_->isLazilyCachedInSlot); return info_->slotIndex; } MDefinition *object() { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index d58146ef7319..8b0effebe03f 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1880,12 +1880,18 @@ struct JSJitInfo { not be enough (e.g. in cases when it can throw). */ // XXXbz should we have a JSValueType for the type of the member? - uint32_t isInSlot : 1; /* True if this is a getter that can get a member - from a slot of the "this" object directly. */ + uint32_t isAlwaysInSlot : 1; /* True if this is a getter that can always + get the value from a slot of the "this" + object. */ + uint32_t isLazilyCachedInSlot : 1; /* True if this is a getter that can + sometimes (if the slot doesn't contain + UndefinedValue()) get the value from a + slot of the "this" object. */ uint32_t isTypedMethod : 1; /* True if this is an instance of JSTypedMethodJitInfo. */ - uint32_t slotIndex : 12; /* If isInSlot is true, the index of the slot to - get the value from. Otherwise 0. */ + uint32_t slotIndex : 11; /* If isAlwaysInSlot or isSometimesInSlot is + true, the index of the slot to get the value + from. Otherwise 0. */ }; static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)), @@ -1943,7 +1949,7 @@ inline int CheckIsParallelNative(JSParallelNative parallelNative); */ #define JS_JITINFO_NATIVE_PARALLEL(infoName, parallelOp) \ const JSJitInfo infoName = \ - {{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,0} + {{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,false,0} #define JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(infoName, wrapperName, serialOp) \ bool wrapperName##_ParallelNativeThreadSafeWrapper(js::ForkJoinContext *cx, unsigned argc, \ diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 7f08a10a5ffc..2ed425763bd1 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5250,7 +5250,8 @@ static const JSJitInfo dom_x_getterinfo = { JSVAL_TYPE_UNKNOWN, /* returnType */ true, /* isInfallible. False in setters. */ true, /* isMovable */ - false, /* isInSlot */ + false, /* isAlwaysInSlot */ + false, /* isLazilyCachedInSlot */ false, /* isTypedMethod */ 0 /* slotIndex */ }; @@ -5264,7 +5265,8 @@ static const JSJitInfo dom_x_setterinfo = { JSVAL_TYPE_UNKNOWN, /* returnType */ false, /* isInfallible. False in setters. */ false, /* isMovable. */ - false, /* isInSlot */ + false, /* isAlwaysInSlot */ + false, /* isLazilyCachedInSlot */ false, /* isTypedMethod */ 0 /* slotIndex */ }; @@ -5278,7 +5280,8 @@ static const JSJitInfo doFoo_methodinfo = { JSVAL_TYPE_UNKNOWN, /* returnType */ false, /* isInfallible. False in setters. */ false, /* isMovable */ - false, /* isInSlot */ + false, /* isAlwaysInSlot */ + false, /* isLazilyCachedInSlot */ false, /* isTypedMethod */ 0 /* slotIndex */ };