Bug 1268805 - Implement PrivateGCThingValue. (r=terrence)

This commit is contained in:
Shu-yu Guo 2016-04-29 15:12:13 -07:00
Родитель f820965675
Коммит e841ff15ad
17 изменённых файлов: 234 добавлений и 57 удалений

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

@ -394,6 +394,9 @@ GCThingIsMarkedGray(GCCellPtr thing)
return js::gc::detail::CellIsMarkedGray(thing.asCell());
}
extern JS_PUBLIC_API(JS::TraceKind)
GCThingTraceKind(js::gc::Cell* thing);
} /* namespace JS */
namespace js {

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

@ -76,8 +76,9 @@ JS_ENUM_HEADER(JSValueType, uint8_t)
JSVAL_TYPE_MAGIC = 0x04,
JSVAL_TYPE_STRING = 0x05,
JSVAL_TYPE_SYMBOL = 0x06,
JSVAL_TYPE_NULL = 0x07,
JSVAL_TYPE_OBJECT = 0x08,
JSVAL_TYPE_PRIVATE_GCTHING = 0x07,
JSVAL_TYPE_NULL = 0x08,
JSVAL_TYPE_OBJECT = 0x0c,
/* These never appear in a jsval; they are only provided as an out-of-band value. */
JSVAL_TYPE_UNKNOWN = 0x20,
@ -100,7 +101,8 @@ JS_ENUM_HEADER(JSValueTag, uint32_t)
JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT,
JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
@ -119,7 +121,8 @@ JS_ENUM_HEADER(JSValueTag, uint32_t)
JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT,
JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
@ -127,15 +130,16 @@ static_assert(sizeof(JSValueTag) == sizeof(uint32_t),
JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
{
JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_SYMBOL = (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (((uint64_t)JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT)
} JS_ENUM_FOOTER(JSValueShiftedTag);
static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t),
@ -163,8 +167,9 @@ typedef uint8_t JSValueType;
#define JSVAL_TYPE_MAGIC ((uint8_t)0x04)
#define JSVAL_TYPE_STRING ((uint8_t)0x05)
#define JSVAL_TYPE_SYMBOL ((uint8_t)0x06)
#define JSVAL_TYPE_NULL ((uint8_t)0x07)
#define JSVAL_TYPE_OBJECT ((uint8_t)0x08)
#define JSVAL_TYPE_PRIVATE_GCTHING ((uint8_t)0x07)
#define JSVAL_TYPE_NULL ((uint8_t)0x08)
#define JSVAL_TYPE_OBJECT ((uint8_t)0x0c)
#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20)
#if defined(JS_NUNBOX32)
@ -179,6 +184,7 @@ typedef uint32_t JSValueTag;
#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
#define JSVAL_TAG_PRIVATE_GCTHING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING))
#elif defined(JS_PUNBOX64)
@ -192,17 +198,19 @@ typedef uint32_t JSValueTag;
#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
#define JSVAL_TAG_PRIVATE_GCTHING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING)
typedef uint64_t JSValueShiftedTag;
#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_SYMBOL (((uint64_t)JSVAL_TAG_SYMBOL) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_PRIVATE_GCTHING (((uint64_t)JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT)
#endif /* JS_PUNBOX64 */
#endif /* !defined(__SUNPRO_CC) && !defined(__xlC__) */
@ -632,6 +640,29 @@ JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
return l.s.payload.ptr;
}
static inline jsval_layout
PRIVATE_GCTHING_TO_JSVAL_IMPL(js::gc::Cell* cell)
{
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::String,
"Private GC thing Values must not be strings. Make a StringValue instead.");
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Symbol,
"Private GC thing Values must not be symbols. Make a SymbolValue instead.");
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Object,
"Private GC thing Values must not be objects. Make an ObjectValue instead.");
jsval_layout l;
MOZ_ASSERT(uintptr_t(cell) > 0x1000);
l.s.tag = JSVAL_TAG_PRIVATE_GCTHING;
l.s.payload.cell = ptr;
return l;
}
static inline bool
JSVAL_IS_PRIVATE_GCTHING_IMPL(jsval_layout l)
{
return l.s.tag == JSVAL_TAG_PRIVATE_GCTHING;
}
static inline bool
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
{
@ -654,6 +685,8 @@ JSVAL_TRACE_KIND_IMPL(jsval_layout l)
"Value type tags must correspond with JS::TraceKinds.");
static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
"Value type tags must correspond with JS::TraceKinds.");
if (MOZ_UNLIKELY(JSVAL_IS_PRIVATE_GCTHING_IMPL(l)))
return (uint32_t)JS::GCThingTraceKind(JSVAL_TO_GCTHING_IMPL(l));
return l.s.tag & 0x03;
}
@ -872,6 +905,12 @@ JSVAL_IS_NULL_IMPL(jsval_layout l)
return l.asBits == JSVAL_SHIFTED_TAG_NULL;
}
static inline bool
JSVAL_IS_PRIVATE_GCTHING_IMPL(jsval_layout l)
{
return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_PRIVATE_GCTHING;
}
static inline bool
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
{
@ -895,6 +934,8 @@ JSVAL_TRACE_KIND_IMPL(jsval_layout l)
"Value type tags must correspond with JS::TraceKinds.");
static_assert((JSVAL_TAG_OBJECT & 0x03) == size_t(JS::TraceKind::Object),
"Value type tags must correspond with JS::TraceKinds.");
if (MOZ_UNLIKELY(JSVAL_IS_PRIVATE_GCTHING_IMPL(l)))
return (uint32_t)JS::GCThingTraceKind(JSVAL_TO_GCTHING_IMPL(l));
return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) & 0x03;
}
@ -916,6 +957,24 @@ JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
return (void*)(l.asBits << 1);
}
static inline jsval_layout
PRIVATE_GCTHING_TO_JSVAL_IMPL(js::gc::Cell* cell)
{
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::String,
"Private GC thing Values must not be strings. Make a StringValue instead.");
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Symbol,
"Private GC thing Values must not be symbols. Make a SymbolValue instead.");
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Object,
"Private GC thing Values must not be objects. Make an ObjectValue instead.");
jsval_layout l;
uint64_t cellBits = (uint64_t)cell;
MOZ_ASSERT(uintptr_t(cellBits) > 0x1000);
MOZ_ASSERT((cellBits >> JSVAL_TAG_SHIFT) == 0);
l.asBits = cellBits | JSVAL_SHIFTED_TAG_PRIVATE_GCTHING;
return l;
}
static inline bool
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
{
@ -1341,6 +1400,23 @@ class Value
return uint32_t(toInt32());
}
/*
* Private GC Thing API
*
* Non-JSObject, JSString, and JS::Symbol cells may be put into the 64-bit
* payload as private GC things. Such Values are considered isMarkable()
* and isGCThing(), and as such, automatically marked. Their traceKind()
* is gotten via their cells.
*/
void setPrivateGCThing(js::gc::Cell* cell) {
data = PRIVATE_GCTHING_TO_JSVAL_IMPL(cell);
}
bool isPrivateGCThing() const {
return JSVAL_IS_PRIVATE_GCTHING_IMPL(data);
}
/*
* An unmarked value is just a void* cast as a Value. Thus, the Value is
* not safe for GC and must not be marked. This API avoids raw casts
@ -1683,6 +1759,14 @@ PrivateUint32Value(uint32_t ui)
return v;
}
static inline Value
PrivateGCThingValue(js::gc::Cell* cell)
{
Value v;
v.setPrivateGCThing(cell);
return v;
}
inline bool
SameType(const Value& lhs, const Value& rhs)
{
@ -1801,6 +1885,7 @@ class MutableValueOperations : public ValueOperations<Outer>
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
void setPrivateGCThing(js::gc::Cell* cell) { this->value().setPrivateGCThing(cell); }
};
/*
@ -1829,6 +1914,7 @@ class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
void setString(JSString* str) { setBarriered(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { setBarriered(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { setBarriered(JS::ObjectValue(obj)); }
void setPrivateGCThing(js::gc::Cell* cell) { setBarriered(JS::PrivateGCThingValue(cell)); }
bool setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
@ -1890,6 +1976,8 @@ DispatchTyped(F f, const JS::Value& val, Args&&... args)
return f(&val.toObject(), mozilla::Forward<Args>(args)...);
if (val.isSymbol())
return f(val.toSymbol(), mozilla::Forward<Args>(args)...);
if (MOZ_UNLIKELY(val.isPrivateGCThing()))
return DispatchTyped(f, val.toGCCellPtr(), mozilla::Forward<Args>(args)...);
MOZ_ASSERT(!val.isMarkable());
return F::defaultValue(val);
}

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

@ -80,9 +80,13 @@ ReadBarrierFunctor<S>::operator()(T* t)
{
InternalBarrierMethods<T*>::readBarrier(t);
}
template void ReadBarrierFunctor<JS::Value>::operator()<JS::Symbol>(JS::Symbol*);
template void ReadBarrierFunctor<JS::Value>::operator()<JSObject>(JSObject*);
template void ReadBarrierFunctor<JS::Value>::operator()<JSString>(JSString*);
// All GC things may be held in a Value, either publicly or as a private GC
// thing.
#define JS_EXPAND_DEF(name, type, _) \
template void ReadBarrierFunctor<JS::Value>::operator()<type>(type*);
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
template <typename S>
template <typename T>
@ -91,9 +95,14 @@ PreBarrierFunctor<S>::operator()(T* t)
{
InternalBarrierMethods<T*>::preBarrier(t);
}
template void PreBarrierFunctor<JS::Value>::operator()<JS::Symbol>(JS::Symbol*);
template void PreBarrierFunctor<JS::Value>::operator()<JSObject>(JSObject*);
template void PreBarrierFunctor<JS::Value>::operator()<JSString>(JSString*);
// All GC things may be held in a Value, either publicly or as a private GC
// thing.
#define JS_EXPAND_DEF(name, type, _) \
template void PreBarrierFunctor<JS::Value>::operator()<type>(type*);
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
template void PreBarrierFunctor<jsid>::operator()<JS::Symbol>(JS::Symbol*);
template void PreBarrierFunctor<jsid>::operator()<JSString>(JSString*);

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

@ -261,7 +261,7 @@ struct InternalBarrierMethods<T*>
static void readBarrier(T* v) { T::readBarrier(v); }
};
template <typename S> struct PreBarrierFunctor : VoidDefaultAdaptor<S> {
template <typename S> struct PreBarrierFunctor : public VoidDefaultAdaptor<S> {
template <typename T> void operator()(T* t);
};

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

@ -2021,7 +2021,7 @@ template <typename S>
struct TenuringTraversalFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, TenuringTracer* trc) {
trc->traverse(&t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
return js::gc::RewrapTaggedPointer<S, T>::wrap(t);
}
};
@ -2427,7 +2427,7 @@ template <typename S>
struct IsMarkedFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, bool* rv) {
*rv = IsMarkedInternal(&t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
return js::gc::RewrapTaggedPointer<S, T>::wrap(t);
}
};
@ -2486,7 +2486,7 @@ template <typename S>
struct IsAboutToBeFinalizedFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, bool* rv) {
*rv = IsAboutToBeFinalizedInternal(&t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
return js::gc::RewrapTaggedPointer<S, T>::wrap(t);
}
};

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

@ -420,14 +420,34 @@ template <typename S, typename T>
struct RewrapTaggedPointer{};
#define DECLARE_REWRAP(S, T, method, prefix) \
template <> struct RewrapTaggedPointer<S, T> { \
static S wrap(T thing) { return method ( prefix thing ); } \
static S wrap(T* thing) { return method ( prefix thing ); } \
}
DECLARE_REWRAP(JS::Value, JSObject*, JS::ObjectOrNullValue, );
DECLARE_REWRAP(JS::Value, JSString*, JS::StringValue, );
DECLARE_REWRAP(JS::Value, JS::Symbol*, JS::SymbolValue, );
DECLARE_REWRAP(jsid, JSString*, NON_INTEGER_ATOM_TO_JSID, (JSAtom*));
DECLARE_REWRAP(jsid, JS::Symbol*, SYMBOL_TO_JSID, );
DECLARE_REWRAP(js::TaggedProto, JSObject*, js::TaggedProto, );
DECLARE_REWRAP(JS::Value, JSObject, JS::ObjectOrNullValue, );
DECLARE_REWRAP(JS::Value, JSString, JS::StringValue, );
DECLARE_REWRAP(JS::Value, JS::Symbol, JS::SymbolValue, );
DECLARE_REWRAP(jsid, JSString, NON_INTEGER_ATOM_TO_JSID, (JSAtom*));
DECLARE_REWRAP(jsid, JS::Symbol, SYMBOL_TO_JSID, );
DECLARE_REWRAP(js::TaggedProto, JSObject, js::TaggedProto, );
#undef DECLARE_REWRAP
template <typename T>
struct IsPrivateGCThingInValue
: public mozilla::EnableIf<mozilla::IsBaseOf<Cell, T>::value &&
!mozilla::IsBaseOf<JSObject, T>::value &&
!mozilla::IsBaseOf<JSString, T>::value &&
!mozilla::IsBaseOf<JS::Symbol, T>::value, T>
{
static_assert(!mozilla::IsSame<Cell, T>::value && !mozilla::IsSame<TenuredCell, T>::value,
"T must not be Cell or TenuredCell");
};
template <typename T>
struct RewrapTaggedPointer<Value, T>
{
static Value wrap(typename IsPrivateGCThingInValue<T>::Type* thing) {
return JS::PrivateGCThingValue(thing);
}
};
} /* namespace gc */

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

