diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 5bd784cee7a..6e80bfa929f 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -631,7 +631,7 @@ impl<'a> Context<'a> { if !self.exposed_globals.insert("slab") { return; } - self.global(&format!("let slab = [];")); + self.global(&format!("let slab = [null];")); } fn expose_global_slab_next(&mut self) { @@ -639,7 +639,8 @@ impl<'a> Context<'a> { return; } self.global(&format!(" - let slab_next = 0; + // Avoid 0 as an index to enable optimizing Option layout + let slab_next = 1; ")); } diff --git a/src/closure.rs b/src/closure.rs index d7227d83d40..809d3e6e40a 100644 --- a/src/closure.rs +++ b/src/closure.rs @@ -7,6 +7,7 @@ use std::cell::UnsafeCell; use std::marker::Unsize; use std::mem::{self, ManuallyDrop}; +use std::num::NonZeroU32; use std::prelude::v1::*; use JsValue; @@ -95,9 +96,12 @@ impl Closure /// /// This is the function where the JS closure is manufactured. pub fn wrap(t: Box) -> Closure { + let idx = unsafe { + NonZeroU32::new_unchecked(!0) + }; Closure { inner: UnsafeCell::new(t), - js: UnsafeCell::new(ManuallyDrop::new(JsValue { idx: !0 })), + js: UnsafeCell::new(ManuallyDrop::new(JsValue { idx })), } } @@ -114,7 +118,7 @@ impl Closure /// cleanup as it can. pub fn forget(self) { unsafe { - let idx = (*self.js.get()).idx; + let idx = (*self.js.get()).idx.get(); if idx != !0 { super::__wbindgen_cb_forget(idx); } @@ -142,7 +146,7 @@ impl<'a, T> IntoWasmAbi for &'a Closure unsafe { let fnptr = WasmClosure::into_abi(&mut **self.inner.get(), extra); extra.push(fnptr); - &mut (*self.js.get()).idx as *const u32 as u32 + &mut (*self.js.get()).idx.get() as *const u32 as u32 } } } @@ -162,7 +166,7 @@ impl Drop for Closure { fn drop(&mut self) { unsafe { - let idx = (*self.js.get()).idx; + let idx = (*self.js.get()).idx.get(); if idx != !0 { super::__wbindgen_cb_drop(idx); } diff --git a/src/convert.rs b/src/convert.rs index 80d49f249c4..3348e91da2e 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -2,6 +2,7 @@ //! at your own risk. use core::mem::{self, ManuallyDrop}; +use core::num::NonZeroU32; use core::ops::{Deref, DerefMut}; use core::slice; use core::str; @@ -242,7 +243,7 @@ impl IntoWasmAbi for JsValue { type Abi = u32; fn into_abi(self, _extra: &mut Stack) -> u32 { - let ret = self.idx; + let ret = self.idx.get(); mem::forget(self); return ret } @@ -252,14 +253,14 @@ impl FromWasmAbi for JsValue { type Abi = u32; unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue { - JsValue { idx: js } + JsValue { idx: NonZeroU32::new_unchecked(js) } } } impl<'a> IntoWasmAbi for &'a JsValue { type Abi = u32; fn into_abi(self, _extra: &mut Stack) -> u32 { - self.idx + self.idx.get() } } @@ -268,7 +269,7 @@ impl RefFromWasmAbi for JsValue { type Anchor = ManuallyDrop; unsafe fn ref_from_abi(js: u32, _extra: &mut Stack) -> Self::Anchor { - ManuallyDrop::new(JsValue { idx: js }) + ManuallyDrop::new(JsValue { idx: NonZeroU32::new_unchecked(js) }) } } diff --git a/src/lib.rs b/src/lib.rs index 85667269e97..7e3999006a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,12 +5,13 @@ //! this crate and this crate also provides JS bindings through the `JsValue` //! interface. -#![feature(use_extern_macros, wasm_import_module, try_reserve, unsize)] +#![feature(use_extern_macros, wasm_import_module, try_reserve, unsize, nonzero)] #![no_std] extern crate wasm_bindgen_macro; use core::cell::UnsafeCell; +use core::num::NonZeroU32; use core::ops::Deref; use core::ptr; @@ -52,7 +53,7 @@ if_std! { /// will transfer into wasm directly and this will likely become more efficient, /// but for now it may be slightly slow. pub struct JsValue { - idx: u32, + idx: NonZeroU32, } impl JsValue { @@ -62,7 +63,7 @@ impl JsValue { /// be owned by the JS garbage collector. pub fn from_str(s: &str) -> JsValue { unsafe { - JsValue { idx: __wbindgen_string_new(s.as_ptr(), s.len()) } + JsValue { idx: NonZeroU32::new_unchecked(__wbindgen_string_new(s.as_ptr(), s.len())) } } } @@ -72,7 +73,7 @@ impl JsValue { /// allocated number) and returns a handle to the JS version of it. pub fn from_f64(n: f64) -> JsValue { unsafe { - JsValue { idx: __wbindgen_number_new(n) } + JsValue { idx: NonZeroU32::new_unchecked(__wbindgen_number_new(n)) } } } @@ -82,21 +83,21 @@ impl JsValue { /// allocated boolean) and returns a handle to the JS version of it. pub fn from_bool(b: bool) -> JsValue { unsafe { - JsValue { idx: __wbindgen_boolean_new(b as u32) } + JsValue { idx: NonZeroU32::new_unchecked(__wbindgen_boolean_new(b as u32)) } } } /// Creates a new JS value representing `undefined`. pub fn undefined() -> JsValue { unsafe { - JsValue { idx: __wbindgen_undefined_new() } + JsValue { idx: NonZeroU32::new_unchecked(__wbindgen_undefined_new()) } } } /// Creates a new JS value representing `null`. pub fn null() -> JsValue { unsafe { - JsValue { idx: __wbindgen_null_new() } + JsValue { idx: NonZeroU32::new_unchecked(__wbindgen_null_new()) } } } @@ -108,7 +109,7 @@ impl JsValue { unsafe { let ptr = description.map(|s| s.as_ptr()).unwrap_or(ptr::null()); let len = description.map(|s| s.len()).unwrap_or(0); - JsValue { idx: __wbindgen_symbol_new(ptr, len) } + JsValue { idx: NonZeroU32::new_unchecked(__wbindgen_symbol_new(ptr, len)) } } } @@ -137,7 +138,7 @@ impl JsValue { pub fn as_f64(&self) -> Option { let mut invalid = 0; unsafe { - let ret = __wbindgen_number_get(self.idx, &mut invalid); + let ret = __wbindgen_number_get(self.idx.get(), &mut invalid); if invalid == 1 { None } else { @@ -155,7 +156,7 @@ impl JsValue { pub fn as_string(&self) -> Option { unsafe { let mut len = 0; - let ptr = __wbindgen_string_get(self.idx, &mut len); + let ptr = __wbindgen_string_get(self.idx.get(), &mut len); if ptr.is_null() { None } else { @@ -172,7 +173,7 @@ impl JsValue { /// `None`. pub fn as_bool(&self) -> Option { unsafe { - match __wbindgen_boolean_get(self.idx) { + match __wbindgen_boolean_get(self.idx.get()) { 0 => Some(false), 1 => Some(true), _ => None, @@ -183,21 +184,21 @@ impl JsValue { /// Tests whether this JS value is `null` pub fn is_null(&self) -> bool { unsafe { - __wbindgen_is_null(self.idx) == 1 + __wbindgen_is_null(self.idx.get()) == 1 } } /// Tests whether this JS value is `undefined` pub fn is_undefined(&self) -> bool { unsafe { - __wbindgen_is_undefined(self.idx) == 1 + __wbindgen_is_undefined(self.idx.get()) == 1 } } /// Tests whether the type of this JS value is `symbol` pub fn is_symbol(&self) -> bool { unsafe { - __wbindgen_is_symbol(self.idx) == 1 + __wbindgen_is_symbol(self.idx.get()) == 1 } } } @@ -269,8 +270,8 @@ extern { impl Clone for JsValue { fn clone(&self) -> JsValue { unsafe { - let idx = __wbindgen_object_clone_ref(self.idx); - JsValue { idx } + let idx = __wbindgen_object_clone_ref(self.idx.get()); + JsValue { idx: NonZeroU32::new_unchecked(idx) } } } } @@ -278,7 +279,7 @@ impl Clone for JsValue { impl Drop for JsValue { fn drop(&mut self) { unsafe { - __wbindgen_object_drop_ref(self.idx); + __wbindgen_object_drop_ref(self.idx.get()); } } }