Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

State of Servo

13,748 views
Skip to first unread message

Patrick Walton

unread,
Jun 25, 2012, 6:33:23 PM6/25/12
to dev-...@lists.mozilla.org
As requested, here's the state of Servo as it stands.

We have a GitHub repository here: https://github.com/mozilla/servo

Currently what we have builds on Mac and Linux. There's no fundamental
reason why it won't work on Windows, but none of us have put in the
effort necessary to bring it up. The sole platform ("widget" backend in
Gecko terminology) is SDL, but there's an in-process planned move to
GLUT, which should land when the Layers infrastructure is ready. We're
undertaking this move because the Mac port of GLUT is maintained by
Apple and much higher-quality than the Mac SDL port. Neither of these
backends are intended to be long-term solutions; for production we will
want true platform-native backends for each platform.

We make heavy use of Git submodules for modularity--like WebKit, we want
the pieces of Servo to be independently hackable. In addition, we'd like
the components of Servo to be reusable for general Rust apps. For
example, networking, URL parsing, and layers are useful functionality
for a variety of applications, and we can benefit from community
contributions to these components when and if Rust becomes widely used.

Where possible, we reuse existing C and C++ libraries. This doesn't
preclude the possibility of rewriting the functionality provided by
these libraries in safe and parallel Rust code, but it helps us get off
the ground. At the moment, these libraries are:

* HarfBuzz (and its dependency Ragel), for text shaping.

* Azure, for 2D graphics.

* SDL (soon to be replaced with GLUT), as an abstraction layer over the
native windowing system.

* stb_image, for image decoding. This is a very simple image library,
likely insecure and missing support for progressive JPEG, but it's
extremely small and simple, devoid of dependencies, and in the public
domain.

* SpiderMonkey, for JavaScript support.

* libuv, for networking. This is a library closely associated with
node.js, which abstracts over the asynchronous I/O mechanisms on each
platform. Most notably, it works on Windows, unlike nearly all of the
alternatives.

Our focus so far has been on laying the proper groundwork for a scalable
rendering engine. In particular, we've been focused on decomposing the
rendering pipeline into tasks (lightweight Rust threads), as this is the
part that's most critical to get right and the most difficult to
retrofit onto existing architectures. Right now, Servo has several tasks
in the rendering pipeline. (When we get tab/window support, each of
these tasks will be replicated for each origin.) As I understand it, the
tasks are:

* A content task, which runs JavaScript, spawns layout tasks, and
manages layout task lifetimes. DOM structures are shared between this
task and the other tasks in a read-copy-update model; if content
concurrently mutates a DOM node that layout is currently operating on,
that DOM node is copied for the duration of that layout operation.

* A layout task, which supervises layout. Currently, layout is mostly
done sequentially, but our intern Margaret Meyerhoffer has begun to
implement parallel CSS selector matching. Conceptually, the layout task
is one supervisor task with many subtasks to perform parallel layout. At
the moment, this task can perform both toy inline and toy block layout.

* A renderer task, which receives display lists and renders them. When
layers infrastructure lands, there will actually be many renderer tasks,
one for each layer. This will allow us to render layers in parallel.

* A platform task, which manages the main OS thread and native platform
event loop. Nothing happens on this task except for that which
absolutely needs to be handled by it (because the native windowing
library demands it).

* An engine task, which supervises the other tasks and does nothing else.

* An I/O task, which handles networking in an evented, asynchronous
manner via libuv. Note that networking is not yet implemented in Servo,
so this task doesn't do much.

Another major planned task (not yet implemented) is:

* A compositor task, to composite layers together. Scrolling and CSS
animations should be handled by this task as well.

Patrick

Robert O'Callahan

unread,
Jun 25, 2012, 7:32:14 PM6/25/12
to Patrick Walton, dev-...@lists.mozilla.org
This all looks pretty good!

On Tue, Jun 26, 2012 at 10:33 AM, PatrickWalton <pwa...@mozilla.com> wrote:

