bug 1366287 - Part 1.2: Add a BigInt type to the Rust bindings. r=Ms2ger
☠☠ backed out by f0cb25b7bdee ☠ ☠
authorRobin Templeton <robin@igalia.com>
Fri, 11 May 2018 19:09:38 -0700
changeset 794514 dd19d38a2b1cf02eebf9ef33f1a9a0e44f844338
parent 794513 76fdbe405fbd1237567bb70e218ef144a7190221
child 794515 c834c0c12a7fcdbeec7b82eac2c9a3fd80a1e90f
push id109697
push userbmo:sledru@mozilla.com
push dateSat, 12 May 2018 10:04:34 +0000
reviewersMs2ger
bugs1366287
milestone62.0a1
bug 1366287 - Part 1.2: Add a BigInt type to the Rust bindings. r=Ms2ger
js/rust/Cargo.toml
js/rust/build.rs
js/rust/src/jsval.rs
js/rust/src/rust.rs
js/src/Cargo.toml
js/src/build.rs
js/src/devtools/automation/variants/bigint
js/src/devtools/automation/variants/bigintdebug
--- a/js/rust/Cargo.toml
+++ b/js/rust/Cargo.toml
@@ -34,16 +34,17 @@ name = "vec_conversion"
 
 [lib]
 doctest = false
 
 [features]
 debugmozjs = ['mozjs_sys/debugmozjs']
 promises = ['mozjs_sys/promises']
 nonzero = []
+bigint = ['mozjs_sys/bigint']
 
 [dependencies.mozjs_sys]
 path = "../src"
 
 [dependencies]
 lazy_static = "1.0"
 libc = "0.2"
 log = "0.4"
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -68,16 +68,20 @@ fn build_jsapi_bindings() {
 
     if cfg!(feature = "debugmozjs") {
         builder = builder
             .clang_arg("-DJS_GC_ZEAL")
             .clang_arg("-DDEBUG")
             .clang_arg("-DJS_DEBUG");
     }
 
+    if cfg!(feature = "bigint") {
+        builder = builder.clang_arg("-DENABLE_BIGINT");
+    }
+
     let include_dir = get_mozjs_include_dir();
     let include_dir = include_dir.to_str()
         .expect("Path to mozjs include dir should be utf-8");
     builder = builder.clang_arg("-I");
     builder = builder.clang_arg(include_dir);
 
     for ty in UNSAFE_IMPL_SYNC_TYPES {
         builder = builder.raw_line(format!("unsafe impl Sync for {} {{}}", ty));
@@ -94,16 +98,20 @@ fn build_jsapi_bindings() {
     for var in WHITELIST_VARS {
         builder = builder.whitelist_var(var);
     }
 
     for func in WHITELIST_FUNCTIONS {
         builder = builder.whitelist_function(func);
     }
 
+    if cfg!(feature = "bigint") {
+        builder = builder.whitelist_type("JS::BigInt");
+    }
+
     for ty in OPAQUE_TYPES {
         builder = builder.opaque_type(ty);
     }
 
     for ty in BLACKLIST_TYPES {
         builder = builder.blacklist_type(ty);
     }
 
--- a/js/rust/src/jsval.rs
+++ b/js/rust/src/jsval.rs
@@ -20,48 +20,54 @@ const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
 #[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),
+    #[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),
 }
 
 #[cfg(target_pointer_width = "32")]
 #[repr(u32)]
 #[allow(dead_code)]
 #[derive(Clone, Copy, Debug)]
 enum ValueTag {
     PRIVATE   = 0,
     INT32     = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_INT32 as u32),
     UNDEFINED = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_UNDEFINED as u32),
     STRING    = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_STRING as u32),
     SYMBOL    = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_SYMBOL as u32),
+    #[cfg(feature = "bigint")]
+    BIGINT    = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BIGINT as u32),
     BOOLEAN   = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BOOLEAN as u32),
     MAGIC     = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_MAGIC as u32),
     NULL      = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_NULL as u32),
     OBJECT    = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_OBJECT as u32),
 }
 
 #[cfg(target_pointer_width = "64")]
 #[repr(u64)]
 #[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),
     SYMBOL     = ((ValueTag::SYMBOL as u64)     << JSVAL_TAG_SHIFT),
