From c496aa16a03734659dba7c152737f0e5a80fd2b9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 11 Oct 2017 23:40:31 +0200 Subject: [PATCH 01/18] Rename the 'unstable' feature of the selectors crate to 'bench' --- components/selectors/Cargo.toml | 2 +- components/selectors/bloom.rs | 2 +- components/selectors/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/selectors/Cargo.toml b/components/selectors/Cargo.toml index a7df20358fa..68681c5dbc5 100644 --- a/components/selectors/Cargo.toml +++ b/components/selectors/Cargo.toml @@ -20,7 +20,7 @@ doctest = false [features] gecko_like_types = [] -unstable = [] +bench = [] [dependencies] bitflags = "0.7" diff --git a/components/selectors/bloom.rs b/components/selectors/bloom.rs index 2b96e4f51f8..d9cb269dbcf 100644 --- a/components/selectors/bloom.rs +++ b/components/selectors/bloom.rs @@ -346,7 +346,7 @@ fn create_and_insert_some_stuff() { } } -#[cfg(feature = "unstable")] +#[cfg(feature = "bench")] #[cfg(test)] mod bench { extern crate test; diff --git a/components/selectors/lib.rs b/components/selectors/lib.rs index 49c107e73d0..c8e7ce175d5 100644 --- a/components/selectors/lib.rs +++ b/components/selectors/lib.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // Make |cargo bench| work. -#![cfg_attr(feature = "unstable", feature(test))] +#![cfg_attr(feature = "bench", feature(test))] #[macro_use] extern crate bitflags; #[macro_use] extern crate cssparser; From 132b540518c7916be2edab58901c45b97fe8f2b3 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 11 Oct 2017 23:41:06 +0200 Subject: [PATCH 02/18] Add an 'unstable' top-level cargo feature to control optional unstable stuff. --- components/compositing/Cargo.toml | 2 +- components/geometry/Cargo.toml | 4 ---- components/layout_thread/Cargo.toml | 5 ++++- components/servo/Cargo.toml | 1 + ports/servo/Cargo.toml | 3 ++- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 40e5b724f1a..51d48fd00ca 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -21,7 +21,7 @@ net_traits = {path = "../net_traits"} profile_traits = {path = "../profile_traits"} script_traits = {path = "../script_traits"} servo_config = {path = "../config"} -servo_geometry = {path = "../geometry", features = ["servo"]} +servo_geometry = {path = "../geometry"} servo_url = {path = "../url"} style_traits = {path = "../style_traits"} time = "0.1.17" diff --git a/components/geometry/Cargo.toml b/components/geometry/Cargo.toml index 956337a06cc..68da8f383f1 100644 --- a/components/geometry/Cargo.toml +++ b/components/geometry/Cargo.toml @@ -9,10 +9,6 @@ publish = false name = "servo_geometry" path = "lib.rs" -[features] -# servo as opposed to geckolib -servo = ["euclid/unstable"] - [dependencies] app_units = "0.5" euclid = "0.15" diff --git a/components/layout_thread/Cargo.toml b/components/layout_thread/Cargo.toml index b83c648b0a6..eea55c032df 100644 --- a/components/layout_thread/Cargo.toml +++ b/components/layout_thread/Cargo.toml @@ -9,6 +9,9 @@ publish = false name = "layout_thread" path = "lib.rs" +[features] +unstable = ["parking_lot/nightly"] + [dependencies] app_units = "0.5" atomic_refcell = "0.1" @@ -26,7 +29,7 @@ log = "0.3.5" metrics = {path = "../metrics"} msg = {path = "../msg"} net_traits = {path = "../net_traits"} -parking_lot = {version = "0.4", features = ["nightly"]} +parking_lot = "0.4" profile_traits = {path = "../profile_traits"} range = {path = "../range"} rayon = "0.8" diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 24e60111214..efc51ea0840 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -19,6 +19,7 @@ energy-profiling = ["profile_traits/energy-profiling"] debugmozjs = ["script/debugmozjs"] googlevr = ["webvr/googlevr"] oculusvr = ["webvr/oculusvr"] +unstable = ["euclid/unstable", "layout_thread/unstable"] [dependencies] bluetooth_traits = {path = "../bluetooth_traits"} diff --git a/ports/servo/Cargo.toml b/ports/servo/Cargo.toml index 80b9c19b831..32e5e8433f6 100644 --- a/ports/servo/Cargo.toml +++ b/ports/servo/Cargo.toml @@ -29,13 +29,14 @@ servo_remutex_tests = {path = "../../tests/unit/servo_remutex"} style_tests = {path = "../../tests/unit/style"} [features] -default = ["webdriver", "max_log_level"] +default = ["webdriver", "max_log_level", "unstable"] max_log_level = ["log/release_max_level_info"] webdriver = ["libservo/webdriver_server"] energy-profiling = ["libservo/energy-profiling"] debugmozjs = ["libservo/debugmozjs"] googlevr = ["libservo/googlevr"] oculusvr = ["libservo/oculusvr"] +unstable = ["libservo/unstable"] [dependencies] backtrace = "0.3" From faff7806b94c62baec964b9a53296499b2fe8e30 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 11 Oct 2017 23:53:13 +0200 Subject: [PATCH 03/18] Remove default features in components/servo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are covered by ports/servo’s defaults. --- components/servo/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index efc51ea0840..86994a945d1 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -12,7 +12,6 @@ path = "lib.rs" crate-type = ["rlib"] [features] -default = ["webdriver", "max_log_level"] max_log_level = ["log/release_max_level_info"] webdriver = ["webdriver_server"] energy-profiling = ["profile_traits/energy-profiling"] From c4bf3ec14f01c4ff2660f2b870a936b4302da394 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 00:28:31 +0200 Subject: [PATCH 04/18] Add a nonzero crate --- components/nonzero/Cargo.toml | 15 +++++++++++++ components/nonzero/lib.rs | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 components/nonzero/Cargo.toml create mode 100644 components/nonzero/lib.rs diff --git a/components/nonzero/Cargo.toml b/components/nonzero/Cargo.toml new file mode 100644 index 00000000000..15ba28f7eae --- /dev/null +++ b/components/nonzero/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "nonzero" +version = "0.0.1" +authors = ["The Servo Project Developers"] +license = "MPL-2.0" +publish = false + +[lib] +path = "lib.rs" + +[features] +unstable = ["serde/unstable"] + +[dependencies] +serde = "1.0.14" diff --git a/components/nonzero/lib.rs b/components/nonzero/lib.rs new file mode 100644 index 00000000000..a787e647165 --- /dev/null +++ b/components/nonzero/lib.rs @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! `NonZero*` types that are either `core::nonzero::NonZero<_>` +//! or some stable types with an equivalent API (but no memory layout optimization). + +#![cfg_attr(feature = "unstable", feature(nonzero))] + +#[cfg(not(feature = "unstable"))] +#[macro_use] +extern crate serde; + +pub use imp::*; + +#[cfg(feature = "unstable")] +mod imp { + extern crate core; + use self::core::nonzero::NonZero; + + pub type NonZeroU32 = NonZero; +} + +#[cfg(not(feature = "unstable"))] +mod imp { + #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] + pub struct NonZeroU32(u32); + + impl NonZeroU32 { + pub fn new(x: u32) -> Option { + if x != 0 { + Some(NonZeroU32(x)) + } else { + None + } + } + + pub fn get(self) -> u32 { + self.0 + } + } +} From 57709dc0bf57d8042b1e57c6281c9cd4a6f6feb1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 00:28:50 +0200 Subject: [PATCH 05/18] Use the new nonzero crate in the msg crate --- Cargo.lock | 9 +++++++++ components/compositing/Cargo.toml | 4 ++++ components/compositing/compositor.rs | 4 ++-- components/compositing/lib.rs | 4 ++-- components/msg/Cargo.toml | 6 +++++- components/msg/constellation_msg.rs | 18 +++++++++++------- components/msg/lib.rs | 8 ++++---- components/servo/Cargo.toml | 7 ++++++- 8 files changed, 43 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee8a17753dd..77ebe5633f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -473,6 +473,7 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", + "nonzero 0.0.1", "profile_traits 0.0.1", "script_traits 0.0.1", "servo_config 0.0.1", @@ -1907,6 +1908,7 @@ dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "nonzero 0.0.1", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.52.0 (git+https://github.com/servo/webrender)", ] @@ -2046,6 +2048,13 @@ name = "nom" version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nonzero" +version = "0.0.1" +dependencies = [ + "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nsstring_vendor" version = "0.1.0" diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 51d48fd00ca..236cf14443c 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -9,6 +9,9 @@ publish = false name = "compositing" path = "lib.rs" +[features] +unstable = ["nonzero/unstable"] + [dependencies] euclid = "0.15" gfx_traits = {path = "../gfx_traits"} @@ -18,6 +21,7 @@ ipc-channel = "0.8" log = "0.3.5" msg = {path = "../msg"} net_traits = {path = "../net_traits"} +nonzero = {path = "../nonzero"} profile_traits = {path = "../profile_traits"} script_traits = {path = "../script_traits"} servo_config = {path = "../config"} diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 35e8a9340ef..7e77157b845 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -6,7 +6,6 @@ use CompositionPipeline; use SendableFrameTree; use compositor_thread::{CompositorProxy, CompositorReceiver}; use compositor_thread::{InitialCompositorState, Msg, RenderListener}; -use core::nonzero::NonZero; use euclid::{Point2D, TypedPoint2D, TypedVector2D, ScaleFactor}; use gfx_traits::Epoch; use gleam::gl; @@ -14,6 +13,7 @@ use image::{DynamicImage, ImageFormat, RgbImage}; use ipc_channel::ipc::{self, IpcSharedMemory}; use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId}; use net_traits::image::base::{Image, PixelFormat}; +use nonzero::NonZeroU32; use profile_traits::time::{self, ProfilerCategory, profile}; use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg}; use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton}; @@ -62,7 +62,7 @@ impl ConvertPipelineIdFromWebRender for webrender_api::PipelineId { fn from_webrender(&self) -> PipelineId { PipelineId { namespace_id: PipelineNamespaceId(self.0), - index: PipelineIndex(NonZero::new(self.1).expect("Webrender pipeline zero?")), + index: PipelineIndex(NonZeroU32::new(self.1).expect("Webrender pipeline zero?")), } } } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index 4e2af3b02f1..ee053c47182 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -3,9 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![deny(unsafe_code)] -#![feature(nonzero)] +#![cfg_attr(feature = "unstable", feature(nonzero))] -extern crate core; extern crate euclid; extern crate gfx_traits; extern crate gleam; @@ -15,6 +14,7 @@ extern crate ipc_channel; extern crate log; extern crate msg; extern crate net_traits; +extern crate nonzero; extern crate profile_traits; extern crate script_traits; extern crate servo_config; diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml index 3cb93c28572..0f1e39e8182 100644 --- a/components/msg/Cargo.toml +++ b/components/msg/Cargo.toml @@ -9,9 +9,13 @@ publish = false name = "msg" path = "lib.rs" +[features] +unstable = ["nonzero/unstable"] + [dependencies] bitflags = "0.7" heapsize = "0.4" heapsize_derive = "0.1" -serde = { version = "1.0.14", features = [ "unstable" ] } +nonzero = {path = "../nonzero"} +serde = "1.0.14" webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 823db993b38..da9bb3ea0cb 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -5,7 +5,7 @@ //! The high-level interface from script to constellation. Using this abstract interface helps //! reduce coupling between these two components. -use core::nonzero::NonZero; +use nonzero::NonZeroU32; use std::cell::Cell; use std::fmt; use webrender_api; @@ -195,9 +195,9 @@ impl PipelineNamespace { }); } - fn next_index(&mut self) -> NonZero { + fn next_index(&mut self) -> NonZeroU32 { self.index += 1; - NonZero::new(self.index).expect("pipeline id index wrapped!") + NonZeroU32::new(self.index).expect("pipeline id index wrapped!") } fn next_pipeline_id(&mut self) -> PipelineId { @@ -221,7 +221,7 @@ thread_local!(pub static PIPELINE_NAMESPACE: Cell> = C pub struct PipelineNamespaceId(pub u32); #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct PipelineIndex(pub NonZero); +pub struct PipelineIndex(pub NonZeroU32); known_heap_size!(0, PipelineIndex); #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd, Serialize)] @@ -264,7 +264,7 @@ impl fmt::Display for PipelineId { } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct BrowsingContextIndex(pub NonZero); +pub struct BrowsingContextIndex(pub NonZeroU32); known_heap_size!(0, BrowsingContextIndex); #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd, Serialize)] @@ -339,11 +339,15 @@ impl PartialEq for TopLevelBrowsingContextId { // We provide ids just for unit testing. pub const TEST_NAMESPACE: PipelineNamespaceId = PipelineNamespaceId(1234); #[allow(unsafe_code)] -pub const TEST_PIPELINE_INDEX: PipelineIndex = unsafe { PipelineIndex(NonZero::new_unchecked(5678)) }; +#[cfg(feature = "unstable")] +pub const TEST_PIPELINE_INDEX: PipelineIndex = unsafe { PipelineIndex(NonZeroU32::new_unchecked(5678)) }; +#[cfg(feature = "unstable")] pub const TEST_PIPELINE_ID: PipelineId = PipelineId { namespace_id: TEST_NAMESPACE, index: TEST_PIPELINE_INDEX }; #[allow(unsafe_code)] +#[cfg(feature = "unstable")] pub const TEST_BROWSING_CONTEXT_INDEX: BrowsingContextIndex = - unsafe { BrowsingContextIndex(NonZero::new_unchecked(8765)) }; + unsafe { BrowsingContextIndex(NonZeroU32::new_unchecked(8765)) }; +#[cfg(feature = "unstable")] pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId = BrowsingContextId { namespace_id: TEST_NAMESPACE, index: TEST_BROWSING_CONTEXT_INDEX }; diff --git a/components/msg/lib.rs b/components/msg/lib.rs index 0876603c1a5..b1743ad02a9 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -2,16 +2,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#![feature(const_fn)] -#![feature(const_nonzero_new)] -#![feature(nonzero)] +#![cfg_attr(feature = "unstable", feature(nonzero))] +#![cfg_attr(feature = "unstable", feature(const_fn))] +#![cfg_attr(feature = "unstable", feature(const_nonzero_new))] #![deny(unsafe_code)] #[macro_use] extern crate bitflags; -extern crate core; #[macro_use] extern crate heapsize; #[macro_use] extern crate heapsize_derive; +extern crate nonzero; #[macro_use] extern crate serde; extern crate webrender_api; diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 86994a945d1..ddfb938850b 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -18,7 +18,12 @@ energy-profiling = ["profile_traits/energy-profiling"] debugmozjs = ["script/debugmozjs"] googlevr = ["webvr/googlevr"] oculusvr = ["webvr/oculusvr"] -unstable = ["euclid/unstable", "layout_thread/unstable"] +unstable = [ + "euclid/unstable", + "layout_thread/unstable", + "msg/unstable", + "compositing/unstable" +] [dependencies] bluetooth_traits = {path = "../bluetooth_traits"} From 8cdf2ad0ed7dbde5a35949606851bc34f603b423 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 00:37:00 +0200 Subject: [PATCH 06/18] Add NonZeroUsize --- components/nonzero/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/components/nonzero/lib.rs b/components/nonzero/lib.rs index a787e647165..4ba341aee5f 100644 --- a/components/nonzero/lib.rs +++ b/components/nonzero/lib.rs @@ -19,10 +19,14 @@ mod imp { use self::core::nonzero::NonZero; pub type NonZeroU32 = NonZero; + pub type NonZeroUsize = NonZero; } #[cfg(not(feature = "unstable"))] mod imp { + use std::cmp; + use std::hash; + #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct NonZeroU32(u32); @@ -39,4 +43,45 @@ mod imp { self.0 } } + + #[derive(Clone, Copy, Debug, Eq)] + pub struct NonZeroUsize(&'static ()); + + impl NonZeroUsize { + pub fn new(x: usize) -> Option { + if x != 0 { + Some(NonZeroUsize(unsafe { &*(x as *const ()) })) + } else { + None + } + } + + pub fn get(self) -> usize { + self.0 as *const () as usize + } + } + + impl PartialEq for NonZeroUsize { + fn eq(&self, other: &Self) -> bool { + self.get() == other.get() + } + } + + impl PartialOrd for NonZeroUsize { + fn partial_cmp(&self, other: &Self) -> Option { + self.get().partial_cmp(&other.get()) + } + } + + impl Ord for NonZeroUsize { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.get().cmp(&other.get()) + } + } + + impl hash::Hash for NonZeroUsize { + fn hash(&self, hasher: &mut H) { + self.get().hash(hasher) + } + } } From ecf3b05153d3e00bea1c1c2476ac0dfd880f3b8d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 00:37:11 +0200 Subject: [PATCH 07/18] Use NonZeroUsize in remutex --- Cargo.lock | 1 + components/constellation/Cargo.toml | 3 +++ components/remutex/Cargo.toml | 4 ++++ components/remutex/lib.rs | 14 +++++++------- components/servo/Cargo.toml | 3 ++- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77ebe5633f7..8a99d247fc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2992,6 +2992,7 @@ version = "0.0.1" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "nonzero 0.0.1", ] [[package]] diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index 2d659bd4342..b9d6177273b 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -9,6 +9,9 @@ publish = false name = "constellation" path = "lib.rs" +[features] +unstable = ["servo_remutex/unstable"] + [dependencies] backtrace = "0.3" bluetooth_traits = { path = "../bluetooth_traits" } diff --git a/components/remutex/Cargo.toml b/components/remutex/Cargo.toml index 8bb165d40df..b3937587a62 100644 --- a/components/remutex/Cargo.toml +++ b/components/remutex/Cargo.toml @@ -9,6 +9,10 @@ publish = false name = "servo_remutex" path = "lib.rs" +[features] +unstable = ["nonzero/unstable"] + [dependencies] lazy_static = "0.2" log = "0.3.5" +nonzero = {path = "../nonzero"} diff --git a/components/remutex/lib.rs b/components/remutex/lib.rs index 8f97da8351f..6793429bf1e 100644 --- a/components/remutex/lib.rs +++ b/components/remutex/lib.rs @@ -10,13 +10,13 @@ //! It provides the same interface as https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/remutex.rs //! so if those types are ever exported, we should be able to replace this implemtation. -#![feature(nonzero)] +#![cfg_attr(feature = "unstable", feature(nonzero))] -extern crate core; +extern crate nonzero; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -use core::nonzero::NonZero; +use nonzero::NonZeroUsize; use std::cell::{Cell, UnsafeCell}; use std::ops::Deref; use std::sync::{LockResult, Mutex, MutexGuard, PoisonError, TryLockError, TryLockResult}; @@ -27,7 +27,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; // TODO: can we use the thread-id crate for this? #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct ThreadId(NonZero); +pub struct ThreadId(NonZeroUsize); lazy_static!{ static ref THREAD_COUNT: AtomicUsize = AtomicUsize::new(1); } @@ -35,7 +35,7 @@ impl ThreadId { #[allow(unsafe_code)] fn new() -> ThreadId { let number = THREAD_COUNT.fetch_add(1, Ordering::SeqCst); - ThreadId(NonZero::new(number).unwrap()) + ThreadId(NonZeroUsize::new(number).unwrap()) } pub fn current() -> ThreadId { THREAD_ID.with(|tls| tls.clone()) @@ -59,13 +59,13 @@ impl AtomicOptThreadId { #[allow(unsafe_code)] pub fn load(&self, ordering: Ordering) -> Option { let number = self.0.load(ordering); - NonZero::new(number).map(ThreadId) + NonZeroUsize::new(number).map(ThreadId) } #[allow(unsafe_code)] pub fn swap(&self, value: Option, ordering: Ordering) -> Option { let number = value.map(|id| id.0.get()).unwrap_or(0); let number = self.0.swap(number, ordering); - NonZero::new(number).map(ThreadId) + NonZeroUsize::new(number).map(ThreadId) } } diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index ddfb938850b..55225482b46 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -22,7 +22,8 @@ unstable = [ "euclid/unstable", "layout_thread/unstable", "msg/unstable", - "compositing/unstable" + "compositing/unstable", + "constellation/unstable", ] [dependencies] From 5e72173e8cbb0006af6fffa0d8bceeda014d825d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 00:49:39 +0200 Subject: [PATCH 08/18] Use NonZeroU32 in canvas_traits --- Cargo.lock | 1 + components/canvas_traits/Cargo.toml | 4 ++++ components/canvas_traits/lib.rs | 5 +++-- components/canvas_traits/webgl.rs | 6 +++--- components/nonzero/lib.rs | 4 ++++ components/servo/Cargo.toml | 1 + 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a99d247fc8..998660b30ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,6 +326,7 @@ dependencies = [ "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "nonzero 0.0.1", "offscreen_gl_context 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "servo_config 0.0.1", diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml index 091c01dc630..d60efb69ad4 100644 --- a/components/canvas_traits/Cargo.toml +++ b/components/canvas_traits/Cargo.toml @@ -9,6 +9,9 @@ publish = false name = "canvas_traits" path = "lib.rs" +[features] +unstable = ["nonzero/unstable"] + [dependencies] cssparser = "0.22.0" euclid = "0.15" @@ -16,6 +19,7 @@ heapsize = "0.4" heapsize_derive = "0.1" ipc-channel = "0.8" lazy_static = "0.2" +nonzero = {path = "../nonzero"} offscreen_gl_context = { version = "0.11", features = ["serde"] } serde = "1.0" servo_config = {path = "../config"} diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 7830d669e3e..8ca51a3ddde 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -4,17 +4,18 @@ #![crate_name = "canvas_traits"] #![crate_type = "rlib"] -#![feature(nonzero)] + +#![cfg_attr(feature = "unstable", feature(nonzero))] #![deny(unsafe_code)] -extern crate core; extern crate cssparser; extern crate euclid; extern crate heapsize; #[macro_use] extern crate heapsize_derive; extern crate ipc_channel; #[macro_use] extern crate lazy_static; +extern crate nonzero; extern crate offscreen_gl_context; #[macro_use] extern crate serde; extern crate servo_config; diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs index 92a66013f4f..98c4115c69c 100644 --- a/components/canvas_traits/webgl.rs +++ b/components/canvas_traits/webgl.rs @@ -2,8 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use core::nonzero::NonZero; use euclid::Size2D; +use nonzero::NonZeroU32; use offscreen_gl_context::{GLContextAttributes, GLLimits}; use std::fmt; use webrender_api; @@ -242,13 +242,13 @@ pub enum WebGLCommand { macro_rules! define_resource_id_struct { ($name:ident) => { #[derive(Clone, Copy, Eq, Hash, PartialEq)] - pub struct $name(NonZero); + pub struct $name(NonZeroU32); impl $name { #[allow(unsafe_code)] #[inline] pub unsafe fn new(id: u32) -> Self { - $name(NonZero::new_unchecked(id)) + $name(NonZeroU32::new_unchecked(id)) } #[inline] diff --git a/components/nonzero/lib.rs b/components/nonzero/lib.rs index 4ba341aee5f..efc6eca2f0a 100644 --- a/components/nonzero/lib.rs +++ b/components/nonzero/lib.rs @@ -39,6 +39,10 @@ mod imp { } } + pub unsafe fn new_unchecked(x: u32) -> Self { + NonZeroU32(x) + } + pub fn get(self) -> u32 { self.0 } diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 55225482b46..d57f1cab270 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -22,6 +22,7 @@ unstable = [ "euclid/unstable", "layout_thread/unstable", "msg/unstable", + "canvas_traits/unstable", "compositing/unstable", "constellation/unstable", ] From d9a311963f8b427ada69b94954e58b0131cd7364 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 00:59:37 +0200 Subject: [PATCH 09/18] Make usage of simd in gfx optional --- components/gfx/Cargo.toml | 5 ++++- components/gfx/lib.rs | 3 ++- components/gfx/text/glyph.rs | 7 +++++-- components/servo/Cargo.toml | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index 3d7aea1b59f..c8ee2d49629 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -10,6 +10,9 @@ publish = false name = "gfx" path = "lib.rs" +[features] +unstable = ["simd"] + [dependencies] app_units = "0.5" bitflags = "0.7" @@ -58,7 +61,7 @@ servo-fontconfig = "0.2.1" xml5ever = {version = "0.10"} [target.'cfg(any(target_feature = "sse2", target_feature = "neon"))'.dependencies] -simd = "0.2.0" +simd = {version = "0.2.0", optional = true} [target.'cfg(target_os = "windows")'.dependencies] dwrote = "0.4" diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index 98df742c183..e2f6eb56e04 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -3,8 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // For SIMD +#![cfg_attr(feature = "unstable", feature(cfg_target_feature))] #![cfg_attr(any(target_os = "linux", target_os = "android"), feature(allocator_api))] -#![feature(cfg_target_feature)] #![deny(unsafe_code)] @@ -53,6 +53,7 @@ extern crate servo_arc; extern crate servo_geometry; extern crate servo_url; #[macro_use] extern crate servo_atoms; +#[cfg(feature = "unstable")] #[cfg(any(target_feature = "sse2", target_feature = "neon"))] extern crate simd; extern crate smallvec; diff --git a/components/gfx/text/glyph.rs b/components/gfx/text/glyph.rs index c0e1be96da7..e765f48ee20 100644 --- a/components/gfx/text/glyph.rs +++ b/components/gfx/text/glyph.rs @@ -5,7 +5,7 @@ use app_units::Au; use euclid::Point2D; use range::{self, EachIndex, Range, RangeIndex}; -#[cfg(any(target_feature = "sse2", target_feature = "neon"))] +#[cfg(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon")))] use simd::u32x4; use std::{fmt, mem, u16}; use std::cmp::{Ordering, PartialOrd}; @@ -74,6 +74,7 @@ pub type GlyphId = u32; // TODO: make this more type-safe. const FLAG_CHAR_IS_SPACE: u32 = 0x40000000; +#[cfg(feature = "unstable")] #[cfg(any(target_feature = "sse2", target_feature = "neon"))] const FLAG_CHAR_IS_SPACE_SHIFT: u32 = 30; const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000; @@ -591,6 +592,7 @@ impl<'a> GlyphStore { } #[inline] + #[cfg(feature = "unstable")] #[cfg(any(target_feature = "sse2", target_feature = "neon"))] fn advance_for_byte_range_simple_glyphs(&self, range: &Range, extra_word_spacing: Au) -> Au { let advance_mask = u32x4::splat(GLYPH_ADVANCE_MASK); @@ -634,13 +636,14 @@ impl<'a> GlyphStore { /// When SIMD isn't available, fallback to the slow path. #[inline] - #[cfg(not(any(target_feature = "sse2", target_feature = "neon")))] + #[cfg(not(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon"))))] fn advance_for_byte_range_simple_glyphs(&self, range: &Range, extra_word_spacing: Au) -> Au { self.advance_for_byte_range_slow_path(range, extra_word_spacing) } /// Used for SIMD. #[inline] + #[cfg(feature = "unstable")] #[cfg(any(target_feature = "sse2", target_feature = "neon"))] #[allow(unsafe_code)] fn transmute_entry_buffer_to_u32_buffer(&self) -> &[u32] { diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index d57f1cab270..016ccc43a76 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -25,6 +25,7 @@ unstable = [ "canvas_traits/unstable", "compositing/unstable", "constellation/unstable", + "gfx/unstable", ] [dependencies] From d6d772eba0d873c3fa079c0b5a8084b91c73eefa Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 01:36:34 +0200 Subject: [PATCH 10/18] Make use of unstable alloc_jemalloc crate optional --- components/profile/Cargo.toml | 3 +++ components/profile/lib.rs | 5 +++-- components/profile/mem.rs | 20 +++++++++++--------- components/servo/Cargo.toml | 1 + 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/components/profile/Cargo.toml b/components/profile/Cargo.toml index 7fbe3db8bca..a02914db61d 100644 --- a/components/profile/Cargo.toml +++ b/components/profile/Cargo.toml @@ -9,6 +9,9 @@ publish = false name = "profile" path = "lib.rs" +[features] +unstable = [] + [dependencies] profile_traits = {path = "../profile_traits"} influent = "0.4" diff --git a/components/profile/lib.rs b/components/profile/lib.rs index 5573907a1c9..96b8edb7e17 100644 --- a/components/profile/lib.rs +++ b/components/profile/lib.rs @@ -2,16 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#![cfg_attr(not(target_os = "windows"), feature(alloc_jemalloc))] +#![cfg_attr(all(feature = "unstable", not(target_os = "windows")), feature(alloc_jemalloc))] #![deny(unsafe_code)] #[allow(unused_extern_crates)] -#[cfg(not(target_os = "windows"))] +#[cfg(all(feature = "unstable", not(target_os = "windows")))] extern crate alloc_jemalloc; extern crate heartbeats_simple; extern crate influent; extern crate ipc_channel; +#[allow(unused_extern_crates)] #[cfg(not(target_os = "windows"))] extern crate libc; #[macro_use] diff --git a/components/profile/mem.rs b/components/profile/mem.rs index 51d51fa23e9..39d3f3ad084 100644 --- a/components/profile/mem.rs +++ b/components/profile/mem.rs @@ -353,14 +353,16 @@ impl ReportsForest { //--------------------------------------------------------------------------- mod system_reporter { - #[cfg(not(target_os = "windows"))] - use libc::{c_char, c_int, c_void, size_t}; + #[cfg(all(feature = "unstable", not(target_os = "windows")))] + use libc::{c_char, c_void, size_t}; + #[cfg(target_os = "linux")] + use libc::c_int; use profile_traits::mem::{Report, ReportKind, ReporterRequest}; - #[cfg(not(target_os = "windows"))] + #[cfg(all(feature = "unstable", not(target_os = "windows")))] use std::ffi::CString; - #[cfg(not(target_os = "windows"))] + #[cfg(all(feature = "unstable", not(target_os = "windows")))] use std::mem::size_of; - #[cfg(not(target_os = "windows"))] + #[cfg(all(feature = "unstable", not(target_os = "windows")))] use std::ptr::null_mut; use super::{JEMALLOC_HEAP_ALLOCATED_STR, SYSTEM_HEAP_ALLOCATED_STR}; #[cfg(target_os = "macos")] @@ -457,14 +459,14 @@ mod system_reporter { None } - #[cfg(not(target_os = "windows"))] + #[cfg(all(feature = "unstable", not(target_os = "windows")))] extern { #[cfg_attr(any(target_os = "macos", target_os = "android"), link_name = "je_mallctl")] fn mallctl(name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t, - newp: *mut c_void, newlen: size_t) -> c_int; + newp: *mut c_void, newlen: size_t) -> ::libc::c_int; } - #[cfg(not(target_os = "windows"))] + #[cfg(all(feature = "unstable", not(target_os = "windows")))] fn jemalloc_stat(value_name: &str) -> Option { // Before we request the measurement of interest, we first send an "epoch" // request. Without that jemalloc gives cached statistics(!) which can be @@ -500,7 +502,7 @@ mod system_reporter { Some(value as usize) } - #[cfg(target_os = "windows")] + #[cfg(any(target_os = "windows", not(feature = "unstable")))] fn jemalloc_stat(_value_name: &str) -> Option { None } diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 016ccc43a76..18837d14078 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -26,6 +26,7 @@ unstable = [ "compositing/unstable", "constellation/unstable", "gfx/unstable", + "profile/unstable", ] [dependencies] From ff23a8536e53fda502dc17f8e9b3d32554ed1264 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 01:50:03 +0200 Subject: [PATCH 11/18] Abuse Vec as an allocator in gfx --- components/gfx/lib.rs | 1 - .../gfx/platform/freetype/font_context.rs | 49 ++++++++++++------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index e2f6eb56e04..beaeba75f21 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -4,7 +4,6 @@ // For SIMD #![cfg_attr(feature = "unstable", feature(cfg_target_feature))] -#![cfg_attr(any(target_os = "linux", target_os = "android"), feature(allocator_api))] #![deny(unsafe_code)] diff --git a/components/gfx/platform/freetype/font_context.rs b/components/gfx/platform/freetype/font_context.rs index 2e654df63f0..7f4c00f2afb 100644 --- a/components/gfx/platform/freetype/font_context.rs +++ b/components/gfx/platform/freetype/font_context.rs @@ -9,7 +9,7 @@ use freetype::freetype::FT_Memory; use freetype::freetype::FT_MemoryRec_; use freetype::freetype::FT_New_Library; use heapsize::{HeapSizeOf, heap_size_of}; -use std::heap::{Heap, Alloc, Layout}; +use std::mem; use std::os::raw::{c_long, c_void}; use std::ptr; use std::rc::Rc; @@ -25,46 +25,59 @@ pub struct User { const FT_ALIGNMENT: usize = 1; extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void { - unsafe { - let layout = Layout::from_size_align(req_size as usize, FT_ALIGNMENT).unwrap(); - let ptr = Heap.alloc(layout).unwrap() as *mut c_void; - let actual_size = heap_size_of(ptr as *const _); + assert!(FT_ALIGNMENT == 1); + let mut vec = Vec::::with_capacity(req_size as usize); + let ptr = vec.as_mut_ptr() as *mut c_void; + mem::forget(vec); + unsafe { + let actual_size = heap_size_of(ptr as *const _); let user = (*mem).user as *mut User; (*user).size += actual_size; - - ptr } + + ptr } extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) { unsafe { let actual_size = heap_size_of(ptr as *const _); - let user = (*mem).user as *mut User; (*user).size -= actual_size; - let layout = Layout::from_size_align(actual_size, FT_ALIGNMENT).unwrap(); - Heap.dealloc(ptr as *mut u8, layout); + assert!(FT_ALIGNMENT == 1); + mem::drop(Vec::::from_raw_parts(ptr as *mut u8, actual_size, 0)) } } extern fn ft_realloc(mem: FT_Memory, _cur_size: c_long, new_req_size: c_long, old_ptr: *mut c_void) -> *mut c_void { + let old_actual_size; + let mut vec; unsafe { - let old_actual_size = heap_size_of(old_ptr as *const _); - let old_layout = Layout::from_size_align(old_actual_size, FT_ALIGNMENT).unwrap(); - let new_layout = Layout::from_size_align(new_req_size as usize, FT_ALIGNMENT).unwrap(); - let result = Heap.realloc(old_ptr as *mut u8, old_layout, new_layout); - let new_ptr = result.unwrap() as *mut c_void; - let new_actual_size = heap_size_of(new_ptr as *const _); + old_actual_size = heap_size_of(old_ptr as *const _); + vec = Vec::::from_raw_parts(old_ptr as *mut u8, old_actual_size, old_actual_size); + }; + let new_req_size = new_req_size as usize; + if new_req_size > old_actual_size { + vec.reserve_exact(new_req_size - old_actual_size) + } else if new_req_size < old_actual_size { + vec.truncate(new_req_size); + vec.shrink_to_fit() + } + + let new_ptr = vec.as_mut_ptr() as *mut c_void; + mem::forget(vec); + + unsafe { + let new_actual_size = heap_size_of(new_ptr as *const _); let user = (*mem).user as *mut User; (*user).size += new_actual_size; (*user).size -= old_actual_size; - - new_ptr } + + new_ptr } // A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from From 7ebedd02a9b8da03c9b5d5d8ff876beeedeb7ecf Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 02:00:33 +0200 Subject: [PATCH 12/18] Use NonZeroUsize in script_layout_interface --- Cargo.lock | 2 ++ components/layout_thread/Cargo.toml | 3 ++- components/layout_thread/dom_wrapper.rs | 11 ++++++----- components/layout_thread/lib.rs | 4 ++-- components/nonzero/lib.rs | 16 +++++++++++++++- components/script_layout_interface/Cargo.toml | 4 ++++ components/script_layout_interface/lib.rs | 10 ++++++---- components/servo/Cargo.toml | 1 + 8 files changed, 38 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 998660b30ae..3f2ad59e575 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1567,6 +1567,7 @@ dependencies = [ "metrics 0.0.1", "msg 0.0.1", "net_traits 0.0.1", + "nonzero 0.0.1", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", "range 0.0.1", @@ -2675,6 +2676,7 @@ dependencies = [ "metrics 0.0.1", "msg 0.0.1", "net_traits 0.0.1", + "nonzero 0.0.1", "profile_traits 0.0.1", "range 0.0.1", "script_traits 0.0.1", diff --git a/components/layout_thread/Cargo.toml b/components/layout_thread/Cargo.toml index eea55c032df..5bb340f893a 100644 --- a/components/layout_thread/Cargo.toml +++ b/components/layout_thread/Cargo.toml @@ -10,7 +10,7 @@ name = "layout_thread" path = "lib.rs" [features] -unstable = ["parking_lot/nightly"] +unstable = ["parking_lot/nightly", "nonzero/unstable"] [dependencies] app_units = "0.5" @@ -29,6 +29,7 @@ log = "0.3.5" metrics = {path = "../metrics"} msg = {path = "../msg"} net_traits = {path = "../net_traits"} +nonzero = {path = "../nonzero"} parking_lot = "0.4" profile_traits = {path = "../profile_traits"} range = {path = "../range"} diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index 525e1afb5f0..2a95324ccb7 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -31,12 +31,12 @@ #![allow(unsafe_code)] use atomic_refcell::{AtomicRef, AtomicRefMut, AtomicRefCell}; -use core::nonzero::NonZero; use gfx_traits::ByteIndex; use html5ever::{LocalName, Namespace}; use layout::data::StyleAndLayoutData; use layout::wrapper::GetRawData; use msg::constellation_msg::{BrowsingContextId, PipelineId}; +use nonzero::NonZeroUsize; use range::Range; use script::layout_exports::{CAN_BE_FRAGMENTED, HAS_DIRTY_DESCENDANTS, IS_IN_DOC}; use script::layout_exports::{CharacterDataTypeId, ElementTypeId, HTMLElementTypeId, NodeTypeId}; @@ -79,7 +79,7 @@ use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocke use style::str::is_whitespace; pub unsafe fn drop_style_and_layout_data(data: OpaqueStyleAndLayoutData) { - let ptr: *mut StyleData = data.ptr.get(); + let ptr = data.ptr.get() as *mut StyleData; let non_opaque: *mut StyleAndLayoutData = ptr as *mut _; let _ = Box::from_raw(non_opaque); } @@ -235,7 +235,8 @@ impl<'ln> LayoutNode for ServoLayoutNode<'ln> { let ptr: *mut StyleAndLayoutData = Box::into_raw(Box::new(StyleAndLayoutData::new())); let opaque = OpaqueStyleAndLayoutData { - ptr: NonZero::new_unchecked(ptr as *mut StyleData), + ptr: NonZeroUsize::new_unchecked(ptr as usize), + phantom: PhantomData, }; self.init_style_and_layout_data(opaque); }; @@ -471,7 +472,7 @@ impl<'le> TElement for ServoLayoutElement<'le> { fn get_data(&self) -> Option<&AtomicRefCell> { unsafe { self.get_style_and_layout_data().map(|d| { - &(*d.ptr.get()).element_data + &(*(d.ptr.get() as *mut StyleData)).element_data }) } } @@ -583,7 +584,7 @@ impl<'le> ServoLayoutElement<'le> { fn get_style_data(&self) -> Option<&StyleData> { unsafe { - self.get_style_and_layout_data().map(|d| &*d.ptr.get()) + self.get_style_and_layout_data().map(|d| &*(d.ptr.get() as *mut StyleData)) } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 8ea36ae100f..1fe552588bf 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -6,11 +6,10 @@ //! painted. #![feature(mpsc_select)] -#![feature(nonzero)] +#![cfg_attr(feature = "unstable", feature(nonzero))] extern crate app_units; extern crate atomic_refcell; -extern crate core; extern crate euclid; extern crate fnv; extern crate gfx; @@ -29,6 +28,7 @@ extern crate log; extern crate metrics; extern crate msg; extern crate net_traits; +extern crate nonzero; extern crate parking_lot; #[macro_use] extern crate profile_traits; diff --git a/components/nonzero/lib.rs b/components/nonzero/lib.rs index efc6eca2f0a..078bd0f5b2c 100644 --- a/components/nonzero/lib.rs +++ b/components/nonzero/lib.rs @@ -31,6 +31,7 @@ mod imp { pub struct NonZeroU32(u32); impl NonZeroU32 { + #[inline] pub fn new(x: u32) -> Option { if x != 0 { Some(NonZeroU32(x)) @@ -39,10 +40,12 @@ mod imp { } } + #[inline] pub unsafe fn new_unchecked(x: u32) -> Self { NonZeroU32(x) } + #[inline] pub fn get(self) -> u32 { self.0 } @@ -52,38 +55,49 @@ mod imp { pub struct NonZeroUsize(&'static ()); impl NonZeroUsize { + #[inline] pub fn new(x: usize) -> Option { if x != 0 { - Some(NonZeroUsize(unsafe { &*(x as *const ()) })) + Some(unsafe { Self::new_unchecked(x) }) } else { None } } + #[inline] + pub unsafe fn new_unchecked(x: usize) -> Self { + NonZeroUsize(&*(x as *const ())) + } + + #[inline] pub fn get(self) -> usize { self.0 as *const () as usize } } impl PartialEq for NonZeroUsize { + #[inline] fn eq(&self, other: &Self) -> bool { self.get() == other.get() } } impl PartialOrd for NonZeroUsize { + #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.get().partial_cmp(&other.get()) } } impl Ord for NonZeroUsize { + #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { self.get().cmp(&other.get()) } } impl hash::Hash for NonZeroUsize { + #[inline] fn hash(&self, hasher: &mut H) { self.get().hash(hasher) } diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml index 0928de56156..acdea4bca17 100644 --- a/components/script_layout_interface/Cargo.toml +++ b/components/script_layout_interface/Cargo.toml @@ -9,6 +9,9 @@ publish = false name = "script_layout_interface" path = "lib.rs" +[features] +unstable = ["nonzero/unstable"] + [dependencies] app_units = "0.5" atomic_refcell = "0.1" @@ -25,6 +28,7 @@ log = "0.3.5" metrics = {path = "../metrics"} msg = {path = "../msg"} net_traits = {path = "../net_traits"} +nonzero = {path = "../nonzero"} profile_traits = {path = "../profile_traits"} range = {path = "../range"} script_traits = {path = "../script_traits"} diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs index ffc41351ee5..f81092a8492 100644 --- a/components/script_layout_interface/lib.rs +++ b/components/script_layout_interface/lib.rs @@ -7,12 +7,11 @@ //! to depend on script. #![deny(unsafe_code)] -#![feature(nonzero)] +#![cfg_attr(feature = "unstable", feature(nonzero))] extern crate app_units; extern crate atomic_refcell; extern crate canvas_traits; -extern crate core; extern crate cssparser; extern crate euclid; extern crate gfx_traits; @@ -26,6 +25,7 @@ extern crate log; extern crate metrics; extern crate msg; extern crate net_traits; +extern crate nonzero; extern crate profile_traits; extern crate range; extern crate script_traits; @@ -43,12 +43,13 @@ pub mod wrapper_traits; use atomic_refcell::AtomicRefCell; use canvas_traits::canvas::CanvasMsg; -use core::nonzero::NonZero; use ipc_channel::ipc::IpcSender; use libc::c_void; use net_traits::image_cache::PendingImageId; +use nonzero::NonZeroUsize; use script_traits::UntrustedNodeAddress; use servo_url::ServoUrl; +use std::marker::PhantomData; use std::sync::atomic::AtomicIsize; use style::data::ElementData; @@ -78,7 +79,8 @@ pub struct OpaqueStyleAndLayoutData { // NB: We really store a `StyleAndLayoutData` here, so be careful! #[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but \ the type lives in layout"] - pub ptr: NonZero<*mut StyleData> + pub ptr: NonZeroUsize, + pub phantom: PhantomData<*mut StyleData>, } #[allow(unsafe_code)] diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 18837d14078..4858ef1b3f3 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -27,6 +27,7 @@ unstable = [ "constellation/unstable", "gfx/unstable", "profile/unstable", + "script_layout_interface/unstable", ] [dependencies] From 45fd384a91248a2018a3d6f5c2103dea4a69fbaa Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 02:14:27 +0200 Subject: [PATCH 13/18] Make use of `impl trait` in constellation optional --- components/constellation/constellation.rs | 34 +++++++++++++++++++++++ components/constellation/lib.rs | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 4141e04d803..1b5c217bea2 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -772,6 +772,7 @@ impl Constellation self.all_descendant_browsing_contexts_iter(BrowsingContextId::from(top_level_browsing_context_id)) } + #[cfg(feature = "unstable")] /// The joint session future is the merge of the session future of every /// browsing_context, sorted chronologically. fn joint_session_future<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId) @@ -782,12 +783,26 @@ impl Constellation .kmerge_by(|a, b| a.instant.cmp(&b.instant) == Ordering::Less) } + #[cfg(not(feature = "unstable"))] + /// The joint session future is the merge of the session future of every + /// browsing_context, sorted chronologically. + fn joint_session_future<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId) + -> Box + 'a> + { + Box::new( + self.all_browsing_contexts_iter(top_level_browsing_context_id) + .map(|browsing_context| browsing_context.next.iter().rev()) + .kmerge_by(|a, b| a.instant.cmp(&b.instant) == Ordering::Less) + ) + } + /// Is the joint session future empty? fn joint_session_future_is_empty(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) -> bool { self.all_browsing_contexts_iter(top_level_browsing_context_id) .all(|browsing_context| browsing_context.next.is_empty()) } + #[cfg(feature = "unstable")] /// The joint session past is the merge of the session past of every /// browsing_context, sorted reverse chronologically. fn joint_session_past<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId) @@ -804,6 +819,25 @@ impl Constellation .map(|(_, entry)| entry) } + #[cfg(not(feature = "unstable"))] + /// The joint session past is the merge of the session past of every + /// browsing_context, sorted reverse chronologically. + fn joint_session_past<'a>(&'a self, top_level_browsing_context_id: TopLevelBrowsingContextId) + -> Box + 'a> + { + Box::new( + self.all_browsing_contexts_iter(top_level_browsing_context_id) + .map(|browsing_context| browsing_context.prev.iter().rev() + .scan(browsing_context.instant, |prev_instant, entry| { + let instant = *prev_instant; + *prev_instant = entry.instant; + Some((instant, entry)) + })) + .kmerge_by(|a, b| a.0.cmp(&b.0) == Ordering::Greater) + .map(|(_, entry)| entry) + ) + } + /// Is the joint session past empty? fn joint_session_past_is_empty(&self, top_level_browsing_context_id: TopLevelBrowsingContextId) -> bool { self.all_browsing_contexts_iter(top_level_browsing_context_id) diff --git a/components/constellation/lib.rs b/components/constellation/lib.rs index 0258702cec9..a0fd36325a8 100644 --- a/components/constellation/lib.rs +++ b/components/constellation/lib.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![deny(unsafe_code)] -#![feature(conservative_impl_trait)] +#![cfg_attr(feature = "unstable", feature(conservative_impl_trait))] #![feature(mpsc_select)] extern crate backtrace; From 4594b40238d7aa5ca3aed885013e16c935c62a0d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 17:39:31 +0200 Subject: [PATCH 14/18] =?UTF-8?q?Use=20wrappers=20in=20the=20nonzero=20cra?= =?UTF-8?q?te=20so=20users=20don=E2=80=99t=20need=20unstable=20features?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/canvas_traits/Cargo.toml | 3 --- components/canvas_traits/lib.rs | 2 -- components/compositing/Cargo.toml | 3 --- components/compositing/lib.rs | 1 - components/constellation/Cargo.toml | 3 --- components/layout/lib.rs | 1 - components/layout_thread/lib.rs | 1 - components/msg/lib.rs | 3 --- components/nonzero/lib.rs | 22 ++++++++++++++++--- components/remutex/Cargo.toml | 3 --- components/remutex/lib.rs | 2 -- components/script_layout_interface/Cargo.toml | 3 --- components/script_layout_interface/lib.rs | 1 - components/servo/Cargo.toml | 5 ----- 14 files changed, 19 insertions(+), 34 deletions(-) diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml index d60efb69ad4..8c514312511 100644 --- a/components/canvas_traits/Cargo.toml +++ b/components/canvas_traits/Cargo.toml @@ -9,9 +9,6 @@ publish = false name = "canvas_traits" path = "lib.rs" -[features] -unstable = ["nonzero/unstable"] - [dependencies] cssparser = "0.22.0" euclid = "0.15" diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 8ca51a3ddde..4664a082fdd 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -5,8 +5,6 @@ #![crate_name = "canvas_traits"] #![crate_type = "rlib"] -#![cfg_attr(feature = "unstable", feature(nonzero))] - #![deny(unsafe_code)] extern crate cssparser; diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 236cf14443c..e8ed7c5d497 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -9,9 +9,6 @@ publish = false name = "compositing" path = "lib.rs" -[features] -unstable = ["nonzero/unstable"] - [dependencies] euclid = "0.15" gfx_traits = {path = "../gfx_traits"} diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index ee053c47182..b2abdcbf94d 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![deny(unsafe_code)] -#![cfg_attr(feature = "unstable", feature(nonzero))] extern crate euclid; extern crate gfx_traits; diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index b9d6177273b..2d659bd4342 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -9,9 +9,6 @@ publish = false name = "constellation" path = "lib.rs" -[features] -unstable = ["servo_remutex/unstable"] - [dependencies] backtrace = "0.3" bluetooth_traits = { path = "../bluetooth_traits" } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index a55fcac4520..efab7c69752 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -5,7 +5,6 @@ #![deny(unsafe_code)] #![feature(box_patterns)] #![feature(conservative_impl_trait)] -#![feature(nonzero)] #![feature(raw)] extern crate app_units; diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 1fe552588bf..3132eccf68a 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -6,7 +6,6 @@ //! painted. #![feature(mpsc_select)] -#![cfg_attr(feature = "unstable", feature(nonzero))] extern crate app_units; extern crate atomic_refcell; diff --git a/components/msg/lib.rs b/components/msg/lib.rs index b1743ad02a9..6181e2d3cc6 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -2,9 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#![cfg_attr(feature = "unstable", feature(nonzero))] -#![cfg_attr(feature = "unstable", feature(const_fn))] -#![cfg_attr(feature = "unstable", feature(const_nonzero_new))] #![deny(unsafe_code)] #[macro_use] diff --git a/components/nonzero/lib.rs b/components/nonzero/lib.rs index 078bd0f5b2c..6682740f34e 100644 --- a/components/nonzero/lib.rs +++ b/components/nonzero/lib.rs @@ -6,8 +6,9 @@ //! or some stable types with an equivalent API (but no memory layout optimization). #![cfg_attr(feature = "unstable", feature(nonzero))] +#![cfg_attr(feature = "unstable", feature(const_fn))] +#![cfg_attr(feature = "unstable", feature(const_nonzero_new))] -#[cfg(not(feature = "unstable"))] #[macro_use] extern crate serde; @@ -18,8 +19,23 @@ mod imp { extern crate core; use self::core::nonzero::NonZero; - pub type NonZeroU32 = NonZero; - pub type NonZeroUsize = NonZero; + #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] + pub struct NonZeroU32(NonZero); + + #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] + pub struct NonZeroUsize(NonZero); + + impl NonZeroU32 { + #[inline] pub const unsafe fn new_unchecked(x: u32) -> Self { NonZeroU32(NonZero::new_unchecked(x)) } + #[inline] pub fn new(x: u32) -> Option { NonZero::new(x).map(NonZeroU32) } + #[inline] pub fn get(self) -> u32 { self.0.get() } + } + + impl NonZeroUsize { + #[inline] pub const unsafe fn new_unchecked(x: usize) -> Self { NonZeroUsize(NonZero::new_unchecked(x)) } + #[inline] pub fn new(x: usize) -> Option { NonZero::new(x).map(NonZeroUsize) } + #[inline] pub fn get(self) -> usize { self.0.get() } + } } #[cfg(not(feature = "unstable"))] diff --git a/components/remutex/Cargo.toml b/components/remutex/Cargo.toml index b3937587a62..f03fa5ada18 100644 --- a/components/remutex/Cargo.toml +++ b/components/remutex/Cargo.toml @@ -9,9 +9,6 @@ publish = false name = "servo_remutex" path = "lib.rs" -[features] -unstable = ["nonzero/unstable"] - [dependencies] lazy_static = "0.2" log = "0.3.5" diff --git a/components/remutex/lib.rs b/components/remutex/lib.rs index 6793429bf1e..2589a6d1162 100644 --- a/components/remutex/lib.rs +++ b/components/remutex/lib.rs @@ -10,8 +10,6 @@ //! It provides the same interface as https://github.com/rust-lang/rust/blob/master/src/libstd/sys/common/remutex.rs //! so if those types are ever exported, we should be able to replace this implemtation. -#![cfg_attr(feature = "unstable", feature(nonzero))] - extern crate nonzero; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml index acdea4bca17..9dfad06a89c 100644 --- a/components/script_layout_interface/Cargo.toml +++ b/components/script_layout_interface/Cargo.toml @@ -9,9 +9,6 @@ publish = false name = "script_layout_interface" path = "lib.rs" -[features] -unstable = ["nonzero/unstable"] - [dependencies] app_units = "0.5" atomic_refcell = "0.1" diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs index f81092a8492..7b45d9688f1 100644 --- a/components/script_layout_interface/lib.rs +++ b/components/script_layout_interface/lib.rs @@ -7,7 +7,6 @@ //! to depend on script. #![deny(unsafe_code)] -#![cfg_attr(feature = "unstable", feature(nonzero))] extern crate app_units; extern crate atomic_refcell; diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 4858ef1b3f3..27358a388b1 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -20,14 +20,9 @@ googlevr = ["webvr/googlevr"] oculusvr = ["webvr/oculusvr"] unstable = [ "euclid/unstable", - "layout_thread/unstable", "msg/unstable", - "canvas_traits/unstable", - "compositing/unstable", - "constellation/unstable", "gfx/unstable", "profile/unstable", - "script_layout_interface/unstable", ] [dependencies] From c2d660037a9a8db2db60be3afd3f643b316cc1a1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 17:41:12 +0200 Subject: [PATCH 15/18] Add a default-except-unstable feature --- ports/servo/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/servo/Cargo.toml b/ports/servo/Cargo.toml index 32e5e8433f6..63803a90f58 100644 --- a/ports/servo/Cargo.toml +++ b/ports/servo/Cargo.toml @@ -29,7 +29,8 @@ servo_remutex_tests = {path = "../../tests/unit/servo_remutex"} style_tests = {path = "../../tests/unit/style"} [features] -default = ["webdriver", "max_log_level", "unstable"] +default = ["unstable", "default-except-unstable"] +default-except-unstable = ["webdriver", "max_log_level"] max_log_level = ["log/release_max_level_info"] webdriver = ["libservo/webdriver_server"] energy-profiling = ["libservo/energy-profiling"] From 4727b92754be504c37a62dfe806999e40a3339f6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 18:00:44 +0200 Subject: [PATCH 16/18] Remove usage of unstable feature conservative_impl_trait in layout --- components/layout/flow.rs | 4 ++-- components/layout/flow_list.rs | 30 ++++++++++++++++++++++++++++-- components/layout/lib.rs | 1 - 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/components/layout/flow.rs b/components/layout/flow.rs index b5afce9471b..05512724843 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -32,7 +32,7 @@ use display_list_builder::{DisplayListBuildState, StackingContextCollectionState use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D}; use flex::FlexFlow; use floats::{Floats, SpeculatedFloatPlacement}; -use flow_list::{FlowList, MutFlowListIterator}; +use flow_list::{FlowList, FlowListIterator, MutFlowListIterator}; use flow_ref::{FlowRef, WeakFlowRef}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use gfx_traits::StackingContextId; @@ -459,7 +459,7 @@ pub fn base(this: &T) -> &BaseFlow { } /// Iterates over the children of this immutable flow. -pub fn child_iter<'a>(flow: &'a Flow) -> impl Iterator { +pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator { base(flow).children.iter() } diff --git a/components/layout/flow_list.rs b/components/layout/flow_list.rs index 97fd6dbc89f..2960579762e 100644 --- a/components/layout/flow_list.rs +++ b/components/layout/flow_list.rs @@ -7,6 +7,7 @@ use flow_ref::FlowRef; use serde::ser::{Serialize, SerializeSeq, Serializer}; use serde_json::{Map, Value, to_value}; use std::collections::{LinkedList, linked_list}; +use std::ops::Deref; use std::sync::Arc; /// This needs to be reworked now that we have dynamically-sized types in Rust. @@ -53,6 +54,10 @@ pub struct MutFlowListIterator<'a> { it: linked_list::IterMut<'a, FlowRef>, } +pub struct FlowListIterator<'a> { + it: linked_list::Iter<'a, FlowRef>, +} + impl FlowList { /// Add an element last in the list /// @@ -101,8 +106,10 @@ impl FlowList { /// SECURITY-NOTE(pcwalton): This does not hand out `FlowRef`s by design. Do not add a method /// to do so! See the comment above in `FlowList`. #[inline] - pub fn iter<'a>(&'a self) -> impl DoubleEndedIterator { - self.flows.iter().map(|flow| &**flow) + pub fn iter<'a>(&'a self) -> FlowListIterator { + FlowListIterator { + it: self.flows.iter(), + } } /// Provide a forward iterator with mutable references @@ -150,12 +157,31 @@ impl FlowList { } } +impl<'a> DoubleEndedIterator for FlowListIterator<'a> { + fn next_back(&mut self) -> Option<&'a Flow> { + self.it.next_back().map(Deref::deref) + } +} + impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> { fn next_back(&mut self) -> Option<&'a mut Flow> { self.it.next_back().map(FlowRef::deref_mut) } } +impl<'a> Iterator for FlowListIterator<'a> { + type Item = &'a Flow; + #[inline] + fn next(&mut self) -> Option<&'a Flow> { + self.it.next().map(Deref::deref) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + impl<'a> Iterator for MutFlowListIterator<'a> { type Item = &'a mut Flow; #[inline] diff --git a/components/layout/lib.rs b/components/layout/lib.rs index efab7c69752..eb337c4b015 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -4,7 +4,6 @@ #![deny(unsafe_code)] #![feature(box_patterns)] -#![feature(conservative_impl_trait)] #![feature(raw)] extern crate app_units; From e13ae77daf8c86db20ec9414043a683c16779bfc Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 18:12:47 +0200 Subject: [PATCH 17/18] Remove usage of unstable feature "raw" --- components/layout/flow.rs | 8 ++++---- components/layout/lib.rs | 10 +++++++++- components/servo/Cargo.toml | 2 +- tests/unit/layout/lib.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 05512724843..fbcf7866931 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -44,7 +44,7 @@ use multicol::MulticolFlow; use parallel::FlowParallelInfo; use serde::ser::{Serialize, SerializeStruct, Serializer}; use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect, max_rect}; -use std::{fmt, mem, raw}; +use std::{fmt, mem}; use std::iter::Zip; use std::slice::IterMut; use std::sync::Arc; @@ -453,7 +453,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { #[allow(unsafe_code)] pub fn base(this: &T) -> &BaseFlow { unsafe { - let obj = mem::transmute::<&&T, &raw::TraitObject>(&this); + let obj = mem::transmute::<&&T, &::TraitObject>(&this); mem::transmute::<*mut (), &BaseFlow>(obj.data) } } @@ -467,7 +467,7 @@ pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator { #[allow(unsafe_code)] pub fn mut_base(this: &mut T) -> &mut BaseFlow { unsafe { - let obj = mem::transmute::<&&mut T, &raw::TraitObject>(&this); + let obj = mem::transmute::<&&mut T, &::TraitObject>(&this); mem::transmute::<*mut (), &mut BaseFlow>(obj.data) } } @@ -1422,7 +1422,7 @@ impl OpaqueFlow { #[allow(unsafe_code)] pub fn from_flow(flow: &Flow) -> OpaqueFlow { unsafe { - let object = mem::transmute::<&Flow, raw::TraitObject>(flow); + let object = mem::transmute::<&Flow, ::TraitObject>(flow); OpaqueFlow(object.data as usize) } } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index eb337c4b015..ab8beba722a 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -4,7 +4,6 @@ #![deny(unsafe_code)] #![feature(box_patterns)] -#![feature(raw)] extern crate app_units; extern crate atomic_refcell; @@ -92,3 +91,12 @@ pub use self::data::LayoutData; // We can't use servo_arc for everything in layout, because the Flow stuff uses // weak references. use servo_arc::Arc as ServoArc; + +/// Stable copy of std::raw::TraitObject +/// test/unit/layout/lib.rs asserts that the memory layout matches. +#[repr(C)] +#[derive(Clone, Copy)] +pub struct TraitObject { + pub data: *mut (), + pub vtable: *mut (), +} diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 27358a388b1..3f7f3c82598 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -20,8 +20,8 @@ googlevr = ["webvr/googlevr"] oculusvr = ["webvr/oculusvr"] unstable = [ "euclid/unstable", - "msg/unstable", "gfx/unstable", + "msg/unstable", "profile/unstable", ] diff --git a/tests/unit/layout/lib.rs b/tests/unit/layout/lib.rs index a763135260a..bc1d9dfd464 100644 --- a/tests/unit/layout/lib.rs +++ b/tests/unit/layout/lib.rs @@ -2,7 +2,36 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#![feature(raw)] + extern crate layout; #[macro_use] extern crate size_of_test; #[cfg(all(test, target_pointer_width = "64"))] mod size_of; + +use std::mem; +use std::ptr; +use std::raw; + +#[test] +fn test_trait_object_layout() { + assert_eq!(mem::size_of::(), mem::size_of::()); + let null: *mut () = ptr::null_mut(); + let a = raw::TraitObject { + data: null, + vtable: null, + }; + let b = layout::TraitObject { + data: null, + vtable: null, + }; + + fn offset(struct_: &T, field: &U) -> usize { + let addr_struct = struct_ as *const T as usize; + let addr_field = field as *const U as usize; + addr_field - addr_struct + } + + assert_eq!(offset(&a, &a.data), offset(&b, &b.data)); + assert_eq!(offset(&a, &a.vtable), offset(&b, &b.vtable)); +} From 11bd81e1157dde8b3131766bf8ebecbb134e54ce Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 12 Oct 2017 18:56:03 +0200 Subject: [PATCH 18/18] Remove usage of unstable feature box_patterns --- components/layout/display_list_builder.rs | 31 ++- components/layout/fragment.rs | 277 ++++++++++++---------- components/layout/lib.rs | 1 - 3 files changed, 170 insertions(+), 139 deletions(-) diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 717b10ed4ee..522766b5f6d 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -21,7 +21,7 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED}; use flow_ref::FlowRef; use fnv::FnvHashMap; use fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo}; -use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo}; +use fragment::SpecificFragmentInfo; use gfx::display_list; use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClipScrollNode}; @@ -2012,14 +2012,12 @@ impl FragmentDisplayListBuilding for Fragment { }; match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref text_fragment), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref text_fragment) => { + SpecificFragmentInfo::TruncatedFragment(ref truncated_fragment) + if truncated_fragment.text_info.is_some() => { + let text_fragment = truncated_fragment.text_info.as_ref().unwrap(); // Create the main text display item. self.build_display_list_for_text_fragment(state, - &*text_fragment, + &text_fragment, &stacking_relative_content_box, &self.style.get_inheritedtext().text_shadow.0, clip); @@ -2029,7 +2027,24 @@ impl FragmentDisplayListBuilding for Fragment { self.style(), stacking_relative_border_box, &stacking_relative_content_box, - &*text_fragment, + &text_fragment, + clip); + } + } + SpecificFragmentInfo::ScannedText(ref text_fragment) => { + // Create the main text display item. + self.build_display_list_for_text_fragment(state, + &text_fragment, + &stacking_relative_content_box, + &self.style.get_inheritedtext().text_shadow.0, + clip); + + if opts::get().show_debug_fragment_borders { + self.build_debug_borders_around_text_fragments(state, + self.style(), + stacking_relative_border_box, + &stacking_relative_content_box, + &text_fragment, clip); } } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 08c26b1d6a6..153fe97992b 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -1460,8 +1460,10 @@ impl Fragment { /// Returns true if and only if this fragment is a generated content fragment. pub fn is_unscanned_generated_content(&self) -> bool { match self.specific { - SpecificFragmentInfo::GeneratedContent(box GeneratedContentInfo::Empty) => false, - SpecificFragmentInfo::GeneratedContent(..) => true, + SpecificFragmentInfo::GeneratedContent(ref content) => match **content { + GeneratedContentInfo::Empty => false, + _ => true, + }, _ => false, } } @@ -1536,41 +1538,45 @@ impl Fragment { }); } - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref text_fragment_info), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref text_fragment_info) => { - let range = &text_fragment_info.range; - - // See http://dev.w3.org/csswg/css-sizing/#max-content-inline-size. - // TODO: Account for soft wrap opportunities. - let max_line_inline_size = text_fragment_info.run - .metrics_for_range(range) - .advance_width; - - let min_line_inline_size = if self.white_space().allow_wrap() { - text_fragment_info.run.min_width_for_range(range) - } else { - max_line_inline_size - }; - - result.union_block(&IntrinsicISizes { - minimum_inline_size: min_line_inline_size, - preferred_inline_size: max_line_inline_size, - }) + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { + let text_fragment_info = t.text_info.as_ref().unwrap(); + handle_text(text_fragment_info, self, &mut result) + } + SpecificFragmentInfo::ScannedText(ref text_fragment_info) => { + handle_text(text_fragment_info, self, &mut result) } - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: None, - .. - }) => return IntrinsicISizesContribution::new(), + SpecificFragmentInfo::TruncatedFragment(_) => { + return IntrinsicISizesContribution::new() + } SpecificFragmentInfo::UnscannedText(..) => { panic!("Unscanned text fragments should have been scanned by now!") } }; + fn handle_text(text_fragment_info: &ScannedTextFragmentInfo, self_: &Fragment, + result: &mut IntrinsicISizesContribution) { + let range = &text_fragment_info.range; + + // See http://dev.w3.org/csswg/css-sizing/#max-content-inline-size. + // TODO: Account for soft wrap opportunities. + let max_line_inline_size = text_fragment_info.run + .metrics_for_range(range) + .advance_width; + + let min_line_inline_size = if self_.white_space().allow_wrap() { + text_fragment_info.run.min_width_for_range(range) + } else { + max_line_inline_size + }; + + result.union_block(&IntrinsicISizes { + minimum_inline_size: min_line_inline_size, + preferred_inline_size: max_line_inline_size, + }) + } + // Take borders and padding for parent inline fragments into account. let writing_mode = self.style.writing_mode; if let Some(ref context) = self.inline_context { @@ -1605,11 +1611,11 @@ impl Fragment { /// this fragment.) pub fn minimum_splittable_inline_size(&self) -> Au { match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref text), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref text) => { + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { + let text = t.text_info.as_ref().unwrap(); + text.run.minimum_splittable_inline_size(&text.range) + } + SpecificFragmentInfo::ScannedText(ref text) => { text.run.minimum_splittable_inline_size(&text.range) } _ => Au(0), @@ -1914,10 +1920,7 @@ impl Fragment { container_inline_size: Au, container_block_size: Option) { match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: None, - .. - }) | + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_none() => return, SpecificFragmentInfo::Generic | SpecificFragmentInfo::GeneratedContent(_) | SpecificFragmentInfo::Table | @@ -1971,11 +1974,14 @@ impl Fragment { } // Text - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref info), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref info) => { + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { + let info = t.text_info.as_ref().unwrap(); + // Scanned text fragments will have already had their content inline-sizes assigned + // by this point. + self.border_box.size.inline = info.content_size.inline + + self.border_padding.inline_start_end(); + } + SpecificFragmentInfo::ScannedText(ref info) => { // Scanned text fragments will have already had their content inline-sizes assigned // by this point. self.border_box.size.inline = info.content_size.inline + @@ -2000,10 +2006,7 @@ impl Fragment { /// Ideally, this should follow CSS 2.1 § 10.6.2. pub fn assign_replaced_block_size_if_necessary(&mut self) { match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: None, - .. - }) | + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_none() => return, SpecificFragmentInfo::Generic | SpecificFragmentInfo::GeneratedContent(_) | SpecificFragmentInfo::Table | @@ -2025,20 +2028,20 @@ impl Fragment { SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | SpecificFragmentInfo::InlineAbsolute(_) | SpecificFragmentInfo::ScannedText(_) | - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(_), - .. - }) | + SpecificFragmentInfo::TruncatedFragment(_) | SpecificFragmentInfo::Svg(_) => {} } match self.specific { // Text - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref info), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref info) => { + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { + let info = t.text_info.as_ref().unwrap(); + // Scanned text fragments' content block-sizes are calculated by the text run + // scanner during flow construction. + self.border_box.size.block = info.content_size.block + + self.border_padding.block_start_end(); + } + SpecificFragmentInfo::ScannedText(ref info) => { // Scanned text fragments' content block-sizes are calculated by the text run // scanner during flow construction. self.border_box.size.block = info.content_size.block + @@ -2115,22 +2118,12 @@ impl Fragment { ascent: ascent, } } - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref info), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref info) => { - // Fragments with no glyphs don't contribute any inline metrics. - // TODO: Filter out these fragments during flow construction? - if info.insertion_point.is_none() && info.content_size.inline == Au(0) { - return InlineMetrics::new(Au(0), Au(0), Au(0)); - } - // See CSS 2.1 § 10.8.1. - let font_metrics = with_thread_local_font_context(layout_context, |font_context| { - text::font_metrics_for_style(font_context, self.style.clone_font()) - }); - let line_height = text::line_height_from_style(&*self.style, &font_metrics); - InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height) + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { + let info = t.text_info.as_ref().unwrap(); + inline_metrics_of_text(info, self, layout_context) + } + SpecificFragmentInfo::ScannedText(ref info) => { + inline_metrics_of_text(info, self, layout_context) } SpecificFragmentInfo::InlineBlock(ref info) => { inline_metrics_of_block(&info.flow_ref, &*self.style) @@ -2138,10 +2131,7 @@ impl Fragment { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => { inline_metrics_of_block(&info.flow_ref, &*self.style) } - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: None, - .. - }) | + SpecificFragmentInfo::TruncatedFragment(..) | SpecificFragmentInfo::InlineAbsolute(_) => { InlineMetrics::new(Au(0), Au(0), Au(0)) } @@ -2158,6 +2148,21 @@ impl Fragment { }; return inline_metrics; + fn inline_metrics_of_text(info: &ScannedTextFragmentInfo, self_: &Fragment, + layout_context: &LayoutContext) -> InlineMetrics { + // Fragments with no glyphs don't contribute any inline metrics. + // TODO: Filter out these fragments during flow construction? + if info.insertion_point.is_none() && info.content_size.inline == Au(0) { + return InlineMetrics::new(Au(0), Au(0), Au(0)); + } + // See CSS 2.1 § 10.8.1. + let font_metrics = with_thread_local_font_context(layout_context, |font_context| { + text::font_metrics_for_style(font_context, self_.style.clone_font()) + }); + let line_height = text::line_height_from_style(&*self_.style, &font_metrics); + InlineMetrics::from_font_metrics(&info.run.font_metrics, line_height) + } + fn inline_metrics_of_block(flow: &FlowRef, style: &ComputedValues) -> InlineMetrics { // CSS 2.1 § 10.8: "The height of each inline-level box in the line box is calculated. // For replaced elements, inline-block elements, and inline-table elements, this is the @@ -2612,12 +2617,12 @@ impl Fragment { pub fn requires_line_break_afterward_if_wrapping_on_newlines(&self) -> bool { match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref scanned_text), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref scanned_text) => { - scanned_text.requires_line_break_afterward_if_wrapping_on_newlines() + SpecificFragmentInfo::TruncatedFragment(ref t) if t.text_info.is_some() => { + let text = t.text_info.as_ref().unwrap(); + text.requires_line_break_afterward_if_wrapping_on_newlines() + } + SpecificFragmentInfo::ScannedText(ref text) => { + text.requires_line_break_afterward_if_wrapping_on_newlines() } _ => false, } @@ -2628,28 +2633,13 @@ impl Fragment { return WhitespaceStrippingResult::RetainFragment } - match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref mut scanned_text_fragment_info), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref mut scanned_text_fragment_info) => { - let leading_whitespace_byte_count = scanned_text_fragment_info.text() - .find(|c| !char_is_whitespace(c)) - .unwrap_or(scanned_text_fragment_info.text().len()); - - let whitespace_len = ByteIndex(leading_whitespace_byte_count as isize); - let whitespace_range = Range::new(scanned_text_fragment_info.range.begin(), - whitespace_len); - let text_bounds = - scanned_text_fragment_info.run.metrics_for_range(&whitespace_range).bounding_box; - self.border_box.size.inline = self.border_box.size.inline - text_bounds.size.width; - scanned_text_fragment_info.content_size.inline = - scanned_text_fragment_info.content_size.inline - text_bounds.size.width; - - scanned_text_fragment_info.range.adjust_by(whitespace_len, -whitespace_len); - - WhitespaceStrippingResult::RetainFragment + return match self.specific { + SpecificFragmentInfo::TruncatedFragment(ref mut t) if t.text_info.is_some() => { + let scanned_text_fragment_info = t.text_info.as_mut().unwrap(); + scanned_text(scanned_text_fragment_info, &mut self.border_box) + } + SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => { + scanned_text(scanned_text_fragment_info, &mut self.border_box) } SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => { let mut new_text_string = String::new(); @@ -2677,6 +2667,27 @@ impl Fragment { &unscanned_text_fragment_info) } _ => WhitespaceStrippingResult::RetainFragment, + }; + + fn scanned_text(scanned_text_fragment_info: &mut ScannedTextFragmentInfo, + border_box: &mut LogicalRect) + -> WhitespaceStrippingResult { + let leading_whitespace_byte_count = scanned_text_fragment_info.text() + .find(|c| !char_is_whitespace(c)) + .unwrap_or(scanned_text_fragment_info.text().len()); + + let whitespace_len = ByteIndex(leading_whitespace_byte_count as isize); + let whitespace_range = Range::new(scanned_text_fragment_info.range.begin(), + whitespace_len); + let text_bounds = + scanned_text_fragment_info.run.metrics_for_range(&whitespace_range).bounding_box; + border_box.size.inline = border_box.size.inline - text_bounds.size.width; + scanned_text_fragment_info.content_size.inline = + scanned_text_fragment_info.content_size.inline - text_bounds.size.width; + + scanned_text_fragment_info.range.adjust_by(whitespace_len, -whitespace_len); + + WhitespaceStrippingResult::RetainFragment } } @@ -2686,32 +2697,13 @@ impl Fragment { return WhitespaceStrippingResult::RetainFragment } - match self.specific { - SpecificFragmentInfo::TruncatedFragment(box TruncatedFragmentInfo { - text_info: Some(ref mut scanned_text_fragment_info), - .. - }) | - SpecificFragmentInfo::ScannedText(box ref mut scanned_text_fragment_info) => { - let mut trailing_whitespace_start_byte = 0; - for (i, c) in scanned_text_fragment_info.text().char_indices().rev() { - if !char_is_whitespace(c) { - trailing_whitespace_start_byte = i + c.len_utf8(); - break; - } - } - let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize); - let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start; - let mut whitespace_range = Range::new(whitespace_start, whitespace_len); - whitespace_range.shift_by(scanned_text_fragment_info.range.begin()); - - let text_bounds = scanned_text_fragment_info.run - .metrics_for_range(&whitespace_range) - .bounding_box; - self.border_box.size.inline -= text_bounds.size.width; - scanned_text_fragment_info.content_size.inline -= text_bounds.size.width; - - scanned_text_fragment_info.range.extend_by(-whitespace_len); - WhitespaceStrippingResult::RetainFragment + return match self.specific { + SpecificFragmentInfo::TruncatedFragment(ref mut t) if t.text_info.is_some() => { + let scanned_text_fragment_info = t.text_info.as_mut().unwrap(); + scanned_text(scanned_text_fragment_info, &mut self.border_box) + } + SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => { + scanned_text(scanned_text_fragment_info, &mut self.border_box) } SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => { let mut trailing_bidi_control_characters_to_retain = Vec::new(); @@ -2741,6 +2733,31 @@ impl Fragment { &unscanned_text_fragment_info) } _ => WhitespaceStrippingResult::RetainFragment, + }; + + fn scanned_text(scanned_text_fragment_info: &mut ScannedTextFragmentInfo, + border_box: &mut LogicalRect) + -> WhitespaceStrippingResult { + let mut trailing_whitespace_start_byte = 0; + for (i, c) in scanned_text_fragment_info.text().char_indices().rev() { + if !char_is_whitespace(c) { + trailing_whitespace_start_byte = i + c.len_utf8(); + break; + } + } + let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize); + let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start; + let mut whitespace_range = Range::new(whitespace_start, whitespace_len); + whitespace_range.shift_by(scanned_text_fragment_info.range.begin()); + + let text_bounds = scanned_text_fragment_info.run + .metrics_for_range(&whitespace_range) + .bounding_box; + border_box.size.inline -= text_bounds.size.width; + scanned_text_fragment_info.content_size.inline -= text_bounds.size.width; + + scanned_text_fragment_info.range.extend_by(-whitespace_len); + WhitespaceStrippingResult::RetainFragment } } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index ab8beba722a..1e48a2b5a6d 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![deny(unsafe_code)] -#![feature(box_patterns)] extern crate app_units; extern crate atomic_refcell;