@ -59,7 +59,7 @@ JS_FOR_EACH_TRACEKIND(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
template <typename S>
struct DoCallbackFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, JS::CallbackTracer* trc, const char* name) {
return js::gc::RewrapTaggedPointer<S, T*>::wrap(DoCallback(trc, &t, name));
return js::gc::RewrapTaggedPointer<S, T>::wrap(DoCallback(trc, &t, name));
}
};

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

@ -733,7 +733,7 @@ class ICGetElemNativeCompiler : public ICStubCompiler
protected:
virtual int32_t getKey() const {
MOZ_ASSERT(static_cast<int32_t>(acctype_) <= 7);
MOZ_ASSERT(static_cast<int32_t>(unboxedType_) <= 8);
MOZ_ASSERT(static_cast<int32_t>(unboxedType_) <= 15);
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(needsAtomize_) << 17) |

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

@ -68,6 +68,7 @@ UNIFIED_SOURCES += [
'testParseJSON.cpp',
'testPersistentRooted.cpp',
'testPreserveJitCode.cpp',
'testPrivateGCThingValue.cpp',
'testProfileStrings.cpp',
'testPropCache.cpp',
'testRegExp.cpp',

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

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsapi.h"
#include "js/HeapAPI.h"
#include "jsapi-tests/tests.h"
class TestTracer : public JS::CallbackTracer
{
void onChild(const JS::GCCellPtr& thing) override {
if (thing.asCell() == expectedCell && thing.kind() == expectedKind)
found = true;
}
public:
js::gc::Cell* expectedCell;
JS::TraceKind expectedKind;
bool found;
explicit TestTracer(JSContext* cx)
: JS::CallbackTracer(JS_GetRuntime(cx)),
found(false)
{ }
};
static const JSClass TestClass = {
"TestClass",
JSCLASS_HAS_RESERVED_SLOTS(1)
};
BEGIN_TEST(testPrivateGCThingValue)
{
JS::RootedObject obj(cx, JS_NewObject(cx, &TestClass));
CHECK(obj);
// Make a JSScript to stick into a PrivateGCThingValue.
JS::RootedScript script(cx);
const char code[] = "'objet petit a'";
JS::CompileOptions options(cx);
options.setFileAndLine(__FILE__, __LINE__);
CHECK(JS_CompileScript(cx, code, sizeof(code) - 1, options, &script));
JS_SetReservedSlot(obj, 0, PrivateGCThingValue(script));
TestTracer trc(cx);
trc.expectedCell = script;
trc.expectedKind = JS::TraceKind::Script;
JS::TraceChildren(&trc, JS::GCCellPtr(obj, JS::TraceKind::Object));
CHECK(trc.found);
return true;
}
END_TEST(testPrivateGCThingValue)

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

@ -6542,3 +6542,10 @@ JS::GetObjectZone(JSObject* obj)
{
return obj->zone();
}
JS_PUBLIC_API(JS::TraceKind)
JS::GCThingTraceKind(js::gc::Cell* thing)
{
MOZ_ASSERT(thing);
return thing->getTraceKind();
}

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

@ -581,13 +581,6 @@ js::ZoneGlobalsAreAllGray(JS::Zone* zone)
return true;
}
JS_FRIEND_API(JS::TraceKind)
js::GCThingTraceKind(void* thing)
{
MOZ_ASSERT(thing);
return static_cast<js::gc::Cell*>(thing)->getTraceKind();
}
JS_FRIEND_API(void)
js::VisitGrayWrapperTargets(Zone* zone, GCThingCallback callback, void* closure)
{

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

@ -507,9 +507,6 @@ VisitGrayWrapperTargets(JS::Zone* zone, GCThingCallback callback, void* closure)
extern JS_FRIEND_API(JSObject*)
GetWeakmapKeyDelegate(JSObject* key);
JS_FRIEND_API(JS::TraceKind)
GCThingTraceKind(void* thing);
/**
* Invoke cellCallback on every gray JS_OBJECT in the given zone.
*/

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

@ -7417,6 +7417,8 @@ JS::GCCellPtr::GCCellPtr(const Value& v)
ptr = checkedCast(&v.toObject(), JS::TraceKind::Object);
else if (v.isSymbol())
ptr = checkedCast(v.toSymbol(), JS::TraceKind::Symbol);
else if (v.isPrivateGCThing())
ptr = checkedCast(v.toGCThing(), v.toGCThing()->getTraceKind());
else
ptr = checkedCast(nullptr, JS::TraceKind::Null);
}

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

