зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1401624: Part 6: Update Rust bindings r=fitzgen
We are changing the representation of values on 64-bit. Part 5 of this patch stack has more details on the changes. Differential Revision: https://phabricator.services.mozilla.com/D29056 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
b4d7776503
Коммит
b1d0f80ddf
|
@ -11,26 +11,35 @@ use std::mem;
|
|||
const JSVAL_TAG_SHIFT: usize = 47;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32;
|
||||
const JSVAL_TAG_MAX_NON_DOUBLE: u64 = 0xE;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const JSVAL_PRIVATE_DOUBLE_BIT: u64 = 0x8000000000000000;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const JSVAL_MAX_OBJECT: u64 = 0x00007FFFFFFFFFFF;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const JSVAL_DOUBLE_ADJUST: u64 = 0x0007FFFFFFFFFFFF;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[repr(u32)]
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum ValueTag {
|
||||
INT32 = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_INT32 as u32),
|
||||
UNDEFINED = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_UNDEFINED as u32),
|
||||
STRING = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_STRING as u32),
|
||||
SYMBOL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_SYMBOL as u32),
|
||||
INT32 = JSValueTag::JSVAL_TAG_INT32 as u32,
|
||||
UNDEFINED = JSValueTag::JSVAL_TAG_UNDEFINED as u32,
|
||||
STRING = JSValueTag::JSVAL_TAG_STRING as u32,
|
||||
SYMBOL = JSValueTag::JSVAL_TAG_SYMBOL as u32,
|
||||
#[cfg(feature = "bigint")]
|
||||
BIGINT = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BIGINT as u32),
|
||||
BOOLEAN = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BOOLEAN as u32),
|
||||
MAGIC = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_MAGIC as u32),
|
||||
NULL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_NULL as u32),
|
||||
OBJECT = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_OBJECT as u32),
|
||||
BIGINT = JSValueTag::JSVAL_TAG_BIGINT as u32,
|
||||
BOOLEAN = JSValueTag::JSVAL_TAG_BOOLEAN as u32,
|
||||
MAGIC = JSValueTag::JSVAL_TAG_MAGIC as u32,
|
||||
NULL = JSValueTag::JSVAL_TAG_NULL as u32,
|
||||
OBJECT = JSValueTag::JSVAL_TAG_OBJECT as u32,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
@ -56,7 +65,6 @@ enum ValueTag {
|
|||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum ValueShiftedTag {
|
||||
MAX_DOUBLE = (((JSVAL_TAG_MAX_DOUBLE as u64) << JSVAL_TAG_SHIFT) | 0xFFFFFFFFu64),
|
||||
INT32 = ((ValueTag::INT32 as u64) << JSVAL_TAG_SHIFT),
|
||||
UNDEFINED = ((ValueTag::UNDEFINED as u64) << JSVAL_TAG_SHIFT),
|
||||
STRING = ((ValueTag::STRING as u64) << JSVAL_TAG_SHIFT),
|
||||
|
@ -69,9 +77,8 @@ enum ValueShiftedTag {
|
|||
OBJECT = ((ValueTag::OBJECT as u64) << JSVAL_TAG_SHIFT),
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF;
|
||||
const JSVAL_PAYLOAD_MASK_GCTHING: u64 = 0x00007FFFFFFFFFFF;
|
||||
|
||||
#[inline(always)]
|
||||
fn AsJSVal(val: u64) -> JS::Value {
|
||||
|
@ -111,8 +118,9 @@ pub fn Int32Value(i: i32) -> JS::Value {
|
|||
#[inline(always)]
|
||||
pub fn DoubleValue(f: f64) -> JS::Value {
|
||||
let bits: u64 = unsafe { mem::transmute(f) };
|
||||
assert!(bits <= ValueShiftedTag::MAX_DOUBLE as u64);
|
||||
AsJSVal(bits)
|
||||
let val = AsJSVal(bits + JSVAL_DOUBLE_ADJUST);
|
||||
assert!(val.is_double());
|
||||
val
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
@ -182,7 +190,9 @@ pub fn ObjectOrNullValue(o: *mut JSObject) -> JS::Value {
|
|||
pub fn PrivateValue(o: *const c_void) -> JS::Value {
|
||||
let ptrBits = o as usize as u64;
|
||||
assert!((ptrBits & 1) == 0);
|
||||
AsJSVal(ptrBits >> 1)
|
||||
let val = AsJSVal((ptrBits >> 1) | JSVAL_PRIVATE_DOUBLE_BIT);
|
||||
assert!(val.is_double());
|
||||
val
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
@ -289,7 +299,7 @@ impl JS::Value {
|
|||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn is_double(&self) -> bool {
|
||||
unsafe {
|
||||
self.asBits() <= ValueShiftedTag::MAX_DOUBLE as u64
|
||||
(self.asBits() >> JSVAL_TAG_SHIFT) > JSVAL_TAG_MAX_NON_DOUBLE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,9 +314,9 @@ impl JS::Value {
|
|||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn is_number(&self) -> bool {
|
||||
const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET: u64 = ValueShiftedTag::UNDEFINED as u64;
|
||||
const JSVAL_MIN_NUMBER_TAG: u64 = ValueTag::INT32 as u64;
|
||||
unsafe {
|
||||
self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET
|
||||
(self.asBits() >> JSVAL_TAG_SHIFT) >= JSVAL_MIN_NUMBER_TAG
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,9 +332,9 @@ impl JS::Value {
|
|||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn is_primitive(&self) -> bool {
|
||||
const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = ValueShiftedTag::OBJECT as u64;
|
||||
const JSVAL_MAX_NONPRIMITIVE_TAG: u64 = ValueTag::OBJECT as u64;
|
||||
unsafe {
|
||||
self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET
|
||||
(self.asBits() >> JSVAL_TAG_SHIFT) > JSVAL_MAX_NONPRIMITIVE_TAG
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,8 +367,7 @@ impl JS::Value {
|
|||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn is_object(&self) -> bool {
|
||||
unsafe {
|
||||
assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64);
|
||||
self.asBits() >= ValueShiftedTag::OBJECT as u64
|
||||
self.asBits() <= JSVAL_MAX_OBJECT
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,7 +418,7 @@ impl JS::Value {
|
|||
pub fn to_boolean(&self) -> bool {
|
||||
assert!(self.is_boolean());
|
||||
unsafe {
|
||||
(self.asBits() & JSVAL_PAYLOAD_MASK) != 0
|
||||
(self.asBits() & 0x1) != 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,6 +440,14 @@ impl JS::Value {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn to_double(&self) -> f64 {
|
||||
assert!(self.is_double());
|
||||
unsafe { mem::transmute(self.asBits() - JSVAL_DOUBLE_ADJUST) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub fn to_double(&self) -> f64 {
|
||||
assert!(self.is_double());
|
||||
unsafe { mem::transmute(self.asBits()) }
|
||||
|
@ -457,7 +474,7 @@ impl JS::Value {
|
|||
pub fn to_string(&self) -> *mut JSString {
|
||||
assert!(self.is_string());
|
||||
unsafe {
|
||||
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
|
||||
let ptrBits = self.asBits() ^ (ValueShiftedTag::STRING as u64);
|
||||
ptrBits as usize as *mut JSString
|
||||
}
|
||||
}
|
||||
|
@ -472,24 +489,8 @@ impl JS::Value {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn is_object_or_null(&self) -> bool {
|
||||
const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET: u64 = ValueShiftedTag::NULL as u64;
|
||||
unsafe {
|
||||
assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64);
|
||||
self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub fn is_object_or_null(&self) -> bool {
|
||||
const JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET: u64 = ValueTag::NULL as u64;
|
||||
unsafe {
|
||||
assert!((self.asBits() >> 32) <= ValueTag::OBJECT as u64);
|
||||
(self.asBits() >> 32) >= JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET
|
||||
}
|
||||
self.is_object() || self.is_null()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -497,7 +498,7 @@ impl JS::Value {
|
|||
pub fn to_object_or_null(&self) -> *mut JSObject {
|
||||
assert!(self.is_object_or_null());
|
||||
unsafe {
|
||||
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
|
||||
let ptrBits = self.asBits() & !(ValueShiftedTag::NULL as u64);
|
||||
assert!((ptrBits & 0x7) == 0);
|
||||
ptrBits as usize as *mut JSObject
|
||||
}
|
||||
|
@ -518,7 +519,7 @@ impl JS::Value {
|
|||
pub fn to_private(&self) -> *const c_void {
|
||||
assert!(self.is_double());
|
||||
unsafe {
|
||||
assert!((self.asBits() & 0x8000000000000000u64) == 0);
|
||||
assert!((self.asBits() & JSVAL_PRIVATE_DOUBLE_BIT) != 0);
|
||||
(self.asBits() << 1) as usize as *const c_void
|
||||
}
|
||||
}
|
||||
|
@ -535,9 +536,8 @@ impl JS::Value {
|
|||
#[inline(always)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub fn is_gcthing(&self) -> bool {
|
||||
const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET: u64 = ValueShiftedTag::STRING as u64;
|
||||
unsafe {
|
||||
self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET
|
||||
self.asBits() < ValueShiftedTag::UNDEFINED as u64
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -555,7 +555,7 @@ impl JS::Value {
|
|||
pub fn to_gcthing(&self) -> *mut c_void {
|
||||
assert!(self.is_gcthing());
|
||||
unsafe {
|
||||
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
|
||||
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK_GCTHING;
|
||||
assert!((ptrBits & 0x7) == 0);
|
||||
ptrBits as *mut c_void
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче