зеркало из https://github.com/mozilla/gecko-dev.git
Bug 650161 - Add a class hook that's called when an object is moved r=terrence
This commit is contained in:
Родитель
fbd9cb9af7
Коммит
9f938c20cc
|
@ -10,7 +10,7 @@
|
|||
#define js_Class_h
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/CallArgs.h"
|
||||
|
@ -185,6 +185,9 @@ typedef JSObject *
|
|||
typedef JSObject *
|
||||
(* JSWeakmapKeyDelegateOp)(JSObject *obj);
|
||||
|
||||
typedef void
|
||||
(* JSObjectMovedOp)(JSObject *obj, const JSObject *old);
|
||||
|
||||
/* js::Class operation signatures. */
|
||||
|
||||
namespace js {
|
||||
|
@ -318,10 +321,19 @@ struct ClassExtension
|
|||
* wrapped object is collected.
|
||||
*/
|
||||
JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
|
||||
|
||||
/*
|
||||
* Optional hook called when an object is moved by a compacting GC.
|
||||
*
|
||||
* There may exist weak pointers to an object that are not traced through
|
||||
* when the normal trace APIs are used, for example objects in the wrapper
|
||||
* cache. This hook allows these pointers to be updated.
|
||||
*/
|
||||
JSObjectMovedOp objectMovedOp;
|
||||
};
|
||||
|
||||
#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
|
||||
#define JS_NULL_CLASS_EXT {nullptr,nullptr,nullptr,false,nullptr}
|
||||
#define JS_NULL_CLASS_EXT {nullptr,nullptr,nullptr,false,nullptr,nullptr}
|
||||
|
||||
struct ObjectOps
|
||||
{
|
||||
|
@ -361,7 +373,7 @@ typedef void (*JSClassInternal)();
|
|||
struct JSClass {
|
||||
JS_CLASS_MEMBERS(JSFinalizeOp);
|
||||
|
||||
void *reserved[31];
|
||||
void *reserved[32];
|
||||
};
|
||||
|
||||
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
|
||||
|
@ -540,6 +552,11 @@ IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
|
|||
inline bool
|
||||
Unbox(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp);
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(bool)
|
||||
HasObjectMovedOp(JSObject *obj);
|
||||
#endif
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* js_Class_h */
|
||||
|
|
|
@ -1195,6 +1195,11 @@ js::IsInRequest(JSContext *cx)
|
|||
{
|
||||
return !!cx->runtime()->requestDepth;
|
||||
}
|
||||
|
||||
bool
|
||||
js::HasObjectMovedOp(JSObject *obj) {
|
||||
return !!GetObjectClass(obj)->ext.objectMovedOp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
|
|
|
@ -262,7 +262,8 @@ namespace js {
|
|||
innerObject, \
|
||||
iteratorObject, \
|
||||
isWrappedNative, \
|
||||
js::proxy_WeakmapKeyDelegate \
|
||||
js::proxy_WeakmapKeyDelegate, \
|
||||
js::proxy_ObjectMoved \
|
||||
}
|
||||
|
||||
#define PROXY_CLASS_WITH_EXT(name, extraSlots, flags, callOp, constructOp, ext) \
|
||||
|
@ -377,6 +378,8 @@ extern JS_FRIEND_API(bool)
|
|||
proxy_Convert(JSContext *cx, JS::HandleObject proxy, JSType hint, JS::MutableHandleValue vp);
|
||||
extern JS_FRIEND_API(void)
|
||||
proxy_Finalize(FreeOp *fop, JSObject *obj);
|
||||
extern JS_FRIEND_API(void)
|
||||
proxy_ObjectMoved(JSObject *obj, const JSObject *old);
|
||||
extern JS_FRIEND_API(bool)
|
||||
proxy_HasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
|
||||
extern JS_FRIEND_API(bool)
|
||||
|
|
|
@ -2172,27 +2172,17 @@ RelocateCell(Zone *zone, Cell *src, AllocKind thingKind, size_t thingSize)
|
|||
// Copy source cell contents to destination.
|
||||
memcpy(dst, src, thingSize);
|
||||
|
||||
// Fixup the pointer to inline object elements if necessary.
|
||||
if (thingKind <= FINALIZE_OBJECT_LAST) {
|
||||
JSObject *srcObj = static_cast<JSObject *>(src);
|
||||
JSObject *dstObj = static_cast<JSObject *>(dst);
|
||||
|
||||
// Fixup the pointer to inline object elements if necessary.
|
||||
if (srcObj->hasFixedElements())
|
||||
dstObj->setFixedElements();
|
||||
|
||||
if (srcObj->is<ArrayBufferObject>()) {
|
||||
// We must fix up any inline data pointers while we know the source
|
||||
// object and before we mark any of the views.
|
||||
ArrayBufferObject::fixupDataPointerAfterMovingGC(
|
||||
srcObj->as<ArrayBufferObject>(), dstObj->as<ArrayBufferObject>());
|
||||
} else if (srcObj->is<TypedArrayObject>()) {
|
||||
TypedArrayObject &typedArray = srcObj->as<TypedArrayObject>();
|
||||
if (!typedArray.hasBuffer()) {
|
||||
JS_ASSERT(srcObj->getPrivate() ==
|
||||
srcObj->fixedData(TypedArrayObject::FIXED_DATA_START));
|
||||
dstObj->setPrivate(dstObj->fixedData(TypedArrayObject::FIXED_DATA_START));
|
||||
}
|
||||
}
|
||||
|
||||
// Call object moved hook if present.
|
||||
if (JSObjectMovedOp op = srcObj->getClass()->ext.objectMovedOp)
|
||||
op(dstObj, srcObj);
|
||||
|
||||
JS_ASSERT_IF(dstObj->isNative(),
|
||||
!PtrIsInRange((const Value*)dstObj->getDenseElements(), src, thingSize));
|
||||
|
|
|
@ -362,6 +362,11 @@ BaseProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy) const
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
BaseProxyHandler::objectMoved(JSObject *proxy, const JSObject *old) const
|
||||
{
|
||||
}
|
||||
|
||||
JSObject *
|
||||
BaseProxyHandler::weakmapKeyDelegate(JSObject *proxy) const
|
||||
{
|
||||
|
@ -2878,6 +2883,13 @@ js::proxy_Finalize(FreeOp *fop, JSObject *obj)
|
|||
obj->as<ProxyObject>().handler()->finalize(fop, obj);
|
||||
}
|
||||
|
||||
void
|
||||
js::proxy_ObjectMoved(JSObject *obj, const JSObject *old)
|
||||
{
|
||||
JS_ASSERT(obj->is<ProxyObject>());
|
||||
obj->as<ProxyObject>().handler()->objectMoved(obj, old);
|
||||
}
|
||||
|
||||
bool
|
||||
js::proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
|
||||
{
|
||||
|
|
|
@ -220,6 +220,7 @@ class JS_FRIEND_API(BaseProxyHandler)
|
|||
virtual bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const;
|
||||
virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp) const;
|
||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy) const;
|
||||
virtual void objectMoved(JSObject *proxy, const JSObject *old) const;
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const;
|
||||
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp) const;
|
||||
|
||||
|
|
|
@ -122,7 +122,14 @@ const Class ArrayBufferObject::class_ = {
|
|||
nullptr, /* construct */
|
||||
ArrayBufferObject::obj_trace,
|
||||
JS_NULL_CLASS_SPEC,
|
||||
JS_NULL_CLASS_EXT
|
||||
{
|
||||
nullptr, /* outerObject */
|
||||
nullptr, /* innerObject */
|
||||
nullptr, /* iteratorObject */
|
||||
false, /* isWrappedNative */
|
||||
nullptr, /* weakmapKeyDelegateOp */
|
||||
ArrayBufferObject::objectMoved
|
||||
}
|
||||
};
|
||||
|
||||
const JSFunctionSpec ArrayBufferObject::jsfuncs[] = {
|
||||
|
@ -929,8 +936,11 @@ ArrayBufferObject::sweep(JSCompartment *compartment)
|
|||
}
|
||||
|
||||
/* static */ void
|
||||
ArrayBufferObject::fixupDataPointerAfterMovingGC(const ArrayBufferObject &src, ArrayBufferObject &dst)
|
||||
ArrayBufferObject::objectMoved(JSObject *obj, const JSObject *old)
|
||||
{
|
||||
ArrayBufferObject &dst = obj->as<ArrayBufferObject>();
|
||||
const ArrayBufferObject &src = old->as<ArrayBufferObject>();
|
||||
|
||||
// Fix up possible inline data pointer.
|
||||
const size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&ArrayBufferObject::class_);
|
||||
if (src.dataPointer() == src.fixedData(reservedSlots))
|
||||
|
|
|
@ -160,7 +160,7 @@ class ArrayBufferObject : public JSObject
|
|||
|
||||
static void sweep(JSCompartment *rt);
|
||||
|
||||
static void fixupDataPointerAfterMovingGC(const ArrayBufferObject &src, ArrayBufferObject &dst);
|
||||
static void objectMoved(JSObject *obj, const JSObject *old);
|
||||
|
||||
static void resetArrayBufferList(JSCompartment *rt);
|
||||
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
|
||||
|
|
|
@ -134,6 +134,16 @@ TypedArrayObject::dataOffset()
|
|||
return JSObject::getPrivateDataOffset(DATA_SLOT);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
TypedArrayObject::ObjectMoved(JSObject *obj, const JSObject *old)
|
||||
{
|
||||
const TypedArrayObject &src = old->as<TypedArrayObject>();
|
||||
if (!src.hasBuffer()) {
|
||||
JS_ASSERT(old->getPrivate() == old->fixedData(FIXED_DATA_START));
|
||||
obj->setPrivate(obj->fixedData(FIXED_DATA_START));
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper clamped uint8_t type */
|
||||
|
||||
uint32_t JS_FASTCALL
|
||||
|
@ -2222,7 +2232,15 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
|||
nullptr, /* hasInstance */ \
|
||||
nullptr, /* construct */ \
|
||||
ArrayBufferViewObject::trace, /* trace */ \
|
||||
TYPED_ARRAY_CLASS_SPEC(_typedArray) \
|
||||
TYPED_ARRAY_CLASS_SPEC(_typedArray), \
|
||||
{ \
|
||||
nullptr, /* outerObject */ \
|
||||
nullptr, /* innerObject */ \
|
||||
nullptr, /* iteratorObject */ \
|
||||
false, /* isWrappedNative */ \
|
||||
nullptr, /* weakmapKeyDelegateOp */ \
|
||||
TypedArrayObject::ObjectMoved \
|
||||
} \
|
||||
}
|
||||
|
||||
template<typename NativeType>
|
||||
|
|
|
@ -125,6 +125,8 @@ class TypedArrayObject : public ArrayBufferViewObject
|
|||
static int dataOffset();
|
||||
|
||||
static bool isOriginalLengthGetter(Scalar::Type type, Native native);
|
||||
|
||||
static void ObjectMoved(JSObject *obj, const JSObject *old);
|
||||
};
|
||||
|
||||
inline bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче