

Experience Report: Developing the Servo Web Browser Engine Using Rust [pdf] - Manishearth
http://arxiv.org/pdf/1505.07383v1.pdf

======
hackuser
The section on open problems is interesting. Can anyone comment on their real
world impact?

 _5\. Open problems

While this work has discussed many challenges in browser design and our
current progress, there are many other interesting open problems.

Just-in-time code. JavaScript engines dynamically produce na-tive code that is
intended to execute more efﬁciently than an in-terpreted strategy.
Unfortunately, this area is a large source of se-curity bugs. These bugs come
from two sources. First, there are potential correctness issues. Many of these
optimizations are only valid when certain conditions of the calling code and
environment hold, and ensuring the specialized code is called only when those
conditions hold is non-trivial. Second, dynamically producing and compiling
native code and patching it into memory while respect-ing all of the
invariants required by the JavaScript runtime (e.g., the garbage collector’s
read/write barriers or free vs. in-use registers) is also a challenge.

Integer overﬂow/underﬂow. It is still an open problem to provide optimized
code that checks for overﬂow or underﬂow without in-curring signiﬁcant
performance penalties. The current plan for Rust is to have debug-only
checking of integer ranges and for Servo to run debug builds against a test
suite, but that may miss scenarios that only occur in optimized builds or that
are not represented by the test suite.

Unsafe code correctness. Today, when we write unsafe code in Rust there is
limited validation of memory lifetimes or type safety within that code block.
However, many of our uses of unsafe code are well-behaved translations of
either pointer lifetimes or data representations that cannot be annotated or
inferred in Rust. We are very interested in additional annotations that would
help us prove basic properties about our unsafe code, even if these
annotations require a theorem prover or ILP solver to check.

Incremental computation. As mentioned in Section 2, all mod-ern browsers use
some combination of dirty bit marking and incre-mental recomputation
heuristics to avoid reprocessing the full page when a mutatation is performed.
Unfortunately, these heuristics are not only frequently the source of
performance differences between browsers, but they are also a source of
correctness bugs. A library that provided a form of self adjusting computation
suited to incre-mental recomputation of only the visible part of the page,
perhaps based on the Adapton [HPHF14] approach, seems promising._

~~~
Manishearth
Note that the paper was written a while ago, so things are a bit outdated
(like the integer overflow bit).

> Just-in-time code.

I'm not the expert on this, but JIT is where a lot of perf wins can be had for
javascript. JIT might even be the best place to work on if you want to make
your polished JS engine faster.

As far as security goes, goto Lars' reply.

> Integer overﬂow/underﬂow.

We now do exactly what was suggested in the paper. Rust enables overflow
checking in debug, and we run our CI in debug anyway (release mode build
integration is half baked now and I need to work on that)

A concrete example would be a loop that just goes on incrementing something.
`for _ in 0..n {ctr++}`. This would be zipped to ctr+=n in release mode
(optimizations and no bounds checking), but in debug mode there would be
bounds checking making it harder to optimize. Additionally in the real world
analogue of this toy example, there would be other slowness in debug, and we
wouldn't hit the overflow condition.

Here's a case where a Rust API has issues, but only when bounds checks are
off: [https://internals.rust-lang.org/t/rc-is-unsafe-mostly-
on-32-...](https://internals.rust-lang.org/t/rc-is-unsafe-mostly-on-32-bit-
targets-due-to-overflow/2120)

> Unsafe code correctness

So, Rust being Rust the situation is vastly better than C++ or similar. But we
still have tons of unsafe bindings and also unsafe being used for perf. Last
rust upgrade we had an unsafe transmute of a refcell that broke stuff and
caused a confusing segfault in some code far away.

Proving correctness is hard, though. C++ is riddled with undefined behavior,
and `unsafe` shares a lot of that UB, _plus_ more UB due to assumptions that
rustc makes. When you write `unsafe`, writing code as if you're in the
wonderful world of C++ won't work. There are assumptions like "&T will never
be mutated" which rustc will make, which should hold even in unsafe code, and
if you do something to break that, you cause UB.

On top of that Rust hasn't been properly formalized yet. So this is something
that's still far off for us. However, a limited form of correctness checking
sounds doable-- but I don't have much knowledge of formal checking to be sure
of this.

Of course, a limited form of unsafe correctness as proposed in the paper

~~~
kibwen
Ms2ger told me recently that a majority of the unsafe code in Servo (ignoring
the stuff needed for FFI) was to work around the lack of DST coercions
(Arc<Trait>) and virtual structs. With the former landing soon and the latter
being in the design phase, how much unsafe code would be left working around
missing Rust features?

------
Manishearth
There have been lots of great posts about experiences with Rust these days,
but nothing about really large applications. While I may be writing about my
own experiences with writing Rust for Servo later, I thought that this might
be a useful thing to share to fill in the gap.

Note that it was written for an academic audience, but it isn't too dense :)