> We make heavy use of Git submodules for modularity--like WebKit, we want
> the pieces of Servo to be independently hackable. In addition, we'd like
> the components of Servo to be reusable for general Rust apps. For example,
> networking, URL parsing, and layers are useful functionality for a variety
> of applications, and we can benefit from community contributions to these
> components when and if Rust becomes widely used.
>

FWIW networking and layers aren't actually part of Webkit (URL parsing
didn't used to be either, but they might have fixed that), and anything
near the core engine is quite tangled. I think LLVM is a more impressive
example of modularity.

Where possible, we reuse existing C and C++ libraries. This doesn't
> preclude the possibility of rewriting the functionality provided by these
> libraries in safe and parallel Rust code, but it helps us get off the
> ground.


Sounds reasonable. I think it is important that these libraries get
rewritten in Rust over time, starting with the most Web-facing code ---
Harfbuzz and stb_image. Obviously sorting out the core browser architecture
is higher priority for now, though I'd still like to see a fast JPEG
decoder in Rust to ensure the language can do it.

* A content task, which runs JavaScript, spawns layout tasks, and manages
> layout task lifetimes. DOM structures are shared between this task and the
> other tasks in a read-copy-update model; if content concurrently mutates a
> DOM node that layout is currently operating on, that DOM node is copied for
> the duration of that layout operation.
>

It seems that right now rcu.rs exposes operations that allow users to do
unsafe things:

Note: if the type `T` contains mutable fields, then there is nothing
to stop the reader from
> mutating those fields in the `read()` method. Do not do this. It will lead to race conditions.
>
> FIXME: We can enforce that this is not done by ensuring that the type `T` contains no mutable
> fields.
>
> # Auxiliary data
>
> Readers can associate a piece of auxiliary data of type `A` along with main nodes. This is
> convenient but dangerous: it is the reader's job to ensure that this data remains live independent
> of the RCU nodes themselves.
>
>
Is the FIXME fixable? We'll want to be able to ensure that dom and layout
aren't part of the TCB.

It would be great to be able to run some DOM microbenchmarks to measure RCU
overhead and ensure that single-threaded DOM manipulation is competitive
with existing engines.

I'm glad we're implementing the DOM in Rust. What's the plan for DOM
bindings? That seems to be the most important piece still missing.

* A layout task, which supervises layout. Currently, layout is mostly done
> sequentially, but our intern Margaret Meyerhoffer has begun to implement
> parallel CSS selector matching. Conceptually, the layout task is one
> supervisor task with many subtasks to perform parallel layout. At the
> moment, this task can perform both toy inline and toy block layout.
>

I hope we can get someone to start porting Leo's stuff here :-).

Small comment about units: glad to see you using 1/60px appunits, but I
would store them as floats (32bit) --- with fractions not allowed (only an
issue for division or multiplication by a genuine float). Integer overflows
are a large latent problem in existing layout engines.

BTW is the plan still to have integer overflow cause task failure by
default in Rust? I sure hope so! Even assuming we do that, we probably
still want float appunits so that layout can handle extreme coordinates
without dying.

Also, in Gecko gfx doesn't know about appunits, only layout does. gfx works
in device pixels, usually floats. I'd keep that separation.

Thanks!
Rob
--
“You have heard that it was said, ‘Love your neighbor and hate your enemy.’
But I tell you, love your enemies and pray for those who persecute you,
that you may be children of your Father in heaven. ... If you love those
who love you, what reward will you get? Are not even the tax collectors
doing that? And if you greet only your own people, what are you doing more
than others?" [Matthew 5:43-47]

Boris Zbarsky

unread,
Jun 25, 2012, 10:02:08 PM6/25/12
to mozilla-...@lists.mozilla.org
On 6/25/12 7:32 PM, Robert O'Callahan wrote:
> I'm glad we're implementing the DOM in Rust. What's the plan for DOM
> bindings? That seems to be the most important piece still missing.

We don't know yet.

