Bug 1804253 part 4 - Optimize checks for native objects and proxies. r=jonco

This saves two dereferences by looking at the shape instead of the class.

Differential Revision: https://phabricator.services.mozilla.com/D164214
This commit is contained in:
Jan de Mooij 2022-12-13 10:58:30 +00:00
Родитель 326592ff60
Коммит 2031ad337d
6 изменённых файлов: 48 добавлений и 20 удалений

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

@ -381,7 +381,7 @@ class JS_PUBLIC_API BaseProxyHandler {
extern JS_PUBLIC_DATA const JSClass ProxyClass;
inline bool IsProxy(const JSObject* obj) {
return JS::GetClass(obj)->isProxyObject();
return reinterpret_cast<const JS::shadow::Object*>(obj)->shape->isProxy();
}
namespace detail {

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

@ -35,8 +35,27 @@ class Shape {
shadow::BaseShape* base;
uint32_t immutableFlags;
enum class Kind : uint8_t {
// SharedShape or DictionaryShape for NativeObject.
// (Only) these two kinds must have the low bit set, to allow for fast
// is-native checking.
Shared = 1,
Dictionary = 3,
// ProxyShape for ProxyObject.
Proxy = 0,
// WasmGCShape for WasmGCObject.
WasmGC = 2,
};
static constexpr uint32_t KIND_SHIFT = 4;
static constexpr uint32_t KIND_MASK = 0b11;
static constexpr uint32_t FIXED_SLOTS_SHIFT = 6;
static constexpr uint32_t FIXED_SLOTS_MASK = 0x1f << FIXED_SLOTS_SHIFT;
bool isProxy() const {
return Kind((immutableFlags >> KIND_SHIFT) & KIND_MASK) == Kind::Proxy;
}
};
} // namespace shadow

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

@ -724,8 +724,13 @@ void MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp,
void MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object,
Register scratch, Label* label) {
loadObjClassUnsafe(object, scratch);
branchTestClassIsProxy(proxy, scratch, label);
constexpr uint32_t ShiftedMask = (Shape::kindMask() << Shape::kindShift());
static_assert(uint32_t(Shape::Kind::Proxy) == 0,
"branchTest32 below depends on proxy kind being 0");
loadPtr(Address(object, JSObject::offsetOfShape()), scratch);
branchTest32(proxy ? Assembler::Zero : Assembler::NonZero,
Address(scratch, Shape::offsetOfImmutableFlags()),
Imm32(ShiftedMask), label);
}
void MacroAssembler::branchTestProxyHandlerFamily(Condition cond,
@ -735,8 +740,7 @@ void MacroAssembler::branchTestProxyHandlerFamily(Condition cond,
Label* label) {
#ifdef DEBUG
Label ok;
loadObjClassUnsafe(proxy, scratch);
branchTestClassIsProxy(true, scratch, &ok);
branchTestObjectIsProxy(true, proxy, scratch, &ok);
assumeUnreachable("Expected ProxyObject in branchTestProxyHandlerFamily");
bind(&ok);
#endif

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

@ -4139,9 +4139,10 @@ void MacroAssembler::branchTestObjCompartment(
void MacroAssembler::branchIfNonNativeObj(Register obj, Register scratch,
Label* label) {
loadObjClassUnsafe(obj, scratch);
branchTest32(Assembler::NonZero, Address(scratch, JSClass::offsetOfFlags()),
Imm32(JSClass::NON_NATIVE), label);
loadPtr(Address(obj, JSObject::offsetOfShape()), scratch);
branchTest32(Assembler::Zero,
Address(scratch, Shape::offsetOfImmutableFlags()),
Imm32(Shape::isNativeBit()), label);
}
void MacroAssembler::branchIfObjectNotExtensible(Register obj, Register scratch,

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

@ -1747,7 +1747,7 @@ extern bool GetNameBoundInEnvironment(JSContext* cx, HandleObject env,
template <>
inline bool JSObject::is<js::NativeObject>() const {
return getClass()->isNativeObject();
return shape()->isNative();
}
namespace js {

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

@ -275,15 +275,7 @@ class Shape : public gc::CellWithTenuredGCPointer<gc::TenuredCell, BaseShape> {
// Base shape, stored in the cell header.
BaseShape* base() const { return headerPtr(); }
enum class Kind : uint8_t {
// SharedShape or DictionaryShape for NativeObject.
Shared,
Dictionary,
// ProxyShape for ProxyObject.
Proxy,
// WasmGCShape for WasmGCObject.
WasmGC,
};
using Kind = JS::shadow::Shape::Kind;
protected:
// Flags that are not modified after the Shape is created. Off-thread Ion
@ -295,9 +287,10 @@ class Shape : public gc::CellWithTenuredGCPointer<gc::TenuredCell, BaseShape> {
// no properties).
MAP_LENGTH_MASK = BitMask(4),
// The Shape Kind.
// The Shape Kind. The NativeObject kinds have the low bit set.
KIND_SHIFT = 4,
KIND_MASK = 0b11,
IS_NATIVE_BIT = 0x1 << KIND_SHIFT,
// Number of fixed slots in objects with this shape.
// FIXED_SLOTS_MAX is the biggest count of fixed slots a Shape can store.
@ -372,6 +365,7 @@ class Shape : public gc::CellWithTenuredGCPointer<gc::TenuredCell, BaseShape> {
objectFlags_(objectFlags) {
MOZ_ASSERT(base);
MOZ_ASSERT(this->kind() == kind, "kind must fit in KIND_MASK");
MOZ_ASSERT(isNative() == base->clasp()->isNativeObject());
}
Shape(const Shape& other) = delete;
@ -379,7 +373,11 @@ class Shape : public gc::CellWithTenuredGCPointer<gc::TenuredCell, BaseShape> {
public:
Kind kind() const { return Kind((immutableFlags >> KIND_SHIFT) & KIND_MASK); }
bool isNative() const { return isShared() || isDictionary(); }
bool isNative() const {
// Note: this is equivalent to `isShared() || isDictionary()`.
return immutableFlags & IS_NATIVE_BIT;
}
bool isShared() const { return kind() == Kind::Shared; }
bool isDictionary() const { return kind() == Kind::Dictionary; }
bool isProxy() const { return kind() == Kind::Proxy; }
@ -416,6 +414,10 @@ class Shape : public gc::CellWithTenuredGCPointer<gc::TenuredCell, BaseShape> {
return offsetof(Shape, immutableFlags);
}
static constexpr uint32_t kindShift() { return KIND_SHIFT; }
static constexpr uint32_t kindMask() { return KIND_MASK; }
static constexpr uint32_t isNativeBit() { return IS_NATIVE_BIT; }
static constexpr size_t offsetOfCachePtr() { return offsetof(Shape, cache_); }
private:
@ -423,6 +425,8 @@ class Shape : public gc::CellWithTenuredGCPointer<gc::TenuredCell, BaseShape> {
static_assert(offsetOfBaseShape() == offsetof(JS::shadow::Shape, base));
static_assert(offsetof(Shape, immutableFlags) ==
offsetof(JS::shadow::Shape, immutableFlags));
static_assert(KIND_SHIFT == JS::shadow::Shape::KIND_SHIFT);
static_assert(KIND_MASK == JS::shadow::Shape::KIND_MASK);
static_assert(FIXED_SLOTS_SHIFT == JS::shadow::Shape::FIXED_SLOTS_SHIFT);
static_assert(FIXED_SLOTS_MASK == JS::shadow::Shape::FIXED_SLOTS_MASK);
// Sanity check Shape size is what we expect.