State of Servo | Patrick Walton | 6/25/12 3:33 PM | 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 |
Re: State of Servo | Robert O'Callahan | 6/25/12 4:32 PM | This all looks pretty good!
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. 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. 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. 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] |
Re: State of Servo | Boris Zbarsky | 6/25/12 7:02 PM | On 6/25/12 7:32 PM, Robert O'Callahan wrote: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 |
Re: State of Servo | Robert O'Callahan | 6/25/12 7:19 PM | How about the obvious approach --- have JS and Rust share the same garbage
collector? |
Re: State of Servo | Boris Zbarsky | 6/25/12 7:31 PM | On 6/25/12 10:19 PM, Robert O'Callahan wrote: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 |
Re: State of Servo | Patrick Walton | 6/25/12 7:51 PM | 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 |
Re: State of Servo | Patrick Walton | 6/25/12 8:01 PM | On 06/25/2012 04:32 PM, Robert O'Callahan 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. 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. Agreed. Note that we need the bindings first :) 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. 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. OK. As long as you think the performance won't suffer with floating point ops, I'm happy to move over. Patrick |
Re: State of Servo | Jesse Ruderman | 6/25/12 8:07 PM | > Small comment about units: glad to see you using 1/60px appunits, but IWhat'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. |
Re: State of Servo | Boris Zbarsky | 6/25/12 8:57 PM | On 6/25/12 11:01 PM, Patrick Walton wrote: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. Hmm. I _could_ try working on a binding generator, I guess. Need to figure out what it needs to spit out. ;) 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 |
Re: State of Servo | Robert O'Callahan | 6/25/12 9:03 PM | On Tue, Jun 26, 2012 at 3:07 PM, Jesse Ruderman <jrud...@gmail.com> wrote: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). We would probably still lay out those pages just fine, albeit with reduced precision on the vertical axis, which doesn't matter much. |
Re: State of Servo | Robert O'Callahan | 6/25/12 10:51 PM | On Tue, Jun 26, 2012 at 10:33 AM, Patrick Walton <pwa...@mozilla.com>wrote: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. |
Re: State of Servo | Robert O'Callahan | 6/25/12 10:55 PM | On Tue, Jun 26, 2012 at 5:51 PM, Robert O'Callahan <rob...@ocallahan.org>wrote: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? |
Re: State of Servo | Boris Zbarsky | 6/26/12 8:00 PM | On 6/26/12 1:51 AM, Robert O'Callahan 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...) -Boris |
Re: State of Servo | Robert O'Callahan | 6/26/12 10:56 PM | On Wed, Jun 27, 2012 at 3:00 PM, Boris Zbarsky <bzba...@mit.edu> wrote:Is this document.domain or more than that? Why can't we have a 1:1 relationship between browsing contexts and compartments? |
Re: State of Servo | Boris Zbarsky | 6/27/12 7:01 AM | On 6/27/12 1:56 AM, Robert O'Callahan wrote:The "same-origin" bit is both document.domain and apparently sandbox CSP policies.... 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 |
Re: State of Servo | Robert O'Callahan | 6/27/12 3:49 PM | On Thu, Jun 28, 2012 at 2:02 AM, Boris Zbarsky <bzba...@mit.edu> wrote: >> Is this document.domain or more than that?<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 :-). 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? |
Re: State of Servo | Boris Zbarsky | 6/27/12 7:19 PM | On 6/27/12 6:49 PM, Robert O'Callahan wrote: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.... 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 |
Re: State of Servo | bigmikel...@gmail.com | 7/2/13 8:31 AM | 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 :) |
Re: State of Servo | Benjamin Smedberg | 7/2/13 8:36 AM | On 7/2/2013 11:31 AM, bigmikel...@gmail.com wrote:No, absolutely not. It's not even worth discussing yet. --BDS |