Issue #1240 - Part 1 - Define a new BigInt primitive type. Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1366287 Part 1.0. However leaving out the --enable-bigint changes.

This commit is contained in:
Brian Smith 2023-07-13 01:59:24 -05:00 • committed by roytam1
commit f041afc61d
43 changed files with 411 additions and 20 deletions

View file

@ -120,7 +120,7 @@ ToBoolean(HandleValue v)
if (v.isSymbol())
return true;
/* The slow path handles strings and objects. */
/* The slow path handles strings, BigInts and objects. */
return js::ToBooleanSlow(v);
}

View file

@ -47,6 +47,7 @@
// Expand the given macro D for each public GC pointer.
#define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
D(JS::Symbol*) \
D(JS::BigInt*) \
D(JSAtom*) \
D(JSFunction*) \
D(JSObject*) \
@ -125,6 +126,7 @@ struct GCPointerPolicy
}
};
template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {};
template <> struct GCPolicy<JS::BigInt*> : public GCPointerPolicy<JS::BigInt*> {};
template <> struct GCPolicy<JSAtom*> : public GCPointerPolicy<JSAtom*> {};
template <> struct GCPolicy<JSFunction*> : public GCPointerPolicy<JSFunction*> {};
template <> struct GCPolicy<JSObject*> : public GCPointerPolicy<JSObject*> {};

View file