In particular, I don't think we've come up with a satisfactory answer to
the ownership model question (aka the "how do we avoid having a cycle
collector" question)...

-Boris

Robert O'Callahan

unread,
Jun 25, 2012, 10:19:10 PM6/25/12
to Boris Zbarsky, mozilla-...@lists.mozilla.org
On Tue, Jun 26, 2012 at 2:02 PM, Boris Zbarsky <bzba...@mit.edu> wrote:

> On 6/25/12 7:32 PM, Robert O'Callahan wrote:
>
>> I'm glad we're implementing the DOM in Rust. What's the plan for DOM
>> bindings? That seems to be the most important piece still missing.
>>
>
> We don't know yet.
>
> In particular, I don't think we've come up with a satisfactory answer to
> the ownership model question (aka the "how do we avoid having a cycle
> collector" question)...
>

How about the obvious approach --- have JS and Rust share the same garbage
collector?

Boris Zbarsky

unread,
Jun 25, 2012, 10:31:56 PM6/25/12
to mozilla-...@lists.mozilla.org
On 6/25/12 10:19 PM, Robert O'Callahan wrote:
> How about the obvious approach --- have JS and Rust share the same garbage
> collector?

Patrick, how feasible is that? That would certainly solve the problem!

At that point we can do DOM bindings the same way we're doing them in
Gecko now, if desired: codegen them from the WebIDL. We can reuse a all
the parser and data model code, and a lot of the logic (e.g. the
overload resolution implementation) and just have to rejigger the actual
code that gets spit out a bit (like make it not C++).

-Boris

Patrick Walton

unread,
Jun 25, 2012, 10:51:33 PM6/25/12
to dev-...@lists.mozilla.org
On 06/25/2012 07:31 PM, Boris Zbarsky wrote:
> On 6/25/12 10:19 PM, Robert O'Callahan wrote:
>> How about the obvious approach --- have JS and Rust share the same
>> garbage
>> collector?
>
> Patrick, how feasible is that? That would certainly solve the problem!
>
> At that point we can do DOM bindings the same way we're doing them in
> Gecko now, if desired: codegen them from the WebIDL. We can reuse a all
> the parser and data model code, and a lot of the logic (e.g. the
> overload resolution implementation) and just have to rejigger the actual
> code that gets spit out a bit (like make it not C++).

As I understand it, that's the plan. The goal is to have JS and Rust
share the JS heap for all the DOM objects.

Note that this doesn't work for layout data structures, because layout
has to be able to allocate concurrently with JavaScript. That doesn't
pose a huge problem, though, because JS has no direct access to those
structures anyway. (It can query the contents of those structures, but
those queries require special handling in any case because in general
query of layout properties requires a reflow.) The tricky part is when
DOM mutations require that layout data structures be discarded (for
example, when nodes are destroyed). The way Niko handles this now is to
have content gather up all those dead layout data structures during JS
object finalization and hand them to layout to be destroyed the next
time layout is triggered. This seems like a reasonable approach; it
keeps sweeping of layout data structures off the content thread, which
is the important thing.

Patrick

Patrick Walton

unread,
Jun 25, 2012, 11:01:16 PM6/25/12
to rob...@ocallahan.org, dev-...@lists.mozilla.org
On 06/25/2012 04:32 PM, Robert O'Callahan wrote:
> FWIW networking and layers aren't actually part of Webkit (URL parsing
> didn't used to be either, but they might have fixed that), and anything
> near the core engine is quite tangled. I think LLVM is a more impressive
> example of modularity.

Ah, interesting. Modularity is one of those things that we need to stay
vigilant about for it to happen. Brian in particular is very keen on
trying to stay modular from the start, and I agree at it's a good goal.

> Is the FIXME fixable? We'll want to be able to ensure that dom and
> layout aren't part of the TCB.

Yes, it should be fixable. Niko and I actually talked about this before
he left for vacation. The easiest way to ensure memory safety is to have
the RCU system actually manage the memory. To eliminate races, we can
use a "const" type bound and the "immutable structures inherit the
mutability of their parent" rule in Rust to make sure there are no races
on the reader side (layout) while ensuring that the writer side
(content) can still write.

In general, we've been trying to innovate using unsafe code in Servo to
figure out what we need, and then folding the ideas back into the Rust
type system to achieve safety.

> It would be great to be able to run some DOM microbenchmarks to measure
> RCU overhead and ensure that single-threaded DOM manipulation is
> competitive with existing engines.

Agreed. Note that we need the bindings first :)

> I'm glad we're implementing the DOM in Rust. What's the plan for DOM
> bindings? That seems to be the most important piece still missing.

As mentioned in the other thread, the plan as of now is to have DOM
objects implemented in Rust but to allocate all the DOM objects in the
JS heap (with a fixed memory layout so that we can share pointers
between JS and Rust). DOM methods that don't need to cross layout
boundaries will be implemented as native functions. As Boris mentioned,
we might be able to reuse the bindings generator here.

> Small comment about units: glad to see you using 1/60px appunits, but I
> would store them as floats (32bit) --- with fractions not allowed (only
> an issue for division or multiplication by a genuine float). Integer
> overflows are a large latent problem in existing layout engines.
>
> BTW is the plan still to have integer overflow cause task failure by
> default in Rust? I sure hope so!

Yes. It's currently unimplemented, but Michael Sullivan has started to
add support for it because we've already hit overflow issues in vector
indexing.

> Even assuming we do that, we probably
> still want float appunits so that layout can handle extreme coordinates
> without dying.

OK. As long as you think the performance won't suffer with floating
point ops, I'm happy to move over.

Patrick

Jesse Ruderman

unread,
Jun 25, 2012, 11:07:47 PM6/25/12
to rob...@ocallahan.org, dev-...@lists.mozilla.org, Patrick Walton
> Small comment about units: glad to see you using 1/60px appunits, but I
> would store them as floats (32bit) --- with fractions not allowed (only an
> issue for division or multiplication by a genuine float). Integer overflows
> are a large latent problem in existing layout engines.

What's the problem you're trying to solve here? If it's a safety
issue, I'm not sure floats are that much safer. If it's web
compatibility, the rounding issues with a 23-bit mantissa will strike
book-length web pages.

Boris Zbarsky

unread,
Jun 25, 2012, 11:57:16 PM6/25/12
to mozilla-...@lists.mozilla.org
On 6/25/12 11:01 PM, Patrick Walton wrote:
> Ah, interesting. Modularity is one of those things that we need to stay
> vigilant about for it to happen. Brian in particular is very keen on
> trying to stay modular from the start, and I agree at it's a good goal.

We can do this as long as we get the inter-module APIs right. Which in
practice means as long as we're willing to fix them once we figure out
we got them wrong and keep doing that....

I'm a lot less interested in modularity if it means that we have to have
two separate implementations of HTTP validation/caching like every
single WebKit port has to do, for example.

> Agreed. Note that we need the bindings first :)

