Auto merge of #18854 - servo:servo-unstable-feature, r=nox

Make optional the usage of some unstable features

With `--no-default-features --features default-except-unstable`, more crates can now be compiled on stable Rust. This will help integrate them in rustc’s regression testing and compiler performance benchmarking.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18854)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-10-13 12:26:39 -05:00 committed by GitHub
commit 78aaa85aec
40 changed files with 549 additions and 236 deletions

13
Cargo.lock generated
View file

@ -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",
@ -472,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",
@ -1564,6 +1566,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",
@ -1906,6 +1909,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.1 (git+https://github.com/servo/webrender)",
]
@ -2045,6 +2049,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"
@ -2664,6 +2675,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",
@ -2982,6 +2994,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]]

View file

@ -16,6 +16,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"}

View file

@ -4,17 +4,16 @@
#![crate_name = "canvas_traits"]
#![crate_type = "rlib"]
#![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;

View file

@ -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<u32>);
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]

View file

@ -18,10 +18,11 @@ 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"}
servo_geometry = {path = "../geometry", features = ["servo"]}
servo_geometry = {path = "../geometry"}
servo_url = {path = "../url"}
style_traits = {path = "../style_traits"}
time = "0.1.17"

View file

@ -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?")),
}
}
}

View file

@ -3,9 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![deny(unsafe_code)]
#![feature(nonzero)]
extern crate core;
extern crate euclid;
extern crate gfx_traits;
extern crate gleam;
@ -15,6 +13,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;

View file

@ -772,6 +772,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
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<Message, LTF, STF> Constellation<Message, LTF, STF>
.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<Iterator<Item = &'a SessionHistoryEntry> + '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<Message, LTF, STF> Constellation<Message, LTF, STF>
.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<Iterator<Item = &'a SessionHistoryEntry> + '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)

View file

@ -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;

View file

@ -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"

View file

@ -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"

View file

@ -3,8 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// For SIMD
#![cfg_attr(any(target_os = "linux", target_os = "android"), feature(allocator_api))]
#![feature(cfg_target_feature)]
#![cfg_attr(feature = "unstable", feature(cfg_target_feature))]
#![deny(unsafe_code)]
@ -53,6 +52,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;

View file

@ -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::<u8>::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::<u8>::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::<u8>::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

View file

@ -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<ByteIndex>, 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<ByteIndex>, 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] {

View file

@ -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);
}
}

View file

@ -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;
@ -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,13 +453,13 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
#[allow(unsafe_code)]
pub fn base<T: ?Sized + Flow>(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)
}
}
/// Iterates over the children of this immutable flow.
pub fn child_iter<'a>(flow: &'a Flow) -> impl Iterator<Item = &'a Flow> {
pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator {
base(flow).children.iter()
}
@ -467,7 +467,7 @@ pub fn child_iter<'a>(flow: &'a Flow) -> impl Iterator<Item = &'a Flow> {
#[allow(unsafe_code)]
pub fn mut_base<T: ?Sized + Flow>(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)
}
}

View file

@ -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<Item = &'a Flow> {
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<usize>) {
self.it.size_hint()
}
}
impl<'a> Iterator for MutFlowListIterator<'a> {
type Item = &'a mut Flow;
#[inline]

View file

@ -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<Au>) {
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<Au>)
-> 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<Au>)
-> 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
}
}

View file

@ -3,10 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![deny(unsafe_code)]
#![feature(box_patterns)]
#![feature(conservative_impl_trait)]
#![feature(nonzero)]
#![feature(raw)]
extern crate app_units;
extern crate atomic_refcell;
@ -94,3 +90,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 (),
}

View file

@ -9,6 +9,9 @@ publish = false
name = "layout_thread"
path = "lib.rs"
[features]
unstable = ["parking_lot/nightly", "nonzero/unstable"]
[dependencies]
app_units = "0.5"
atomic_refcell = "0.1"
@ -26,7 +29,8 @@ log = "0.3.5"
metrics = {path = "../metrics"}
msg = {path = "../msg"}
net_traits = {path = "../net_traits"}
parking_lot = {version = "0.4", features = ["nightly"]}
nonzero = {path = "../nonzero"}
parking_lot = "0.4"
profile_traits = {path = "../profile_traits"}
range = {path = "../range"}
rayon = "0.8"

View file

@ -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<ElementData>> {
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))
}
}

View file

@ -6,11 +6,9 @@
//! painted.
#![feature(mpsc_select)]
#![feature(nonzero)]
extern crate app_units;
extern crate atomic_refcell;
extern crate core;
extern crate euclid;
extern crate fnv;
extern crate gfx;
@ -29,6 +27,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;

View file

@ -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"]}

View file

@ -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<u32> {
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<Option<PipelineNamespace>> = C
pub struct PipelineNamespaceId(pub u32);
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct PipelineIndex(pub NonZero<u32>);
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<u32>);
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<BrowsingContextId> 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 };

View file

@ -2,16 +2,13 @@
* 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)]
#![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;

View file

@ -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"

121
components/nonzero/lib.rs Normal file
View file

@ -0,0 +1,121 @@
/* 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_attr(feature = "unstable", feature(const_fn))]
#![cfg_attr(feature = "unstable", feature(const_nonzero_new))]
#[macro_use]
extern crate serde;
pub use imp::*;
#[cfg(feature = "unstable")]
mod imp {
extern crate core;
use self::core::nonzero::NonZero;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct NonZeroU32(NonZero<u32>);
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct NonZeroUsize(NonZero<usize>);
impl NonZeroU32 {
#[inline] pub const unsafe fn new_unchecked(x: u32) -> Self { NonZeroU32(NonZero::new_unchecked(x)) }
#[inline] pub fn new(x: u32) -> Option<Self> { 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<Self> { NonZero::new(x).map(NonZeroUsize) }
#[inline] pub fn get(self) -> usize { self.0.get() }
}
}
#[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);
impl NonZeroU32 {
#[inline]
pub fn new(x: u32) -> Option<Self> {
if x != 0 {
Some(NonZeroU32(x))
} else {
None
}
}
#[inline]
pub unsafe fn new_unchecked(x: u32) -> Self {
NonZeroU32(x)
}
#[inline]
pub fn get(self) -> u32 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq)]
pub struct NonZeroUsize(&'static ());
impl NonZeroUsize {
#[inline]
pub fn new(x: usize) -> Option<Self> {
if x != 0 {
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<cmp::Ordering> {
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<H: hash::Hasher>(&self, hasher: &mut H) {
self.get().hash(hasher)
}
}
}

View file

@ -9,6 +9,9 @@ publish = false
name = "profile"
path = "lib.rs"
[features]
unstable = []
[dependencies]
profile_traits = {path = "../profile_traits"}
influent = "0.4"

View file

@ -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]

View file

@ -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<usize> {
// 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<usize> {
None
}

View file

@ -12,3 +12,4 @@ path = "lib.rs"
[dependencies]
lazy_static = "0.2"
log = "0.3.5"
nonzero = {path = "../nonzero"}

View file

@ -10,13 +10,11 @@
//! 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)]
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 +25,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<usize>);
pub struct ThreadId(NonZeroUsize);
lazy_static!{ static ref THREAD_COUNT: AtomicUsize = AtomicUsize::new(1); }
@ -35,7 +33,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 +57,13 @@ impl AtomicOptThreadId {
#[allow(unsafe_code)]
pub fn load(&self, ordering: Ordering) -> Option<ThreadId> {
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<ThreadId>, ordering: Ordering) -> Option<ThreadId> {
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)
}
}

View file

@ -25,6 +25,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"}

View file

@ -7,12 +7,10 @@
//! to depend on script.
#![deny(unsafe_code)]
#![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 +24,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 +42,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 +78,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)]

View file

@ -20,7 +20,7 @@ doctest = false
[features]
gecko_like_types = []
unstable = []
bench = []
[dependencies]
bitflags = "0.7"

View file

@ -346,7 +346,7 @@ fn create_and_insert_some_stuff() {
}
}
#[cfg(feature = "unstable")]
#[cfg(feature = "bench")]
#[cfg(test)]
mod bench {
extern crate test;

View file

@ -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;

View file

@ -12,13 +12,18 @@ 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"]
debugmozjs = ["script/debugmozjs"]
googlevr = ["webvr/googlevr"]
oculusvr = ["webvr/oculusvr"]
unstable = [
"euclid/unstable",
"gfx/unstable",
"msg/unstable",
"profile/unstable",
]
[dependencies]
bluetooth_traits = {path = "../bluetooth_traits"}

View file

@ -29,13 +29,15 @@ servo_remutex_tests = {path = "../../tests/unit/servo_remutex"}
style_tests = {path = "../../tests/unit/style"}
[features]
default = ["webdriver", "max_log_level"]
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"]
debugmozjs = ["libservo/debugmozjs"]
googlevr = ["libservo/googlevr"]
oculusvr = ["libservo/oculusvr"]
unstable = ["libservo/unstable"]
[dependencies]
backtrace = "0.3"

View file

@ -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::<raw::TraitObject>(), mem::size_of::<layout::TraitObject>());
let null: *mut () = ptr::null_mut();
let a = raw::TraitObject {
data: null,
vtable: null,
};
let b = layout::TraitObject {
data: null,
vtable: null,
};
fn offset<T, U>(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));
}