Bug 645416, part 21 - Add symbol jsids (SYMBOL_TO_JSID), removing the legacy support for object jsids (OBJECT_TO_JSID). r=terrence,r=jimb,r=efaust.

With just this patch, there are not actually any symbol jsids flowing through
the system, just as there are not actually any object jsids. But a subsequent
patch (part 23) changes this.

This patch deletes some code in CTypes.cpp that is simply confused about how
element accesses work: Int64 and UInt64 objects were never actually converted
to object jsids, so the code being removed here was already dead code.

--HG--
extra : rebase_source : 86f421c6454344e76ce5219b7b1aed5c83b45f24
This commit is contained in:
Jason Orendorff 2014-06-23 10:56:52 -05:00
Родитель fa961606bb
Коммит edb4532fbf
16 изменённых файлов: 101 добавлений и 131 удалений

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

@ -40,7 +40,7 @@ struct jsid
#define JSID_TYPE_STRING 0x0
#define JSID_TYPE_INT 0x1
#define JSID_TYPE_VOID 0x2
#define JSID_TYPE_OBJECT 0x4
#define JSID_TYPE_SYMBOL 0x4
#define JSID_TYPE_MASK 0x7
// Avoid using canonical 'id' for jsid parameters since this is a magic word in
@ -98,34 +98,35 @@ INT_TO_JSID(int32_t i)
}
static MOZ_ALWAYS_INLINE bool
JSID_IS_OBJECT(jsid id)
JSID_IS_SYMBOL(jsid id)
{
return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT &&
(size_t)JSID_BITS(id) != JSID_TYPE_OBJECT;
return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_SYMBOL &&
JSID_BITS(id) != JSID_TYPE_SYMBOL;
}
static MOZ_ALWAYS_INLINE JSObject *
JSID_TO_OBJECT(jsid id)
static MOZ_ALWAYS_INLINE JS::Symbol *
JSID_TO_SYMBOL(jsid id)
{
MOZ_ASSERT(JSID_IS_OBJECT(id));
return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
MOZ_ASSERT(JSID_IS_SYMBOL(id));
return (JS::Symbol *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
}
static MOZ_ALWAYS_INLINE jsid
OBJECT_TO_JSID(JSObject *obj)
SYMBOL_TO_JSID(JS::Symbol *sym)
{
jsid id;
MOZ_ASSERT(obj != nullptr);
MOZ_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
JS_ASSERT(!js::gc::IsInsideNursery(JS::AsCell(obj)));
JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT);
MOZ_ASSERT(sym != nullptr);
MOZ_ASSERT((size_t(sym) & JSID_TYPE_MASK) == 0);
JS_ASSERT(!js::gc::IsInsideNursery(JS::AsCell(sym)));
JS_ASSERT(!JS::IsPoisonedPtr(sym));
JSID_BITS(id) = (size_t(sym) | JSID_TYPE_SYMBOL);
return id;
}
static MOZ_ALWAYS_INLINE bool
JSID_IS_GCTHING(jsid id)
{
return JSID_IS_STRING(id) || JSID_IS_OBJECT(id);
return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id);
}
static MOZ_ALWAYS_INLINE void *
@ -145,11 +146,9 @@ JSID_IS_VOID(const jsid id)
static MOZ_ALWAYS_INLINE bool
JSID_IS_EMPTY(const jsid id)
{
return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT);
return ((size_t)JSID_BITS(id) == JSID_TYPE_SYMBOL);
}
#undef id
extern JS_PUBLIC_DATA(const jsid) JSID_VOID;
extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY;
@ -159,12 +158,12 @@ extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
namespace js {
inline bool
IsPoisonedId(jsid iden)
IsPoisonedId(jsid id)
{
if (JSID_IS_STRING(iden))
return JS::IsPoisonedPtr(JSID_TO_STRING(iden));
if (JSID_IS_OBJECT(iden))
return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden));
if (JSID_IS_STRING(id))
return JS::IsPoisonedPtr(JSID_TO_STRING(id));
if (JSID_IS_SYMBOL(id))
return JS::IsPoisonedPtr(JSID_TO_SYMBOL(id));
return false;
}
@ -179,6 +178,8 @@ template <> struct GCMethods<jsid>
#endif
};
#undef id
}
#endif /* js_Id_h */

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