Hmm. I _could_ try working on a binding generator, I guess. Need to
figure out what it needs to spit out. ;)

> As mentioned in the other thread, the plan as of now is to have DOM
> objects implemented in Rust but to allocate all the DOM objects in the
> JS heap (with a fixed memory layout so that we can share pointers
> between JS and Rust). DOM methods that don't need to cross layout
> boundaries will be implemented as native functions. As Boris mentioned,
> we might be able to reuse the bindings generator here.

So that doesn't quite solve the problem, though it gets us close: we
also need to make sure that various ways to attach sets of JS objects to
DOM objects (primarily addEventListener, but also various other callback
setups) work. We may be able to handle this with just trace class
hooks, I think, as long a we're clear on which DOM object owns what on
the Rust side.

-Boris

Robert O'Callahan

unread,
Jun 26, 2012, 12:03:20 AM6/26/12
to Jesse Ruderman, dev-...@lists.mozilla.org, Patrick Walton
On Tue, Jun 26, 2012 at 3:07 PM, Jesse Ruderman <jrud...@gmail.com> wrote:

> > Small comment about units: glad to see you using 1/60px appunits, but I
> > would store them as floats (32bit) --- with fractions not allowed (only
> an
> > issue for division or multiplication by a genuine float). Integer
> overflows
> > are a large latent problem in existing layout engines.
>
> What's the problem you're trying to solve here? If it's a safety
> issue, I'm not sure floats are that much safer.