+    #[cfg(feature = "bigint")]
+    BIGINT     = ((ValueTag::BIGINT as u64)     << JSVAL_TAG_SHIFT),
     BOOLEAN    = ((ValueTag::BOOLEAN as u64)    << JSVAL_TAG_SHIFT),
     MAGIC      = ((ValueTag::MAGIC as u64)      << JSVAL_TAG_SHIFT),
     NULL       = ((ValueTag::NULL as u64)       << JSVAL_TAG_SHIFT),
     OBJECT     = ((ValueTag::OBJECT as u64)     << JSVAL_TAG_SHIFT),
 }
 
 
 #[cfg(target_pointer_width = "64")]
@@ -182,16 +188,33 @@ pub fn PrivateValue(o: *const c_void) ->
 #[cfg(target_pointer_width = "32")]
 #[inline(always)]
 pub fn PrivateValue(o: *const c_void) -> JS::Value {
     let ptrBits = o as usize as u64;
     assert!((ptrBits & 1) == 0);
     BuildJSVal(ValueTag::PRIVATE, ptrBits)
 }
 
+#[inline(always)]
+#[cfg(feature = "bigint")]
+#[cfg(target_pointer_width = "64")]
+pub fn BigIntValue(b: &JS::BigInt) -> JS::Value {
+    let bits = b as *const JS::BigInt as usize as u64;
+    assert!((bits >> JSVAL_TAG_SHIFT) == 0);
+    BuildJSVal(ValueTag::BIGINT, bits)
+}
+
+#[inline(always)]
+#[cfg(target_pointer_width = "32")]
+#[inline(always)]
+pub fn BigIntValue(s: &JS::BigInt) -> JS::Value {
+    let bits = s as *const JS::BigInt as usize as u64;
+    BuildJSVal(ValueTag::BIGINT, bits)
+}
+
 impl JS::Value {
     #[inline(always)]
     unsafe fn asBits(&self) -> u64 {
         self.asBits_
     }
 
     #[inline(always)]
     #[cfg(target_pointer_width = "64")]
@@ -359,16 +382,34 @@ impl JS::Value {
     #[cfg(target_pointer_width = "32")]
     pub fn is_symbol(&self) -> bool {
         unsafe {
             (self.asBits() >> 32) == ValueTag::SYMBOL as u64
         }
     }
 
     #[inline(always)]
+    #[cfg(feature = "bigint")]
+    #[cfg(target_pointer_width = "64")]
+    pub fn is_bigint(&self) -> bool {
+        unsafe {
+            (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BIGINT as u64
+        }
+    }
+
+    #[inline(always)]
+    #[cfg(feature = "bigint")]
+    #[cfg(target_pointer_width = "32")]
+    pub fn is_bigint(&self) -> bool {
+        unsafe {
+            (self.asBits() >> 32) == ValueTag::BIGINT as u64
+        }
+    }
+
+    #[inline(always)]
     #[cfg(target_pointer_width = "64")]
     pub fn to_boolean(&self) -> bool {
         assert!(self.is_boolean());
         unsafe {
             (self.asBits() & JSVAL_PAYLOAD_MASK) != 0
         }
     }
 
--- a/js/rust/src/rust.rs
+++ b/js/rust/src/rust.rs
@@ -301,16 +301,22 @@ impl RootKind for *mut JSString {
     fn rootKind() -> JS::RootKind { JS::RootKind::String }
 }
 
 impl RootKind for *mut JS::Symbol {
     #[inline(always)]
     fn rootKind() -> JS::RootKind { JS::RootKind::Symbol }
 }
 
+#[cfg(feature = "bigint")]
+impl RootKind for *mut JS::BigInt {
+    #[inline(always)]
+    fn rootKind() -> JS::RootKind { JS::RootKind::BigInt }
+}
+
 impl RootKind for *mut JSScript {
     #[inline(always)]
     fn rootKind() -> JS::RootKind { JS::RootKind::Script }
 }
 
 impl RootKind for jsid {
     #[inline(always)]
     fn rootKind() -> JS::RootKind { JS::RootKind::Id }
--- a/js/src/Cargo.toml
+++ b/js/src/Cargo.toml
@@ -3,16 +3,17 @@ name = "mozjs_sys"
 version = "0.0.0"
 authors = ["Mozilla"]
 links = "mozjs"
 build = "build.rs"
 
 [features]
 debugmozjs = []
 promises = []
+bigint = []
 
 [lib]
 name = "mozjs_sys"
 path = "lib.rs"
 
 [build-dependencies]
 num_cpus = "1.1.0"
 
--- a/js/src/build.rs
+++ b/js/src/build.rs
@@ -11,37 +11,35 @@ fn main() {
     let out_dir = env::var("OUT_DIR").expect("Should have env var OUT_DIR");
     let target = env::var("TARGET").expect("Should have env var TARGET");
 
     let js_src = env::var("CARGO_MANIFEST_DIR").expect("Should have env var CARGO_MANIFEST_DIR");
 
     env::set_var("MAKEFLAGS", format!("-j{}", num_cpus::get()));
     env::set_current_dir(&js_src).unwrap();
 
-    let variant = if cfg!(feature = "debugmozjs") {
-        "plaindebug"
-    } else {
-        "plain"
-    };
+    let variant = format!("{}{}",
+                          if cfg!(feature = "bigint") { "bigint" } else { "plain" },
+                          if cfg!(feature = "debugmozjs") { "debug" } else { "" });
 
     let python = env::var("PYTHON").unwrap_or("python2.7".into());
     let mut cmd = Command::new(&python);
     cmd.args(&["./devtools/automation/autospider.py",
                // Only build SpiderMonkey, don't run all the tests.
                "--build-only",
                // Disable Mozilla's jemalloc; Rust has its own jemalloc that we
                // can swap in instead and everything using a single malloc is
                // good.
                "--no-jemalloc",
                // Don't try to clobber the output directory. Without
                // this option, the build will fail because the directory
                // already exists but wasn't created by autospider.
                "--dep",
                "--objdir", &out_dir,
-               variant])
+               &variant])
         .env("SOURCE", &js_src)
         .env("PWD", &js_src)
         .stdout(Stdio::inherit())
         .stderr(Stdio::inherit());
     println!("Running command: {:?}", cmd);
     let result = cmd
         .status()
         .expect("Should spawn autospider OK");
@@ -49,16 +47,20 @@ fn main() {
 
     println!("cargo:rustc-link-search=native={}/js/src/build", out_dir);
     println!("cargo:rustc-link-search=native={}/js/src", out_dir);
     println!("cargo:rustc-link-lib=static=js_static");
 
     println!("cargo:rustc-link-search=native={}/dist/bin", out_dir);
     println!("cargo:rustc-link-lib=nspr4");
 
+    if cfg!(feature = "bigint") {
+        println!("cargo:rustc-link-lib=gmp");
+    }
+
     if target.contains("windows") {
         println!("cargo:rustc-link-lib=winmm");
         if target.contains("gnu") {
             println!("cargo:rustc-link-lib=stdc++");
         }
     } else {
         println!("cargo:rustc-link-lib=stdc++");
     }
new file mode 100644
--- /dev/null
+++ b/js/src/devtools/automation/variants/bigint
@@ -0,0 +1,7 @@
+{
+    "configure-args": "--enable-bigint",
+    "optimize": true,
+    "env": {
+        "JSTESTS_EXTRA_ARGS": "--jitflags=all"
+    }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/devtools/automation/variants/bigintdebug
@@ -0,0 +1,7 @@
+{
+    "configure-args": "--enable-bigint",
+    "debug": true,
+    "env": {
+        "JSTESTS_EXTRA_ARGS": "--jitflags=debug"
+    }
+}