Bug 1694044 - Merge similar implementations into NativeLookupOwnPropertyInline. r=jandem

Merge the following implementations:
  - NativeLookupOwnPropertyInline
  - NativeLookupOwnPropertyNoResolve
  - LookupOwnPropertyPure

Use templates to differential different handling of resolve hooks. This tries
to maintain most of the existing nuance to avoid changing too much at once.

We no longer support anything with a lookupProperty hook. Previously the JITs
would tolerate them, but in practice do nothing useful. One case was for
environment objects which triggered this during SetProp but would later
abort. The other case was TypedObjects which are no longer meaningully
supported by the JITs and are treated no differently than unknown.

Differential Revision: https://phabricator.services.mozilla.com/D106239
This commit is contained in:
Ted Campbell 2021-02-25 14:58:57 +00:00
Родитель 187a93fbea
Коммит dd39a2a8f0
2 изменённых файлов: 48 добавлений и 86 удалений

Просмотреть файл

@ -2157,57 +2157,12 @@ bool js::LookupPropertyPure(JSContext* cx, JSObject* obj, jsid id,
bool js::LookupOwnPropertyPure(JSContext* cx, JSObject* obj, jsid id,
PropertyResult* propp) {
JS::AutoCheckCannotGC nogc;
if (obj->is<NativeObject>()) {
// Search for a native dense element, typed array element, or property.
if (JSID_IS_INT(id)) {
uint32_t index = JSID_TO_INT(id);
if (obj->as<NativeObject>().containsDenseElement(index)) {
propp->setDenseElement(index);
return true;
}
}
if (obj->is<TypedArrayObject>()) {
mozilla::Maybe<uint64_t> index;
if (!ToTypedArrayIndex(cx, id, &index)) {
cx->recoverFromOutOfMemory();
return false;
}
if (index.isSome()) {
if (index.value() < obj->as<TypedArrayObject>().length().get()) {
propp->setTypedArrayElement(index.value());
} else {
propp->setTypedArrayOutOfRange();
}
return true;
}
}
if (Shape* shape = obj->as<NativeObject>().lookupPure(id)) {
propp->setNativeProperty(shape);
return true;
}
// Fail if there's a resolve hook, unless the mayResolve hook tells
// us the resolve hook won't define a property with this id.
if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj)) {
return false;
}
} else if (obj->is<TypedObject>()) {
if (obj->as<TypedObject>().typeDescr().hasProperty(cx, id)) {
propp->setTypedObjectProperty();
return true;
}
} else {
if (obj->getOpsLookupProperty()) {
return false;
}
propp->setNotFound();
return true;
return NativeLookupOwnPropertyInline<NoGC,
LookupResolveMode::CheckMayResolve>(
cx, &obj->as<NativeObject>(), id, propp);
}
static inline bool NativeGetPureInline(NativeObject* pobj, jsid id,

Просмотреть файл

@ -27,6 +27,7 @@
#include "gc/Marking-inl.h"
#include "gc/ObjectKind-inl.h"
#include "vm/JSObject-inl.h"
#include "vm/Shape-inl.h"
namespace js {
@ -617,6 +618,8 @@ inline bool NativeObject::denseElementsMaybeInIteration() {
static MOZ_ALWAYS_INLINE bool CallResolveOp(
JSContext* cx, HandleNativeObject obj, HandleId id,
MutableHandle<PropertyResult> propp) {
MOZ_ASSERT(!cx->isHelperThreadContext());
// Avoid recursion on (obj, id) already being resolved on cx.
AutoResolving resolving(cx, obj, id);
if (resolving.alreadyStarted()) {
@ -632,6 +635,7 @@ static MOZ_ALWAYS_INLINE bool CallResolveOp(
}
if (!resolved) {
propp.setNotFound();
return true;
}
@ -660,11 +664,24 @@ static MOZ_ALWAYS_INLINE bool CallResolveOp(
return true;
}
template <AllowGC allowGC>
enum class LookupResolveMode {
IgnoreResolve,
CheckResolve,
CheckMayResolve,
};
template <AllowGC allowGC,
LookupResolveMode resolveMode = LookupResolveMode::CheckResolve>
static MOZ_ALWAYS_INLINE bool NativeLookupOwnPropertyInline(
JSContext* cx, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp) {
// Native objects should should avoid `lookupProperty` hooks, and those that
// use them should avoid recursively triggering lookup, and those that still
// violate this guidance are the ModuleEnvironmentObject.
MOZ_ASSERT_IF(obj->getOpsLookupProperty(),
obj->template is<ModuleEnvironmentObject>());
// Check for a native dense element.
if (JSID_IS_INT(id)) {
uint32_t index = JSID_TO_INT(id);
@ -706,9 +723,27 @@ static MOZ_ALWAYS_INLINE bool NativeLookupOwnPropertyInline(
return true;
}
// id was not found in obj. Try obj's resolve hook, if any.
// Some callers explicitily want us to ignore the resolve hook entirely. In
// that case, we report the property as NotFound.
if constexpr (resolveMode == LookupResolveMode::IgnoreResolve) {
propp.setNotFound();
return true;
}
// JITs in particular use the `mayResolve` hook to determine a JSClass can
// never resolve this property name (for all instances of the class).
if constexpr (resolveMode == LookupResolveMode::CheckMayResolve) {
static_assert(allowGC == false,
"CheckMayResolve can only be used with NoGC");
MOZ_ASSERT(propp.isNotFound());
return !ClassMayResolveId(cx->names(), obj->getClass(), id, obj);
}
MOZ_ASSERT(resolveMode == LookupResolveMode::CheckResolve);
// If there is no resolve hook, the property definitely does not exist.
if (obj->getClass()->getResolve()) {
MOZ_ASSERT(!cx->isHelperThreadContext());
if constexpr (!allowGC) {
return false;
} else {
@ -726,41 +761,12 @@ static MOZ_ALWAYS_INLINE bool NativeLookupOwnPropertyInline(
*/
[[nodiscard]] static inline bool NativeLookupOwnPropertyNoResolve(
JSContext* cx, NativeObject* obj, jsid id, PropertyResult* result) {
// Check for a native dense element.
if (JSID_IS_INT(id)) {
uint32_t index = JSID_TO_INT(id);
if (obj->containsDenseElement(index)) {
result->setDenseElement(index);
return true;
}
}
// Check for a typed array element.
if (obj->is<TypedArrayObject>()) {
mozilla::Maybe<uint64_t> index;
if (!ToTypedArrayIndex(cx, id, &index)) {
return false;
}
if (index.isSome()) {
if (index.value() < obj->as<TypedArrayObject>().length().get()) {
result->setTypedArrayElement(index.value());
} else {
result->setTypedArrayOutOfRange();
}
return true;
}
}
// Check for a native property.
if (Shape* shape = obj->lookup(cx, id)) {
result->setNativeProperty(shape);
} else {
result->setNotFound();
}
return true;
return NativeLookupOwnPropertyInline<NoGC, LookupResolveMode::IgnoreResolve>(
cx, obj, id, result);
}
template <AllowGC allowGC>
template <AllowGC allowGC,
LookupResolveMode resolveMode = LookupResolveMode::CheckResolve>
static MOZ_ALWAYS_INLINE bool NativeLookupPropertyInline(
JSContext* cx, typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
@ -770,7 +776,8 @@ static MOZ_ALWAYS_INLINE bool NativeLookupPropertyInline(
typename MaybeRooted<NativeObject*, allowGC>::RootType current(cx, obj);
while (true) {
if (!NativeLookupOwnPropertyInline<allowGC>(cx, current, id, propp)) {
if (!NativeLookupOwnPropertyInline<allowGC, resolveMode>(cx, current, id,
propp)) {
return false;
}
if (propp.isFound()) {