I'm not sure either since I haven't built a layout engine using floats, but
I'm hopeful.

In Gecko when an nscoord overflows we can wrap around and end up with
something negative that should never be negative, or otherwise violate
pretty much any invariant involving coordinates. With floats, invariants of
the form "x >= 0 implies y + x >= y and y - x <= y" will always hold (until
you hit NaNs, which are pretty hard to hit from content since most features
don't let you multiply two CSS values). Invariants preconditioned on x > 0
could fail, but I get the feeling those are rare (perhaps because widths
and heights are often zero but never negative).

If it's web
> compatibility, the rounding issues with a 23-bit mantissa will strike
> book-length web pages.
>

We would probably still lay out those pages just fine, albeit with reduced
precision on the vertical axis, which doesn't matter much.

Robert O'Callahan

unread,
Jun 26, 2012, 1:51:28 AM6/26/12
to Patrick Walton, dev-...@lists.mozilla.org
On Tue, Jun 26, 2012 at 10:33 AM, Patrick Walton <pwa...@mozilla.com>wrote:

> (When we get tab/window support, each of these tasks will be replicated
> for each origin.)


BTW I think we should try to have separate tasks per browsing context (i.e.
per document). In some cases browsing contexts with the same origin can
communicate and will need to ensure JS observes serial execution, but we
can use messages to achieve that and when JS isn't running we should be
able to run many HTML5 tasks for same-origin documents in parallel.

Robert O'Callahan

unread,
Jun 26, 2012, 1:55:22 AM6/26/12
to Patrick Walton, dev-...@lists.mozilla.org
On Tue, Jun 26, 2012 at 5:51 PM, Robert O'Callahan <rob...@ocallahan.org>wrote:

> On Tue, Jun 26, 2012 at 10:33 AM, Patrick Walton <pwa...@mozilla.com>wrote:
>
>> (When we get tab/window support, each of these tasks will be replicated
>> for each origin.)
>
>
> BTW I think we should try to have separate tasks per browsing context
> (i.e. per document). In some cases browsing contexts with the same origin
> can communicate and will need to ensure JS observes serial execution, but
> we can use messages to achieve that and when JS isn't running we should be
> able to run many HTML5 tasks for same-origin documents in parallel.
>

I guess that would require using compartments to provide cross-Rust-task
proxies when JS in one document accesses the heap of JS in another
document. Can we do that?

Boris Zbarsky

unread,
Jun 26, 2012, 11:00:47 PM6/26/12
to mozilla-...@lists.mozilla.org
On 6/26/12 1:51 AM, Robert O'Callahan wrote:
> On Tue, Jun 26, 2012 at 10:33 AM, Patrick Walton<pwa...@mozilla.com>wrote:
>
>> (When we get tab/window support, each of these tasks will be replicated
>> for each origin.)
>
>
> BTW I think we should try to have separate tasks per browsing context (i.e.
> per document). In some cases browsing contexts with the same origin can
> communicate and will need to ensure JS observes serial execution, but we
> can use messages to achieve that and when JS isn't running we should be
> able to run many HTML5 tasks for same-origin documents in parallel.

Note also that "same-origin" is not invariant for the lifetime of the
document, so I think we'll want various tasks per-compartment anyway
(which is not quite the same as either per-browsing-context or
per-document...)

-Boris

Robert O'Callahan

unread,
Jun 27, 2012, 1:56:55 AM6/27/12
to Boris Zbarsky, mozilla-...@lists.mozilla.org
On Wed, Jun 27, 2012 at 3:00 PM, Boris Zbarsky <bzba...@mit.edu> wrote:

> Note also that "same-origin" is not invariant for the lifetime of the
> document, so I think we'll want various tasks per-compartment anyway (which
> is not quite the same as either per-browsing-context or per-document...)
>

