зеркало из https://github.com/mozilla/gecko-dev.git
Bug 773049 - Implement the Value interface in MutableHandle<Value> and Rooted<Value> (in addition to Handle<Value> and EncapsulatedValue which already manually implemented it), consolidating the Value interface bits in ValueOperations and MutableValueOperations classes using CRTP. r=bhackett
--HG-- extra : rebase_source : 436385599a7f071792c2d14037e1a1c639427c4f
This commit is contained in:
Родитель
3d9aec9dc1
Коммит
d63f0497f0
|
@ -303,7 +303,7 @@ struct HeapPtrHasher
|
|||
template <class T>
|
||||
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
|
||||
|
||||
class EncapsulatedValue
|
||||
class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
|
||||
{
|
||||
protected:
|
||||
Value value;
|
||||
|
@ -328,44 +328,20 @@ class EncapsulatedValue
|
|||
Value *unsafeGet() { return &value; }
|
||||
operator const Value &() const { return value; }
|
||||
|
||||
bool isUndefined() const { return value.isUndefined(); }
|
||||
bool isNull() const { return value.isNull(); }
|
||||
bool isBoolean() const { return value.isBoolean(); }
|
||||
bool isTrue() const { return value.isTrue(); }
|
||||
bool isFalse() const { return value.isFalse(); }
|
||||
bool isNumber() const { return value.isNumber(); }
|
||||
bool isInt32() const { return value.isInt32(); }
|
||||
bool isDouble() const { return value.isDouble(); }
|
||||
bool isString() const { return value.isString(); }
|
||||
bool isObject() const { return value.isObject(); }
|
||||
bool isMagic() const { return value.isMagic(); }
|
||||
bool isMagic(JSWhyMagic why) const { return value.isMagic(why); }
|
||||
bool isGCThing() const { return value.isGCThing(); }
|
||||
bool isMarkable() const { return value.isMarkable(); }
|
||||
|
||||
bool toBoolean() const { return value.toBoolean(); }
|
||||
double toNumber() const { return value.toNumber(); }
|
||||
int32_t toInt32() const { return value.toInt32(); }
|
||||
double toDouble() const { return value.toDouble(); }
|
||||
JSString *toString() const { return value.toString(); }
|
||||
JSObject &toObject() const { return value.toObject(); }
|
||||
JSObject *toObjectOrNull() const { return value.toObjectOrNull(); }
|
||||
void *toGCThing() const { return value.toGCThing(); }
|
||||
|
||||
JSGCTraceKind gcKind() const { return value.gcKind(); }
|
||||
|
||||
uint64_t asRawBits() const { return value.asRawBits(); }
|
||||
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic whyMagic() const { return value.whyMagic(); }
|
||||
#endif
|
||||
|
||||
static inline void writeBarrierPre(const Value &v);
|
||||
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
||||
|
||||
protected:
|
||||
inline void pre();
|
||||
inline void pre(JSCompartment *comp);
|
||||
|
||||
private:
|
||||
friend class ValueOperations<EncapsulatedValue>;
|
||||
const Value * extract() const { return &value; }
|
||||
};
|
||||
|
||||
class HeapValue : public EncapsulatedValue
|
||||
|
|
|
@ -79,13 +79,19 @@ struct NullPtr
|
|||
static void * const constNullValue;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class HandleBase {};
|
||||
|
||||
/*
|
||||
* Reference to a T that has been rooted elsewhere. This is most useful
|
||||
* as a parameter type, which guarantees that the T lvalue is properly
|
||||
* rooted. See "Move GC Stack Rooting" above.
|
||||
*
|
||||
* If you want to add additional methods to Handle for a specific
|
||||
* specialization, define a HandleBase<T> specialization containing them.
|
||||
*/
|
||||
template <typename T>
|
||||
class Handle
|
||||
class Handle : public HandleBase<T>
|
||||
{
|
||||
public:
|
||||
/* Creates a handle from a handle of a type convertible to T. */
|
||||
|
@ -139,10 +145,6 @@ class Handle
|
|||
void operator =(S v) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/* Defined in jsapi.h under Value definition */
|
||||
template <>
|
||||
class Handle<Value>;
|
||||
|
||||
typedef Handle<JSObject*> HandleObject;
|
||||
typedef Handle<JSFunction*> HandleFunction;
|
||||
typedef Handle<JSScript*> HandleScript;
|
||||
|
@ -150,12 +152,19 @@ typedef Handle<JSString*> HandleString;
|
|||
typedef Handle<jsid> HandleId;
|
||||
typedef Handle<Value> HandleValue;
|
||||
|
||||
template <typename T>
|
||||
class MutableHandleBase {};
|
||||
|
||||
/*
|
||||
* Similar to a handle, but the underlying storage can be changed. This is
|
||||
* useful for outparams.
|
||||
*
|
||||
* If you want to add additional methods to MutableHandle for a specific
|
||||
* specialization, define a MutableHandleBase<T> specialization containing
|
||||
* them.
|
||||
*/
|
||||
template <typename T>
|
||||
class MutableHandle
|
||||
class MutableHandle : public MutableHandleBase<T>
|
||||
{
|
||||
public:
|
||||
template <typename S>
|
||||
|
@ -199,13 +208,20 @@ struct RootMethods<T *>
|
|||
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class RootedBase {};
|
||||
|
||||
/*
|
||||
* Local variable of type T whose value is always rooted. This is typically
|
||||
* used for local variables, or for non-rooted values being passed to a
|
||||
* function that requires a handle, e.g. Foo(Root<T>(cx, x)).
|
||||
*
|
||||
* If you want to add additional methods to MutableHandle for a specific
|
||||
* specialization, define a MutableHandleBase<T> specialization containing
|
||||
* them.
|
||||
*/
|
||||
template <typename T>
|
||||
class Rooted
|
||||
class Rooted : public RootedBase<T>
|
||||
{
|
||||
void init(JSContext *cx_)
|
||||
{
|
||||
|
|
190
js/src/jsapi.h
190
js/src/jsapi.h
|
@ -614,75 +614,6 @@ IsPoisonedValue(const Value &v)
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
/* This is a specialization of the general Handle template in gc/Root.h */
|
||||
template <>
|
||||
class Handle<Value>
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Construct a handle from an explicitly rooted location. This is the
|
||||
* normal way to create a handle, and normally happens implicitly.
|
||||
*/
|
||||
inline Handle(Rooted<Value> &root) {
|
||||
ptr = root.address();
|
||||
}
|
||||
|
||||
/*
|
||||
* This may be called only if the location of the T is guaranteed
|
||||
* to be marked (for some reason other than being a Rooted),
|
||||
* e.g., if it is guaranteed to be reachable from an implicit root.
|
||||
*
|
||||
* Create a Handle from a raw location of a T.
|
||||
*/
|
||||
static Handle fromMarkedLocation(const Value *p) {
|
||||
Handle h;
|
||||
h.ptr = p;
|
||||
return h;
|
||||
}
|
||||
|
||||
const Value *address() const { return ptr; }
|
||||
const Value &get() const { return *ptr; }
|
||||
operator const Value &() const { return *ptr; }
|
||||
|
||||
bool operator==(const Handle &h) const { return *ptr == *h.ptr; }
|
||||
bool operator!=(const Handle &h) const { return *ptr != *h.ptr; }
|
||||
|
||||
bool isUndefined() const { return ptr->isUndefined(); }
|
||||
bool isNull() const { return ptr->isNull(); }
|
||||
bool isBoolean() const { return ptr->isBoolean(); }
|
||||
bool isTrue() const { return ptr->isTrue(); }
|
||||
bool isFalse() const { return ptr->isFalse(); }
|
||||
bool isNumber() const { return ptr->isNumber(); }
|
||||
bool isInt32() const { return ptr->isInt32(); }
|
||||
bool isDouble() const { return ptr->isDouble(); }
|
||||
bool isString() const { return ptr->isString(); }
|
||||
bool isObject() const { return ptr->isObject(); }
|
||||
bool isMagic() const { return ptr->isMagic(); }
|
||||
bool isMagic(JSWhyMagic why) const { return ptr->isMagic(why); }
|
||||
bool isGCThing() const { return ptr->isGCThing(); }
|
||||
bool isMarkable() const { return ptr->isMarkable(); }
|
||||
|
||||
bool toBoolean() const { return ptr->toBoolean(); }
|
||||
double toNumber() const { return ptr->toNumber(); }
|
||||
int32_t toInt32() const { return ptr->toInt32(); }
|
||||
double toDouble() const { return ptr->toDouble(); }
|
||||
JSString *toString() const { return ptr->toString(); }
|
||||
JSObject &toObject() const { return ptr->toObject(); }
|
||||
JSObject *toObjectOrNull() const { return ptr->toObjectOrNull(); }
|
||||
void *toGCThing() const { return ptr->toGCThing(); }
|
||||
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic whyMagic() const { return ptr->whyMagic(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
Handle() {}
|
||||
|
||||
const Value *ptr;
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NullValue()
|
||||
{
|
||||
|
@ -883,6 +814,8 @@ SameType(const Value &lhs, const Value &rhs)
|
|||
return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
template <> struct RootMethods<const Value>
|
||||
{
|
||||
static Value initial() { return UndefinedValue(); }
|
||||
|
@ -897,6 +830,125 @@ template <> struct RootMethods<Value>
|
|||
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
|
||||
};
|
||||
|
||||
template <class Outer> class MutableValueOperations;
|
||||
|
||||
/*
|
||||
* A class designed for CRTP use in implementing the non-mutating parts of the
|
||||
* Value interface in Value-like classes. Outer must be a class inheriting
|
||||
* ValueOperations<Outer> with a visible extract() method returning the
|
||||
* const Value* abstracted by Outer.
|
||||
*/
|
||||
template <class Outer>
|
||||
class ValueOperations
|
||||
{
|
||||
friend class MutableValueOperations<Outer>;
|
||||
const Value * value() const { return static_cast<const Outer*>(this)->extract(); }
|
||||
|
||||
public:
|
||||
bool isUndefined() const { return value()->isUndefined(); }
|
||||
bool isNull() const { return value()->isNull(); }
|
||||
bool isBoolean() const { return value()->isBoolean(); }
|
||||
bool isTrue() const { return value()->isTrue(); }
|
||||
bool isFalse() const { return value()->isFalse(); }
|
||||
bool isNumber() const { return value()->isNumber(); }
|
||||
bool isInt32() const { return value()->isInt32(); }
|
||||
bool isDouble() const { return value()->isDouble(); }
|
||||
bool isString() const { return value()->isString(); }
|
||||
bool isObject() const { return value()->isObject(); }
|
||||
bool isMagic() const { return value()->isMagic(); }
|
||||
bool isMagic(JSWhyMagic why) const { return value()->isMagic(why); }
|
||||
bool isMarkable() const { return value()->isMarkable(); }
|
||||
bool isPrimitive() const { return value()->isPrimitive(); }
|
||||
|
||||
bool toBoolean() const { return value()->toBoolean(); }
|
||||
double toNumber() const { return value()->toNumber(); }
|
||||
int32_t toInt32() const { return value()->toInt32(); }
|
||||
double toDouble() const { return value()->toDouble(); }
|
||||
JSString *toString() const { return value()->toString(); }
|
||||
JSObject &toObject() const { return value()->toObject(); }
|
||||
JSObject *toObjectOrNull() const { return value()->toObjectOrNull(); }
|
||||
void *toGCThing() const { return value()->toGCThing(); }
|
||||
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic whyMagic() const { return value()->whyMagic(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* A class designed for CRTP use in implementing the mutating parts of the
|
||||
* Value interface in Value-like classes. Outer must be a class inheriting
|
||||
* MutableValueOperations<Outer> with visible extractMutable() and extract()
|
||||
* methods returning the const Value* and Value* abstracted by Outer.
|
||||
*/
|
||||
template <class Outer>
|
||||
class MutableValueOperations : public ValueOperations<Outer>
|
||||
{
|
||||
Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
|
||||
|
||||
public:
|
||||
void setNull() { value()->setNull(); }
|
||||
void setUndefined() { value()->setUndefined(); }
|
||||
void setInt32(int32_t i) { value()->setInt32(i); }
|
||||
void setDouble(double d) { value()->setDouble(d); }
|
||||
void setString(JSString *str) { value()->setString(str); }
|
||||
void setString(const JS::Anchor<JSString *> &str) { value()->setString(str); }
|
||||
void setObject(JSObject &obj) { value()->setObject(obj); }
|
||||
void setBoolean(bool b) { value()->setBoolean(b); }
|
||||
void setMagic(JSWhyMagic why) { value()->setMagic(why); }
|
||||
bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
|
||||
bool setNumber(double d) { return value()->setNumber(d); }
|
||||
void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(); }
|
||||
};
|
||||
|
||||
/*
|
||||
* Augment the generic Handle<T> interface when T = Value with type-querying
|
||||
* and value-extracting operations.
|
||||
*/
|
||||
template <>
|
||||
class HandleBase<Value> : public ValueOperations<Handle<Value> >
|
||||
{
|
||||
friend class ValueOperations<Handle<Value> >;
|
||||
const Value * extract() const {
|
||||
return static_cast<const Handle<Value>*>(this)->address();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Augment the generic MutableHandle<T> interface when T = Value with
|
||||
* type-querying, value-extracting, and mutating operations.
|
||||
*/
|
||||
template <>
|
||||
class MutableHandleBase<Value> : public MutableValueOperations<MutableHandle<Value> >
|
||||
{
|
||||
friend class ValueOperations<Handle<Value> >;
|
||||
const Value * extract() const {
|
||||
return static_cast<const MutableHandle<Value>*>(this)->address();
|
||||
}
|
||||
|
||||
friend class MutableValueOperations<Handle<Value> >;
|
||||
Value * extractMutable() {
|
||||
return static_cast<MutableHandle<Value>*>(this)->address();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Augment the generic Rooted<T> interface when T = Value with type-querying,
|
||||
* value-extracting, and mutating operations.
|
||||
*/
|
||||
template <>
|
||||
class RootedBase<Value> : public MutableValueOperations<Rooted<Value> >
|
||||
{
|
||||
friend class ValueOperations<Rooted<Value> >;
|
||||
const Value * extract() const {
|
||||
return static_cast<const Rooted<Value>*>(this)->address();
|
||||
}
|
||||
|
||||
friend class MutableValueOperations<Handle<Value> >;
|
||||
Value * extractMutable() {
|
||||
return static_cast<Rooted<Value>*>(this)->address();
|
||||
}
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
|
Загрузка…
Ссылка в новой задаче