Bug 1723715 part 13 - Move builtin constructors to GlobalObjectData. r=jonco

This replaces the JS_OFF_THREAD_CONSTRUCTOR MagicValue for off-thread constructors
with the same placeholder object we use for the prototype. These constructors
aren't used by off-thread parsing and handling this another way requires a lot
of complexity. With Stencil work the off-thread global will hopefully be removed
eventually.

Differential Revision: https://phabricator.services.mozilla.com/D121993
This commit is contained in:
Jan de Mooij 2021-08-09 15:25:09 +00:00
Родитель 12961aecf7
Коммит 6ad790bd22
15 изменённых файлов: 143 добавлений и 145 удалений

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

@ -572,7 +572,7 @@ static const uint32_t JSCLASS_FOREGROUND_FINALIZE =
// application.
static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 2;
JSCLASS_GLOBAL_APPLICATION_SLOTS + 2;
static constexpr uint32_t JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(uint32_t n) {
return JSCLASS_IS_GLOBAL |

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

@ -241,9 +241,6 @@ enum JSWhyMagic {
/** arguments object can't be created because environment is dead. */
JS_MISSING_ARGUMENTS,
/** standard constructors are not created for off-thread parsing. */
JS_OFF_THREAD_CONSTRUCTOR,
/** for local use */
JS_GENERIC_MAGIC,

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

@ -4044,12 +4044,10 @@ void js::ArraySpeciesLookup::initialize(JSContext* cx) {
return;
}
// Get the canonical Array constructor.
const Value& arrayCtorValue = cx->global()->getConstructor(JSProto_Array);
MOZ_ASSERT(arrayCtorValue.isObject(),
"The Array constructor is initialized iff Array.prototype is "
"initialized");
JSFunction* arrayCtor = &arrayCtorValue.toObject().as<JSFunction>();
// Get the canonical Array constructor. The Array constructor must be
// initialized if Array.prototype is initialized.
JSObject& arrayCtorObject = cx->global()->getConstructor(JSProto_Array);
JSFunction* arrayCtor = &arrayCtorObject.as<JSFunction>();
// Shortcut returns below means Array[@@species] will never be
// optimizable, set to disabled now, and clear it later when we succeed.

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

@ -6730,7 +6730,8 @@ extern JS_PUBLIC_API bool JS_DefineDebuggerObject(JSContext* cx,
if (!debuggeeWouldRunProto) {
return false;
}
debuggeeWouldRunCtor = global->getConstructor(JSProto_DebuggeeWouldRun);
debuggeeWouldRunCtor =
ObjectValue(global->getConstructor(JSProto_DebuggeeWouldRun));
RootedId debuggeeWouldRunId(
cx, NameToId(ClassName(JSProto_DebuggeeWouldRun, cx)));
if (!DefineDataProperty(cx, debugCtor, debuggeeWouldRunId,

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

@ -4626,8 +4626,8 @@ AttachDecision InstanceOfIRGenerator::tryAttachStub() {
return AttachDecision::NoAction;
}
Value funProto = cx_->global()->getPrototype(JSProto_Function);
if (hasInstanceHolder != &funProto.toObject()) {
JSObject& funProto = cx_->global()->getPrototype(JSProto_Function);
if (hasInstanceHolder != &funProto) {
trackAttached(IRGenerator::NotAttached);
return AttachDecision::NoAction;
}

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

@ -7940,8 +7940,8 @@ static bool GetSharedObject(JSContext* cx, unsigned argc, Value* vp) {
JSProto_WebAssembly)) {
return false;
}
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject());
RootedObject proto(cx,
&cx->global()->getPrototype(JSProto_WasmMemory));
newObj = WasmMemoryObject::create(cx, maybesab, proto);
MOZ_ASSERT_IF(newObj, newObj->as<WasmMemoryObject>().isShared());
if (!newObj) {

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

@ -274,8 +274,7 @@ bool GlobalObject::resolveConstructor(JSContext* cx,
// for Function, which is a problem. So if Function is being resolved
// before Object.prototype exists, we just resolve Object instead, since we
// know that Function will also be resolved before we return.
if (key == JSProto_Function &&
global->getPrototype(JSProto_Object).isUndefined()) {
if (key == JSProto_Function && !global->hasPrototype(JSProto_Object)) {
return resolveConstructor(cx, global, JSProto_Object,
IfClassIsDisabled::DoNothing);
}
@ -316,7 +315,7 @@ bool GlobalObject::resolveConstructor(JSContext* cx,
// criteria that protects entry into this function.
MOZ_ASSERT(!global->isStandardClassResolved(key));
global->setPrototype(key, ObjectValue(*proto));
global->setPrototype(key, proto);
}
}
@ -335,7 +334,7 @@ bool GlobalObject::resolveConstructor(JSContext* cx,
}
}
global->setConstructor(key, ObjectValue(*ctor));
global->setConstructor(key, ctor);
}
if (const JSFunctionSpec* funs = clasp->specPrototypeFunctions()) {
@ -403,9 +402,9 @@ bool GlobalObject::resolveConstructor(JSContext* cx,
}
// Infallible operations that modify the global object.
global->setConstructor(key, ObjectValue(*ctor));
global->setConstructor(key, ctor);
if (proto) {
global->setPrototype(key, ObjectValue(*proto));
global->setPrototype(key, proto);
}
}
@ -476,7 +475,7 @@ const JSClass GlobalObject::OffThreadPlaceholderObject::class_ = {
"off-thread-prototype-placeholder", JSCLASS_HAS_RESERVED_SLOTS(1)};
/* static */ GlobalObject::OffThreadPlaceholderObject*
GlobalObject::OffThreadPlaceholderObject::New(JSContext* cx, unsigned slot) {
GlobalObject::OffThreadPlaceholderObject::New(JSContext* cx, JSProtoKey key) {
Rooted<OffThreadPlaceholderObject*> placeholder(cx);
placeholder =
NewObjectWithGivenProto<OffThreadPlaceholderObject>(cx, nullptr);
@ -484,7 +483,7 @@ GlobalObject::OffThreadPlaceholderObject::New(JSContext* cx, unsigned slot) {
return nullptr;
}
placeholder->setReservedSlot(SlotIndexOrProtoKindSlot, Int32Value(slot));
placeholder->setReservedSlot(ProtoKeyOrProtoKindSlot, Int32Value(key));
return placeholder;
}
@ -497,14 +496,14 @@ GlobalObject::OffThreadPlaceholderObject::New(JSContext* cx, ProtoKind kind) {
return nullptr;
}
placeholder->setReservedSlot(SlotIndexOrProtoKindSlot,
placeholder->setReservedSlot(ProtoKeyOrProtoKindSlot,
Int32Value(-int32_t(kind)));
return placeholder;
}
inline int32_t
GlobalObject::OffThreadPlaceholderObject::getSlotIndexOrProtoKind() const {
return getReservedSlot(SlotIndexOrProtoKindSlot).toInt32();
GlobalObject::OffThreadPlaceholderObject::getProtoKeyOrProtoKind() const {
return getReservedSlot(ProtoKeyOrProtoKindSlot).toInt32();
}
/* static */
@ -523,7 +522,7 @@ bool GlobalObject::resolveOffThreadConstructor(JSContext* cx,
key == JSProto_AsyncGeneratorFunction);
Rooted<OffThreadPlaceholderObject*> placeholder(cx);
placeholder = OffThreadPlaceholderObject::New(cx, prototypeSlot(key));
placeholder = OffThreadPlaceholderObject::New(cx, key);
if (!placeholder) {
return false;
}
@ -533,8 +532,11 @@ bool GlobalObject::resolveOffThreadConstructor(JSContext* cx,
return false;
}
global->setPrototype(key, ObjectValue(*placeholder));
global->setConstructor(key, MagicValue(JS_OFF_THREAD_CONSTRUCTOR));
// Use the placeholder for both constructor and prototype. The constructor
// isn't used off-thread, but we need to initialize both at the same time to
// satisfy invariants.
global->setPrototype(key, placeholder);
global->setConstructor(key, placeholder);
return true;
}
@ -563,9 +565,10 @@ JSObject* GlobalObject::createOffThreadBuiltinProto(
JSObject* GlobalObject::getPrototypeForOffThreadPlaceholder(JSObject* obj) {
auto placeholder = &obj->as<OffThreadPlaceholderObject>();
int32_t value = placeholder->getSlotIndexOrProtoKind();
int32_t value = placeholder->getProtoKeyOrProtoKind();
if (value >= 0) {
return &getSlot(value).toObject();
MOZ_ASSERT(value < int32_t(JSProto_LIMIT));
return &getPrototype(JSProtoKey(value));
}
MOZ_ASSERT(-value < int32_t(ProtoKind::Limit));
return &getBuiltinProto(ProtoKind(-value));
@ -589,8 +592,8 @@ bool GlobalObject::initBuiltinConstructor(JSContext* cx,
return false;
}
global->setConstructor(key, ObjectValue(*ctor));
global->setPrototype(key, ObjectValue(*proto));
global->setConstructor(key, ctor);
global->setPrototype(key, proto);
return true;
}
@ -1126,7 +1129,7 @@ JSObject* GlobalObject::createIteratorPrototype(JSContext* cx,
if (!ensureConstructor(cx, global, JSProto_Iterator)) {
return nullptr;
}
JSObject* proto = &global->getPrototype(JSProto_Iterator).toObject();
JSObject* proto = &global->getPrototype(JSProto_Iterator);
global->initBuiltinProto(ProtoKind::IteratorProto, proto);
return proto;
}
@ -1142,7 +1145,7 @@ JSObject* GlobalObject::createAsyncIteratorPrototype(
if (!ensureConstructor(cx, global, JSProto_AsyncIterator)) {
return nullptr;
}
JSObject* proto = &global->getPrototype(JSProto_AsyncIterator).toObject();
JSObject* proto = &global->getPrototype(JSProto_AsyncIterator);
global->initBuiltinProto(ProtoKind::AsyncIteratorProto, proto);
return proto;
}
@ -1154,6 +1157,12 @@ void GlobalObject::releaseData(JSFreeOp* fop) {
}
void GlobalObjectData::trace(JSTracer* trc) {
for (auto& ctorWithProto : builtinConstructors) {
TraceNullableEdge(trc, &ctorWithProto.constructor, "global-builtin-ctor");
TraceNullableEdge(trc, &ctorWithProto.prototype,
"global-builtin-ctor-proto");
}
for (auto& proto : builtinProtos) {
TraceNullableEdge(trc, &proto, "global-builtin-proto");
}

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

@ -68,6 +68,21 @@ class GlobalObjectData {
public:
GlobalObjectData() = default;
// The original values for built-in constructors (with their prototype
// objects) based on JSProtoKey.
//
// This is necessary to implement spec language speaking in terms of "the
// original Array prototype object", or "as if by the expression new Array()"
// referring to the original Array constructor. The actual (writable and even
// deletable) Object, Array, &c. properties are not stored here.
struct ConstructorWithProto {
HeapPtr<JSObject*> constructor;
HeapPtr<JSObject*> prototype;
};
using CtorArray =
mozilla::EnumeratedArray<JSProtoKey, JSProto_LIMIT, ConstructorWithProto>;
CtorArray builtinConstructors;
// Built-in prototypes for this global. Note that this is different from the
// set of built-in constructors/prototypes based on JSProtoKey.
enum class ProtoKind {
@ -159,15 +174,8 @@ class GlobalObject : public NativeObject {
/* Count of slots set aside for application use. */
static const unsigned APPLICATION_SLOTS = JSCLASS_GLOBAL_APPLICATION_SLOTS;
/*
* Count of slots to store built-in prototypes and initial visible
* properties for the constructors.
*/
static const unsigned STANDARD_CLASS_SLOTS = JSProto_LIMIT * 2;
enum : unsigned {
/* One-off properties stored after slots for built-ins. */
GLOBAL_DATA_SLOT = APPLICATION_SLOTS + STANDARD_CLASS_SLOTS,
GLOBAL_DATA_SLOT = APPLICATION_SLOTS,
WINDOW_PROXY,
/* Total reserved-slot count for global objects. */
@ -184,16 +192,6 @@ class GlobalObject : public NativeObject {
using ProtoKind = GlobalObjectData::ProtoKind;
static unsigned constructorSlot(JSProtoKey key) {
MOZ_ASSERT(key < JSProto_LIMIT);
return APPLICATION_SLOTS + key;
}
static unsigned prototypeSlot(JSProtoKey key) {
MOZ_ASSERT(key < JSProto_LIMIT);
return APPLICATION_SLOTS + JSProto_LIMIT + key;
}
GlobalObjectData* maybeData() {
Value v = getReservedSlot(GLOBAL_DATA_SLOT);
return static_cast<GlobalObjectData*>(v.toPrivate());
@ -237,9 +235,14 @@ class GlobalObject : public NativeObject {
data().eval.init(evalFun);
}
Value getConstructor(JSProtoKey key) const {
return getReservedSlot(constructorSlot(key));
bool hasConstructor(JSProtoKey key) const {
return bool(data().builtinConstructors[key].constructor);
}
JSObject& getConstructor(JSProtoKey key) const {
MOZ_ASSERT(hasConstructor(key));
return *maybeGetConstructor(key);
}
static bool skipDeselectedConstructor(JSContext* cx, JSProtoKey key);
static bool initBuiltinConstructor(JSContext* cx,
Handle<GlobalObject*> global,
@ -267,7 +270,7 @@ class GlobalObject : public NativeObject {
if (!GlobalObject::ensureConstructor(cx, global, key)) {
return nullptr;
}
return &global->getConstructor(key).toObject();
return &global->getConstructor(key);
}
static JSObject* getOrCreatePrototype(JSContext* cx, JSProtoKey key) {
@ -276,61 +279,60 @@ class GlobalObject : public NativeObject {
if (!GlobalObject::ensureConstructor(cx, global, key)) {
return nullptr;
}
return &global->getPrototype(key).toObject();
return &global->getPrototype(key);
}
JSObject* maybeGetConstructor(JSProtoKey protoKey) const {
MOZ_ASSERT(JSProto_Null < protoKey);
MOZ_ASSERT(protoKey < JSProto_LIMIT);
const Value& v = getConstructor(protoKey);
return v.isObject() ? &v.toObject() : nullptr;
return data().builtinConstructors[protoKey].constructor;
}
JSObject* maybeGetPrototype(JSProtoKey protoKey) const {
MOZ_ASSERT(JSProto_Null < protoKey);
MOZ_ASSERT(protoKey < JSProto_LIMIT);
const Value& v = getPrototype(protoKey);
return v.isObject() ? &v.toObject() : nullptr;
return data().builtinConstructors[protoKey].prototype;
}
static bool maybeResolveGlobalThis(JSContext* cx,
Handle<GlobalObject*> global,
bool* resolved);
void setConstructor(JSProtoKey key, const Value& v) {
setReservedSlot(constructorSlot(key), v);
void setConstructor(JSProtoKey key, JSObject* obj) {
MOZ_ASSERT(obj);
data().builtinConstructors[key].constructor = obj;
}
Value getPrototype(JSProtoKey key) const {
return getReservedSlot(prototypeSlot(key));
bool hasPrototype(JSProtoKey key) const {
return bool(data().builtinConstructors[key].prototype);
}
JSObject& getPrototype(JSProtoKey key) const {
MOZ_ASSERT(hasPrototype(key));
return *maybeGetPrototype(key);
}
void setPrototype(JSProtoKey key, const Value& value) {
setReservedSlot(prototypeSlot(key), value);
void setPrototype(JSProtoKey key, JSObject* obj) {
MOZ_ASSERT(obj);
data().builtinConstructors[key].prototype = obj;
}
/*
* Lazy standard classes need a way to indicate they have been initialized.
* Otherwise, when we delete them, we might accidentally recreate them via
* a lazy initialization. We use the presence of an object in the
* getConstructor(key) reserved slot to indicate that they've been
* initialized.
* a lazy initialization. We use the presence of an object in the constructor
* array to indicate that they've been initialized.
*
* Note: A few builtin objects, like JSON and Math, are not constructors,
* so getConstructor is a bit of a misnomer.
*/
bool isStandardClassResolved(JSProtoKey key) const {
// If the constructor is undefined, then it hasn't been initialized.
Value value = getConstructor(key);
MOZ_ASSERT(value.isUndefined() || value.isObject() ||
value.isMagic(JS_OFF_THREAD_CONSTRUCTOR));
return !value.isUndefined();
return hasConstructor(key);
}
private:
bool classIsInitialized(JSProtoKey key) const {
bool inited = !getConstructor(key).isUndefined();
MOZ_ASSERT(inited == !getPrototype(key).isUndefined());
bool inited = hasConstructor(key);
MOZ_ASSERT(inited == hasPrototype(key));
return inited;
}
@ -400,7 +402,7 @@ class GlobalObject : public NativeObject {
return nullptr;
}
}
return &global->getPrototype(JSProto_Object).toObject();
return &global->getPrototype(JSProto_Object);
}
static JSObject* getOrCreateFunctionConstructor(
@ -410,7 +412,7 @@ class GlobalObject : public NativeObject {
return nullptr;
}
}
return &global->getConstructor(JSProto_Function).toObject();
return &global->getConstructor(JSProto_Function);
}
static JSObject* getOrCreateFunctionPrototype(JSContext* cx,
@ -420,7 +422,7 @@ class GlobalObject : public NativeObject {
return nullptr;
}
}
return &global->getPrototype(JSProto_Function).toObject();
return &global->getPrototype(JSProto_Function);
}
static NativeObject* getOrCreateArrayPrototype(JSContext* cx,
@ -428,12 +430,12 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Array)) {
return nullptr;
}
return &global->getPrototype(JSProto_Array).toObject().as<NativeObject>();
return &global->getPrototype(JSProto_Array).as<NativeObject>();
}
NativeObject* maybeGetArrayPrototype() {
if (classIsInitialized(JSProto_Array)) {
return &getPrototype(JSProto_Array).toObject().as<NativeObject>();
return &getPrototype(JSProto_Array).as<NativeObject>();
}
return nullptr;
}
@ -443,7 +445,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Boolean)) {
return nullptr;
}
return &global->getPrototype(JSProto_Boolean).toObject();
return &global->getPrototype(JSProto_Boolean);
}
static JSObject* getOrCreateNumberPrototype(JSContext* cx,
@ -451,7 +453,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Number)) {
return nullptr;
}
return &global->getPrototype(JSProto_Number).toObject();
return &global->getPrototype(JSProto_Number);
}
static JSObject* getOrCreateStringPrototype(JSContext* cx,
@ -459,7 +461,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_String)) {
return nullptr;
}
return &global->getPrototype(JSProto_String).toObject();
return &global->getPrototype(JSProto_String);
}
static JSObject* getOrCreateSymbolPrototype(JSContext* cx,
@ -467,7 +469,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Symbol)) {
return nullptr;
}
return &global->getPrototype(JSProto_Symbol).toObject();
return &global->getPrototype(JSProto_Symbol);
}
static JSObject* getOrCreateBigIntPrototype(JSContext* cx,
@ -475,7 +477,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_BigInt)) {
return nullptr;
}
return &global->getPrototype(JSProto_BigInt).toObject();
return &global->getPrototype(JSProto_BigInt);
}
static JSObject* getOrCreatePromisePrototype(JSContext* cx,
@ -483,7 +485,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Promise)) {
return nullptr;
}
return &global->getPrototype(JSProto_Promise).toObject();
return &global->getPrototype(JSProto_Promise);
}
static JSObject* getOrCreateRegExpPrototype(JSContext* cx,
@ -491,12 +493,12 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_RegExp)) {
return nullptr;
}
return &global->getPrototype(JSProto_RegExp).toObject();
return &global->getPrototype(JSProto_RegExp);
}
JSObject* maybeGetRegExpPrototype() {
if (classIsInitialized(JSProto_RegExp)) {
return &getPrototype(JSProto_RegExp).toObject();
return &getPrototype(JSProto_RegExp);
}
return nullptr;
}
@ -506,7 +508,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_SavedFrame)) {
return nullptr;
}
return &global->getPrototype(JSProto_SavedFrame).toObject();
return &global->getPrototype(JSProto_SavedFrame);
}
static JSObject* getOrCreateArrayBufferConstructor(
@ -514,7 +516,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_ArrayBuffer)) {
return nullptr;
}
return &global->getConstructor(JSProto_ArrayBuffer).toObject();
return &global->getConstructor(JSProto_ArrayBuffer);
}
static JSObject* getOrCreateArrayBufferPrototype(
@ -522,7 +524,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_ArrayBuffer)) {
return nullptr;
}
return &global->getPrototype(JSProto_ArrayBuffer).toObject();
return &global->getPrototype(JSProto_ArrayBuffer);
}
static JSObject* getOrCreateSharedArrayBufferPrototype(
@ -530,7 +532,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_SharedArrayBuffer)) {
return nullptr;
}
return &global->getPrototype(JSProto_SharedArrayBuffer).toObject();
return &global->getPrototype(JSProto_SharedArrayBuffer);
}
static JSObject* getOrCreateCustomErrorPrototype(JSContext* cx,
@ -540,7 +542,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, key)) {
return nullptr;
}
return &global->getPrototype(key).toObject();
return &global->getPrototype(key);
}
static JSFunction* getOrCreateErrorConstructor(JSContext* cx,
@ -548,7 +550,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Error)) {
return nullptr;
}
return &global->getConstructor(JSProto_Error).toObject().as<JSFunction>();
return &global->getConstructor(JSProto_Error).as<JSFunction>();
}
static JSObject* getOrCreateErrorPrototype(JSContext* cx,
@ -561,7 +563,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Set)) {
return nullptr;
}
return &global->getPrototype(JSProto_Set).toObject().as<NativeObject>();
return &global->getPrototype(JSProto_Set).as<NativeObject>();
}
static NativeObject* getOrCreateWeakSetPrototype(
@ -569,7 +571,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_WeakSet)) {
return nullptr;
}
return &global->getPrototype(JSProto_WeakSet).toObject().as<NativeObject>();
return &global->getPrototype(JSProto_WeakSet).as<NativeObject>();
}
static bool ensureModulePrototypesCreated(JSContext* cx,
@ -611,9 +613,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_TypedArray)) {
return nullptr;
}
return &global->getConstructor(JSProto_TypedArray)
.toObject()
.as<JSFunction>();
return &global->getConstructor(JSProto_TypedArray).as<JSFunction>();
}
static JSObject* getOrCreateTypedArrayPrototype(
@ -621,7 +621,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_TypedArray)) {
return nullptr;
}
return &global->getPrototype(JSProto_TypedArray).toObject();
return &global->getPrototype(JSProto_TypedArray);
}
private:
@ -703,7 +703,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
return nullptr;
}
return &global->getPrototype(JSProto_GeneratorFunction).toObject();
return &global->getPrototype(JSProto_GeneratorFunction);
}
static JSObject* getOrCreateGeneratorFunction(JSContext* cx,
@ -711,7 +711,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
return nullptr;
}
return &global->getConstructor(JSProto_GeneratorFunction).toObject();
return &global->getConstructor(JSProto_GeneratorFunction);
}
static JSObject* getOrCreateAsyncFunctionPrototype(
@ -719,7 +719,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_AsyncFunction)) {
return nullptr;
}
return &global->getPrototype(JSProto_AsyncFunction).toObject();
return &global->getPrototype(JSProto_AsyncFunction);
}
static JSObject* getOrCreateAsyncFunction(JSContext* cx,
@ -727,7 +727,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_AsyncFunction)) {
return nullptr;
}
return &global->getConstructor(JSProto_AsyncFunction).toObject();
return &global->getConstructor(JSProto_AsyncFunction);
}
static JSObject* createAsyncIteratorPrototype(JSContext* cx,
@ -754,7 +754,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getPrototype(JSProto_AsyncGeneratorFunction).toObject();
return &global->getPrototype(JSProto_AsyncGeneratorFunction);
}
static JSObject* getOrCreateAsyncGeneratorFunction(
@ -762,7 +762,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getConstructor(JSProto_AsyncGeneratorFunction).toObject();
return &global->getConstructor(JSProto_AsyncGeneratorFunction);
}
void setAsyncGeneratorPrototype(JSObject* obj) {
@ -794,7 +794,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_DataView)) {
return nullptr;
}
return &global->getPrototype(JSProto_DataView).toObject();
return &global->getPrototype(JSProto_DataView);
}
static JSObject* getOrCreatePromiseConstructor(JSContext* cx,
@ -802,7 +802,7 @@ class GlobalObject : public NativeObject {
if (!ensureConstructor(cx, global, JSProto_Promise)) {
return nullptr;
}
return &global->getConstructor(JSProto_Promise).toObject();
return &global->getConstructor(JSProto_Promise);
}
static NativeObject* getOrCreateWrapForValidIteratorPrototype(
@ -972,13 +972,13 @@ class GlobalObject : public NativeObject {
// A class used in place of a prototype during off-thread parsing.
struct OffThreadPlaceholderObject : public NativeObject {
// The slot either stores a slot index (Int32Value >= 0) or a ProtoKind
// The slot either stores a JSProtoKey (Int32Value >= 0) or a ProtoKind
// (Int32Value < 0).
static const int32_t SlotIndexOrProtoKindSlot = 0;
static const int32_t ProtoKeyOrProtoKindSlot = 0;
static const JSClass class_;
static OffThreadPlaceholderObject* New(JSContext* cx, unsigned slot);
static OffThreadPlaceholderObject* New(JSContext* cx, JSProtoKey key);
static OffThreadPlaceholderObject* New(JSContext* cx, ProtoKind kind);
inline int32_t getSlotIndexOrProtoKind() const;
inline int32_t getProtoKeyOrProtoKind() const;
};
static bool isOffThreadPrototypePlaceholder(JSObject* obj) {

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

@ -1044,7 +1044,7 @@ static bool EnsureConstructor(JSContext* cx, Handle<GlobalObject*> global,
}
// Set the used-as-prototype flag here because we can't GC in mergeRealms.
RootedObject proto(cx, &global->getPrototype(key).toObject());
RootedObject proto(cx, &global->getPrototype(key));
return JSObject::setIsUsedAsPrototype(cx, proto);
}

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

@ -798,8 +798,7 @@ static void fun_trace(JSTracer* trc, JSObject* obj) {
static JSObject* CreateFunctionConstructor(JSContext* cx, JSProtoKey key) {
Rooted<GlobalObject*> global(cx, cx->global());
RootedObject functionProto(
cx, &global->getPrototype(JSProto_Function).toObject());
RootedObject functionProto(cx, &global->getPrototype(JSProto_Function));
RootedObject functionCtor(
cx, NewFunctionWithProto(
@ -822,7 +821,7 @@ static bool FunctionPrototype(JSContext* cx, unsigned argc, Value* vp) {
static JSObject* CreateFunctionPrototype(JSContext* cx, JSProtoKey key) {
Rooted<GlobalObject*> self(cx, cx->global());
RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject());
RootedObject objectProto(cx, &self->getPrototype(JSProto_Object));
return NewFunctionWithProto(
cx, FunctionPrototype, 0, FunctionFlags::NATIVE_FUN, nullptr,

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

@ -1796,8 +1796,7 @@ bool js::GetObjectFromIncumbentGlobal(JSContext* cx, MutableHandleObject obj) {
}
static bool IsStandardPrototype(JSObject* obj, JSProtoKey key) {
Value v = obj->nonCCWGlobal().getPrototype(key);
return v.isObject() && obj == &v.toObject();
return obj->nonCCWGlobal().maybeGetPrototype(key) == obj;
}
JSProtoKey JS::IdentifyStandardInstance(JSObject* obj) {
@ -1835,10 +1834,13 @@ JSProtoKey JS::IdentifyStandardConstructor(JSObject* obj) {
return JSProto_Null;
}
static_assert(JSProto_Null == 0,
"Loop below can start at 1 to skip JSProto_Null");
GlobalObject& global = obj->as<JSFunction>().global();
for (size_t k = 0; k < JSProto_LIMIT; ++k) {
for (size_t k = 1; k < JSProto_LIMIT; ++k) {
JSProtoKey key = static_cast<JSProtoKey>(k);
if (global.getConstructor(key) == ObjectValue(*obj)) {
if (global.maybeGetConstructor(key) == obj) {
return key;
}
}

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

@ -30,13 +30,13 @@ using JS::Value;
using js::NativeObject;
JSFunction* js::PromiseLookup::getPromiseConstructor(JSContext* cx) {
const Value& val = cx->global()->getConstructor(JSProto_Promise);
return val.isObject() ? &val.toObject().as<JSFunction>() : nullptr;
JSObject* obj = cx->global()->maybeGetConstructor(JSProto_Promise);
return obj ? &obj->as<JSFunction>() : nullptr;
}
NativeObject* js::PromiseLookup::getPromisePrototype(JSContext* cx) {
const Value& val = cx->global()->getPrototype(JSProto_Promise);
return val.isObject() ? &val.toObject().as<NativeObject>() : nullptr;
JSObject* obj = cx->global()->maybeGetPrototype(JSProto_Promise);
return obj ? &obj->as<NativeObject>() : nullptr;
}
bool js::PromiseLookup::isDataPropertyNative(JSContext* cx, NativeObject* obj,

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

@ -2492,8 +2492,7 @@ bool JSStructuredCloneReader::readSharedWasmMemory(uint32_t nbytes,
cx, &payload.toObject().as<SharedArrayBufferObject>());
// Construct the memory.
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory));
RootedObject memory(cx, WasmMemoryObject::create(cx, sab, proto));
if (!memory) {
return false;

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

@ -3903,8 +3903,7 @@ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx,
wasm::SharedExceptionTag tag,
HandleArrayBufferObject values,
HandleArrayObject refs) {
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmException).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmException));
AutoSetNewObjectMetadata metadata(cx);
RootedWasmExceptionObject obj(
@ -4141,7 +4140,7 @@ class AsyncInstantiateTask : public OffThreadPromiseTask {
bool resolve(JSContext* cx, Handle<PromiseObject*> promise) override {
RootedObject instanceProto(
cx, &cx->global()->getPrototype(JSProto_WasmInstance).toObject());
cx, &cx->global()->getPrototype(JSProto_WasmInstance));
RootedWasmInstanceObject instanceObj(cx);
if (!module_->instantiate(cx, imports_.get(), instanceProto,
@ -4158,8 +4157,8 @@ class AsyncInstantiateTask : public OffThreadPromiseTask {
return RejectWithPendingException(cx, promise);
}
RootedObject moduleProto(
cx, &cx->global()->getPrototype(JSProto_WasmModule).toObject());
RootedObject moduleProto(cx,
&cx->global()->getPrototype(JSProto_WasmModule));
RootedObject moduleObj(
cx, WasmModuleObject::create(cx, *module_, moduleProto));
if (!moduleObj) {
@ -4207,8 +4206,7 @@ static bool AsyncInstantiate(JSContext* cx, const Module& module,
static bool ResolveCompile(JSContext* cx, const Module& module,
Handle<PromiseObject*> promise) {
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmModule).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmModule));
RootedObject moduleObj(cx, WasmModuleObject::create(cx, module, proto));
if (!moduleObj) {
return RejectWithPendingException(cx, promise);

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

@ -350,8 +350,7 @@ JSObject* Module::createObject(JSContext* cx) const {
return nullptr;
}
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmModule).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmModule));
return WasmModuleObject::create(cx, *this, proto);
}
@ -741,8 +740,7 @@ bool Module::instantiateMemory(JSContext* cx,
return false;
}
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory));
memory.set(WasmMemoryObject::create(cx, buffer, proto));
if (!memory) {
return false;
@ -788,8 +786,7 @@ bool Module::instantiateLocalTag(JSContext* cx, const TagDesc& ed,
if (ed.isExport) {
// If the tag description is exported, create an export tag
// object for it.
RootedObject proto(cx,
&cx->global()->getPrototype(JSProto_WasmTag).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTag));
RootedWasmTagObject tagObj(cx, WasmTagObject::create(cx, ed.type, proto));
if (!tagObj) {
return false;
@ -875,8 +872,7 @@ bool Module::instantiateLocalTable(JSContext* cx, const TableDesc& td,
SharedTable table;
Rooted<WasmTableObject*> tableObj(cx);
if (td.importedOrExported) {
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmTable).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmTable));
tableObj.set(WasmTableObject::create(cx, td.initialLength, td.maximumLength,
td.elemType, proto));
if (!tableObj) {
@ -950,8 +946,7 @@ static bool EnsureExportedGlobalObject(JSContext* cx,
val.set(Val(global.type()));
}
RootedObject proto(
cx, &cx->global()->getPrototype(JSProto_WasmGlobal).toObject());
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmGlobal));
RootedWasmGlobalObject go(
cx, WasmGlobalObject::create(cx, val, global.isMutable(), proto));
if (!go) {