@ -831,37 +831,43 @@ obj_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, Value *vp)
return GetOwnPropertyDescriptor(cx, obj, id, args.rval());
}
// ES6 draft rev25 (2014/05/22) 19.1.2.14 Object.keys(O)
static bool
obj_keys(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
// steps 1-2
RootedObject obj(cx);
if (!GetFirstArgumentAsObject(cx, args, "Object.keys", &obj))
return false;
// Steps 3-10. Since JSITER_SYMBOLS and JSITER_HIDDEN are not passed,
// GetPropertyNames performs the type check in step 10.c. and the
// [[Enumerable]] check specified in step 10.c.iii.
AutoIdVector props(cx);
if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props))
return false;
AutoValueVector vals(cx);
if (!vals.reserve(props.length()))
AutoValueVector namelist(cx);
if (!namelist.reserve(props.length()))
return false;
for (size_t i = 0, len = props.length(); i < len; i++) {
jsid id = props[i];
JSString *str;
if (JSID_IS_STRING(id)) {
vals.infallibleAppend(StringValue(JSID_TO_STRING(id)));
} else if (JSID_IS_INT(id)) {
JSString *str = Int32ToString<CanGC>(cx, JSID_TO_INT(id));
str = JSID_TO_STRING(id);
} else {
str = Int32ToString<CanGC>(cx, JSID_TO_INT(id));
if (!str)
return false;
vals.infallibleAppend(StringValue(str));
} else {
JS_ASSERT(JSID_IS_OBJECT(id));
}
namelist.infallibleAppend(StringValue(str));
}
// step 11
JS_ASSERT(props.length() <= UINT32_MAX);
JSObject *aobj = NewDenseCopiedArray(cx, uint32_t(vals.length()), vals.begin());
JSObject *aobj = NewDenseCopiedArray(cx, uint32_t(namelist.length()), namelist.begin());
if (!aobj)
return false;
@ -909,7 +915,7 @@ obj_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
} else if (JSID_IS_ATOM(id)) {
vals[i].setString(JSID_TO_STRING(id));
} else {
vals[i].setObject(*JSID_TO_OBJECT(id));
vals[i].setSymbol(JSID_TO_SYMBOL(id));
}
}

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

@ -1873,9 +1873,9 @@ jsvalToSize(JSContext* cx, jsval val, bool allowString, size_t* result)
template<class IntegerType>
static bool
jsidToBigInteger(JSContext* cx,
jsid val,
bool allowString,
IntegerType* result)
jsid val,
bool allowString,
IntegerType* result)
{
JS_STATIC_ASSERT(NumericLimits<IntegerType>::is_exact);
@ -1892,22 +1892,6 @@ jsidToBigInteger(JSContext* cx,
// toString() on the object for us.)
return StringToInteger(cx, JSID_TO_STRING(val), result);
}
if (JSID_IS_OBJECT(val)) {
// Allow conversion from an Int64 or UInt64 object directly.
JSObject* obj = JSID_TO_OBJECT(val);
if (UInt64::IsUInt64(obj)) {
// Make sure the integer fits in IntegerType.
uint64_t i = Int64Base::GetInt(obj);
return ConvertExact(i, result);
}
if (Int64::IsInt64(obj)) {
// Make sure the integer fits in IntegerType.
int64_t i = Int64Base::GetInt(obj);
return ConvertExact(i, result);
}
}
return false;
}

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

