зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1260984 (part 3) - Separate js::ClassSpec from js::Class. r=jorendorff.
js::ClassSpec is often all null. When it's not all null, it's often duplicated among classes. By pulling it out into its own struct, and using a (possibly null) pointer in js::Class, we can save 138 KiB per process on 64-bit, and half that on 32-bit. --HG-- extra : rebase_source : 852ac6770ace46958d018107e78c5c44ebd6528a
This commit is contained in:
Родитель
394034a83e
Коммит
3e563eab78
|
@ -624,7 +624,7 @@ inline ClassObjectCreationOp DELEGATED_CLASSSPEC(const ClassSpec* spec) {
|
|||
return reinterpret_cast<ClassObjectCreationOp>(const_cast<ClassSpec*>(spec));
|
||||
}
|
||||
|
||||
#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
|
||||
#define JS_NULL_CLASS_SPEC nullptr
|
||||
#define JS_NULL_CLASS_EXT {false,nullptr}
|
||||
|
||||
struct ObjectOps
|
||||
|
@ -654,7 +654,7 @@ typedef void (*JSClassInternal)();
|
|||
struct JSClass {
|
||||
JS_CLASS_MEMBERS(JSFinalizeOp);
|
||||
|
||||
void* reserved[12];
|
||||
void* reserved[5];
|
||||
};
|
||||
|
||||
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
|
||||
|
@ -756,7 +756,7 @@ namespace js {
|
|||
struct Class
|
||||
{
|
||||
JS_CLASS_MEMBERS(FinalizeOp);
|
||||
ClassSpec spec;
|
||||
const ClassSpec* spec;
|
||||
ClassExtension ext;
|
||||
const ObjectOps* ops;
|
||||
|
||||
|
@ -804,6 +804,26 @@ struct Class
|
|||
|
||||
static size_t offsetOfFlags() { return offsetof(Class, flags); }
|
||||
|
||||
bool specDefined() const { return spec ? spec->defined() : false; }
|
||||
bool specDependent() const { return spec ? spec->dependent() : false; }
|
||||
JSProtoKey specParentKey() const { return spec ? spec->parentKey() : JSProto_Null; }
|
||||
bool specShouldDefineConstructor()
|
||||
const { return spec ? spec->shouldDefineConstructor() : true; }
|
||||
ClassObjectCreationOp specCreateConstructorHook()
|
||||
const { return spec ? spec->createConstructorHook() : nullptr; }
|
||||
ClassObjectCreationOp specCreatePrototypeHook()
|
||||
const { return spec ? spec->createPrototypeHook() : nullptr; }
|
||||
const JSFunctionSpec* specConstructorFunctions()
|
||||
const { return spec ? spec->constructorFunctions() : nullptr; }
|
||||
const JSPropertySpec* specConstructorProperties()
|
||||
const { return spec ? spec->constructorProperties() : nullptr; }
|
||||
const JSFunctionSpec* specPrototypeFunctions()
|
||||
const { return spec ? spec->prototypeFunctions() : nullptr; }
|
||||
const JSPropertySpec* specPrototypeProperties()
|
||||
const { return spec ? spec->prototypeProperties() : nullptr; }
|
||||
FinishClassInitOp specFinishInitHook()
|
||||
const { return spec ? spec->finishInitHook() : nullptr; }
|
||||
|
||||
LookupPropertyOp getOpsLookupProperty() const { return ops ? ops->lookupProperty : nullptr; }
|
||||
DefinePropertyOp getOpsDefineProperty() const { return ops ? ops->defineProperty : nullptr; }
|
||||
HasPropertyOp getOpsHasProperty() const { return ops ? ops->hasProperty : nullptr; }
|
||||
|
|
|
@ -1211,6 +1211,16 @@ FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject pro
|
|||
return true;
|
||||
}
|
||||
|
||||
static const ClassSpec PlainObjectClassSpec = {
|
||||
CreateObjectConstructor,
|
||||
CreateObjectPrototype,
|
||||
object_static_methods,
|
||||
nullptr,
|
||||
object_methods,
|
||||
object_properties,
|
||||
FinishObjectClassInit
|
||||
};
|
||||
|
||||
const Class PlainObject::class_ = {
|
||||
js_Object_str,
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
|
||||
|
@ -1226,15 +1236,7 @@ const Class PlainObject::class_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
CreateObjectConstructor,
|
||||
CreateObjectPrototype,
|
||||
object_static_methods,
|
||||
nullptr,
|
||||
object_methods,
|
||||
object_properties,
|
||||
FinishObjectClassInit
|
||||
}
|
||||
&PlainObjectClassSpec
|
||||
};
|
||||
|
||||
const Class* const js::ObjectClassPtr = &PlainObject::class_;
|
||||
|
|
|
@ -397,6 +397,14 @@ CreatePromisePrototype(JSContext* cx, JSProtoKey key)
|
|||
return cx->global()->createBlankPrototype(cx, &PromiseObject::protoClass_);
|
||||
}
|
||||
|
||||
static const ClassSpec PromiseObjectClassSpec = {
|
||||
GenericCreateConstructor<PromiseConstructor, 1, gc::AllocKind::FUNCTION>,
|
||||
CreatePromisePrototype,
|
||||
promise_static_methods,
|
||||
promise_static_properties,
|
||||
promise_methods
|
||||
};
|
||||
|
||||
const Class PromiseObject::class_ = {
|
||||
"Promise",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_HAS_CACHED_PROTO(JSProto_Promise) |
|
||||
|
@ -413,13 +421,18 @@ const Class PromiseObject::class_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
GenericCreateConstructor<PromiseConstructor, 1, gc::AllocKind::FUNCTION>,
|
||||
CreatePromisePrototype,
|
||||
promise_static_methods,
|
||||
promise_static_properties,
|
||||
promise_methods
|
||||
}
|
||||
&PromiseObjectClassSpec
|
||||
};
|
||||
|
||||
static const ClassSpec PromiseObjectProtoClassSpec = {
|
||||
DELEGATED_CLASSSPEC(PromiseObject::class_.spec),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
ClassSpec::IsDelegated
|
||||
};
|
||||
|
||||
const Class PromiseObject::protoClass_ = {
|
||||
|
@ -437,14 +450,5 @@ const Class PromiseObject::protoClass_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
DELEGATED_CLASSSPEC(&PromiseObject::class_.spec),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
ClassSpec::IsDelegated
|
||||
}
|
||||
&PromiseObjectProtoClassSpec
|
||||
};
|
||||
|
|
|
@ -3262,6 +3262,16 @@ array_proto_finish(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto)
|
|||
return DefineProperty(cx, proto, id, value, nullptr, nullptr, JSPROP_READONLY);
|
||||
}
|
||||
|
||||
static const ClassSpec ArrayObjectClassSpec = {
|
||||
GenericCreateConstructor<ArrayConstructor, 1, AllocKind::FUNCTION, &jit::JitInfo_Array>,
|
||||
CreateArrayPrototype,
|
||||
array_static_methods,
|
||||
nullptr,
|
||||
array_methods,
|
||||
nullptr,
|
||||
array_proto_finish
|
||||
};
|
||||
|
||||
const Class ArrayObject::class_ = {
|
||||
"Array",
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Array) | JSCLASS_DELAY_METADATA_CALLBACK,
|
||||
|
@ -3277,15 +3287,7 @@ const Class ArrayObject::class_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
GenericCreateConstructor<ArrayConstructor, 1, AllocKind::FUNCTION, &jit::JitInfo_Array>,
|
||||
CreateArrayPrototype,
|
||||
array_static_methods,
|
||||
nullptr,
|
||||
array_methods,
|
||||
nullptr,
|
||||
array_proto_finish
|
||||
}
|
||||
&ArrayObjectClassSpec
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -3272,6 +3272,16 @@ FinishDateClassInit(JSContext* cx, HandleObject ctor, HandleObject proto)
|
|||
nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
static const ClassSpec DateObjectClassSpec = {
|
||||
GenericCreateConstructor<DateConstructor, 7, gc::AllocKind::FUNCTION>,
|
||||
CreateDatePrototype,
|
||||
date_static_methods,
|
||||
nullptr,
|
||||
date_methods,
|
||||
nullptr,
|
||||
FinishDateClassInit
|
||||
};
|
||||
|
||||
const Class DateObject::class_ = {
|
||||
js_Date_str,
|
||||
JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
|
||||
|
@ -3288,15 +3298,18 @@ const Class DateObject::class_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
GenericCreateConstructor<DateConstructor, 7, gc::AllocKind::FUNCTION>,
|
||||
CreateDatePrototype,
|
||||
date_static_methods,
|
||||
nullptr,
|
||||
date_methods,
|
||||
nullptr,
|
||||
FinishDateClassInit
|
||||
}
|
||||
&DateObjectClassSpec
|
||||
};
|
||||
|
||||
static const ClassSpec DateObjectProtoClassSpec = {
|
||||
DELEGATED_CLASSSPEC(DateObject::class_.spec),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
ClassSpec::IsDelegated
|
||||
};
|
||||
|
||||
const Class DateObject::protoClass_ = {
|
||||
|
@ -3314,16 +3327,7 @@ const Class DateObject::protoClass_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
DELEGATED_CLASSSPEC(&DateObject::class_.spec),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
ClassSpec::IsDelegated
|
||||
}
|
||||
&DateObjectProtoClassSpec
|
||||
};
|
||||
|
||||
JSObject*
|
||||
|
|
|
@ -65,7 +65,7 @@ static const JSFunctionSpec exception_methods[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
#define IMPLEMENT_ERROR_SUBCLASS_EXTRA_FLAGS(name, extraClassSpecFlags) \
|
||||
#define IMPLEMENT_ERROR_CLASS(name, classSpecPtr) \
|
||||
{ \
|
||||
js_Error_str, /* yes, really */ \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##name) | \
|
||||
|
@ -82,60 +82,59 @@ static const JSFunctionSpec exception_methods[] = {
|
|||
nullptr, /* hasInstance */ \
|
||||
nullptr, /* construct */ \
|
||||
nullptr, /* trace */ \
|
||||
{ \
|
||||
ErrorObject::createConstructor, \
|
||||
ErrorObject::createProto, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
exception_methods, \
|
||||
exception_properties, \
|
||||
nullptr, \
|
||||
JSProto_Error | extraClassSpecFlags \
|
||||
} \
|
||||
classSpecPtr \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_ERROR_SUBCLASS(name) \
|
||||
IMPLEMENT_ERROR_SUBCLASS_EXTRA_FLAGS(name, 0)
|
||||
const ClassSpec
|
||||
ErrorObject::errorClassSpec_ = {
|
||||
ErrorObject::createConstructor,
|
||||
ErrorObject::createProto,
|
||||
nullptr,
|
||||
nullptr,
|
||||
exception_methods,
|
||||
exception_properties,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const ClassSpec
|
||||
ErrorObject::subErrorClassSpec_ = {
|
||||
ErrorObject::createConstructor,
|
||||
ErrorObject::createProto,
|
||||
nullptr,
|
||||
nullptr,
|
||||
exception_methods,
|
||||
exception_properties,
|
||||
nullptr,
|
||||
JSProto_Error
|
||||
};
|
||||
|
||||
const ClassSpec
|
||||
ErrorObject::debuggeeWouldRunClassSpec_ = {
|
||||
ErrorObject::createConstructor,
|
||||
ErrorObject::createProto,
|
||||
nullptr,
|
||||
nullptr,
|
||||
exception_methods,
|
||||
exception_properties,
|
||||
nullptr,
|
||||
JSProto_Error | ClassSpec::DontDefineConstructor
|
||||
};
|
||||
|
||||
const Class
|
||||
ErrorObject::classes[JSEXN_LIMIT] = {
|
||||
{
|
||||
js_Error_str,
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Error) |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(ErrorObject::RESERVED_SLOTS),
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* getProperty */
|
||||
nullptr, /* setProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
exn_finalize,
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
ErrorObject::createConstructor,
|
||||
ErrorObject::createProto,
|
||||
nullptr,
|
||||
nullptr,
|
||||
exception_methods,
|
||||
exception_properties,
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
IMPLEMENT_ERROR_SUBCLASS(InternalError),
|
||||
IMPLEMENT_ERROR_SUBCLASS(EvalError),
|
||||
IMPLEMENT_ERROR_SUBCLASS(RangeError),
|
||||
IMPLEMENT_ERROR_SUBCLASS(ReferenceError),
|
||||
IMPLEMENT_ERROR_SUBCLASS(SyntaxError),
|
||||
IMPLEMENT_ERROR_SUBCLASS(TypeError),
|
||||
IMPLEMENT_ERROR_SUBCLASS(URIError),
|
||||
IMPLEMENT_ERROR_CLASS(Error, &ErrorObject::errorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(InternalError, &ErrorObject::subErrorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(EvalError, &ErrorObject::subErrorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(RangeError, &ErrorObject::subErrorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(ReferenceError, &ErrorObject::subErrorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(SyntaxError, &ErrorObject::subErrorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(TypeError, &ErrorObject::subErrorClassSpec_),
|
||||
IMPLEMENT_ERROR_CLASS(URIError, &ErrorObject::subErrorClassSpec_),
|
||||
|
||||
// DebuggeeWouldRun is a subclass of Error but is accessible via the
|
||||
// Debugger constructor, not the global.
|
||||
IMPLEMENT_ERROR_SUBCLASS_EXTRA_FLAGS(DebuggeeWouldRun, ClassSpec::DontDefineConstructor),
|
||||
IMPLEMENT_ERROR_CLASS(DebuggeeWouldRun, &ErrorObject::debuggeeWouldRunClassSpec_)
|
||||
};
|
||||
|
||||
JSErrorReport*
|
||||
|
|
|
@ -643,7 +643,7 @@ inline bool
|
|||
StandardClassIsDependent(JSProtoKey key)
|
||||
{
|
||||
const Class* clasp = ProtoKeyToClass(key);
|
||||
return clasp && clasp->spec.defined() && clasp->spec.dependent();
|
||||
return clasp && clasp->specDefined() && clasp->specDependent();
|
||||
}
|
||||
|
||||
// Returns the key for the class inherited by a given standard class (that
|
||||
|
@ -662,7 +662,7 @@ ParentKeyForStandardClass(JSProtoKey key)
|
|||
|
||||
// If we're dependent, return the key of the class we depend on.
|
||||
if (StandardClassIsDependent(key))
|
||||
return ProtoKeyToClass(key)->spec.parentKey();
|
||||
return ProtoKeyToClass(key)->specParentKey();
|
||||
|
||||
// Otherwise, we inherit [Object].
|
||||
return JSProto_Object;
|
||||
|
|
|
@ -834,6 +834,15 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
|
|||
return functionProto;
|
||||
}
|
||||
|
||||
static const ClassSpec JSFunctionClassSpec = {
|
||||
CreateFunctionConstructor,
|
||||
CreateFunctionPrototype,
|
||||
nullptr,
|
||||
nullptr,
|
||||
function_methods,
|
||||
function_properties
|
||||
};
|
||||
|
||||
const Class JSFunction::class_ = {
|
||||
js_Function_str,
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
|
||||
|
@ -849,14 +858,7 @@ const Class JSFunction::class_ = {
|
|||
fun_hasInstance,
|
||||
nullptr, /* construct */
|
||||
fun_trace,
|
||||
{
|
||||
CreateFunctionConstructor,
|
||||
CreateFunctionPrototype,
|
||||
nullptr,
|
||||
nullptr,
|
||||
function_methods,
|
||||
function_properties
|
||||
}
|
||||
&JSFunctionClassSpec
|
||||
};
|
||||
|
||||
const Class* const js::FunctionClassPtr = &JSFunction::class_;
|
||||
|
|
|
@ -41,6 +41,10 @@ class ErrorObject : public NativeObject
|
|||
static bool checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName,
|
||||
MutableHandle<ErrorObject*> error);
|
||||
|
||||
static const ClassSpec errorClassSpec_;
|
||||
static const ClassSpec subErrorClassSpec_;
|
||||
static const ClassSpec debuggeeWouldRunClassSpec_;
|
||||
|
||||
protected:
|
||||
static const uint32_t EXNTYPE_SLOT = 0;
|
||||
static const uint32_t STACK_SLOT = EXNTYPE_SLOT + 1;
|
||||
|
|
|
@ -162,7 +162,7 @@ GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JS
|
|||
// GlobalObject::initStandardClasses that want to just carpet-bomb-call
|
||||
// ensureConstructor with every JSProtoKey. So it's easier to just handle
|
||||
// it here.
|
||||
bool haveSpec = clasp && clasp->spec.defined();
|
||||
bool haveSpec = clasp && clasp->specDefined();
|
||||
if (!init && !haveSpec)
|
||||
return true;
|
||||
|
||||
|
@ -195,8 +195,8 @@ GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JS
|
|||
// |createPrototype|, |prototypeFunctions|, and |prototypeProperties|
|
||||
// should all be null.
|
||||
RootedObject proto(cx);
|
||||
if (clasp->spec.createPrototypeHook()) {
|
||||
proto = clasp->spec.createPrototypeHook()(cx, key);
|
||||
if (ClassObjectCreationOp createPrototype = clasp->specCreatePrototypeHook()) {
|
||||
proto = createPrototype(cx, key);
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
|
@ -211,12 +211,12 @@ GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JS
|
|||
}
|
||||
|
||||
// Create the constructor.
|
||||
RootedObject ctor(cx, clasp->spec.createConstructorHook()(cx, key));
|
||||
RootedObject ctor(cx, clasp->specCreateConstructorHook()(cx, key));
|
||||
if (!ctor)
|
||||
return false;
|
||||
|
||||
RootedId id(cx, NameToId(ClassName(key, cx)));
|
||||
if (clasp->spec.shouldDefineConstructor()) {
|
||||
if (clasp->specShouldDefineConstructor()) {
|
||||
if (!global->addDataProperty(cx, id, constructorPropertySlot(key), 0))
|
||||
return false;
|
||||
}
|
||||
|
@ -229,19 +229,19 @@ GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JS
|
|||
// operating on the self-hosting global, in which case we don't want any
|
||||
// functions and properties on the builtins and their prototypes.
|
||||
if (!StandardClassIsDependent(key) && !cx->runtime()->isSelfHostingGlobal(global)) {
|
||||
if (const JSFunctionSpec* funs = clasp->spec.prototypeFunctions()) {
|
||||
if (const JSFunctionSpec* funs = clasp->specPrototypeFunctions()) {
|
||||
if (!JS_DefineFunctions(cx, proto, funs))
|
||||
return false;
|
||||
}
|
||||
if (const JSPropertySpec* props = clasp->spec.prototypeProperties()) {
|
||||
if (const JSPropertySpec* props = clasp->specPrototypeProperties()) {
|
||||
if (!JS_DefineProperties(cx, proto, props))
|
||||
return false;
|
||||
}
|
||||
if (const JSFunctionSpec* funs = clasp->spec.constructorFunctions()) {
|
||||
if (const JSFunctionSpec* funs = clasp->specConstructorFunctions()) {
|
||||
if (!JS_DefineFunctions(cx, ctor, funs))
|
||||
return false;
|
||||
}
|
||||
if (const JSPropertySpec* props = clasp->spec.constructorProperties()) {
|
||||
if (const JSPropertySpec* props = clasp->specConstructorProperties()) {
|
||||
if (!JS_DefineProperties(cx, ctor, props))
|
||||
return false;
|
||||
}
|
||||
|
@ -252,10 +252,12 @@ GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JS
|
|||
return false;
|
||||
|
||||
// Call the post-initialization hook, if provided.
|
||||
if (clasp->spec.finishInitHook() && !clasp->spec.finishInitHook()(cx, ctor, proto))
|
||||
return false;
|
||||
if (FinishClassInitOp finishInit = clasp->specFinishInitHook()) {
|
||||
if (!finishInit(cx, ctor, proto))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (clasp->spec.shouldDefineConstructor()) {
|
||||
if (clasp->specShouldDefineConstructor()) {
|
||||
// Stash type information, so that what we do here is equivalent to
|
||||
// initBuiltinConstructor.
|
||||
AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
|
@ -416,11 +418,11 @@ InitBareBuiltinCtor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey prot
|
|||
MOZ_ASSERT(cx->runtime()->isSelfHostingGlobal(global));
|
||||
const Class* clasp = ProtoKeyToClass(protoKey);
|
||||
RootedObject proto(cx);
|
||||
proto = clasp->spec.createPrototypeHook()(cx, protoKey);
|
||||
proto = clasp->specCreatePrototypeHook()(cx, protoKey);
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
RootedObject ctor(cx, clasp->spec.createConstructorHook()(cx, protoKey));
|
||||
RootedObject ctor(cx, clasp->specCreateConstructorHook()(cx, protoKey));
|
||||
if (!ctor)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -185,6 +185,15 @@ RegExpObject::trace(JSTracer* trc, JSObject* obj)
|
|||
}
|
||||
}
|
||||
|
||||
static const ClassSpec RegExpObjectClassSpec = {
|
||||
GenericCreateConstructor<js::regexp_construct, 2, gc::AllocKind::FUNCTION>,
|
||||
CreateRegExpPrototype,
|
||||
nullptr,
|
||||
js::regexp_static_props,
|
||||
js::regexp_methods,
|
||||
js::regexp_properties
|
||||
};
|
||||
|
||||
const Class RegExpObject::class_ = {
|
||||
js_RegExp_str,
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
|
@ -202,16 +211,7 @@ const Class RegExpObject::class_ = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
RegExpObject::trace,
|
||||
|
||||
// ClassSpec
|
||||
{
|
||||
GenericCreateConstructor<js::regexp_construct, 2, gc::AllocKind::FUNCTION>,
|
||||
CreateRegExpPrototype,
|
||||
nullptr,
|
||||
js::regexp_static_props,
|
||||
js::regexp_methods,
|
||||
js::regexp_properties
|
||||
}
|
||||
&RegExpObjectClassSpec
|
||||
};
|
||||
|
||||
RegExpObject*
|
||||
|
|
|
@ -18,6 +18,8 @@ class SavedFrame : public NativeObject {
|
|||
friend class SavedStacks;
|
||||
friend struct ::JSStructuredCloneReader;
|
||||
|
||||
static const ClassSpec classSpec_;
|
||||
|
||||
public:
|
||||
static const Class class_;
|
||||
static const JSPropertySpec protoAccessors[];
|
||||
|
|
|
@ -289,6 +289,17 @@ SavedFrame::finishSavedFrameInit(JSContext* cx, HandleObject ctor, HandleObject
|
|||
return FreezeObject(cx, proto);
|
||||
}
|
||||
|
||||
const ClassSpec SavedFrame::classSpec_ = {
|
||||
GenericCreateConstructor<SavedFrame::construct, 0, gc::AllocKind::FUNCTION>,
|
||||
GenericCreatePrototype,
|
||||
SavedFrame::staticFunctions,
|
||||
nullptr,
|
||||
SavedFrame::protoFunctions,
|
||||
SavedFrame::protoAccessors,
|
||||
SavedFrame::finishSavedFrameInit,
|
||||
ClassSpec::DontDefineConstructor
|
||||
};
|
||||
|
||||
/* static */ const Class SavedFrame::class_ = {
|
||||
"SavedFrame",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
|
@ -307,18 +318,7 @@ SavedFrame::finishSavedFrameInit(JSContext* cx, HandleObject ctor, HandleObject
|
|||
nullptr, // hasInstance
|
||||
nullptr, // construct
|
||||
nullptr, // trace
|
||||
|
||||
// ClassSpec
|
||||
{
|
||||
GenericCreateConstructor<SavedFrame::construct, 0, gc::AllocKind::FUNCTION>,
|
||||
GenericCreatePrototype,
|
||||
SavedFrame::staticFunctions,
|
||||
nullptr,
|
||||
SavedFrame::protoFunctions,
|
||||
SavedFrame::protoAccessors,
|
||||
SavedFrame::finishSavedFrameInit,
|
||||
ClassSpec::DontDefineConstructor
|
||||
}
|
||||
&SavedFrame::classSpec_
|
||||
};
|
||||
|
||||
/* static */ const JSFunctionSpec
|
||||
|
|
|
@ -861,6 +861,18 @@ TypedArrayObject::staticFunctions[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
static const ClassSpec
|
||||
TypedArrayObjectSharedTypedArrayPrototypeClassSpec = {
|
||||
GenericCreateConstructor<TypedArrayConstructor, 3, gc::AllocKind::FUNCTION>,
|
||||
GenericCreatePrototype,
|
||||
TypedArrayObject::staticFunctions,
|
||||
nullptr,
|
||||
TypedArrayObject::protoFunctions,
|
||||
TypedArrayObject::protoAccessors,
|
||||
nullptr,
|
||||
ClassSpec::DontDefineConstructor
|
||||
};
|
||||
|
||||
/* static */ const Class
|
||||
TypedArrayObject::sharedTypedArrayPrototypeClass = {
|
||||
// Actually ({}).toString.call(%TypedArray%.prototype) should throw,
|
||||
|
@ -883,16 +895,7 @@ TypedArrayObject::sharedTypedArrayPrototypeClass = {
|
|||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
{
|
||||
GenericCreateConstructor<TypedArrayConstructor, 3, gc::AllocKind::FUNCTION>,
|
||||
GenericCreatePrototype,
|
||||
TypedArrayObject::staticFunctions,
|
||||
nullptr,
|
||||
TypedArrayObject::protoFunctions,
|
||||
TypedArrayObject::protoAccessors,
|
||||
nullptr,
|
||||
ClassSpec::DontDefineConstructor
|
||||
}
|
||||
&TypedArrayObjectSharedTypedArrayPrototypeClassSpec
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -1905,24 +1908,36 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint32, uint32_t, uint32_t)
|
|||
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float32, float, float)
|
||||
IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
||||
|
||||
#define TYPED_ARRAY_CLASS_SPEC(_typedArray) \
|
||||
#define IMPL_TYPED_ARRAY_CLASS_SPEC(_type) \
|
||||
{ \
|
||||
_typedArray::createConstructor, \
|
||||
_typedArray::createPrototype, \
|
||||
_type##Array::createConstructor, \
|
||||
_type##Array::createPrototype, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
_typedArray::finishClassInit, \
|
||||
_type##Array::finishClassInit, \
|
||||
JSProto_TypedArray \
|
||||
}
|
||||
|
||||
#define IMPL_TYPED_ARRAY_CLASS(_typedArray) \
|
||||
static const ClassSpec TypedArrayObjectClassSpecs[Scalar::MaxTypedArrayViewType] = {
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Int8),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Uint8),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Int16),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Uint16),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Int32),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Uint32),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Float32),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Float64),
|
||||
IMPL_TYPED_ARRAY_CLASS_SPEC(Uint8Clamped)
|
||||
};
|
||||
|
||||
#define IMPL_TYPED_ARRAY_CLASS(_type) \
|
||||
{ \
|
||||
#_typedArray, \
|
||||
#_type "Array", \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) | \
|
||||
JSCLASS_HAS_PRIVATE | \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray) | \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##_type##Array) | \
|
||||
JSCLASS_DELAY_METADATA_CALLBACK, \
|
||||
nullptr, /* addProperty */ \
|
||||
nullptr, /* delProperty */ \
|
||||
|
@ -1936,19 +1951,43 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
|||
nullptr, /* hasInstance */ \
|
||||
nullptr, /* construct */ \
|
||||
TypedArrayObject::trace, /* trace */ \
|
||||
TYPED_ARRAY_CLASS_SPEC(_typedArray) \
|
||||
&TypedArrayObjectClassSpecs[Scalar::Type::_type] \
|
||||
}
|
||||
|
||||
const Class TypedArrayObject::classes[Scalar::MaxTypedArrayViewType] = {
|
||||
IMPL_TYPED_ARRAY_CLASS(Int8Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint8Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Int16Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint16Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Int32Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint32Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Float32Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Float64Array),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint8ClampedArray)
|
||||
IMPL_TYPED_ARRAY_CLASS(Int8),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint8),
|
||||
IMPL_TYPED_ARRAY_CLASS(Int16),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint16),
|
||||
IMPL_TYPED_ARRAY_CLASS(Int32),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint32),
|
||||
IMPL_TYPED_ARRAY_CLASS(Float32),
|
||||
IMPL_TYPED_ARRAY_CLASS(Float64),
|
||||
IMPL_TYPED_ARRAY_CLASS(Uint8Clamped)
|
||||
};
|
||||
|
||||
#define IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(_type) \
|
||||
{ \
|
||||
DELEGATED_CLASSSPEC(TypedArrayObject::classes[Scalar::Type::_type].spec), \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
JSProto_TypedArray | ClassSpec::IsDelegated \
|
||||
}
|
||||
|
||||
static const ClassSpec TypedArrayObjectProtoClassSpecs[Scalar::MaxTypedArrayViewType] = {
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Int8),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Uint8),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Int16),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Uint16),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Int32),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Uint32),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Float32),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Float64),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS_SPEC(Uint8Clamped)
|
||||
};
|
||||
|
||||
// The various typed array prototypes are supposed to 1) be normal objects,
|
||||
|
@ -1958,7 +1997,7 @@ const Class TypedArrayObject::classes[Scalar::MaxTypedArrayViewType] = {
|
|||
// prototype's class have the relevant typed array's cached JSProtoKey in them.
|
||||
// Thus we need one class with cached prototype per kind of typed array, with a
|
||||
// delegated ClassSpec.
|
||||
#define IMPL_TYPED_ARRAY_PROTO_CLASS(typedArray, i) \
|
||||
#define IMPL_TYPED_ARRAY_PROTO_CLASS(_type) \
|
||||
{ \
|
||||
/*
|
||||
* Actually ({}).toString.call(Uint8Array.prototype) should throw, because
|
||||
|
@ -1967,8 +2006,8 @@ const Class TypedArrayObject::classes[Scalar::MaxTypedArrayViewType] = {
|
|||
* above), but it's what we've always done, so keep doing it till we
|
||||
* implement @@toStringTag or ES6 changes.
|
||||
*/ \
|
||||
#typedArray "Prototype", \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##typedArray), \
|
||||
#_type "ArrayPrototype", \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##_type##Array), \
|
||||
nullptr, /* addProperty */ \
|
||||
nullptr, /* delProperty */ \
|
||||
nullptr, /* getProperty */ \
|
||||
|
@ -1981,28 +2020,19 @@ const Class TypedArrayObject::classes[Scalar::MaxTypedArrayViewType] = {
|
|||
nullptr, /* hasInstance */ \
|
||||
nullptr, /* construct */ \
|
||||
nullptr, /* trace */ \
|
||||
{ \
|
||||
DELEGATED_CLASSSPEC(&TypedArrayObject::classes[i].spec), \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
JSProto_TypedArray | ClassSpec::IsDelegated \
|
||||
} \
|
||||
&TypedArrayObjectProtoClassSpecs[Scalar::Type::_type] \
|
||||
}
|
||||
|
||||
const Class TypedArrayObject::protoClasses[Scalar::MaxTypedArrayViewType] = {
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Int8Array, 0),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint8Array, 1),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Int16Array, 2),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint16Array, 3),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Int32Array, 4),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint32Array, 5),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Float32Array, 6),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Float64Array, 7),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint8ClampedArray, 8)
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Int8),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint8),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Int16),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint16),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Int32),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint32),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Float32),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Float64),
|
||||
IMPL_TYPED_ARRAY_PROTO_CLASS(Uint8Clamped)
|
||||
};
|
||||
|
||||
/* static */ bool
|
||||
|
|
|
@ -573,11 +573,11 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
|
|||
|
||||
if (ShouldResolveStaticProperties(standardConstructor)) {
|
||||
const js::Class* clasp = js::ProtoKeyToClass(standardConstructor);
|
||||
MOZ_ASSERT(clasp->spec.defined());
|
||||
MOZ_ASSERT(clasp->specDefined());
|
||||
|
||||
if (!TryResolvePropertyFromSpecs(cx, id, holder,
|
||||
clasp->spec.constructorFunctions(),
|
||||
clasp->spec.constructorProperties(), desc)) {
|
||||
clasp->specConstructorFunctions(),
|
||||
clasp->specConstructorProperties(), desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -656,13 +656,13 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
|
|||
|
||||
// Grab the JSClass. We require all Xrayable classes to have a ClassSpec.
|
||||
const js::Class* clasp = js::GetObjectClass(target);
|
||||
MOZ_ASSERT(clasp->spec.defined());
|
||||
MOZ_ASSERT(clasp->specDefined());
|
||||
|
||||
// Indexed array properties are handled above, so we can just work with the
|
||||
// class spec here.
|
||||
if (!TryResolvePropertyFromSpecs(cx, id, holder,
|
||||
clasp->spec.prototypeFunctions(),
|
||||
clasp->spec.prototypeProperties(),
|
||||
clasp->specPrototypeFunctions(),
|
||||
clasp->specPrototypeProperties(),
|
||||
desc)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -864,11 +864,11 @@ JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags
|
|||
|
||||
if (ShouldResolveStaticProperties(standardConstructor)) {
|
||||
const js::Class* clasp = js::ProtoKeyToClass(standardConstructor);
|
||||
MOZ_ASSERT(clasp->spec.defined());
|
||||
MOZ_ASSERT(clasp->specDefined());
|
||||
|
||||
if (!AppendNamesFromFunctionAndPropertySpecs(
|
||||
cx, clasp->spec.constructorFunctions(),
|
||||
clasp->spec.constructorProperties(), flags, props)) {
|
||||
cx, clasp->specConstructorFunctions(),
|
||||
clasp->specConstructorProperties(), flags, props)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -905,11 +905,11 @@ JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags
|
|||
|
||||
// Grab the JSClass. We require all Xrayable classes to have a ClassSpec.
|
||||
const js::Class* clasp = js::GetObjectClass(target);
|
||||
MOZ_ASSERT(clasp->spec.defined());
|
||||
MOZ_ASSERT(clasp->specDefined());
|
||||
|
||||
return AppendNamesFromFunctionAndPropertySpecs(
|
||||
cx, clasp->spec.prototypeFunctions(),
|
||||
clasp->spec.prototypeProperties(), flags, props);
|
||||
cx, clasp->specPrototypeFunctions(),
|
||||
clasp->specPrototypeProperties(), flags, props);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче