Skip to content
Permalink
Browse files

style: Allow references to static C++ URLExtraData objects from Rust …

…UrlExtraData.

Each user agent style sheet has a unique URLExtraData object containing
its URL, but since they are refcounted objects, we can't share them
easily across processes.  Rather than adding support for copying them
into a shared memory buffer like we will do with the Rust objects, here
we just set up a static array of URLExtraData objects per UA style
sheet.  The array will be filled in in a later patch.

Rust UrlExtraData objects, once they are transformed into their
sharable form and copied into the shared memory buffer, will reference
them by an index.

Differential Revision: https://phabricator.services.mozilla.com/D17182
  • Loading branch information...
heycam authored and emilio committed Mar 30, 2019
1 parent 5ebc3f8 commit 91586eea0e1748531eb010d2f1061eb834f384e5
Showing with 72 additions and 11 deletions.
  1. +72 −11 components/style/stylesheets/mod.rs
@@ -23,6 +23,10 @@ mod stylesheet;
pub mod supports_rule;
pub mod viewport_rule;

#[cfg(feature = "gecko")]
use crate::gecko_bindings::sugar::refptr::RefCounted;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::{bindings, structs};
use crate::parser::ParserContext;
use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
@@ -32,6 +36,8 @@ use cssparser::{parse_one_rule, Parser, ParserInput};
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
use servo_arc::Arc;
use std::fmt;
#[cfg(feature = "gecko")]
use std::mem;
use style_traits::ParsingMode;

pub use self::counter_style_rule::CounterStyleRule;
@@ -60,18 +66,56 @@ pub use self::viewport_rule::ViewportRule;
pub type UrlExtraData = ::servo_url::ServoUrl;

/// Extra data that the backend may need to resolve url values.
///
/// If the usize's lowest bit is 0, then this is a strong reference to a
/// structs::URLExtraData object.
///
/// Otherwise, shifting the usize's bits the right by one gives the
/// UserAgentStyleSheetID value corresponding to the style sheet whose
/// URLExtraData this is, which is stored in URLExtraData_sShared. We don't
/// hold a strong reference to that object from here, but we rely on that
/// array's objects being held alive until shutdown.
///
/// We use this packed representation rather than an enum so that
/// `from_ptr_ref` can work.
#[cfg(feature = "gecko")]
#[derive(PartialEq)]
pub struct UrlExtraData(usize);

#[cfg(feature = "gecko")]
#[derive(Clone, PartialEq)]
pub struct UrlExtraData(
pub crate::gecko_bindings::sugar::refptr::RefPtr<crate::gecko_bindings::structs::URLExtraData>,
);
impl Clone for UrlExtraData {
fn clone(&self) -> UrlExtraData {
UrlExtraData::new(self.ptr())
}
}

#[cfg(feature = "gecko")]
impl Drop for UrlExtraData {
fn drop(&mut self) {
// No need to release when we have an index into URLExtraData_sShared.
if self.0 & 1 == 0 {
unsafe {
self.as_ref().release();
}
}
}
}

#[cfg(feature = "gecko")]
impl UrlExtraData {
/// Create a new UrlExtraData wrapping a pointer to the specified Gecko
/// URLExtraData object.
pub fn new(ptr: *mut structs::URLExtraData) -> UrlExtraData {
unsafe {
(*ptr).addref();
}
UrlExtraData(ptr as usize)
}

/// True if this URL scheme is chrome.
#[inline]
pub fn is_chrome(&self) -> bool {
self.0.mIsChrome
self.as_ref().mIsChrome
}

/// Create a reference to this `UrlExtraData` from a reference to pointer.
@@ -80,16 +124,30 @@ impl UrlExtraData {
///
/// This method doesn't touch refcount.
#[inline]
pub unsafe fn from_ptr_ref(ptr: &*mut crate::gecko_bindings::structs::URLExtraData) -> &Self {
::std::mem::transmute(ptr)
pub unsafe fn from_ptr_ref(ptr: &*mut structs::URLExtraData) -> &Self {
mem::transmute(ptr)
}

/// Returns a pointer to the Gecko URLExtraData object.
pub fn ptr(&self) -> *mut structs::URLExtraData {
if self.0 & 1 == 0 {
self.0 as *mut structs::URLExtraData
} else {
unsafe {
let sheet_id = self.0 >> 1;
structs::URLExtraData_sShared[sheet_id].mRawPtr
}
}
}

fn as_ref(&self) -> &structs::URLExtraData {
unsafe { &*(self.ptr() as *const structs::URLExtraData) }
}
}

#[cfg(feature = "gecko")]
impl fmt::Debug for UrlExtraData {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use crate::gecko_bindings::{bindings, structs};

struct DebugURI(*mut structs::nsIURI);
impl fmt::Debug for DebugURI {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@@ -105,10 +163,13 @@ impl fmt::Debug for UrlExtraData {
formatter
.debug_struct("URLExtraData")
.field("is_chrome", &self.is_chrome())
.field("base", &DebugURI(self.0.mBaseURI.raw::<structs::nsIURI>()))
.field(
"base",
&DebugURI(self.as_ref().mBaseURI.raw::<structs::nsIURI>()),
)
.field(
"referrer",
&DebugURI(self.0.mReferrer.raw::<structs::nsIURI>()),
&DebugURI(self.as_ref().mReferrer.raw::<structs::nsIURI>()),
)
.finish()
}

0 comments on commit 91586ee

Please sign in to comment.
You can’t perform that action at this time.