Is this document.domain or more than that? Why can't we have a 1:1
relationship between browsing contexts and compartments?

Boris Zbarsky

unread,
Jun 27, 2012, 10:01:50 AM6/27/12
to mozilla-...@lists.mozilla.org
On 6/27/12 1:56 AM, Robert O'Callahan wrote:
> On Wed, Jun 27, 2012 at 3:00 PM, Boris Zbarsky<bzba...@mit.edu> wrote:
>
>> Note also that "same-origin" is not invariant for the lifetime of the
>> document, so I think we'll want various tasks per-compartment anyway (which
>> is not quite the same as either per-browsing-context or per-document...)
>>
>
> Is this document.domain or more than that?

The "same-origin" bit is both document.domain and apparently sandbox CSP
policies....

> Why can't we have a 1:1
> relationship between browsing contexts and compartments?

Because a given browsing context can load multiple documents (one after
another), and those can be from different domains. So it has many
compartments corresponding to it. For example, if I have a reference to
a node in a document and the document is unloaded and replaced with
another document, that shouldn't affect whether I can touch the node I
already have a reference to.

-Boris

Robert O'Callahan

unread,
Jun 27, 2012, 6:49:11 PM6/27/12
to Boris Zbarsky, mozilla-...@lists.mozilla.org
On Thu, Jun 28, 2012 at 2:02 AM, Boris Zbarsky <bzba...@mit.edu> wrote:

> On 6/27/12 1:56 AM, Robert O'Callahan wrote:
>
>> Is this document.domain or more than that?
>>
>
> The "same-origin" bit is both document.domain and apparently sandbox CSP
> policies....


<iframe sandbox> and CSP can't actually dynamically change the origin of a
document, can they? If they can we'd better fix that before it's too late
:-).


> Why can't we have a 1:1
>> relationship between browsing contexts and compartments?
>>
>
> Because a given browsing context can load multiple documents (one after
> another), and those can be from different domains. So it has many
> compartments corresponding to it. For example, if I have a reference to a
> node in a document and the document is unloaded and replaced with another
> document, that shouldn't affect whether I can touch the node I already have
> a reference to.


Oops, of course. The question then is, can we have a 1:1 relationship
between documents-loaded-in-a-browsing-context (what's the spec name for
that?) and compartments?

Boris Zbarsky

unread,
Jun 27, 2012, 10:19:13 PM6/27/12
to mozilla-...@lists.mozilla.org
On 6/27/12 6:49 PM, Robert O'Callahan wrote:
> <iframe sandbox> and CSP can't actually dynamically change the origin of a
> document, can they? If they can we'd better fix that before it's too late
> :-).

The proposal to do sandboxing via CSP and the fact that you can put your
CSP into a <meta> tag mean that you can in fact dynamically change the
origin of a document, from whatever origin it had to a null principal,
when said <meta> tag is parsed. Devdatta is implementing that right now...

I do think it's somewhat daft, but people really want to do sandboxing
via CSP....

> Oops, of course. The question then is, can we have a 1:1 relationship
> between documents-loaded-in-a-browsing-context (what's the spec name for
> that?) and compartments?

Not quite, because of silliness with about:blank.

I do think we can have a 1:1 relationship between a Window and a
compartment (and do in Gecko right now).

-Boris

bigmikel...@gmail.com

unread,
Jul 2, 2013, 11:31:07 AM7/2/13
to
So, here's a question nobodies seemed to ask yet: Has anyone decided, exactly, what the user agent string will look like?

Another browser will invariably mean another browser to have to target specifically, in certain cases :)

Benjamin Smedberg

unread,
Jul 2, 2013, 11:36:50 AM7/2/13
to bigmikel...@gmail.com, dev-...@lists.mozilla.org
On 7/2/2013 11:31 AM, bigmikel...@gmail.com wrote:
> So, here's a question nobodies seemed to ask yet: Has anyone decided, exactly, what the user agent string will look like?
No, absolutely not. It's not even worth discussing yet.

--BDS

0 new messages