@ -181,12 +181,14 @@ MarkUnbarriered(JSTracer *trc, T **thingp, const char *name);
void
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
// These two declarations are also present in gc/Marking.h, via the DeclMarker
// These three declarations are also present in gc/Marking.h, via the DeclMarker
// macro. Not great, but hard to avoid.
void
MarkObjectUnbarriered(JSTracer *trc, JSObject **obj, const char *name);
void
MarkStringUnbarriered(JSTracer *trc, JSString **str, const char *name);
void
MarkSymbolUnbarriered(JSTracer *trc, JS::Symbol **sym, const char *name);
// Note that some subclasses (e.g. ObjectImpl) specialize some of these
// methods.
@ -391,24 +393,24 @@ struct InternalGCMethods<Value>
template <>
struct InternalGCMethods<jsid>
{
static bool isMarkable(jsid id) { return JSID_IS_OBJECT(id) || JSID_IS_STRING(id); }
static bool isMarkable(jsid id) { return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id); }
static void preBarrier(jsid id) {
#ifdef JSGC_INCREMENTAL
if (JSID_IS_OBJECT(id)) {
JSObject *obj = JSID_TO_OBJECT(id);
JS::shadow::Zone *shadowZone = ShadowZoneOfObjectFromAnyThread(obj);
if (shadowZone->needsBarrier()) {
js::gc::MarkObjectUnbarriered(shadowZone->barrierTracer(), &obj, "write barrier");
JS_ASSERT(obj == JSID_TO_OBJECT(id));
}
} else if (JSID_IS_STRING(id)) {
if (JSID_IS_STRING(id)) {
JSString *str = JSID_TO_STRING(id);
JS::shadow::Zone *shadowZone = ShadowZoneOfStringFromAnyThread(str);
if (shadowZone->needsBarrier()) {
js::gc::MarkStringUnbarriered(shadowZone->barrierTracer(), &str, "write barrier");
JS_ASSERT(str == JSID_TO_STRING(id));
}
} else if (JSID_IS_SYMBOL(id)) {
JS::Symbol *sym = JSID_TO_SYMBOL(id);
JS::shadow::Zone *shadowZone = ShadowZoneOfSymbolFromAnyThread(sym);
if (shadowZone->needsBarrier()) {
js::gc::MarkSymbolUnbarriered(shadowZone->barrierTracer(), &sym, "write barrier");
JS_ASSERT(sym == JSID_TO_SYMBOL(id));
}
}
#endif
}

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

@ -679,11 +679,11 @@ MarkIdInternal(JSTracer *trc, jsid *id)
trc->setTracingLocation((void *)id);
MarkInternal(trc, &str);
*id = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom *>(str));
} else if (MOZ_UNLIKELY(JSID_IS_OBJECT(*id))) {
JSObject *obj = JSID_TO_OBJECT(*id);
} else if (JSID_IS_SYMBOL(*id)) {
JS::Symbol *sym = JSID_TO_SYMBOL(*id);
trc->setTracingLocation((void *)id);
MarkInternal(trc, &obj);
*id = OBJECT_TO_JSID(obj);
MarkInternal(trc, &sym);
*id = SYMBOL_TO_JSID(sym);
} else {
/* Unset realLocation manually if we do not call MarkInternal. */
trc->unsetTracingLocation();
@ -1094,8 +1094,8 @@ ScanShape(GCMarker *gcmarker, Shape *shape)
const BarrieredBase<jsid> &id = shape->propidRef();
if (JSID_IS_STRING(id))
PushMarkStack(gcmarker, JSID_TO_STRING(id));
else if (MOZ_UNLIKELY(JSID_IS_OBJECT(id)))
PushMarkStack(gcmarker, JSID_TO_OBJECT(id));
else if (JSID_IS_SYMBOL(id))
PushMarkStack(gcmarker, JSID_TO_SYMBOL(id));
shape = shape->previous();
if (shape && shape->markIfUnmarked(gcmarker->getMarkColor()))

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

@ -170,7 +170,7 @@ IsAddressableGCThing(JSRuntime *rt, uintptr_t w,
* do not touch the low two bits. Thus any word with the low two bits set
* is not a valid GC-thing.
*/
JS_STATIC_ASSERT(JSID_TYPE_STRING == 0 && JSID_TYPE_OBJECT == 4);
JS_STATIC_ASSERT(JSID_TYPE_STRING == 0 && JSID_TYPE_SYMBOL == 4);
if (w & 0x3)
return CGCT_LOWBITSET;

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

@ -6,17 +6,24 @@ FRAGMENT(jsid, simple) {
JS::Rooted<JSString *> interned(cx, JS_InternJSString(cx, string));
JS::Rooted<jsid> string_id(cx, INTERNED_STRING_TO_JSID(cx, interned));
jsid int_id = INT_TO_JSID(1729);
JS::Rooted<jsid> unique_symbol_id(
cx, SYMBOL_TO_JSID(JS::NewSymbol(cx, interned)));
JS::Rooted<jsid> registry_symbol_id(
cx, SYMBOL_TO_JSID(JS::GetSymbolFor(cx, interned)));
JS::Rooted<jsid> well_known_symbol_id(
cx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(cx, JS::SymbolCode::iterator)));
jsid void_id = JSID_VOID;
JS::Rooted<jsid> object_id(cx, OBJECT_TO_JSID(JS::CurrentGlobalOrNull(cx)));
jsid empty_id = JSID_EMPTY;
breakpoint();
(void) string;
(void) interned;
(void) string_id;
(void) int_id;
(void) unique_symbol_id;
(void) registry_symbol_id;
(void) well_known_symbol_id;
(void) void_id;
(void) object_id;
(void) empty_id;
}
void

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

@ -6,8 +6,12 @@ run_fragment('jsid.simple')
assert_pretty('string_id', '$jsid("moon")')
assert_pretty('int_id', '$jsid(1729)')
unique_symbol_pretty = str(gdb.parse_and_eval('unique_symbol_id')).split('@')[0]
assert_eq(unique_symbol_pretty, '$jsid(Symbol("moon"))')
assert_pretty('registry_symbol_id', '$jsid(Symbol.for("moon"))')
assert_pretty('well_known_symbol_id', '$jsid(Symbol.iterator)')
assert_pretty('void_id', 'JSID_VOID')
assert_pretty('object_id', '$jsid((JSObject *) [object global] delegate)')
assert_pretty('empty_id', 'JSID_EMPTY')
run_fragment('jsid.handles')

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

@ -542,19 +542,17 @@ class MacroAssembler : public MacroAssemblerSpecific
// carries a reference to a gcthing. Need to unpack the pointer,
// push it using ImmGCPtr, and then rematerialize the id at runtime.
// double-checking this here to ensure we don't lose sync
// with implementation of JSID_IS_GCTHING.
if (JSID_IS_OBJECT(id)) {
JSObject *obj = JSID_TO_OBJECT(id);
movePtr(ImmGCPtr(obj), scratchReg);
JS_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
orPtr(Imm32(JSID_TYPE_OBJECT), scratchReg);
Push(scratchReg);
} else {
if (JSID_IS_STRING(id)) {
JSString *str = JSID_TO_STRING(id);
JS_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
JS_ASSERT(JSID_TYPE_STRING == 0x0);
Push(ImmGCPtr(str));
} else {
MOZ_ASSERT(JSID_IS_SYMBOL(id));
JS::Symbol *sym = JSID_TO_SYMBOL(id);
movePtr(ImmGCPtr(sym), scratchReg);
orPtr(Imm32(JSID_TYPE_SYMBOL), scratchReg);
Push(scratchReg);
}
} else {
Push(ImmWord(JSID_BITS(id)));

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

@ -1077,9 +1077,9 @@ JS_WrapId(JSContext *cx, JS::MutableHandleId idp)
jsid id = idp.get();
if (JSID_IS_STRING(id))
JS::ExposeGCThingToActiveJS(JSID_TO_STRING(id), JSTRACE_STRING);
else if (JSID_IS_OBJECT(id))
JS::ExposeGCThingToActiveJS(JSID_TO_OBJECT(id), JSTRACE_OBJECT);
return cx->compartment()->wrapId(cx, idp.address());
else if (JSID_IS_SYMBOL(id))
JS::ExposeGCThingToActiveJS(JSID_TO_STRING(id), JSTRACE_STRING);
return true;
}
/*

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

@ -126,19 +126,7 @@ class CompartmentChecker
check(*p);
}
void check(jsid id) {
if (JSID_IS_OBJECT(id))
check(JSID_TO_OBJECT(id));
}
void check(JSIdArray *ida) {
if (ida) {
for (int i = 0; i < ida->length; i++) {
if (JSID_IS_OBJECT(ida->vector[i]))
check(ida->vector[i]);
}
}
}
void check(jsid id) {}
void check(JSScript *script) {
if (script)

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

@ -2056,10 +2056,10 @@ IdToValue(jsid id)
{
if (JSID_IS_STRING(id))
return JS::StringValue(JSID_TO_STRING(id));
if (MOZ_LIKELY(JSID_IS_INT(id)))
if (JSID_IS_INT(id))
return JS::Int32Value(JSID_TO_INT(id));
if (MOZ_LIKELY(JSID_IS_OBJECT(id)))
return JS::ObjectValue(*JSID_TO_OBJECT(id));
if (JSID_IS_SYMBOL(id))
return JS::SymbolValue(JSID_TO_SYMBOL(id));
JS_ASSERT(JSID_IS_VOID(id));
return JS::UndefinedValue();
}

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

@ -297,17 +297,14 @@ Shape::dump(JSContext *cx, FILE *fp) const
JSLinearString *str;
if (JSID_IS_ATOM(propid)) {
str = JSID_TO_ATOM(propid);
if (!str)
fputs("<error>", fp);
else
FileEscapedString(fp, str, '"');
} else {
JS_ASSERT(JSID_IS_OBJECT(propid));
Value v = IdToValue(propid);
JSString *s = ToStringSlow<NoGC>(cx, v);
fputs("object ", fp);
str = s ? s->ensureLinear(cx) : nullptr;
JS_ASSERT(JSID_IS_SYMBOL(propid));
JSID_TO_SYMBOL(propid)->dump(fp);
}
if (!str)
fputs("<error>", fp);
else
FileEscapedString(fp, str, '"');
}
fprintf(fp, " g/s %p/%p slot %d attrs %x ",

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

@ -5305,12 +5305,8 @@ DebuggerObject_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
vals[i].setString(str);
} else if (JSID_IS_ATOM(id)) {
vals[i].setString(JSID_TO_STRING(id));
if (!cx->compartment()->wrap(cx, vals[i]))
return false;
} else {
vals[i].setObject(*JSID_TO_OBJECT(id));
if (!dbg->wrapDebuggeeValue(cx, vals[i]))
return false;
MOZ_ASSERT_UNREACHABLE("GetPropertyNames must return only string and int jsids");
}
}

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

@ -8,7 +8,7 @@
#include "js/RootingAPI.h"
const jsid JSID_VOID = { size_t(JSID_TYPE_VOID) };
const jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
const jsid JSID_EMPTY = { size_t(JSID_TYPE_SYMBOL) };
static const jsid voidIdValue = JSID_VOID;
static const jsid emptyIdValue = JSID_EMPTY;

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

@ -301,19 +301,6 @@ JS_SetWatchPoint(JSContext *cx, HandleObject origobj, HandleId id,
if (!obj)
return false;
RootedId propid(cx);
if (JSID_IS_INT(id)) {
propid = id;
} else if (JSID_IS_OBJECT(id)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH_PROP);
return false;
} else {
RootedValue val(cx, IdToValue(id));
if (!ValueToId<CanGC>(cx, val, &propid))
return false;
}
if (!obj->isNative() || obj->is<TypedArrayObject>()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH,
obj->getClass()->name);
@ -327,7 +314,7 @@ JS_SetWatchPoint(JSContext *cx, HandleObject origobj, HandleId id,
if (!JSObject::sparsifyDenseElements(cx, obj))
return false;
types::MarkTypePropertyNonData(cx, obj, propid);
types::MarkTypePropertyNonData(cx, obj, id);
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
if (!wpmap) {
@ -338,7 +325,7 @@ JS_SetWatchPoint(JSContext *cx, HandleObject origobj, HandleId id,
}
cx->compartment()->watchpointMap = wpmap;
}
return wpmap->watch(cx, obj, propid, handler, closure);
return wpmap->watch(cx, obj, id, handler, closure);
}
JS_PUBLIC_API(bool)