Enabling Link Time Optimization (LTO) with MMTk

MMTk's API is designed with an assumption that LTO will be enabled for a performant build. It is essential to allow the Rust compiler to optimize across the crate boundary between the binding crate and mmtk-core. LTO allows inlining for both directions (from mmtk-core to the binding, and from the binding to mmtk-core), and allows further optimization such as specializing and constant folding for the VMBinding trait.

We suggest enabling LTO for the release build in the binding's manifest (Cargo.toml) by adding a profile for the release build, so LTO is always enabled for a release build.

[profile.release]
lto = true

If your binding project is a Rust binary (e.g. the VM is written in Rust), this should be enough. However, if your binding project is a library, there are some limitations with cargo that you should be aware of.

Binding as a library

Cargo only allows LTO for certain crate types. You will need to specify the crate type properly, otherwise cargo may skip LTO without any warning or error.

[lib]
...
# be careful - LTO is only allowed for certain crate types
crate-type = ["cdylib"]

At the time of writing, cargo has some limitations about LTO with different crate types:

  1. LTO is only allowed with cdylib and staticlib (other than bin). Check the code of can_lto for your Rust version to clarify.
  2. If the crate-type field includes any type that LTO is not allowed, LTO will be skipped for all the libraries generated (https://github.com/rust-lang/rust/issues/51009). For example, if you have crate-type = ["cdylib", "rlib"] and cargo cannot do LTO for rlib, LTO will be skipped for cdylib as well. So only keep the crate type that you actually need in the crate-type field.