@ -580,6 +580,7 @@ struct UnusedGCThingSizes
macro(Other, GCHeapUnused, objectGroup) \
macro(Other, GCHeapUnused, string) \
macro(Other, GCHeapUnused, symbol) \
macro(Other, GCHeapUnused, bigInt) \
macro(Other, GCHeapUnused, jitcode) \
macro(Other, GCHeapUnused, scope) \
macro(Other, GCHeapUnused, regExpShared)
@ -599,6 +600,7 @@ struct UnusedGCThingSizes
case JS::TraceKind::Object: object += n; break;
case JS::TraceKind::String: string += n; break;
case JS::TraceKind::Symbol: symbol += n; break;
case JS::TraceKind::BigInt: bigInt += n; break;
case JS::TraceKind::Script: script += n; break;
case JS::TraceKind::Shape: shape += n; break;
case JS::TraceKind::BaseShape: baseShape += n; break;
@ -640,6 +642,8 @@ struct ZoneStats
{
#define FOR_EACH_SIZE(macro) \
macro(Other, GCHeapUsed, symbolsGCHeap) \
macro(Other, GCHeapUsed, bigIntsGCHeap) \
macro(Other, MallocHeap, bigIntsMallocHeap) \
macro(Other, GCHeapAdmin, gcHeapArenaAdmin) \
macro(Other, GCHeapUsed, lazyScriptsGCHeap) \
macro(Other, MallocHeap, lazyScriptsMallocHeap) \

View file

@ -60,7 +60,8 @@ enum class TraceKind
JitCode = 0x1F,
LazyScript = 0x2F,
Scope = 0x3F,
RegExpShared = 0x4F
RegExpShared = 0x4F,
BigInt = 0x5F
};
const static uintptr_t OutOfLineTraceKindMask = 0x07;
static_assert(uintptr_t(JS::TraceKind::BaseShape) & OutOfLineTraceKindMask, "mask bits are set");
@ -91,6 +92,7 @@ struct MapTypeToTraceKind {
D(Shape, js::Shape, true) \
D(String, JSString, false) \
D(Symbol, JS::Symbol, false) \
D(BigInt, JS::BigInt, false) \
D(RegExpShared, js::RegExpShared, true)
// Map from all public types to their trace kind.

View file

@ -141,6 +141,7 @@ class JS_PUBLIC_API(CallbackTracer) : public JSTracer
virtual void onObjectEdge(JSObject** objp) { onChild(JS::GCCellPtr(*objp)); }
virtual void onStringEdge(JSString** strp) { onChild(JS::GCCellPtr(*strp)); }
virtual void onSymbolEdge(JS::Symbol** symp) { onChild(JS::GCCellPtr(*symp)); }
virtual void onBigIntEdge(JS::BigInt** bip) { onChild(JS::GCCellPtr(*bip)); }
virtual void onScriptEdge(JSScript** scriptp) { onChild(JS::GCCellPtr(*scriptp)); }
virtual void onShapeEdge(js::Shape** shapep) {
onChild(JS::GCCellPtr(*shapep, JS::TraceKind::Shape));
@ -226,6 +227,7 @@ class JS_PUBLIC_API(CallbackTracer) : public JSTracer
void dispatchToOnEdge(JSObject** objp) { onObjectEdge(objp); }
void dispatchToOnEdge(JSString** strp) { onStringEdge(strp); }
void dispatchToOnEdge(JS::Symbol** symp) { onSymbolEdge(symp); }
void dispatchToOnEdge(JS::BigInt** bip) { onBigIntEdge(bip); }
void dispatchToOnEdge(JSScript** scriptp) { onScriptEdge(scriptp); }
void dispatchToOnEdge(js::Shape** shapep) { onShapeEdge(shapep); }
void dispatchToOnEdge(js::ObjectGroup** groupp) { onObjectGroupEdge(groupp); }

View file

@ -39,6 +39,7 @@ namespace JS {
typedef unsigned char Latin1Char;
class Symbol;
class BigInt;
class Value;
template <typename T> class Handle;
template <typename T> class MutableHandle;
@ -53,6 +54,7 @@ typedef Handle<JSObject*> HandleObject;
typedef Handle<JSScript*> HandleScript;
typedef Handle<JSString*> HandleString;
typedef Handle<JS::Symbol*> HandleSymbol;
typedef Handle<JS::BigInt*> HandleBigInt;
typedef Handle<Value> HandleValue;
typedef Handle<StackGCVector<Value>> HandleValueVector;
@ -62,6 +64,7 @@ typedef MutableHandle<JSObject*> MutableHandleObject;
typedef MutableHandle<JSScript*> MutableHandleScript;
typedef MutableHandle<JSString*> MutableHandleString;
typedef MutableHandle<JS::Symbol*> MutableHandleSymbol;
typedef MutableHandle<JS::BigInt*> MutableHandleBigInt;
typedef MutableHandle<Value> MutableHandleValue;
typedef MutableHandle<StackGCVector<Value>> MutableHandleValueVector;
@ -70,6 +73,7 @@ typedef Rooted<JSFunction*> RootedFunction;
typedef Rooted<JSScript*> RootedScript;
typedef Rooted<JSString*> RootedString;
typedef Rooted<JS::Symbol*> RootedSymbol;
typedef Rooted<JS::BigInt*> RootedBigInt;
typedef Rooted<jsid> RootedId;
typedef Rooted<JS::Value> RootedValue;
@ -81,6 +85,7 @@ typedef PersistentRooted<JSObject*> PersistentRootedObject;
typedef PersistentRooted<JSScript*> PersistentRootedScript;
typedef PersistentRooted<JSString*> PersistentRootedString;
typedef PersistentRooted<JS::Symbol*> PersistentRootedSymbol;
typedef PersistentRooted<JS::BigInt*> PersistentRootedBigInt;
typedef PersistentRooted<Value> PersistentRootedValue;

View file

@ -1056,6 +1056,22 @@ class JS_PUBLIC_API(Concrete<JS::Symbol>) : TracerConcrete<JS::Symbol> {
static const char16_t concreteTypeName[];
};
template<>
class JS_PUBLIC_API(Concrete<JS::BigInt>) : TracerConcrete<JS::BigInt> {
protected:
explicit Concrete(JS::BigInt* ptr) : TracerConcrete(ptr) {}
public:
static void construct(void* storage, JS::BigInt* ptr) {
new (storage) Concrete(ptr);
}
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
const char16_t* typeName() const override { return concreteTypeName; }
static const char16_t concreteTypeName[];
};
template<>
class JS_PUBLIC_API(Concrete<JSScript>) : TracerConcreteWithCompartment<JSScript> {
protected:

View file

@ -56,6 +56,7 @@ JS_ENUM_HEADER(JSValueType, uint8_t)
JSVAL_TYPE_STRING = 0x06,
JSVAL_TYPE_SYMBOL = 0x07,
JSVAL_TYPE_PRIVATE_GCTHING = 0x08,
JSVAL_TYPE_BIGINT = 0x09,
JSVAL_TYPE_OBJECT = 0x0c,
/* These never appear in a jsval; they are only provided as an out-of-band value. */
@ -80,6 +81,7 @@ 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_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT,
JSVAL_TAG_BIGINT = JSVAL_TAG_CLEAR | JSVAL_TYPE_BIGINT,
JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_CLEAR | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
@ -100,6 +102,7 @@ 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_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT,
JSVAL_TAG_BIGINT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BIGINT,
JSVAL_TAG_PRIVATE_GCTHING = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_PRIVATE_GCTHING
} JS_ENUM_FOOTER(JSValueTag);
@ -117,6 +120,7 @@ JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
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_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_BIGINT = (((uint64_t)JSVAL_TAG_BIGINT) << JSVAL_TAG_SHIFT),
JSVAL_SHIFTED_TAG_PRIVATE_GCTHING = (((uint64_t)JSVAL_TAG_PRIVATE_GCTHING) << JSVAL_TAG_SHIFT)
} JS_ENUM_FOOTER(JSValueShiftedTag);
@ -275,7 +279,7 @@ CanonicalizeNaN(double d)
*
* - JS::Value has setX() and isX() members for X in
*
* { Int32, Double, String, Symbol, Boolean, Undefined, Null, Object, Magic }
* { Int32, Double, String, Symbol, BigInt, Boolean, Undefined, Null, Object, Magic }
*
* JS::Value also contains toX() for each of the non-singleton types.
*
@ -370,6 +374,11 @@ class MOZ_NON_PARAM alignas(8) Value
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_SYMBOL, PayloadType(sym));
}
void setBigInt(JS::BigInt* bi) {
MOZ_ASSERT(uintptr_t(bi) > 0x1000);
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_BIGINT, PayloadType(bi));
}
void setObject(JSObject& obj) {
MOZ_ASSERT(uintptr_t(&obj) > 0x1000 || uintptr_t(&obj) == 0x48);
#if defined(JS_PUNBOX64)
@ -519,6 +528,10 @@ class MOZ_NON_PARAM alignas(8) Value
return toTag() == JSVAL_TAG_SYMBOL;
}
bool isBigInt() const {
return toTag() == JSVAL_TAG_BIGINT;
}
bool isObject() const {
#if defined(JS_NUNBOX32)
return toTag() == JSVAL_TAG_OBJECT;
@ -583,6 +596,8 @@ class MOZ_NON_PARAM alignas(8) Value
"Value type tags must correspond with JS::TraceKinds.");
if (MOZ_UNLIKELY(isPrivateGCThing()))
return JS::GCThingTraceKind(toGCThing());
if (MOZ_UNLIKELY(isBigInt()))
return JS::TraceKind::BigInt;
return JS::TraceKind(toTag() & 0x03);
}
@ -647,6 +662,15 @@ class MOZ_NON_PARAM alignas(8) Value
#endif
}
JS::BigInt* toBigInt() const {
MOZ_ASSERT(isBigInt());
#if defined(JS_NUNBOX32)
return data.s.payload.bi;
#elif defined(JS_PUNBOX64)
return reinterpret_cast<JS::BigInt*>(data.asBits & JSVAL_SHIFTED_TAG_BIGINT);
#endif
}
JSObject& toObject() const {
MOZ_ASSERT(isObject());
#if defined(JS_NUNBOX32)
@ -759,6 +783,8 @@ class MOZ_NON_PARAM alignas(8) Value
"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::BigInt,
"Private GC thing Values must not be BigInts. Make a BigIntValue instead.");
MOZ_ASSERT(JS::GCThingTraceKind(cell) != JS::TraceKind::Object,
"Private GC thing Values must not be objects. Make an ObjectValue instead.");
@ -811,6 +837,7 @@ class MOZ_NON_PARAM alignas(8) Value
uint32_t boo; // Don't use |bool| -- it must be four bytes.
JSString* str;
JS::Symbol* sym;
JS::BigInt* bi;
JSObject* obj;
js::gc::Cell* cell;
void* ptr;
@ -866,6 +893,7 @@ class MOZ_NON_PARAM alignas(8) Value
uint32_t boo; // Don't use |bool| -- it must be four bytes.
JSString* str;
JS::Symbol* sym;
JS::BigInt* bi;
JSObject* obj;
js::gc::Cell* cell;
void* ptr;
@ -1097,6 +1125,14 @@ SymbolValue(JS::Symbol* sym)
return v;
}
static inline Value
BigIntValue(JS::BigInt* bi)
{
Value v;
v.setBigInt(bi);
return v;
}
static inline Value
BooleanValue(bool boo)
{
@ -1365,6 +1401,7 @@ class WrappedPtrOperations<JS::Value, Wrapper>
bool isDouble() const { return value().isDouble(); }
bool isString() const { return value().isString(); }
bool isSymbol() const { return value().isSymbol(); }
bool isBigInt() const { return value().isBigInt(); }
bool isObject() const { return value().isObject(); }
bool isMagic() const { return value().isMagic(); }
bool isMagic(JSWhyMagic why) const { return value().isMagic(why); }
@ -1380,6 +1417,7 @@ class WrappedPtrOperations<JS::Value, Wrapper>
double toDouble() const { return value().toDouble(); }
JSString* toString() const { return value().toString(); }
JS::Symbol* toSymbol() const { return value().toSymbol(); }
JS::BigInt* toBigInt() const { return value().toBigInt(); }
JSObject& toObject() const { return value().toObject(); }
JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
gc::Cell* toGCThing() const { return value().toGCThing(); }
@ -1421,6 +1459,7 @@ class MutableWrappedPtrOperations<JS::Value, Wrapper> : public WrappedPtrOperati
void setNumber(double d) { set(JS::NumberValue(d)); }
void setString(JSString* str) { set(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { set(JS::SymbolValue(sym)); }
void setBigInt(JS::BigInt* bi) { set(JS::BigIntValue(bi)); }
void setObject(JSObject& obj) { set(JS::ObjectValue(obj)); }
void setObjectOrNull(JSObject* arg) { set(JS::ObjectOrNullValue(arg)); }
void setPrivate(void* ptr) { set(JS::PrivateValue(ptr)); }