@ -1145,7 +1145,7 @@ Forwarded(T* t)
struct ForwardedFunctor : public IdentityDefaultAdaptor<Value> {
template <typename T> inline Value operator()(T* t) {
return js::gc::RewrapTaggedPointer<Value, T*>::wrap(Forwarded(t));
return js::gc::RewrapTaggedPointer<Value, T>::wrap(Forwarded(t));
}
};

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

@ -299,7 +299,7 @@ JSGCThingParticipant::Traverse(void* aPtr,
reinterpret_cast<char*>(this) - offsetof(CycleCollectedJSRuntime,
mGCThingCycleCollectorGlobal));
JS::GCCellPtr cellPtr(aPtr, js::GCThingTraceKind(aPtr));
JS::GCCellPtr cellPtr(aPtr, JS::GCThingTraceKind(aPtr));
runtime->TraverseGCThing(CycleCollectedJSRuntime::TRAVERSE_FULL, cellPtr, aCb);
return NS_OK;
}

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

@ -3076,7 +3076,7 @@ nsCycleCollector::ScanIncrementalRoots()
// If the object is still marked gray by the GC, nothing could have gotten
// hold of it, so it isn't an incremental root.
if (pi->mParticipant == jsParticipant) {
JS::GCCellPtr ptr(pi->mPointer, js::GCThingTraceKind(pi->mPointer));
JS::GCCellPtr ptr(pi->mPointer, JS::GCThingTraceKind(pi->mPointer));
if (GCThingIsGrayCCThing(ptr)) {
continue;
}
@ -3291,7 +3291,7 @@ nsCycleCollector::CollectWhite()
++numWhiteJSZones;
zone = static_cast<JS::Zone*>(pinfo->mPointer);
} else {
JS::GCCellPtr ptr(pinfo->mPointer, js::GCThingTraceKind(pinfo->mPointer));
JS::GCCellPtr ptr(pinfo->mPointer, JS::GCThingTraceKind(pinfo->mPointer));
zone = JS::GetTenuredGCThingZone(ptr);
}
mJSRuntime->AddZoneWaitingForGC(zone);