mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-05 08:09:15 +00:00
Bug 1554113 - Support (Big)Int64 fields in typed objects r=till
Differential Revision: https://phabricator.services.mozilla.com/D40396 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
e500fdddbb
commit
043f0bc30b
@ -52,6 +52,28 @@ static void ReportCannotConvertTo(JSContext* cx, HandleValue fromValue,
|
||||
InformalValueTypeName(fromValue), toType);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BigInt* CreateBigInt(JSContext* cx, T i);
|
||||
template <>
|
||||
BigInt* CreateBigInt<int64_t>(JSContext* cx, int64_t i) {
|
||||
return BigInt::createFromInt64(cx, i);
|
||||
}
|
||||
template <>
|
||||
BigInt* CreateBigInt<uint64_t>(JSContext* cx, uint64_t u) {
|
||||
return BigInt::createFromUint64(cx, u);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ConvertBigInt(BigInt* bi);
|
||||
template <>
|
||||
int64_t ConvertBigInt<int64_t>(BigInt* bi) {
|
||||
return BigInt::toInt64(bi);
|
||||
}
|
||||
template <>
|
||||
uint64_t ConvertBigInt<uint64_t>(BigInt* bi) {
|
||||
return BigInt::toUint64(bi);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline T* ToObjectIf(HandleValue value) {
|
||||
if (!value.isObject()) {
|
||||
@ -233,25 +255,38 @@ bool ScalarTypeDescr::call(JSContext* cx, unsigned argc, Value* vp) {
|
||||
Rooted<ScalarTypeDescr*> descr(cx, &args.callee().as<ScalarTypeDescr>());
|
||||
ScalarTypeDescr::Type type = descr->type();
|
||||
|
||||
double number;
|
||||
if (!ToNumber(cx, args[0], &number)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == Scalar::Uint8Clamped) {
|
||||
number = ClampDoubleToUint8(number);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
#define SCALARTYPE_CALL(constant_, type_, name_) \
|
||||
#define NUMBER_CALL(constant_, type_, name_) \
|
||||
case constant_: { \
|
||||
double number; \
|
||||
if (!ToNumber(cx, args[0], &number)) { \
|
||||
return false; \
|
||||
} \
|
||||
if (type == Scalar::Uint8Clamped) { \
|
||||
number = ClampDoubleToUint8(number); \
|
||||
} \
|
||||
type_ converted = ConvertScalar<type_>(number); \
|
||||
args.rval().setNumber((double)converted); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALARTYPE_CALL)
|
||||
#undef SCALARTYPE_CALL
|
||||
JS_FOR_EACH_SCALAR_NUMBER_TYPE_REPR(NUMBER_CALL)
|
||||
#undef NUMBER_CALL
|
||||
#define BIGINT_CALL(constant_, type_, name_) \
|
||||
case constant_: { \
|
||||
BigInt* bi = ToBigInt(cx, args[0]); \
|
||||
if (!bi) { \
|
||||
return false; \
|
||||
} \
|
||||
type_ converted = ConvertBigInt<type_>(bi); \
|
||||
BigInt* ret = CreateBigInt<type_>(cx, converted); \
|
||||
if (!ret) { \
|
||||
return false; \
|
||||
} \
|
||||
args.rval().setBigInt(ret); \
|
||||
return true; \
|
||||
}
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(BIGINT_CALL)
|
||||
#undef BIGINT_CALL
|
||||
case Scalar::Int64:
|
||||
case Scalar::MaxTypedArrayViewType:
|
||||
MOZ_CRASH();
|
||||
@ -268,7 +303,8 @@ TypeDescr* GlobalObject::getOrCreateScalarTypeDescr(
|
||||
slot = TypedObjectModuleObject::Int32Desc;
|
||||
break;
|
||||
case Scalar::Int64:
|
||||
MOZ_CRASH("No Int64 support yet");
|
||||
slot = TypedObjectModuleObject::Int64Desc;
|
||||
break;
|
||||
case Scalar::Float32:
|
||||
slot = TypedObjectModuleObject::Float32Desc;
|
||||
break;
|
||||
@ -1381,6 +1417,11 @@ bool GlobalObject::initTypedObjectModule(JSContext* cx,
|
||||
}
|
||||
module->initReservedSlot(TypedObjectModuleObject::Int32Desc, typeDescr);
|
||||
|
||||
if (!JS_GetProperty(cx, module, "int64", &typeDescr)) {
|
||||
return false;
|
||||
}
|
||||
module->initReservedSlot(TypedObjectModuleObject::Int64Desc, typeDescr);
|
||||
|
||||
if (!JS_GetProperty(cx, module, "float32", &typeDescr)) {
|
||||
return false;
|
||||
}
|
||||
@ -2504,7 +2545,7 @@ bool js::GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define JS_STORE_SCALAR_CLASS_IMPL(_constant, T, _name) \
|
||||
#define JS_STORE_NUMBER_CLASS_IMPL(_constant, T, _name) \
|
||||
bool js::StoreScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) { \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
MOZ_ASSERT(args.length() == 3); \
|
||||
@ -2526,6 +2567,29 @@ bool js::GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define JS_STORE_BIGINT_CLASS_IMPL(_constant, T, _name) \
|
||||
bool js::StoreScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) { \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
MOZ_ASSERT(args.length() == 3); \
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypedObject>()); \
|
||||
MOZ_RELEASE_ASSERT(args[1].isInt32()); \
|
||||
int32_t offset = args[1].toInt32(); \
|
||||
BigInt* bi = ToBigInt(cx, args[2]); \
|
||||
if (!bi) { \
|
||||
return false; \
|
||||
} \
|
||||
TypedObject& typedObj = args[0].toObject().as<TypedObject>(); \
|
||||
\
|
||||
/* Should be guaranteed by the typed objects API: */ \
|
||||
MOZ_ASSERT(offset % MOZ_ALIGNOF(T) == 0); \
|
||||
\
|
||||
JS::AutoCheckCannotGC nogc(cx); \
|
||||
T* target = reinterpret_cast<T*>(typedObj.typedMem(offset, nogc)); \
|
||||
*target = ConvertBigInt<T>(bi); \
|
||||
args.rval().setUndefined(); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define JS_STORE_REFERENCE_CLASS_IMPL(_constant, T, _name) \
|
||||
bool js::StoreReference##_name::Func(JSContext* cx, unsigned argc, \
|
||||
Value* vp) { \
|
||||
@ -2552,7 +2616,7 @@ bool js::GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define JS_LOAD_SCALAR_CLASS_IMPL(_constant, T, _name) \
|
||||
#define JS_LOAD_NUMBER_CLASS_IMPL(_constant, T, _name) \
|
||||
bool js::LoadScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) { \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
MOZ_ASSERT(args.length() == 2); \
|
||||
@ -2571,6 +2635,32 @@ bool js::GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp) {
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define JS_LOAD_BIGINT_CLASS_IMPL(_constant, T, _name) \
|
||||
bool js::LoadScalar##T::Func(JSContext* cx, unsigned argc, Value* vp) { \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
MOZ_ASSERT(args.length() == 2); \
|
||||
MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypedObject>()); \
|
||||
MOZ_RELEASE_ASSERT(args[1].isInt32()); \
|
||||
\
|
||||
TypedObject& typedObj = args[0].toObject().as<TypedObject>(); \
|
||||
int32_t offset = args[1].toInt32(); \
|
||||
\
|
||||
/* Should be guaranteed by the typed objects API: */ \
|
||||
MOZ_ASSERT(offset % MOZ_ALIGNOF(T) == 0); \
|
||||
\
|
||||
T value; \
|
||||
{ \
|
||||
JS::AutoCheckCannotGC nogc(cx); \
|
||||
value = *reinterpret_cast<T*>(typedObj.typedMem(offset, nogc)); \
|
||||
} \
|
||||
BigInt* bi = CreateBigInt<T>(cx, value); \
|
||||
if (!bi) { \
|
||||
return false; \
|
||||
} \
|
||||
args.rval().setBigInt(bi); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define JS_LOAD_REFERENCE_CLASS_IMPL(_constant, T, _name) \
|
||||
bool js::LoadReference##_name::Func(JSContext* cx, unsigned argc, \
|
||||
Value* vp) { \
|
||||
@ -2688,8 +2778,10 @@ void LoadReferencestring::load(GCPtrString* heap, MutableHandleValue v) {
|
||||
|
||||
// I was using templates for this stuff instead of macros, but ran
|
||||
// into problems with the Unagi compiler.
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_IMPL)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_IMPL)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(JS_STORE_NUMBER_CLASS_IMPL)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(JS_LOAD_NUMBER_CLASS_IMPL)
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(JS_STORE_BIGINT_CLASS_IMPL)
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(JS_LOAD_BIGINT_CLASS_IMPL)
|
||||
JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_IMPL)
|
||||
JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_IMPL)
|
||||
|
||||
|
@ -271,25 +271,32 @@ class ScalarTypeDescr : public SimpleTypeDescr {
|
||||
static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
// Enumerates the cases of ScalarTypeDescr::Type which have
|
||||
// unique C representation. In particular, omits Uint8Clamped since it
|
||||
// is just a Uint8.
|
||||
#define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(MACRO_) \
|
||||
MACRO_(Scalar::Int8, int8_t, int8) \
|
||||
MACRO_(Scalar::Uint8, uint8_t, uint8) \
|
||||
MACRO_(Scalar::Int16, int16_t, int16) \
|
||||
MACRO_(Scalar::Uint16, uint16_t, uint16) \
|
||||
MACRO_(Scalar::Int32, int32_t, int32) \
|
||||
MACRO_(Scalar::Uint32, uint32_t, uint32) \
|
||||
MACRO_(Scalar::Float32, float, float32) \
|
||||
MACRO_(Scalar::Float64, double, float64) \
|
||||
MACRO_(Scalar::BigInt64, int64_t, bigint64) \
|
||||
// Enumerates the cases of ScalarTypeDescr::Type which have unique C
|
||||
// representation and which are representable as JS Number values. In
|
||||
// particular, omits Uint8Clamped since it is just a Uint8.
|
||||
#define JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(MACRO_) \
|
||||
MACRO_(Scalar::Int8, int8_t, int8) \
|
||||
MACRO_(Scalar::Uint8, uint8_t, uint8) \
|
||||
MACRO_(Scalar::Int16, int16_t, int16) \
|
||||
MACRO_(Scalar::Uint16, uint16_t, uint16) \
|
||||
MACRO_(Scalar::Int32, int32_t, int32) \
|
||||
MACRO_(Scalar::Uint32, uint32_t, uint32) \
|
||||
MACRO_(Scalar::Float32, float, float32) \
|
||||
MACRO_(Scalar::Float64, double, float64)
|
||||
|
||||
// Must be in same order as the enum ScalarTypeDescr::Type:
|
||||
#define JS_FOR_EACH_SCALAR_NUMBER_TYPE_REPR(MACRO_) \
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(MACRO_) \
|
||||
MACRO_(Scalar::Uint8Clamped, uint8_t, uint8Clamped)
|
||||
|
||||
#define JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(MACRO_) \
|
||||
MACRO_(Scalar::BigInt64, int64_t, bigint64) \
|
||||
MACRO_(Scalar::BigUint64, uint64_t, biguint64)
|
||||
|
||||
// Must be in same order as the enum ScalarTypeDescr::Type:
|
||||
#define JS_FOR_EACH_SCALAR_TYPE_REPR(MACRO_) \
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(MACRO_) \
|
||||
MACRO_(Scalar::Uint8Clamped, uint8_t, uint8Clamped)
|
||||
#define JS_FOR_EACH_SCALAR_TYPE_REPR(MACRO_) \
|
||||
JS_FOR_EACH_SCALAR_NUMBER_TYPE_REPR(MACRO_) \
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(MACRO_)
|
||||
|
||||
enum class ReferenceType {
|
||||
TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
|
||||
@ -993,8 +1000,10 @@ MOZ_MUST_USE bool UnboxBoxedWasmAnyRef(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// I was using templates for this stuff instead of macros, but ran
|
||||
// into problems with the Unagi compiler.
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_DEFN)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_DEFN)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_DEFN)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_DEFN)
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(JS_STORE_SCALAR_CLASS_DEFN)
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(JS_LOAD_SCALAR_CLASS_DEFN)
|
||||
JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_DEFN)
|
||||
JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_DEFN)
|
||||
|
||||
|
@ -115,6 +115,12 @@ function TypedObjectGetScalar(descr, typedObj, offset) {
|
||||
|
||||
case JS_SCALARTYPEREPR_FLOAT64:
|
||||
return Load_float64(typedObj, offset | 0);
|
||||
|
||||
case JS_SCALARTYPEREPR_BIGINT64:
|
||||
return Load_bigint64(typedObj, offset | 0);
|
||||
|
||||
case JS_SCALARTYPEREPR_BIGUINT64:
|
||||
return Load_biguint64(typedObj, offset | 0);
|
||||
}
|
||||
|
||||
assert(false, "Unhandled scalar type: " + type);
|
||||
@ -254,6 +260,12 @@ function TypedObjectSetScalar(descr, typedObj, offset, fromValue) {
|
||||
|
||||
case JS_SCALARTYPEREPR_FLOAT64:
|
||||
return Store_float64(typedObj, offset | 0, +fromValue);
|
||||
|
||||
case JS_SCALARTYPEREPR_BIGINT64:
|
||||
return Store_bigint64(typedObj, offset | 0, fromValue);
|
||||
|
||||
case JS_SCALARTYPEREPR_BIGUINT64:
|
||||
return Store_biguint64(typedObj, offset | 0, fromValue);
|
||||
}
|
||||
|
||||
assert(false, "Unhandled scalar type: " + type);
|
||||
|
4
js/src/jit-test/tests/bigint/bug1554113.js
Normal file
4
js/src/jit-test/tests/bigint/bug1554113.js
Normal file
@ -0,0 +1,4 @@
|
||||
var T = TypedObject;
|
||||
x = T.biguint64;
|
||||
var ST = new T.StructType({ x });
|
||||
new ST({'x':0n});
|
@ -2438,7 +2438,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
#define LOAD_AND_STORE_SCALAR_FN_DECLS(_constant, _type, _name) \
|
||||
JS_FN("Store_" #_name, js::StoreScalar##_type::Func, 3, 0), \
|
||||
JS_FN("Load_" #_name, js::LoadScalar##_type::Func, 3, 0),
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(LOAD_AND_STORE_SCALAR_FN_DECLS)
|
||||
JS_FOR_EACH_UNIQUE_SCALAR_NUMBER_TYPE_REPR_CTYPE(LOAD_AND_STORE_SCALAR_FN_DECLS)
|
||||
JS_FOR_EACH_SCALAR_BIGINT_TYPE_REPR(LOAD_AND_STORE_SCALAR_FN_DECLS)
|
||||
// clang-format on
|
||||
#undef LOAD_AND_STORE_SCALAR_FN_DECLS
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user