Merge mozilla-central to autoland.
authorCosmin Sabou <csabou@mozilla.com>
Wed, 28 Nov 2018 06:11:15 +0200
changeset 504906 d0ba364e7190bf47cd2f43033824afba026409a9
parent 504905 0dd1b93495d527f6a9faa9606e2c1fd295a9eb2f (current diff)
parent 504888 a12d80e08655c13245add6f6dacc91f8a6d9cf89 (diff)
child 504907 eb60816546795a5fad643951818dbd4ea9b711ea
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland.
dom/base/nsGlobalWindowOuter.cpp
dom/canvas/test/reftest/drawCustomFocusRing.html
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -156,18 +156,18 @@ dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "baldrdash"
 version = "0.1.0"
 dependencies = [
  "bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-wasm 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "base64"
 version = "0.9.2"
@@ -452,71 +452,71 @@ name = "cose-c"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-bforest 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-codegen-meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.23.0"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift-frontend 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cranelift-frontend 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "wasmparser 0.21.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasmparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "crc"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2895,17 +2895,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.21.8"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "webdriver"
 version = "0.38.0"
 dependencies = [
  "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3158,22 +3158,22 @@ dependencies = [
 "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
 "checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
 "checksum core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7caa6cb9e76ddddbea09a03266d6b3bc98cd41e9fb9b017c473e7cca593ec25"
 "checksum core-foundation-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2a53cce0ddcf7e7e1f998738d757d5a3bf08bf799a180e50ebe50d298f52f5a"
 "checksum core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62ceafe1622ffc9a332199096841d0ff9912ec8cf8f9cde01e254a7d5217cd10"
 "checksum core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f46450d6f2397261af420b4ccce23807add2e45fa206410a03d66fb7f050ae"
 "checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
 "checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
-"checksum cranelift-bforest 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5f8e1ab4f73b59a98531a8013d8ed3ca7edb4e36984cb301d9c06f6892787b"
-"checksum cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437ec8212686e6cdacfea75aaedb4ab8b013869be1e8693a4cb97a60f135035"
-"checksum cranelift-codegen-meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4eac16097b96e9f609df735555f2d1658531750fbc3805bca1daca7671aef9eb"
-"checksum cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9be3f82369346201c2e0cff720522e6eb55459e51c916b2199f25cff2058ca96"
-"checksum cranelift-frontend 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5d18ab2bc89a09b4275442a9559dc0f947b9a8ad9ae9ee89452a057df54ced"
-"checksum cranelift-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5906a111814d43d84002ef974eb0c023804fd4d1866b34f43c1bb588a759ad8"
+"checksum cranelift-bforest 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"
+"checksum cranelift-codegen 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92fa0fa287cf00a6739c46aba114957e0a8eeeb4f0d1aa65d6ed0699c34ca6b"
+"checksum cranelift-codegen-meta 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"
+"checksum cranelift-entity 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9a0329208e5e0d7d4d6e64cd50985d4c4cbfdbeeb594ae2157a094b98e8dcc"
+"checksum cranelift-frontend 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98d9eb4a2343435d520499236c805725c88d6d55eefb9a6ad0819b7970c76bdd"
+"checksum cranelift-wasm 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5022a3a3d1044fdc8c97909b5e8d701884982dcfb43885034d004cfdd9b7d577"
 "checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
 "checksum crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8153ef04a7594ded05b427ffad46ddeaf22e63fd48d42b3e1e3bb4db07cae7"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-epoch 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2af0e75710d6181e234c8ecc79f14a97907850a541b13b0be1dd10992f2e4620"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b"
 "checksum cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "730363a45c4e248d4f21d3e5c1156d1a9cdec0855056c0d9539e814bc59865c3"
@@ -3388,17 +3388,17 @@ dependencies = [
 "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
 "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
-"checksum wasmparser 0.21.8 (registry+https://github.com/rust-lang/crates.io-index)" = "202e4cd4d99aa8adb8fe6280e099fdd2e5003c8d09c27de6969ff04dba60ef39"
+"checksum wasmparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4e0f66e314a8e63ff5c3cc5103f7d0a3de9ee98bb61a960adcf7f1d9debd2f"
 "checksum webidl 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f807f7488d680893f7188aa09d7672a3a0a8461975a098a2edf0a52e3fee29"
 "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
--- a/browser/components/extensions/schemas/menus.json
+++ b/browser/components/extensions/schemas/menus.json
@@ -108,16 +108,22 @@
             "optional": true,
             "description": "Will be present for elements with a 'src' URL."
           },
           "pageUrl": {
             "type": "string",
             "optional": true,
             "description": "The URL of the page where the menu item was clicked. This property is not set if the click occured in a context where there is no current page, such as in a launcher context menu."
           },
+          "frameId": {
+           "type": "integer",
+           "optional": true,
+           "minimum": 0,
+           "description": "The id of the frame of the element where the context menu was clicked."
+          },
           "frameUrl": {
             "type": "string",
             "optional": true,
             "description": " The URL of the frame of the element where the context menu was clicked, if it was in a frame."
           },
           "selectionText": {
             "type": "string",
             "optional": true,
--- a/browser/components/payments/res/containers/address-form.js
+++ b/browser/components/payments/res/containers/address-form.js
@@ -407,22 +407,22 @@ export default class AddressForm extends
    */
   static merchantFieldErrorsForForm(state, stateKey) {
     let {paymentDetails} = state.request;
     switch (stateKey.join("|")) {
       case "selectedShippingAddress": {
         return paymentDetails.shippingAddressErrors;
       }
       case "selectedPayerAddress": {
-        return paymentDetails.payer;
+        return paymentDetails.payerErrors;
       }
       case "basic-card-page|billingAddressGUID": {
         // `paymentMethod` can be null.
-        return (paymentDetails.paymentMethod
-                && paymentDetails.paymentMethod.billingAddress) || {};
+        return (paymentDetails.paymentMethodErrors
+                && paymentDetails.paymentMethodErrors.billingAddress) || {};
       }
       default: {
         throw new Error("Unknown selectedStateKey");
       }
     }
   }
 }
 
--- a/browser/components/payments/res/debugging.js
+++ b/browser/components/payments/res/debugging.js
@@ -48,18 +48,18 @@ let REQUEST_1 = {
       {
         label: "Square",
         amount: {
           currency: "USD",
           value: "5",
         },
       },
     ],
-    payer: {},
-    paymentMethod: {},
+    payerErrors: {},
+    paymentMethodErrors: {},
     shippingAddressErrors: {},
     shippingOptions: [
       {
         id: "std",
         label: "Standard (3-5 business days)",
         amount: {
           currency: "USD",
           value: 10,
@@ -130,18 +130,18 @@ let REQUEST_2 = {
         label: "Tax",
         type: "tax",
         amount: {
           currency: "USD",
           value: "1.50",
         },
       },
     ],
-    payer: {},
-    paymentMethod: {},
+    payerErrors: {},
+    paymentMethoErrors: {},
     shippingAddressErrors: {},
     shippingOptions: [
       {
         id: "123",
         label: "Fast (default)",
         amount: {
           currency: "USD",
           value: 10,
@@ -482,17 +482,17 @@ let buttonActions = {
 
   setBasicCards1() {
     paymentDialog.setStateFromParent({savedBasicCards: BASIC_CARDS_1});
   },
 
   setBasicCardErrors() {
     let request = Object.assign({}, requestStore.getState().request);
     request.paymentDetails = Object.assign({}, requestStore.getState().request.paymentDetails);
-    request.paymentDetails.paymentMethod = {
+    request.paymentDetails.paymentMethodErrors = {
       cardNumber: "",
       cardholderName: "",
       cardSecurityCode: "",
       expiryMonth: "",
       expiryYear: "",
       billingAddress: {
         addressLine: "Can only buy from ROADS, not DRIVES, BOULEVARDS, or STREETS",
         city: "Can only buy from CITIES, not TOWNSHIPS or VILLAGES",
@@ -525,17 +525,17 @@ let buttonActions = {
     paymentDialog.setStateFromParent({
       request: Object.assign({}, request, { completeStatus }),
     });
   },
 
   setPayerErrors() {
     let request = Object.assign({}, requestStore.getState().request);
     request.paymentDetails = Object.assign({}, requestStore.getState().request.paymentDetails);
-    request.paymentDetails.payer = {
+    request.paymentDetails.payerErrors = {
       email: "Only @mozilla.com emails are supported",
       name: "Payer name must start with M",
       phone: "Payer area codes must start with 1",
     };
     requestStore.setState({
       request,
     });
   },
--- a/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js
+++ b/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js
@@ -41,18 +41,18 @@ export let requestStore = new PaymentsSt
     tabId: null,
     topLevelPrincipal: {URI: {displayHost: null}},
     requestId: null,
     paymentMethods: [],
     paymentDetails: {
       id: null,
       totalItem: {label: null, amount: {currency: null, value: 0}},
       displayItems: [],
-      payer: {},
-      paymentMethod: null,
+      payerErrors: {},
+      paymentMethodErrors: null,
       shippingAddressErrors: {},
       shippingOptions: [],
       modifiers: null,
       error: "",
     },
     paymentOptions: {
       requestPayerName: false,
       requestPayerEmail: false,
--- a/browser/components/payments/test/mochitest/test_address_form.html
+++ b/browser/components/payments/test/mochitest/test_address_form.html
@@ -703,17 +703,17 @@ add_task(async function test_customMerch
   await asyncElementRendered();
 
   is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
      "Check fields are visibly valid - shipping errors are not relevant to a billing address form");
 
   await form.requestStore.setState({
     request: {
       paymentDetails: {
-        paymentMethod: {
+        paymentMethodErrors: {
           billingAddress: {
             addressLine: "Billing Street address needs to start with a D",
             city: "Billing City needs to start with a B",
             country: "Billing Country needs to start with a C",
             organization: "Billing organization needs to start with an A",
             phone: "Billing Telephone needs to start with a 9",
             postalCode: "Billing Postal code needs to start with a 0",
             recipient: "Billing Name needs to start with a Z",
@@ -748,17 +748,17 @@ add_task(async function test_merchantPay
       id: "payer-address-page",
     },
     "payer-address-page": {
       addressFields: "name email tel",
       guid: address1.guid,
     },
     request: {
       paymentDetails: {
-        payer: {
+        payerErrors: {
           email: "Email must be @mozilla.org",
           name: "Name needs to start with a W",
           phone: "Telephone needs to start with a 1",
         },
       },
       paymentOptions: {},
     },
     savedAddresses: {
@@ -766,32 +766,32 @@ add_task(async function test_merchantPay
     },
   };
   await form.requestStore.setState(state);
   display.appendChild(form);
   await asyncElementRendered();
 
   function checkValidationMessage(selector, property) {
     is(form.form.querySelector(selector).validationMessage,
-       state.request.paymentDetails.payer[property],
+       state.request.paymentDetails.payerErrors[property],
        "Validation message should match for " + selector);
   }
 
   ok(form.saveButton.disabled, "Save button should be disabled due to validation errors");
 
   checkValidationMessage("#tel", "phone");
   checkValidationMessage("#family-name", "name");
   checkValidationMessage("#email", "email");
 
   is(form.querySelectorAll(":-moz-ui-invalid").length, 3, "Check payer fields are visibly invalid");
 
   await form.requestStore.setState({
     request: {
       paymentDetails: {
-        payer: {},
+        payerErrors: {},
       },
       paymentOptions: {},
     },
   });
   await asyncElementRendered();
 
   is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
      "Check payer fields are visibly valid after clearing merchant errors");
--- a/browser/components/payments/test/mochitest/test_address_picker.html
+++ b/browser/components/payments/test/mochitest/test_address_picker.html
@@ -251,20 +251,20 @@ add_task(async function test_merchantErr
   await asyncElementRendered();
   ok(!picker1.classList.contains("invalid-selected-option"),
      "No errors visible when merchant errors cleared");
   ok(isHidden(picker1.invalidLabel), "The invalid label should be hidden");
 
   info("Set billing address and payer errors which aren't relevant to this picker");
   let requestWithNonShippingAddressErrors = deepClone(request);
   Object.assign(requestWithNonShippingAddressErrors.paymentDetails, {
-    payer: {
+    payerErrors: {
       name: "Your name is too short",
     },
-    paymentMethod: {
+    paymentMethodErrors: {
       billingAddress: {
         country: "Your billing country is not supported",
       },
     },
     shippingAddressErrors: {},
   });
   picker1.requestStore.setState({
     request: requestWithNonShippingAddressErrors,
--- a/browser/components/urlbar/tests/browser/browser.ini
+++ b/browser/components/urlbar/tests/browser/browser.ini
@@ -4,12 +4,13 @@
 
 [DEFAULT]
 support-files =
   head.js
 
 [browser_UrlbarInput_formatValue.js]
 [browser_UrlbarInput_overflow.js]
 [browser_UrlbarInput_tooltip.js]
+skip-if = asan # Bug 1504985
 [browser_UrlbarInput_trimURLs.js]
 subsuite = clipboard
 [browser_UrlbarInput_unit.js]
 support-files = empty.xul
--- a/browser/modules/AsyncTabSwitcher.jsm
+++ b/browser/modules/AsyncTabSwitcher.jsm
@@ -743,16 +743,17 @@ class AsyncTabSwitcher {
   onPaint(event) {
     if (this.switchPaintId != -1 &&
         event.transactionId >= this.switchPaintId) {
       if (this._tabSwitchStopWatchRunning) {
         let time = TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_COMPOSITE_E10S_MS", this.window);
         if (time != -1) {
           TelemetryStopwatch.finish("FX_TAB_SWITCH_COMPOSITE_E10S_MS", this.window);
           this.log("DEBUG: tab switch time including compositing = " + time);
+          this._tabSwitchStopWatchRunning = false;
         }
       }
       this.addMarker("AsyncTabSwitch:Composited");
       this.switchPaintId = -1;
     }
 
     this.maybeVisibleTabs.clear();
   }
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -499,17 +499,17 @@ class Automation(object):
   def checkForCrashes(self, minidumpDir, symbolsPath):
     return mozcrash.check_for_crashes(minidumpDir, symbolsPath, test_name=self.lastTestSeen)
 
   def runApp(self, testURL, env, app, profileDir, extraArgs, utilityPath = None,
              xrePath = None, certPath = None,
              debuggerInfo = None, symbolsPath = None,
              timeout = -1, maxTime = None, onLaunch = None,
              detectShutdownLeaks = False, screenshotOnFail=False, testPath=None, bisectChunk=None,
-             valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None, outputHandler=None):
+             valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None, outputHandler=None, e10s=True):
     """
     Run the app, log the duration it took to execute, return the status code.
     Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
     """
 
     if utilityPath == None:
       utilityPath = self.DIST_BIN
     if xrePath == None:
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -23,34 +23,69 @@ fennecLogcatFilters = ["The character en
                        "Use of Mutation Events is deprecated. Use MutationObserver instead.",
                        "Unexpected value from nativeGetEnabledTags: 0"]
 
 
 class RemoteAutomation(Automation):
 
     def __init__(self, device, appName='', remoteProfile=None, remoteLog=None,
                  processArgs=None):
-        self._device = device
-        self._appName = appName
-        self._remoteProfile = remoteProfile
-        self._remoteLog = remoteLog
-        self._processArgs = processArgs or {}
-
+        self.device = device
+        self.appName = appName
+        self.remoteProfile = remoteProfile
+        self.remoteLog = remoteLog
+        self.processArgs = processArgs or {}
         self.lastTestSeen = "remoteautomation.py"
         Automation.__init__(self)
 
+    def runApp(self, testURL, env, app, profileDir, extraArgs,
+               utilityPath=None, xrePath=None, debuggerInfo=None, symbolsPath=None,
+               timeout=-1, maxTime=None, e10s=True, **kwargs):
+        """
+        Run the app, log the duration it took to execute, return the status code.
+        Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing
+        for |timeout| seconds.
+        """
+
+        if utilityPath is None:
+            utilityPath = self.DIST_BIN
+        if xrePath is None:
+            xrePath = self.DIST_BIN
+        if timeout == -1:
+            timeout = self.DEFAULT_TIMEOUT
+        self.utilityPath = utilityPath
+
+        cmd, args = self.buildCommandLine(app, debuggerInfo, profileDir, testURL, extraArgs)
+        startTime = datetime.datetime.now()
+
+        self.lastTestSeen = "remoteautomation.py"
+        self.launchApp([cmd] + args,
+                       env=self.environment(env=env, crashreporter=not debuggerInfo),
+                       e10s=e10s, **self.processArgs)
+
+        self.log.info("remoteautomation.py | Application pid: %d", self.pid)
+
+        status = self.waitForFinish(timeout, maxTime)
+        self.log.info("remoteautomation.py | Application ran for: %s",
+                      str(datetime.datetime.now() - startTime))
+
+        crashed = self.checkForCrashes(symbolsPath)
+        if crashed:
+            status = 1
+
+        return status, self.lastTestSeen
+
     # Set up what we need for the remote environment
-    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False,
-                    lsanPath=None, ubsanPath=None):
+    def environment(self, env=None, crashreporter=True, **kwargs):
         # Because we are running remote, we don't want to mimic the local env
         # so no copying of os.environ
         if env is None:
             env = {}
 
-        if crashreporter and not debugger:
+        if crashreporter:
             env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
             env['MOZ_CRASHREPORTER'] = '1'
             env['MOZ_CRASHREPORTER_SHUTDOWN'] = '1'
         else:
             env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
         # Crash on non-local network connections by default.
         # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
@@ -70,407 +105,388 @@ class RemoteAutomation(Automation):
         # standard WebRTC setting for NSPR_LOG_MODULES is not available.
         # env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')  # NOQA: E501
         env.setdefault('R_LOG_LEVEL', '6')
         env.setdefault('R_LOG_DESTINATION', 'stderr')
         env.setdefault('R_LOG_VERBOSE', '1')
 
         return env
 
-    def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo,
-                      symbolsPath, outputHandler=None):
+    def waitForFinish(self, timeout, maxTime):
         """ Wait for tests to finish.
             If maxTime seconds elapse or no output is detected for timeout
             seconds, kill the process and fail the test.
         """
-        proc.utilityPath = utilityPath
         # maxTime is used to override the default timeout, we should honor that
-        status = proc.wait(timeout=maxTime, noOutputTimeout=timeout)
-        self.lastTestSeen = proc.getLastTestSeen
+        status = self.wait(timeout=maxTime, noOutputTimeout=timeout)
 
-        topActivity = self._device.get_top_activity(timeout=60)
-        if topActivity == proc.procName:
-            print("Browser unexpectedly found running. Killing...")
-            proc.kill(True)
+        topActivity = self.device.get_top_activity(timeout=60)
+        if topActivity == self.procName:
+            self.log.info("%s unexpectedly found running. Killing..." % self.procName)
+            self.kill(True)
         if status == 1:
             if maxTime:
-                print("TEST-UNEXPECTED-FAIL | %s | application ran for longer than "
-                      "allowed maximum time of %s seconds" % (
-                          self.lastTestSeen, maxTime))
+                self.log.error("TEST-UNEXPECTED-FAIL | %s | "
+                               "application ran for longer than allowed maximum time "
+                               "of %s seconds" % (self.lastTestSeen, maxTime))
             else:
-                print("TEST-UNEXPECTED-FAIL | %s | application ran for longer than "
-                      "allowed maximum time" % (self.lastTestSeen))
+                self.log.error("TEST-UNEXPECTED-FAIL | %s | "
+                               "application ran for longer than allowed maximum time"
+                               % self.lastTestSeen)
         if status == 2:
-            print("TEST-UNEXPECTED-FAIL | %s | application timed out after %d "
-                  "seconds with no output"
-                  % (self.lastTestSeen, int(timeout)))
+            self.log.error("TEST-UNEXPECTED-FAIL | %s | "
+                           "application timed out after %d seconds with no output"
+                           % (self.lastTestSeen, int(timeout)))
 
         return status
 
     def deleteANRs(self):
         # Remove files from the dalvik stack-trace directory.
-        if not self._device.is_dir(self._device.stack_trace_dir, root=True):
+        if not self.device.is_dir(self.device.stack_trace_dir, root=True):
             return
         try:
-            for trace_file in self._device.ls(self._device.stack_trace_dir, root=True):
-                trace_path = posixpath.join(self._device.stack_trace_dir, trace_file)
-                self._device.chmod(trace_path, root=True)
-                self._device.rm(trace_path, root=True)
+            for trace_file in self.device.ls(self.device.stack_trace_dir, root=True):
+                trace_path = posixpath.join(self.device.stack_trace_dir, trace_file)
+                self.device.chmod(trace_path, root=True)
+                self.device.rm(trace_path, root=True)
         except Exception as e:
-            print("Error deleting %s: %s" % (self._device.stack_trace_dir, str(e)))
+            print("Error deleting %s: %s" % (self.device.stack_trace_dir, str(e)))
 
     def checkForANRs(self):
-        if not self._device.is_dir(self._device.stack_trace_dir):
-            print("%s not found" % self._device.stack_trace_dir)
+        if not self.device.is_dir(self.device.stack_trace_dir):
+            print("%s not found" % self.device.stack_trace_dir)
             return
         try:
-            for trace_file in self._device.ls(self._device.stack_trace_dir, root=True):
-                trace_path = posixpath.join(self._device.stack_trace_dir, trace_file)
-                t = self._device.get_file(trace_path)
+            for trace_file in self.device.ls(self.device.stack_trace_dir, root=True):
+                trace_path = posixpath.join(self.device.stack_trace_dir, trace_file)
+                t = self.device.get_file(trace_path)
                 if t:
                     stripped = t.strip()
                     if len(stripped) > 0:
                         print("Contents of %s:" % trace_path)
                         print(t)
             # Once reported, delete traces
             self.deleteANRs()
         except Exception as e:
-            print("Error pulling %s: %s" % (self._device.stack_trace_dir, str(e)))
+            print("Error pulling %s: %s" % (self.device.stack_trace_dir, str(e)))
 
     def deleteTombstones(self):
         # delete any tombstone files from device
-        self._device.rm("/data/tombstones", force=True,
-                        recursive=True, root=True)
+        self.device.rm("/data/tombstones", force=True, recursive=True, root=True)
 
     def checkForTombstones(self):
         # pull any tombstones from device and move to MOZ_UPLOAD_DIR
         remoteDir = "/data/tombstones"
         uploadDir = os.environ.get('MOZ_UPLOAD_DIR', None)
         if uploadDir:
             if not os.path.exists(uploadDir):
                 os.mkdir(uploadDir)
-            if self._device.is_dir(remoteDir):
+            if self.device.is_dir(remoteDir):
                 # copy tombstone files from device to local upload directory
-                self._device.chmod(remoteDir, recursive=True, root=True)
-                self._device.pull(remoteDir, uploadDir)
+                self.device.chmod(remoteDir, recursive=True, root=True)
+                self.device.pull(remoteDir, uploadDir)
                 self.deleteTombstones()
                 for f in glob.glob(os.path.join(uploadDir, "tombstone_??")):
                     # add a unique integer to the file name, in case there are
                     # multiple tombstones generated with the same name, for
                     # instance, after multiple robocop tests
                     for i in xrange(1, sys.maxint):
                         newname = "%s.%d.txt" % (f, i)
                         if not os.path.exists(newname):
                             os.rename(f, newname)
                             break
             else:
                 print("%s does not exist; tombstone check skipped" % remoteDir)
         else:
             print("MOZ_UPLOAD_DIR not defined; tombstone check skipped")
 
-    def checkForCrashes(self, directory, symbolsPath):
+    def checkForCrashes(self, symbolsPath):
         self.checkForANRs()
         self.checkForTombstones()
 
-        logcat = self._device.get_logcat(
+        logcat = self.device.get_logcat(
             filter_out_regexps=fennecLogcatFilters)
 
         javaException = mozcrash.check_for_java_exception(
             logcat, test_name=self.lastTestSeen)
         if javaException:
             return True
 
         # If crash reporting is disabled (MOZ_CRASHREPORTER!=1), we can't say
         # anything.
         if not self.CRASHREPORTER:
             return False
 
         try:
             dumpDir = tempfile.mkdtemp()
-            remoteCrashDir = posixpath.join(self._remoteProfile, 'minidumps')
-            if not self._device.is_dir(remoteCrashDir):
+            remoteCrashDir = posixpath.join(self.remoteProfile, 'minidumps')
+            if not self.device.is_dir(remoteCrashDir):
                 # If crash reporting is enabled (MOZ_CRASHREPORTER=1), the
                 # minidumps directory is automatically created when Fennec
                 # (first) starts, so its lack of presence is a hint that
                 # something went wrong.
                 print("Automation Error: No crash directory (%s) found on remote device" %
                       remoteCrashDir)
                 return True
-            self._device.pull(remoteCrashDir, dumpDir)
+            self.device.pull(remoteCrashDir, dumpDir)
 
             logger = get_default_logger()
             crashed = mozcrash.log_crashes(
                 logger, dumpDir, symbolsPath, test=self.lastTestSeen)
 
         finally:
             try:
                 shutil.rmtree(dumpDir)
             except Exception as e:
                 print("WARNING: unable to remove directory %s: %s" % (
                     dumpDir, str(e)))
         return crashed
 
     def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
         # If remote profile is specified, use that instead
-        if self._remoteProfile:
-            profileDir = self._remoteProfile
+        if self.remoteProfile:
+            profileDir = self.remoteProfile
 
         # Hack for robocop, if app is "am" and extraArgs contains the rest of the stuff, lets
         # assume extraArgs is all we need
         if app == "am" and extraArgs[0] in ('instrument', 'start'):
             return app, extraArgs
 
         cmd, args = Automation.buildCommandLine(
             self, app, debuggerInfo, profileDir, testURL, extraArgs)
         try:
             args.remove('-foreground')
         except Exception:
             pass
         return app, args
 
-    def Process(self, cmd, stdout=None, stderr=None, env=None, cwd=None):
-        return self.RProcess(self._device, cmd, self._remoteLog, env, cwd, self._appName,
-                             **self._processArgs)
+    def launchApp(self, cmd, env=None, e10s=True, messageLogger=None, counts=None):
+        self.messageLogger = messageLogger
+        self.stdoutlen = 0
+
+        if self.appName and self.device.process_exist(self.appName):
+            print("remoteautomation.py %s is already running. Stopping..." % self.appName)
+            self.device.stop_application(self.appName, root=True)
+
+        self.counts = counts
+        if self.counts is not None:
+            self.counts['pass'] = 0
+            self.counts['fail'] = 0
+            self.counts['todo'] = 0
 
-    class RProcess(object):
-        def __init__(self, device, cmd, stdout=None, env=None, cwd=None, app=None,
-                     messageLogger=None, counts=None):
-            self.device = device
-            self.lastTestSeen = "remoteautomation.py"
-            self.messageLogger = messageLogger
-            self.proc = stdout
+        if cmd[0] == 'am':
+            cmd = ' '.join(cmd)
+            self.procName = self.appName
+            if not self.device.shell_bool(cmd):
+                print("remote_automation.py failed to launch %s" % cmd)
+        else:
             self.procName = cmd[0].split(posixpath.sep)[-1]
-            self.stdoutlen = 0
-            self.utilityPath = None
+            args = cmd
+            if args[0] == self.appName:
+                args = args[1:]
+            url = args[-1:][0]
+            if url.startswith('/'):
+                # this is probably a reftest profile directory, not a url
+                url = None
+            else:
+                args = args[:-1]
+            if 'geckoview' in self.appName:
+                activity = "TestRunnerActivity"
+                self.device.launch_activity(self.appName, activity_name=activity, e10s=e10s,
+                                            moz_env=env, extra_args=args, url=url)
+            else:
+                self.device.launch_fennec(self.appName, moz_env=env, extra_args=args, url=url)
+
+        # Setting timeout at 1 hour since on a remote device this takes much longer.
+        # Temporarily increased to 110 minutes because no more chunks can be created.
+        self.timeout = 6600
+
+        # Used to buffer log messages until we meet a line break
+        self.logBuffer = ""
 
-            if app and self.device.process_exist(app):
-                print("remoteautomation.py %s is already running. Stopping...")
-                self.device.stop_application(app, root=True)
+    @property
+    def pid(self):
+        procs = self.device.get_process_list()
+        # limit the comparison to the first 75 characters due to a
+        # limitation in processname length in android.
+        pids = [proc[0] for proc in procs if proc[1] == self.procName[:75]]
+
+        if pids is None or len(pids) < 1:
+            return 0
+        return pids[0]
 
-            self.counts = counts
-            if self.counts is not None:
-                self.counts['pass'] = 0
-                self.counts['fail'] = 0
-                self.counts['todo'] = 0
+    def read_stdout(self):
+        """
+        Fetch the full remote log file, log any new content and return True if new
+        content processed.
+        """
+        if not self.device.is_file(self.remoteLog):
+            return False
+        try:
+            newLogContent = self.device.get_file(self.remoteLog, offset=self.stdoutlen)
+        except ADBTimeoutError:
+            raise
+        except Exception as e:
+            self.log.info("remoteautomation.py | exception reading log: %s" % str(e))
+            return False
+        if not newLogContent:
+            return False
 
-            if cmd[0] == 'am':
-                cmd = ' '.join(cmd)
-                self.procName = app
-                if not self.device.shell_bool(cmd):
-                    print("remote_automation.py failed to launch %s" % cmd)
+        self.stdoutlen += len(newLogContent)
+
+        if self.messageLogger is None:
+            testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", newLogContent)
+            if testStartFilenames:
+                self.lastTestSeen = testStartFilenames[-1]
+            print(newLogContent)
+            return True
+
+        self.logBuffer += newLogContent
+        lines = self.logBuffer.split('\n')
+        lines = [l for l in lines if l]
+
+        if lines:
+            if self.logBuffer.endswith('\n'):
+                # all lines are complete; no need to buffer
+                self.logBuffer = ""
             else:
-                args = cmd
-                if args[0] == app:
-                    args = args[1:]
-                url = args[-1:][0]
-                if url.startswith('/'):
-                    # this is probably a reftest profile directory, not a url
-                    url = None
-                else:
-                    args = args[:-1]
-                if 'geckoview' in app:
-                    activity = "TestRunnerActivity"
-                    self.device.launch_activity(app, activity, e10s=True, moz_env=env,
-                                                extra_args=args, url=url)
-                else:
-                    self.device.launch_fennec(
-                        app, moz_env=env, extra_args=args, url=url)
+                # keep the last (unfinished) line in the buffer
+                self.logBuffer = lines[-1]
+                del lines[-1]
+
+        if not lines:
+            return False
 
-            # Setting timeout at 1 hour since on a remote device this takes much longer.
-            # Temporarily increased to 110 minutes because no more chunks can be created.
-            self.timeout = 6600
+        for line in lines:
+            # This passes the line to the logger (to be logged or buffered)
+            parsed_messages = self.messageLogger.write(line)
+            for message in parsed_messages:
+                if isinstance(message, dict) and message.get('action') == 'test_start':
+                    self.lastTestSeen = message['test']
+                if isinstance(message, dict) and message.get('action') == 'log':
+                    line = message['message'].strip()
+                    if self.counts:
+                        m = re.match(".*:\s*(\d*)", line)
+                        if m:
+                            try:
+                                val = int(m.group(1))
+                                if "Passed:" in line:
+                                    self.counts['pass'] += val
+                                elif "Failed:" in line:
+                                    self.counts['fail'] += val
+                                elif "Todo:" in line:
+                                    self.counts['todo'] += val
+                            except ADBTimeoutError:
+                                raise
+                            except Exception:
+                                pass
+
+        return True
 
-            # Used to buffer log messages until we meet a line break
-            self.logBuffer = ""
-
-        @property
-        def pid(self):
-            procs = self.device.get_process_list()
-            # limit the comparison to the first 75 characters due to a
-            # limitation in processname length in android.
-            pids = [proc[0] for proc in procs if proc[1] == self.procName[:75]]
+    # Wait for the remote process to end (or for its activity to go to background).
+    # While waiting, periodically retrieve the process output and print it.
+    # If the process is still running after *timeout* seconds, return 1;
+    # If the process is still running but no output is received in *noOutputTimeout*
+    # seconds, return 2;
+    # Else, once the process exits/goes to background, return 0.
+    def wait(self, timeout=None, noOutputTimeout=None):
+        timer = 0
+        noOutputTimer = 0
+        interval = 10
+        if timeout is None:
+            timeout = self.timeout
+        status = 0
+        top = self.procName
+        slowLog = False
+        endTime = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
+        while top == self.procName:
+            # Get log updates on each interval, but if it is taking
+            # too long, only do it every 60 seconds
+            hasOutput = False
+            if (not slowLog) or (timer % 60 == 0):
+                startRead = datetime.datetime.now()
+                hasOutput = self.read_stdout()
+                if (datetime.datetime.now() - startRead) > datetime.timedelta(seconds=5):
+                    slowLog = True
+                if hasOutput:
+                    noOutputTimer = 0
+                if self.counts and 'pass' in self.counts and self.counts['pass'] > 0:
+                    interval = 0.5
+            time.sleep(interval)
+            timer += interval
+            noOutputTimer += interval
+            if datetime.datetime.now() > endTime:
+                status = 1
+                break
+            if (noOutputTimeout and noOutputTimer > noOutputTimeout):
+                status = 2
+                break
+            if not hasOutput:
+                top = self.device.get_top_activity(timeout=60)
+                if top is None:
+                    print("Failed to get top activity, retrying, once...")
+                    top = self.device.get_top_activity(timeout=60)
+        # Flush anything added to stdout during the sleep
+        self.read_stdout()
+        print("wait for %s complete; top activity=%s" % (self.procName, top))
+        return status
 
-            if pids is None or len(pids) < 1:
-                return 0
-            return pids[0]
-
-        def read_stdout(self):
-            """
-            Fetch the full remote log file, log any new content and return True if new
-            content processed.
-            """
-            if not self.device.is_file(self.proc):
-                return False
+    def kill(self, stagedShutdown=False):
+        # Take a screenshot to capture the screen state just before
+        # the application is killed.
+        # Do not use the on-device screenshot options since
+        # they rarely work well with Firefox on the Android
+        # emulator. dump_screen provides an effective
+        # screenshot of the emulator and its host desktop.
+        if not self.device._device_serial.startswith('emulator-'):
+            dump_device_screen(self.device, get_default_logger())
+        elif self.utilityPath:
+            dump_screen(self.utilityPath, get_default_logger())
+        if stagedShutdown:
+            # Trigger an ANR report with "kill -3" (SIGQUIT)
             try:
-                newLogContent = self.device.get_file(
-                    self.proc, offset=self.stdoutlen)
+                self.device.pkill(self.procName, sig=3, attempts=1, root=True)
             except ADBTimeoutError:
                 raise
-            except Exception:
-                return False
-            if not newLogContent:
-                return False
-
-            self.stdoutlen += len(newLogContent)
-
-            if self.messageLogger is None:
-                testStartFilenames = re.findall(
-                    r"TEST-START \| ([^\s]*)", newLogContent)
-                if testStartFilenames:
-                    self.lastTestSeen = testStartFilenames[-1]
-                print(newLogContent)
-                return True
-
-            self.logBuffer += newLogContent
-            lines = self.logBuffer.split('\n')
-            lines = [l for l in lines if l]
-
-            if lines:
-                if self.logBuffer.endswith('\n'):
-                    # all lines are complete; no need to buffer
-                    self.logBuffer = ""
+            except:  # NOQA: E722
+                pass
+            time.sleep(3)
+            # Trigger a breakpad dump with "kill -6" (SIGABRT)
+            try:
+                self.device.pkill(self.procName, sig=6, attempts=1, root=True)
+            except ADBTimeoutError:
+                raise
+            except:  # NOQA: E722
+                pass
+            # Wait for process to end
+            retries = 0
+            while retries < 3:
+                if self.device.process_exist(self.procName):
+                    print("%s still alive after SIGABRT: waiting..." % self.procName)
+                    time.sleep(5)
                 else:
-                    # keep the last (unfinished) line in the buffer
-                    self.logBuffer = lines[-1]
-                    del lines[-1]
-
-            if not lines:
-                return False
-
-            for line in lines:
-                # This passes the line to the logger (to be logged or buffered)
-                parsed_messages = self.messageLogger.write(line)
-                for message in parsed_messages:
-                    if isinstance(message, dict) and message.get('action') == 'test_start':
-                        self.lastTestSeen = message['test']
-                    if isinstance(message, dict) and message.get('action') == 'log':
-                        line = message['message'].strip()
-                        if self.counts:
-                            m = re.match(".*:\s*(\d*)", line)
-                            if m:
-                                try:
-                                    val = int(m.group(1))
-                                    if "Passed:" in line:
-                                        self.counts['pass'] += val
-                                    elif "Failed:" in line:
-                                        self.counts['fail'] += val
-                                    elif "Todo:" in line:
-                                        self.counts['todo'] += val
-                                except ADBTimeoutError:
-                                    raise
-                                except Exception:
-                                    pass
-
-            return True
-
-        @property
-        def getLastTestSeen(self):
-            return self.lastTestSeen
-
-        # Wait for the remote process to end (or for its activity to go to background).
-        # While waiting, periodically retrieve the process output and print it.
-        # If the process is still running after *timeout* seconds, return 1;
-        # If the process is still running but no output is received in *noOutputTimeout*
-        # seconds, return 2;
-        # Else, once the process exits/goes to background, return 0.
-        def wait(self, timeout=None, noOutputTimeout=None):
-            timer = 0
-            noOutputTimer = 0
-            interval = 10
-            if timeout is None:
-                timeout = self.timeout
-            status = 0
-            top = self.procName
-            slowLog = False
-            endTime = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
-            while top == self.procName:
-                # Get log updates on each interval, but if it is taking
-                # too long, only do it every 60 seconds
-                hasOutput = False
-                if (not slowLog) or (timer % 60 == 0):
-                    startRead = datetime.datetime.now()
-                    hasOutput = self.read_stdout()
-                    if (datetime.datetime.now() - startRead) > datetime.timedelta(seconds=5):
-                        slowLog = True
-                    if hasOutput:
-                        noOutputTimer = 0
-                    if self.counts and 'pass' in self.counts and self.counts['pass'] > 0:
-                        interval = 0.5
-                time.sleep(interval)
-                timer += interval
-                noOutputTimer += interval
-                if datetime.datetime.now() > endTime:
-                    status = 1
                     break
-                if (noOutputTimeout and noOutputTimer > noOutputTimeout):
-                    status = 2
-                    break
-                if not hasOutput:
-                    top = self.device.get_top_activity(timeout=60)
-                    if top is None:
-                        print("Failed to get top activity, retrying, once...")
-                        top = self.device.get_top_activity(timeout=60)
-            # Flush anything added to stdout during the sleep
-            self.read_stdout()
-            print("wait for %s complete; top activity=%s" % (self.procName, top))
-            return status
-
-        def kill(self, stagedShutdown=False):
-            # Take a screenshot to capture the screen state just before
-            # the application is killed.
-            if not self.device._device_serial.startswith('emulator-'):
-                dump_device_screen(self.device, get_default_logger())
-            elif self.utilityPath:
-                # Do not use the on-device screenshot options since
-                # they rarely work well with Firefox on the Android
-                # emulator. dump_screen provides an effective
-                # screenshot of the emulator and its host desktop.
-                dump_screen(self.utilityPath, get_default_logger())
-            if stagedShutdown:
-                # Trigger an ANR report with "kill -3" (SIGQUIT)
+                retries += 1
+            if self.device.process_exist(self.procName):
                 try:
-                    self.device.pkill(self.procName, sig=3, attempts=1, root=True)
+                    self.device.pkill(self.procName, sig=9, attempts=1, root=True)
                 except ADBTimeoutError:
                     raise
                 except:  # NOQA: E722
-                    pass
-                time.sleep(3)
-                # Trigger a breakpad dump with "kill -6" (SIGABRT)
-                try:
-                    self.device.pkill(self.procName, sig=6, attempts=1, root=True)
-                except ADBTimeoutError:
-                    raise
-                except:  # NOQA: E722
-                    pass
-                # Wait for process to end
-                retries = 0
-                while retries < 3:
-                    if self.device.process_exist(self.procName):
-                        print("%s still alive after SIGABRT: waiting..." % self.procName)
-                        time.sleep(5)
-                    else:
-                        break
-                    retries += 1
-                if self.device.process_exist(self.procName):
-                    try:
-                        self.device.pkill(self.procName, sig=9, attempts=1, root=True)
-                    except ADBTimeoutError:
-                        raise
-                    except:  # NOQA: E722
-                        print("%s still alive after SIGKILL!" % self.procName)
-                if self.device.process_exist(self.procName):
-                    self.device.stop_application(self.procName)
-            else:
+                    print("%s still alive after SIGKILL!" % self.procName)
+            if self.device.process_exist(self.procName):
                 self.device.stop_application(self.procName)
-            # Test harnesses use the MOZ_CRASHREPORTER environment variables to suppress
-            # the interactive crash reporter, but that may not always be effective;
-            # check for and cleanup errant crashreporters.
-            crashreporter = "%s.CrashReporter" % self.procName
-            if self.device.process_exist(crashreporter):
-                print("Warning: %s unexpectedly found running. Killing..." % crashreporter)
-                try:
-                    self.device.pkill(crashreporter, root=True)
-                except ADBTimeoutError:
-                    raise
-                except:  # NOQA: E722
-                    pass
-            if self.device.process_exist(crashreporter):
-                print("ERROR: %s still running!!" % crashreporter)
+        else:
+            self.device.stop_application(self.procName)
+        # Test harnesses use the MOZ_CRASHREPORTER environment variables to suppress
+        # the interactive crash reporter, but that may not always be effective;
+        # check for and cleanup errant crashreporters.
+        crashreporter = "%s.CrashReporter" % self.procName
+        if self.device.process_exist(crashreporter):
+            print("Warning: %s unexpectedly found running. Killing..." % crashreporter)
+            try:
+                self.device.pkill(crashreporter, root=True)
+            except ADBTimeoutError:
+                raise
+            except:  # NOQA: E722
+                pass
+        if self.device.process_exist(crashreporter):
+            print("ERROR: %s still running!!" % crashreporter)
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -493,16 +493,37 @@ nsOuterWindowProxy::getPropertyDescripto
 
   if (desc.object()) {
     return true;
   }
 
   return js::Wrapper::getPropertyDescriptor(cx, proxy, id, desc);
 }
 
+/**
+ * IsNonConfigurableReadonlyPrimitiveGlobalProp returns true for
+ * property names that fit the following criteria:
+ *
+ * 1) The ES spec defines a property with that name on globals.
+ * 2) The property is non-configurable.
+ * 3) The property is non-writable (readonly).
+ * 4) The value of the property is a primitive (so doesn't change
+ *    observably on when navigation happens).
+ *
+ * Such properties can act as actual non-configurable properties on a
+ * WindowProxy, because they are not affected by navigation.
+ */
+static bool
+IsNonConfigurableReadonlyPrimitiveGlobalProp(JSContext* cx, JS::Handle<jsid> id)
+{
+  return id == GetJSIDByIndex(cx, XPCJSContext::IDX_NAN) ||
+         id == GetJSIDByIndex(cx, XPCJSContext::IDX_UNDEFINED) ||
+         id == GetJSIDByIndex(cx, XPCJSContext::IDX_INFINITY);
+}
+
 bool
 nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx,
                                              JS::Handle<JSObject*> proxy,
                                              JS::Handle<jsid> id,
                                              JS::MutableHandle<JS::PropertyDescriptor> desc)
                                              const
 {
   bool found;
@@ -510,34 +531,106 @@ nsOuterWindowProxy::getOwnPropertyDescri
     return false;
   }
   if (found) {
     FillPropertyDescriptor(desc, proxy, true);
     return true;
   }
   // else fall through to js::Wrapper
 
-  return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
+  bool ok = js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
+  if (!ok) {
+    return false;
+  }
+
+#ifndef RELEASE_OR_BETA // To be turned on in bug 1496510.
+  if (!IsNonConfigurableReadonlyPrimitiveGlobalProp(cx, id)) {
+    desc.setConfigurable(true);
+  }
+#endif
+
+  return true;
 }
 
 bool
 nsOuterWindowProxy::defineProperty(JSContext* cx,
                                    JS::Handle<JSObject*> proxy,
                                    JS::Handle<jsid> id,
                                    JS::Handle<JS::PropertyDescriptor> desc,
                                    JS::ObjectOpResult &result) const
 {
   if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
     // Spec says to Reject whether this is a supported index or not,
     // since we have no indexed setter or indexed creator.  It is up
     // to the caller to decide whether to throw a TypeError.
     return result.failCantDefineWindowElement();
   }
 
-  return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
+  JS::ObjectOpResult ourResult;
+  bool ok = js::Wrapper::defineProperty(cx, proxy, id, desc, ourResult);
+  if (!ok) {
+    return false;
+  }
+
+  if (!ourResult.ok()) {
+    // It's possible that this failed because the page got the existing
+    // descriptor (which we force to claim to be configurable) and then tried to
+    // redefine the property with the descriptor it got but a different value.
+    // We want to allow this case to succeed, so check for it and if we're in
+    // that case try again but now with an attempt to define a non-configurable
+    // property.
+    if (!desc.hasConfigurable() || !desc.configurable()) {
+      // The incoming descriptor was not explicitly marked "configurable: true",
+      // so it failed for some other reason.  Just propagate that reason out.
+      result = ourResult;
+      return true;
+    }
+
+    JS::Rooted<JS::PropertyDescriptor> existingDesc(cx);
+    ok = js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, &existingDesc);
+    if (!ok) {
+      return false;
+    }
+    if (!existingDesc.object() || existingDesc.configurable()) {
+      // We have no existing property, or its descriptor is already configurable
+      // (on the Window itself, where things really can be non-configurable).
+      // So we failed for some other reason, which we should propagate out.
+      result = ourResult;
+      return true;
+    }
+
+    JS::Rooted<JS::PropertyDescriptor> updatedDesc(cx, desc);
+    updatedDesc.setConfigurable(false);
+
+    JS::ObjectOpResult ourNewResult;
+    ok = js::Wrapper::defineProperty(cx, proxy, id, updatedDesc, ourNewResult);
+    if (!ok) {
+      return false;
+    }
+
+    if (!ourNewResult.ok()) {
+      // Twiddling the configurable flag didn't help.  Just return this failure
+      // out to the caller.
+      result = ourNewResult;
+      return true;
+    }
+  }
+
+#ifndef RELEASE_OR_BETA // To be turned on in bug 1496510.
+  if (desc.hasConfigurable() && !desc.configurable() &&
+      !IsNonConfigurableReadonlyPrimitiveGlobalProp(cx, id)) {
+    // Give callers a way to detect that they failed to "really" define a
+    // non-configurable property.
+    result.failCantDefineWindowNonConfigurable();
+    return true;
+  }
+#endif
+
+  result.succeed();
+  return true;
 }
 
 bool
 nsOuterWindowProxy::ownPropertyKeys(JSContext *cx,
                                     JS::Handle<JSObject*> proxy,
                                     JS::AutoIdVector &props) const
 {
   // Just our indexed stuff followed by our "normal" own property names.
--- a/dom/base/test/test_window_define_nonconfigurable.html
+++ b/dom/base/test/test_window_define_nonconfigurable.html
@@ -13,68 +13,65 @@ https://bugzilla.mozilla.org/show_bug.cg
   /**
    * Test for Bug 1107443, modified when it was backed out in bug 1329323.
    * This is now testing the _current_ behavior, not the desired one; expect
    * failures in this test and needing to update it when bug 1329324 is
    * fixed.
    */
   var retval = Object.defineProperty(window, "nosuchprop",
                                      { value: 5, configurable: false });
-  todo_is(retval, false,
-          "Should return false when 'failing' to define non-configurable property via Object.defineProperty.")
+  is(retval, false,
+     "Should return false when 'failing' to define non-configurable property via Object.defineProperty.")
   var desc = Object.getOwnPropertyDescriptor(window, "nosuchprop");
   is(typeof(desc), "object", "Should have a property 'nosuchprop' now");
-  todo_is(desc.configurable, true,
-          "Property 'nosuchprop' should be configurable");
+  is(desc.configurable, true,
+     "Property 'nosuchprop' should be configurable");
   is(desc.writable, false, "Property 'nosuchprop' should be readonly");
   is(desc.value, 5, "Property 'nosuchprop' should have the right value");
 
   retval = Object.defineProperty(window, "nosuchprop2", { value: 6 });
   is(retval, window,
      "Should return object when succesfully defining 'nosuchprop2'");
   desc = Object.getOwnPropertyDescriptor(window, "nosuchprop2");
   is(typeof(desc), "object", "Should have a property 'nosuchprop2' now");
-  todo_is(desc.configurable, true,
-          "Property 'nosuchprop2' should be configurable");
+  is(desc.configurable, true,
+     "Property 'nosuchprop2' should be configurable");
   is(desc.writable, false, "Property 'nosuchprop2' should be readonly");
   is(desc.value, 6, "Property 'nosuchprop2' should have the right value");
 
   retval = Object.defineProperty(window, "nosuchprop3",
                                  { value: 7, configurable: true });
   is(retval, window,
      "Should return object when succesfully defining 'nosuchprop3'");
   desc = Object.getOwnPropertyDescriptor(window, "nosuchprop3");
   is(typeof(desc), "object", "Should have a property 'nosuchprop3' now");
   is(desc.configurable, true,
           "Property 'nosuchprop3' should be configurable");
   is(desc.writable, false, "Property 'nosuchprop3' should be readonly");
   is(desc.value, 7, "Property 'nosuchprop3' should have the right value");
 
-  // XXXbz it's not actually entirely clear what behavior the
-  // Reflect.defineProperty bits should have.  Check it carefully once there's a
-  // spec.
   retval = Reflect.defineProperty(window, "nosuchprop4",
                                   { value: 8, configurable: false });
-  todo_is(retval, false,
-          "Should not be able to Reflect.defineProperty if non-configurable");
+  is(retval, false,
+     "Should not be able to Reflect.defineProperty if non-configurable");
   desc = Object.getOwnPropertyDescriptor(window, "nosuchprop4");
   is(typeof(desc), "object", "Should have a property 'nosuchprop4' now");
-  todo_is(desc.configurable, true,
-          "Property 'nosuchprop4' should be configurable");
+  is(desc.configurable, true,
+     "Property 'nosuchprop4' should be configurable");
   is(desc.writable, false, "Property 'nosuchprop4' should be readonly");
   is(desc.value, 8, "Property 'nosuchprop4' should have the right value");
 
   retval = Reflect.defineProperty(window, "nosuchprop5",
                                   { value: 9 });
   is(retval, true,
      "Should be able to Reflect.defineProperty with default configurability");
   desc = Object.getOwnPropertyDescriptor(window, "nosuchprop5");
   is(typeof(desc), "object", "Should have a property 'nosuchprop5' now");
-  todo_is(desc.configurable, true,
-          "Property 'nosuchprop5' should be configurable");
+  is(desc.configurable, true,
+     "Property 'nosuchprop5' should be configurable");
   is(desc.writable, false, "Property 'nosuchprop5' should be readonly");
   is(desc.value, 9, "Property 'nosuchprop5' should have the right value");
 
   retval = Reflect.defineProperty(window, "nosuchprop6",
                                   { value: 10, configurable: true });
   is(retval, true,
      "Should be able to Reflect.defineProperty if configurable");
   desc = Object.getOwnPropertyDescriptor(window, "nosuchprop6");
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/Unused.h"
 #include "mozilla/UseCounter.h"
 
 #include "AccessCheck.h"
 #include "js/JSON.h"
 #include "js/StableStringChars.h"
+#include "js/Symbol.h"
 #include "jsfriendapi.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsHTMLTags.h"
 #include "nsIDocShell.h"
 #include "nsIDOMGlobalPropertyInitializer.h"
 #include "nsINode.h"
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -4,18 +4,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_BindingUtils_h__
 #define mozilla_dom_BindingUtils_h__
 
 #include "jsfriendapi.h"
 #include "js/CharacterEncoding.h"
+#include "js/Conversions.h"
+#include "js/MemoryFunctions.h"
 #include "js/Wrapper.h"
-#include "js/Conversions.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Alignment.h"
 #include "mozilla/Array.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/DeferredFinalize.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/CallbackObject.h"
 #include "mozilla/dom/DOMJSClass.h"
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -13953,16 +13953,23 @@ class CGBindingRoot(CGThing):
                         props.isCrossOriginSetter)
 
             return any(hasCrossOriginProperty(m) for m in desc.interface.members)
 
         bindingDeclareHeaders["jsapi.h"] = any(descriptorHasCrossOriginProperties(d) for d in descriptors)
         bindingDeclareHeaders["jspubtd.h"] = not bindingDeclareHeaders["jsapi.h"]
         bindingDeclareHeaders["js/RootingAPI.h"] = not bindingDeclareHeaders["jsapi.h"]
 
+        def descriptorHasIteratorAlias(desc):
+            def hasIteratorAlias(m):
+                return m.isMethod() and "@@iterator" in m.aliases
+            return any(hasIteratorAlias(m) for m in desc.interface.members)
+
+        bindingHeaders["js/Symbol.h"] = any(descriptorHasIteratorAlias(d) for d in descriptors)
+
         def descriptorRequiresPreferences(desc):
             iface = desc.interface
             return any(m.getExtendedAttribute("Pref") for m in iface.members + [iface])
 
         def descriptorDeprecated(desc):
             iface = desc.interface
             return any(m.getExtendedAttribute("Deprecated") for m in iface.members + [iface])
 
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2038,48 +2038,52 @@ IndexedBufferBinding::ByteCount() const
 }
 
 ////////////////////////////////////////
 
 ScopedUnpackReset::ScopedUnpackReset(const WebGLContext* const webgl)
     : ScopedGLWrapper<ScopedUnpackReset>(webgl->gl)
     , mWebGL(webgl)
 {
+    // clang-format off
     if (mWebGL->mPixelStore_UnpackAlignment != 4) mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
 
     if (mWebGL->IsWebGL2()) {
         if (mWebGL->mPixelStore_UnpackRowLength   != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH  , 0);
         if (mWebGL->mPixelStore_UnpackImageHeight != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0);
         if (mWebGL->mPixelStore_UnpackSkipPixels  != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , 0);
         if (mWebGL->mPixelStore_UnpackSkipRows    != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS   , 0);
         if (mWebGL->mPixelStore_UnpackSkipImages  != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , 0);
 
         if (mWebGL->mBoundPixelUnpackBuffer) mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
     }
+    // clang-format on
 }
 
 void
 ScopedUnpackReset::UnwrapImpl()
 {
+    // clang-format off
     mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mWebGL->mPixelStore_UnpackAlignment);
 
     if (mWebGL->IsWebGL2()) {
         mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH  , mWebGL->mPixelStore_UnpackRowLength  );
         mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mWebGL->mPixelStore_UnpackImageHeight);
         mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , mWebGL->mPixelStore_UnpackSkipPixels );
         mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS   , mWebGL->mPixelStore_UnpackSkipRows   );
         mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , mWebGL->mPixelStore_UnpackSkipImages );
 
         GLuint pbo = 0;
         if (mWebGL->mBoundPixelUnpackBuffer) {
             pbo = mWebGL->mBoundPixelUnpackBuffer->mGLName;
         }
 
         mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, pbo);
     }
+    // clang-format on
 }
 
 ////////////////////
 
 void
 ScopedFBRebinder::UnwrapImpl()
 {
     const auto fnName = [&](WebGLFramebuffer* fb) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -43,25 +43,25 @@
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsWrapperCache.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 
 class nsIDocShell;
 
-/*
- * WebGL-only GLenums
- */
-#define LOCAL_GL_BROWSER_DEFAULT_WEBGL                       0x9244
-#define LOCAL_GL_CONTEXT_LOST_WEBGL                          0x9242
-#define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL               0x9247
-#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL          0x9243
-#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL                         0x9240
-#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL              0x9241
+// WebGL-only GLenums
+// clang-format off
+#define LOCAL_GL_BROWSER_DEFAULT_WEBGL              0x9244
+#define LOCAL_GL_CONTEXT_LOST_WEBGL                 0x9242
+#define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL      0x9247
+#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243
+#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL                0x9240
+#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL     0x9241
+// clang-format on
 
 namespace mozilla {
 class ScopedCopyTexImageSource;
 class ScopedDrawCallWrapper;
 class ScopedResolveTexturesForDraw;
 class ScopedUnpackReset;
 class WebGLActiveInfo;
 class WebGLBuffer;
--- a/dom/canvas/WebGLFormats.cpp
+++ b/dom/canvas/WebGLFormats.cpp
@@ -113,16 +113,18 @@ AddCompressedFormatInfo(EffectiveFormat 
     const CompressedFormatInfo info = { format, uint8_t(bytesPerBlock), blockWidth,
                                         blockHeight, family };
     AlwaysInsert(gCompressedFormatInfoMap, format, info);
 }
 
 static void
 InitCompressedFormatInfo()
 {
+    // clang-format off
+
     // GLES 3.0.4, p147, table 3.19
     // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_ETC2                     ,  64, 4, 4, CompressionFamily::ES3);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ETC2                    ,  64, 4, 4, CompressionFamily::ES3);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA8_ETC2_EAC                , 128, 4, 4, CompressionFamily::ES3);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC         , 128, 4, 4, CompressionFamily::ES3);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_R11_EAC                       ,  64, 4, 4, CompressionFamily::ES3);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RG11_EAC                      , 128, 4, 4, CompressionFamily::ES3);
@@ -189,16 +191,18 @@ InitCompressedFormatInfo()
     // IMG_texture_compression_pvrtc
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_4BPPV1 , 256,  8, 8, CompressionFamily::PVRTC);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_4BPPV1, 256,  8, 8, CompressionFamily::PVRTC);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_2BPPV1 , 256, 16, 8, CompressionFamily::PVRTC);
     AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_2BPPV1, 256, 16, 8, CompressionFamily::PVRTC);
 
     // OES_compressed_ETC1_RGB8_texture
     AddCompressedFormatInfo(EffectiveFormat::ETC1_RGB8_OES, 64, 4, 4, CompressionFamily::ETC1);
+
+    // clang-format on
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 static void
 AddFormatInfo(EffectiveFormat format, const char* name, GLenum sizedFormat,
               uint8_t bytesPerPixel, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
               uint8_t d, uint8_t s, UnsizedFormat unsizedFormat, bool isSRGB,
@@ -267,16 +271,19 @@ AddFormatInfo(EffectiveFormat format, co
                               ToBaseType(componentType), isSRGB, compressedFormatInfo,
                               bytesPerPixel, r,g,b,a,d,s };
     AlwaysInsert(gFormatInfoMap, format, info);
 }
 
 static void
 InitFormatInfo()
 {
+    // This function is full of expressive formatting, so:
+    // clang-format off
+
 #define FOO(x) EffectiveFormat::x, #x, LOCAL_GL_ ## x
 
     // GLES 3.0.4, p130-132, table 3.13
     AddFormatInfo(FOO(R8            ),  1,  8, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::NormUInt);
     AddFormatInfo(FOO(R8_SNORM      ),  1,  8, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::NormInt );
     AddFormatInfo(FOO(RG8           ),  2,  8, 8, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::NormUInt);
     AddFormatInfo(FOO(RG8_SNORM     ),  2,  8, 8, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::NormInt );
     AddFormatInfo(FOO(RGB8          ),  3,  8, 8, 8, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
@@ -484,16 +491,17 @@ InitFormatInfo()
 
     SET_BY_SUFFIX(8)   // WebGL decided that RGB8 should be guaranteed renderable.
     SET_BY_SUFFIX(16F) // RGB16F is renderable in EXT_color_buffer_half_float, though not
                        // EXT_color_buffer_float.
     SET_BY_SUFFIX(32F) // Technically RGB32F is never renderable, but no harm here.
 
 #undef SET_BY_SUFFIX
 
+
     //////
 
 #define SET_BY_SUFFIX(X) \
         SET_COPY_DECAY(   R##X, R##X,   MAX,    MAX,     MAX, MAX, MAX, MAX) \
         SET_COPY_DECAY(  RG##X, R##X, RG##X,    MAX,     MAX, MAX, MAX, MAX) \
         SET_COPY_DECAY(RGBA##X, R##X, RG##X, RGB##X, RGBA##X, MAX, MAX, MAX)
 
     SET_BY_SUFFIX(8I)
@@ -516,16 +524,18 @@ InitFormatInfo()
 
     SET_COPY_DECAY(RGB10_A2UI, R8UI, RG8UI, RGB8UI, RGB10_A2UI, MAX, MAX, MAX)
 
     SET_COPY_DECAY(SRGB8_ALPHA8, MAX, MAX, MAX, SRGB8_ALPHA8, MAX, Alpha8, MAX)
 
     SET_COPY_DECAY(R11F_G11F_B10F, R16F, RG16F, R11F_G11F_B10F, MAX, Luminance16F, MAX, MAX)
 
 #undef SET_COPY_DECAY
+
+    // clang-format on
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 bool gAreFormatTablesInitialized = false;
 
 static void
 EnsureInitFormatTables(const StaticMutexAutoLock&) // Prove that you locked it!
@@ -762,36 +772,42 @@ AddLegacyFormats_LA8(FormatUsageAuthorit
         pi = {LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
         dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
         fnAdd(EffectiveFormat::Alpha8, FormatUsageInfo::kAlphaSwizzleRGBA);
 
         pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
         dui = {LOCAL_GL_RG8, LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE};
         fnAdd(EffectiveFormat::Luminance8Alpha8, FormatUsageInfo::kLumAlphaSwizzleRGBA);
     } else {
+        // clang-format off
         AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE      , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8      );
         AddSimpleUnsized(fua, LOCAL_GL_ALPHA          , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Alpha8          );
         AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8Alpha8);
+        // clang-format on
     }
 
     return true;
 }
 
 static bool
 AddUnsizedFormats(FormatUsageAuthority* fua, gl::GLContext* gl)
 {
+    // clang-format off
+
     // GLES 2.0.25, p63, Table 3.4
     AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE         , EffectiveFormat::RGBA8  );
     AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4, EffectiveFormat::RGBA4  );
     AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1, EffectiveFormat::RGB5_A1);
     AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_BYTE         , EffectiveFormat::RGB8   );
     AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_SHORT_5_6_5  , EffectiveFormat::RGB565 );
 
     // L, A, LA
     return AddLegacyFormats_LA8(fua, gl);
+
+    // clang-format on
 }
 
 void
 FormatUsageInfo::SetRenderable()
 {
     this->isRenderable = true;
 
 #ifdef DEBUG
@@ -889,16 +905,17 @@ FormatUsageAuthority::CreateForWebGL2(gl
     {
         auto usage = ptr->EditUsage(effFormat);
 
         const PackingInfo pi = {unpackFormat, unpackType};
         const DriverUnpackInfo dui = {internalFormat, unpackFormat, unpackType};
         ptr->AddTexUnpack(usage, pi, dui);
     };
 
+    // clang-format off
 #define FOO(x) EffectiveFormat::x, LOCAL_GL_ ## x
 
     // RGBA
     fnAddSizedUnpack(FOO(RGBA8       ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
     fnAddSizedUnpack(FOO(RGBA4       ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4     );
     fnAddSizedUnpack(FOO(RGBA4       ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
     fnAddSizedUnpack(FOO(RGB5_A1     ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1     );
     fnAddSizedUnpack(FOO(RGB5_A1     ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
@@ -979,16 +996,17 @@ FormatUsageAuthority::CreateForWebGL2(gl
     fnAddSizedUnpack(FOO(DEPTH_COMPONENT24 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT  );
     fnAddSizedUnpack(FOO(DEPTH_COMPONENT32F), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_FLOAT         );
 
     // DEPTH_STENCIL
     fnAddSizedUnpack(FOO(DEPTH24_STENCIL8 ), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_UNSIGNED_INT_24_8             );
     fnAddSizedUnpack(FOO(DEPTH32F_STENCIL8), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
 
 #undef FOO
+    // clang-format on
 
     ////////////////////////////////////////////////////////////////////////////
 
     // For renderable, see GLES 3.0.4, p212 "Framebuffer Completeness"
     // For filterable, see GLES 3.0.4, p161 "...a texture is complete unless..."
 
     const auto fnAllowES3TexFormat = [ptr](GLenum sizedFormat, EffectiveFormat effFormat,
                                            bool isRenderable, bool isFilterable)
--- a/dom/canvas/crashtests/crashtests.list
+++ b/dom/canvas/crashtests/crashtests.list
@@ -1,15 +1,15 @@
 load 0px-size-font-667225.html
 load 0px-size-font-shadow.html
 load 360293-1.html
 load 421715-1.html
 load 553938-1.html
 load 647480.html
-load 727547.html
+skip-if(Android&&browserIsRemote) load 727547.html # bug 1507207
 load 729116.html
 load 745699-1.html
 load 746813-1.html
 load 743499-negative-size.html
 skip-if(Android) load 745818-large-source.html # Bug XXX - Crashes Android mid-run w/o a stack
 load 767337-1.html
 load 779426.html
 skip-if(Android) load 780392-1.html
deleted file mode 100644
--- a/dom/canvas/test/reftest/drawCustomFocusRing.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--docytpe html-->
-<html><head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<meta charset="UTF-8">
-<script>
-window.onload=function(){
-var c=document.getElementById("myCanvas").getContext("2d");
-var in1=document.getElementById("in1");
-var in2=document.getElementById("in2");
-in1.onfocus=function(){
-c.beginPath();
-c.rect(10, 10, 200, 200);
-if(c.drawCustomFocusRing(in1)) {
-   c.stroke();
-}
-c.beginPath();
-c.rect(10, 220, 200, 200);
-if(c.drawCustomFocusRing(in2)) {
-   c.stroke();
-}
-}
-in1.focus();
-}
-</script>
-</head>
-<body>
-<canvas id="myCanvas" height="500" width="500" style="border:1px solid black">
-   <input id="in1" type="range" min="1" max="12">
-   <input id="in2" type="range" min="1" max="12">
-</canvas>
-
-</body></html>
--- a/dom/canvas/test/reftest/reftest.list
+++ b/dom/canvas/test/reftest/reftest.list
@@ -152,17 +152,16 @@ skip-if(true) pref(webgl.disable-angle,t
 == clip-multiple-move-1.html clip-multiple-move-1-ref.html
 fuzzy-if(skiaContent,0-1,0-150) == clip-multiple-move-2.html clip-multiple-move-2-ref.html
 
 # Bug 815648
 == stroketext-shadow.html stroketext-shadow-ref.html
 
 # focus rings
 pref(canvas.focusring.enabled,true) skip-if(cocoaWidget) skip-if(winWidget) fuzzy-if(skiaContent&&!cocoaWidget&&!winWidget,0-1,0-2) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
-pref(canvas.customfocusring.enabled,true) skip-if(Android||cocoaWidget||winWidget) fuzzy-if(gtkWidget,0-64,0-410) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
 
 # Check that captureStream() displays in a local video element
 == capturestream.html wrapper.html?green.png
 
 fuzzy-if(azureSkia,0-16,0-2) fuzzy-if(Android,0-3,0-40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
 
 # Canvas Filter Reftests
 include filters/reftest.list
--- a/dom/canvas/test/test_canvas_focusring.html
+++ b/dom/canvas/test/test_canvas_focusring.html
@@ -4,36 +4,16 @@
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 const Cc = SpecialPowers.Cc;
 const Cr = SpecialPowers.Cr;
 SpecialPowers.setBoolPref("canvas.focusring.enabled", true);
-SpecialPowers.setBoolPref("canvas.customfocusring.enabled", true);
-</script>
-
-<p>Canvas test: drawCustomFocusRing</p>
-<canvas id="c688" class="output" width="100" height="50">+
-    <input id="button1" type="range" min="1" max="12"></input>
-    <input id="button2" type="range" min="1" max="12"></input>
-</canvas>
-<script type="text/javascript">
-function test_drawCustomFocusRing_canvas() {
-   var c = document.getElementById("c688");
-   var ctx = c.getContext("2d");
-   ctx.beginPath();
-   var b1 = document.getElementById('button1');
-   var b2 = document.getElementById('button2');
-   ok(!ctx.drawCustomFocusRing(b1), "button 1 is focused");
-   ok(!ctx.drawCustomFocusRing(b2), "button 2 is focused");
-   b1.focus();
-   ok(ctx.drawCustomFocusRing(b1), "button 1 should not be focused");
-}
 </script>
 
 <p>Canvas test: drawFocusIfNeeded</p>
 <canvas id="c689" class="output" width="50" height="25">
     <input id="button3" type="range" min="1" max="12"></input>
     <input id="button4" type="range" min="1" max="12"></input>
 </canvas>
 <script type="text/javascript">
@@ -73,28 +53,21 @@ function test_drawFocusIfNeeded_canvas()
 }
 </script>
 
 
 <script>
 
 function runTests() {
  try {
-  test_drawCustomFocusRing_canvas();
- } catch(e) {
-  throw e;
-  ok(false, "unexpected exception thrown in: test_drawCustomFocusRing_canvas");
- }
-  try {
   test_drawFocusIfNeeded_canvas();
  } catch(e) {
   throw e;
   ok(false, "unexpected exception thrown in: test_drawFocusIfNeeded_canvas");
  }
 
  SpecialPowers.setBoolPref("canvas.focusring.enabled", false);
- SpecialPowers.setBoolPref("canvas.customfocusring.enabled", false);
  SimpleTest.finish();
 }
 
 addLoadEvent(runTests);
 
 </script>
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -6,16 +6,17 @@
 
 
 #include "Key.h"
 
 #include <algorithm>
 #include <stdint.h> // for UINT32_MAX, uintptr_t
 #include "IndexedDatabaseManager.h"
 #include "js/Date.h"
+#include "js/MemoryFunctions.h"
 #include "js/Value.h"
 #include "jsfriendapi.h"
 #include "mozilla/Casting.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/EndianUtils.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageValueArray.h"
--- a/dom/interfaces/payments/nsIPaymentRequest.idl
+++ b/dom/interfaces/payments/nsIPaymentRequest.idl
@@ -58,19 +58,19 @@ interface nsIPaymentDetails : nsISupport
   readonly attribute nsIPaymentItem totalItem;
   readonly attribute nsIArray displayItems;
   readonly attribute nsIArray shippingOptions;
   readonly attribute nsIArray modifiers;
   readonly attribute AString error;
   [implicit_jscontext]
   readonly attribute jsval shippingAddressErrors;
   [implicit_jscontext]
-  readonly attribute jsval payer;
+  readonly attribute jsval payerErrors;
   [implicit_jscontext]
-  readonly attribute jsval paymentMethod;
+  readonly attribute jsval paymentMethodErrors;
 };
 
 [scriptable, builtinclass, uuid(d53f9f20-138e-47cc-9fd5-db16a3f6d301)]
 interface nsIPaymentOptions : nsISupports
 {
   readonly attribute boolean requestPayerName;
   readonly attribute boolean requestPayerEmail;
   readonly attribute boolean requestPayerPhone;
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -14,16 +14,17 @@
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "MediaFormatReader.h"
 #include "MediaQueue.h"
 #include "BufferMediaResource.h"
 #include "DecoderTraits.h"
 #include "AudioContext.h"
 #include "AudioBuffer.h"
+#include "js/MemoryFunctions.h"
 #include "MediaContainerType.h"
 #include "nsContentUtils.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsMimeTypes.h"
 #include "VideoUtils.h"
 #include "WebAudioUtils.h"
 #include "mozilla/dom/Promise.h"
--- a/dom/payments/PaymentRequestData.cpp
+++ b/dom/payments/PaymentRequestData.cpp
@@ -476,28 +476,28 @@ PaymentDetails::GetShippingAddressErrors
   errors.Init(mShippingAddressErrors);
   if (!ToJSValue(aCx, errors, aErrors)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PaymentDetails::GetPayer(JSContext* aCx, JS::MutableHandleValue aErrors)
+PaymentDetails::GetPayerErrors(JSContext* aCx, JS::MutableHandleValue aErrors)
 {
   PayerErrors errors;
   errors.Init(mPayerErrors);
   if (!ToJSValue(aCx, errors, aErrors)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PaymentDetails::GetPaymentMethod(JSContext* aCx, JS::MutableHandleValue aErrors)
+PaymentDetails::GetPaymentMethodErrors(JSContext* aCx, JS::MutableHandleValue aErrors)
 {
   if (mPaymentMethodErrors.IsEmpty()) {
     aErrors.set(JS::NullValue());
     return NS_OK;
   }
   nsresult rv = DeserializeToJSValue(mPaymentMethodErrors, aCx ,aErrors);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -553,37 +553,37 @@ PaymentDetails::Update(nsIPaymentDetails
   rv = aDetails->GetError(mError);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   PaymentDetails* rowDetails = static_cast<PaymentDetails*>(aDetails);
   MOZ_ASSERT(rowDetails);
   mShippingAddressErrors = rowDetails->GetShippingAddressErrors();
-  mPayerErrors = rowDetails->GetPayer();
-  mPaymentMethodErrors = rowDetails->GetPaymentMethod();
+  mPayerErrors = rowDetails->GetPayerErrors();
+  mPaymentMethodErrors = rowDetails->GetPaymentMethodErrors();
 
   return NS_OK;
 
 }
 
 const nsString&
 PaymentDetails::GetShippingAddressErrors() const
 {
   return mShippingAddressErrors;
 }
 
 const nsString&
-PaymentDetails::GetPayer() const
+PaymentDetails::GetPayerErrors() const
 {
   return mPayerErrors;
 }
 
 const nsString&
-PaymentDetails::GetPaymentMethod() const
+PaymentDetails::GetPaymentMethodErrors() const
 {
   return mPaymentMethodErrors;
 }
 
 nsresult
 PaymentDetails::UpdateErrors(const nsAString& aError,
                              const nsAString& aPayerErrors,
                              const nsAString& aPaymentMethodErrors,
--- a/dom/payments/PaymentRequestData.h
+++ b/dom/payments/PaymentRequestData.h
@@ -126,18 +126,18 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPAYMENTDETAILS
 
 
   static nsresult Create(const IPCPaymentDetails& aIPCDetails,
                          nsIPaymentDetails** aDetails);
   nsresult Update(nsIPaymentDetails* aDetails, const bool aRequestShipping);
   const nsString& GetShippingAddressErrors() const;
-  const nsString& GetPayer() const;
-  const nsString& GetPaymentMethod() const;
+  const nsString& GetPayerErrors() const;
+  const nsString& GetPaymentMethodErrors() const;
   nsresult UpdateErrors(const nsAString& aError,
                         const nsAString& aPayerErrors,
                         const nsAString& aPaymentMethodErrors,
                         const nsAString& aShippingAddressErrors);
 
 private:
   PaymentDetails(const nsAString& aId,
                  nsIPaymentItem* aTotalItem,
--- a/dom/payments/test/BasicCardErrorsChromeScript.js
+++ b/dom/payments/test/BasicCardErrorsChromeScript.js
@@ -94,17 +94,17 @@ const TestingUIService = {
     paymentSrv.respondPayment(
       showResponse.QueryInterface(Ci.nsIPaymentActionResponse)
     );
   },
   // Handles response.retry({ paymentMethod }):
   updatePayment(requestId) {
     // Let's echo what was sent in by the error...
     const request = paymentSrv.getPaymentRequestById(requestId);
-    this.showPayment(requestId, request.paymentDetails.paymentMethod);
+    this.showPayment(requestId, request.paymentDetails.paymentMethodErrors);
   },
   // Handles response.complete()
   completePayment(requestId) {
     const request = paymentSrv.getPaymentRequestById(requestId);
     const completeResponse = Cc[
       "@mozilla.org/dom/payments/payment-complete-action-response;1"
     ].createInstance(Ci.nsIPaymentCompleteActionResponse);
     completeResponse.init(
--- a/dom/payments/test/PayerDetailsChromeScript.js
+++ b/dom/payments/test/PayerDetailsChromeScript.js
@@ -30,17 +30,17 @@ const TestingUIService = {
     paymentSrv.respondPayment(
       showResponse.QueryInterface(Ci.nsIPaymentActionResponse)
     );
   },
   // .retry({ payer }) and .updateWith({payerErrors}) both get routed here:
   updatePayment(requestId) {
     // Let's echo what was sent in by the error...
     const request = paymentSrv.getPaymentRequestById(requestId);
-    const { name, email, phone } = request.paymentDetails.payer;
+    const { name, email, phone } = request.paymentDetails.payerErrors;
     const { error } = request.paymentDetails;
     // Let's use the .error as the switch
     switch (error) {
       case "retry-fire-payerdetaichangeevent": {
         paymentSrv.changePayerDetail(requestId, name, email, phone);
         break;
       }
       case "update-with": {
--- a/dom/payments/test/RetryPaymentChromeScript.js
+++ b/dom/payments/test/RetryPaymentChromeScript.js
@@ -107,17 +107,17 @@ function checkPayerErrors(testName, erro
       emitTestFail(`${testName}: Expected '${expected}' on payerErrors.${key}, but got '${msg}'.`);
       return;
     }
   }
 }
 
 function checkPaymentMethodErrors(testName, errors) {
   if (!errors) {
-    emitTestFail(`${testName} :Expect non-null payerMethodErrors, but got null.`);
+    emitTestFail(`${testName} :Expect non-null paymentMethodErrors, but got null.`);
     return;
   }
   for (const [key, msg] of Object.entries(errors)) {
     const expected = `method ${key} error`;
     if (msg !== expected) {
       emitTestFail(
         `${testName}: Expected '${expected}' on paymentMethodErrors.${key}, but got '${msg}'.`
       );
@@ -143,18 +143,18 @@ const DummyUIService = {
   },
   updatePayment(requestId) {
     const payment = paymentSrv.getPaymentRequestById(requestId);
     if (payment.paymentDetails.error !== "error") {
       emitTestFail("Expect 'error' on details.error, but got '" +
                    payment.paymentDetails.error + "'");
     }
     checkAddressErrors(this.testName, payment.paymentDetails.shippingAddressErrors)
-    checkPayerErrors(this.testName, payment.paymentDetails.payer);
-    checkPaymentMethodErrors(this.testName, payment.paymentDetails.paymentMethod);
+    checkPayerErrors(this.testName, payment.paymentDetails.payerErrors);
+    checkPaymentMethodErrors(this.testName, payment.paymentDetails.paymentMethodErrors);
     if (this.rejectRetry) {
       rejectPayment(requestId);
     } else {
       acceptPayment(requestId, "retry");
     }
   },
   closePayment: (requestId) => {respondRequestId = requestId},
   QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -20,16 +20,17 @@
 #include "nsJSUtils.h"
 #include "nsIDocument.h"
 #include "nsIXPConnect.h"
 #include "xpcpublic.h"
 #include "nsIContent.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsWrapperCacheInlines.h"
 #include "js/GCHashTable.h"
+#include "js/Symbol.h"
 #include "js/TracingAPI.h"
 #include "js/Wrapper.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
 
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -10,16 +10,17 @@
 #include "ScriptTrace.h"
 #include "ModuleLoadRequest.h"
 #include "ModuleScript.h"
 
 #include "prsystem.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/CompilationAndEvaluation.h"
+#include "js/MemoryFunctions.h"
 #include "js/OffThreadScriptCompilation.h"
 #include "js/SourceText.h"
 #include "js/Utility.h"
 #include "xpcpublic.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIContent.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/DocGroup.h"
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -238,19 +238,16 @@ interface CanvasDrawPath {
   boolean isPointInStroke(double x, double y);
   [NeedsSubjectPrincipal] // Only required because overloads can't have different extended attributes.
   boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
 };
 
 [NoInterfaceObject]
 interface CanvasUserInterface {
   [Pref="canvas.focusring.enabled", Throws] void drawFocusIfNeeded(Element element);
-// NOT IMPLEMENTED  void drawSystemFocusRing(Path path, HTMLElement element);
-  [Pref="canvas.customfocusring.enabled"] boolean drawCustomFocusRing(Element element);
-// NOT IMPLEMENTED  boolean drawCustomFocusRing(Path path, HTMLElement element);
 // NOT IMPLEMENTED  void scrollPathIntoView();
 // NOT IMPLEMENTED  void scrollPathIntoView(Path path);
 };
 
 [NoInterfaceObject]
 interface CanvasText {
   // text (see also the CanvasPathDrawingStyles interface)
   [Throws, LenientFloat]
--- a/dom/workers/ChromeWorkerScope.cpp
+++ b/dom/workers/ChromeWorkerScope.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ChromeWorkerScope.h"
 
 #include "jsapi.h"
+#include "js/MemoryFunctions.h"
 
 #include "nsXPCOM.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsString.h"
 
 #include "WorkerPrivate.h"
 
 namespace mozilla {
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -71,16 +71,17 @@
 #include "nsIWindowWatcher.h"
 #include "nsIConsoleService.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "nsStringBuffer.h"
 #include "nsIFileChannel.h"
 #include "mozilla/Telemetry.h"
 #include "js/JSON.h"
+#include "js/MemoryFunctions.h"
 #include "jsfriendapi.h"
 #include "GeckoProfiler.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "mozilla/Attributes.h"
 #include "MultipartBlobImpl.h"
 #include "nsIPermissionManager.h"
 #include "nsMimeTypes.h"
 #include "nsIHttpChannelInternal.h"
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-52944
+52951
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -2785,17 +2785,17 @@ Confucian/SM
 Confucianism/MS
 Confucius/M
 Cong/M
 Congo/M
 Congolese/M
 Congregational
 Congregationalist/MS
 Congress/MS
-Congressional
+Congressional/Y
 Congreve/M
 Conley/M
 Conn/MR
 Connecticut/M
 Connemara/M
 Conner/M
 Connery/M
 Connie/M
@@ -20668,17 +20668,17 @@ congratulation/M
 congratulatory
 congregant/MS
 congregate/GNDSX
 congregation/M
 congregational
 congregationalism/M
 congregationalist/MS
 congress/MS
-congressional
+congressional/Y
 congressman/M
 congressmen
 congresspeople
 congressperson/MS
 congresswoman/M
 congresswomen
 congruence/M
 congruent/Y
@@ -23774,16 +23774,17 @@ downtrodden
 downturn/MS
 downward/S
 downwind
 downy/RT
 dowry/SM
 dowse/DRSZG
 dowser/M
 dox/SDG
+doxastic
 doxology/SM
 doxx/SDG
 doyen/SM
 doyenne/MS
 doz/XGDNS
 doze/M
 dozen/MH
 dozily
@@ -30054,16 +30055,17 @@ hopped
 hopper/MS
 hopping
 hopscotch/MDSG
 hora/MS
 horde/DSMG
 horehound/SM
 horizon/SM
 horizontal/SMY
+hormesis
 hormonal
 hormone/SM
 horn/MDS
 hornbeam/S
 hornblende/M
 hornet/MS
 hornless
 hornlike
@@ -49602,16 +49604,18 @@ transference/M
 transferred
 transferring
 transfiguration/M
 transfigure/GDS
 transfinite
 transfix/DSG
 transform/BSZGMDR
 transformation/SM
+transformational
+transformative
 transformer/M
 transfuse/DSXGN
 transfusion/M
 transgender/SD
 transgenderism
 transgene/S
 transgenic
 transgress/GDS
@@ -50822,16 +50826,17 @@ upstream
 upstroke/SM
 upsurge/MGDS
 upswing/MS
 uptake/SM
 uptempo
 upthrust/GSM
 uptick/SM
 uptight
+uptime
 uptown/M
 uptrend
 upturn/GSMD
 upward/SY
 upwind
 uracil/M
 uranium/M
 urban
@@ -50914,19 +50919,21 @@ vac/S
 vacancy/SM
 vacant/Y
 vacate/DSG
 vacation/ZGMDRS
 vacationer/M
 vacationist/SM
 vaccinate/GNDSX
 vaccination/M
+vaccinator/S
 vaccine/SM
 vacillate/XGNDS
 vacillation/M
+vacinal
 vacuity/M
 vacuole/MS
 vacuous/YP
 vacuousness/M
 vacuum/GSMD
 vagabond/SMDG
 vagabondage/M
 vagarious
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -476,22 +476,24 @@ DrawBlitProg::Draw(const BaseArgs& args,
     GLenum vaa0Type;
     GLint vaa0Normalized;
     GLsizei vaa0Stride;
     GLvoid* vaa0Pointer;
     if (mParent.mQuadVAO) {
         oldVAO = gl->GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING);
         gl->fBindVertexArray(mParent.mQuadVAO);
     } else {
+        // clang-format off
         gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vaa0Enabled);
         gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &vaa0Size);
         gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint*)&vaa0Type);
         gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vaa0Normalized);
         gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, (GLint*)&vaa0Stride);
         gl->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &vaa0Pointer);
+        // clang-format on
 
         gl->fEnableVertexAttribArray(0);
         const ScopedBindArrayBuffer bindVBO(gl, mParent.mQuadVBO);
         gl->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
     }
 
     gl->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
 
--- a/gfx/gl/GLConsts.h
+++ b/gfx/gl/GLConsts.h
@@ -1,15 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GLCONSTS_H_
 #define GLCONSTS_H_
 
+// clang-format off
+
 /**
  * GENERATED FILE, DO NOT MODIFY DIRECTLY.
  * This is a file generated directly from the official OpenGL registry
  * xml available http://www.opengl.org/registry/#specfiles.
  *
  * To generate this file, see tutorial in 'GLParseRegistryXML.py'.
  */
 
@@ -6994,11 +6996,11 @@
 #define LOCAL_WGL_VIDEO_OUT_COLOR_NV                         0x20C3
 #define LOCAL_WGL_VIDEO_OUT_DEPTH_NV                         0x20C5
 #define LOCAL_WGL_VIDEO_OUT_FIELD_1                          0x20C9
 #define LOCAL_WGL_VIDEO_OUT_FIELD_2                          0x20CA
 #define LOCAL_WGL_VIDEO_OUT_FRAME                            0x20C8
 #define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_1_2               0x20CB
 #define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_2_1               0x20CC
 
-
+// clang-format on
 
 #endif // GLCONSTS_H_
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -58,21 +58,23 @@ namespace mozilla {
 namespace gl {
 
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 MOZ_THREAD_LOCAL(uintptr_t) GLContext::sCurrentContext;
 
 // If adding defines, don't forget to undefine symbols. See #undef block below.
+// clang-format off
 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } }
 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } }
 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } }
 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } }
 #define END_SYMBOLS { nullptr, { nullptr } }
+// clang-format on
 
 // should match the order of GLExtensions, and be null-terminated.
 static const char* const sExtensionNames[] = {
     "NO_EXTENSION",
     "GL_AMD_compressed_ATC_texture",
     "GL_ANGLE_depth_texture",
     "GL_ANGLE_framebuffer_blit",
     "GL_ANGLE_framebuffer_multisample",
@@ -378,16 +380,17 @@ GLContext::LoadFeatureSymbols(const char
 };
 
 bool
 GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
 {
     if (!MakeCurrent(true))
         return false;
 
+    // clang-format off
     const SymLoadStruct coreSymbols[] = {
         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
@@ -506,16 +509,17 @@ GLContext::InitWithPrefixImpl(const char
 
         { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
 
         END_SYMBOLS
     };
+    // clang-format on
 
     if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL"))
         return false;
 
     {
         const SymLoadStruct symbols[] = {
             { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatus",
                                                                 "GetGraphicsResetStatusARB",
@@ -582,47 +586,47 @@ GLContext::InitWithPrefixImpl(const char
         printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
     }
 
     ////////////////
 
     // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
     if (mProfile == ContextProfile::OpenGLES) {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
+            CORE_SYMBOL(GetShaderPrecisionFormat),
+            CORE_SYMBOL(ClearDepthf),
+            CORE_SYMBOL(DepthRangef),
             END_SYMBOLS
         };
 
         if (!LoadGLSymbols(this, prefix, trygl, symbols, "OpenGL ES"))
             return false;
     } else {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
+            CORE_SYMBOL(ClearDepth),
+            CORE_SYMBOL(DepthRange),
+            CORE_SYMBOL(ReadBuffer),
+            CORE_SYMBOL(MapBuffer),
+            CORE_SYMBOL(UnmapBuffer),
+            CORE_SYMBOL(PointParameterf),
+            CORE_SYMBOL(DrawBuffer),
             // The following functions are only used by Skia/GL in desktop mode.
             // Other parts of Gecko should avoid using these
-            { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fPolygonMode, { "PolygonMode", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
+            CORE_SYMBOL(DrawBuffers),
+            CORE_SYMBOL(ClientActiveTexture),
+            CORE_SYMBOL(DisableClientState),
+            CORE_SYMBOL(EnableClientState),
+            CORE_SYMBOL(LoadIdentity),
+            CORE_SYMBOL(LoadMatrixf),
+            CORE_SYMBOL(MatrixMode),
+            CORE_SYMBOL(PolygonMode),
+            CORE_SYMBOL(TexGeni),
+            CORE_SYMBOL(TexGenf),
+            CORE_SYMBOL(TexGenfv),
+            CORE_SYMBOL(VertexPointer),
             END_SYMBOLS
         };
 
         if (!LoadGLSymbols(this, prefix, trygl, symbols, "Desktop OpenGL"))
             return false;
     }
 
     ////////////////
@@ -1035,54 +1039,56 @@ GLContext::LoadMoreSymbols(const char* p
                               resetStrategy);
             }
             MarkUnsupported(GLFeature::robustness);
         }
     }
 
     if (IsSupported(GLFeature::sync)) {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fFenceSync,      { "FenceSync",      nullptr } },
-            { (PRFuncPtr*) &mSymbols.fIsSync,         { "IsSync",         nullptr } },
-            { (PRFuncPtr*) &mSymbols.fDeleteSync,     { "DeleteSync",     nullptr } },
-            { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fWaitSync,       { "WaitSync",       nullptr } },
-            { (PRFuncPtr*) &mSymbols.fGetInteger64v,  { "GetInteger64v",  nullptr } },
-            { (PRFuncPtr*) &mSymbols.fGetSynciv,      { "GetSynciv",      nullptr } },
+            CORE_SYMBOL(FenceSync),
+            CORE_SYMBOL(IsSync),
+            CORE_SYMBOL(DeleteSync),
+            CORE_SYMBOL(ClientWaitSync),
+            CORE_SYMBOL(WaitSync),
+            CORE_SYMBOL(GetInteger64v),
+            CORE_SYMBOL(GetSynciv),
             END_SYMBOLS
         };
         fnLoadForFeature(symbols, GLFeature::sync);
     }
 
     if (IsExtensionSupported(OES_EGL_image)) {
         const SymLoadStruct symbols[] = {
             { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } },
             { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } },
             END_SYMBOLS
         };
         fnLoadForExt(symbols, OES_EGL_image);
     }
 
     if (IsExtensionSupported(APPLE_texture_range)) {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
+            CORE_SYMBOL(TextureRangeAPPLE),
             END_SYMBOLS
         };
         fnLoadForExt(symbols, APPLE_texture_range);
     }
 
     if (IsExtensionSupported(APPLE_fence)) {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fFinishObjectAPPLE, { "FinishObjectAPPLE", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fTestObjectAPPLE, { "TestObjectAPPLE", nullptr } },
+            CORE_SYMBOL(FinishObjectAPPLE),
+            CORE_SYMBOL(TestObjectAPPLE),
             END_SYMBOLS
         };
         fnLoadForExt(symbols, APPLE_fence);
     }
 
+// clang-format off
+
     if (IsSupported(GLFeature::vertex_array_object)) {
         const SymLoadStruct coreSymbols[] = {
             { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", nullptr } },
             { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", nullptr } },
             { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", nullptr } },
             { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", nullptr } },
             END_SYMBOLS
         };
@@ -1495,44 +1501,46 @@ GLContext::LoadMoreSymbols(const char* p
             { (PRFuncPtr*) &mSymbols.fFinishFence,  { "FinishFenceNV",  nullptr } },
             { (PRFuncPtr*) &mSymbols.fIsFence,      { "IsFenceNV",      nullptr } },
             { (PRFuncPtr*) &mSymbols.fGetFenceiv,   { "GetFenceivNV",   nullptr } },
             END_SYMBOLS
         };
         fnLoadForExt(symbols, NV_fence);
     }
 
+// clang-format off
+
     if (IsExtensionSupported(NV_texture_barrier)) {
         const SymLoadStruct symbols[] = {
             { (PRFuncPtr*) &mSymbols.fTextureBarrier, { "TextureBarrierNV", nullptr } },
             END_SYMBOLS
         };
         fnLoadForExt(symbols, NV_texture_barrier);
     }
 
     if (IsSupported(GLFeature::read_buffer)) {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
+            CORE_SYMBOL(ReadBuffer),
             END_SYMBOLS
         };
         fnLoadForFeature(symbols, GLFeature::read_buffer);
     }
 
     if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
         const SymLoadStruct symbols[] = {
-            { (PRFuncPtr*) &mSymbols.fResolveMultisampleFramebufferAPPLE, { "ResolveMultisampleFramebufferAPPLE", nullptr } },
+            CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE),
             END_SYMBOLS
         };
         fnLoadForExt(symbols, APPLE_framebuffer_multisample);
     }
 
     // Load developer symbols, don't fail if we can't find them.
     const SymLoadStruct devSymbols[] = {
-            { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
-            { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
+            CORE_SYMBOL(GetTexImage),
+            CORE_SYMBOL(GetTexLevelParameteriv),
             END_SYMBOLS
     };
     const bool warnOnFailures = ShouldSpew();
     LoadSymbols(devSymbols, trygl, prefix, warnOnFailures);
 }
 
 #undef CORE_SYMBOL
 #undef CORE_EXT_SYMBOL2
--- a/gfx/gl/GLDefs.h
+++ b/gfx/gl/GLDefs.h
@@ -15,16 +15,18 @@ bool CheckContextLost(const GLContext* g
 }
 }
 
 #define MOZ_GL_ASSERT(glContext,expr) \
   MOZ_ASSERT((expr) || mozilla::gl::CheckContextLost(glContext))
 
 // -
 
+// clang-format off
+
 // TODO: use official constant names instead of followed ones.
 
 // IMG_texture_compression_pvrtc
 #define LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1            0x8C00
 #define LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1            0x8C01
 #define LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1           0x8C02
 #define LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1           0x8C03
 
@@ -88,9 +90,11 @@ bool CheckContextLost(const GLContext* g
 // Others
 #define LOCAL_EGL_PRESERVED_RESOURCES                   0x3030
 #define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
 #define LOCAL_GL_CONTEXT_FLAGS_ARB                      0x2094
 #define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB           0x00000001
 #define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB  0x00000002
 #define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB          0x00000004
 
+// clang-format on
+
 #endif
--- a/gfx/gl/GLParseRegistryXML.py
+++ b/gfx/gl/GLParseRegistryXML.py
@@ -50,16 +50,18 @@ class GLConstHeader:
         self.write([
             '/* This Source Code Form is subject to the terms of the Mozilla Public',
             ' * License, v. 2.0. If a copy of the MPL was not distributed with this',
             ' * file, You can obtain one at http://mozilla.org/MPL/2.0/. */',
             '',
             '#ifndef GLCONSTS_H_',
             '#define GLCONSTS_H_',
             '',
+            '// clang-format off',
+            '',
             '/**',
             ' * GENERATED FILE, DO NOT MODIFY DIRECTLY.',
             ' * This is a file generated directly from the official OpenGL registry',
             ' * xml available http://www.opengl.org/registry/#specfiles.',
             ' *',
             ' * To generate this file, see tutorial in \'GLParseRegistryXML.py\'.',
             ' */',
             ''
@@ -84,16 +86,18 @@ class GLConstHeader:
 
     def formatLibEnd(self, lib):
         # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
         self.write(2)
 
     def formatFileEnd(self):
         self.write([
             '',
+            '// clang-format on',
+            '',
             '#endif // GLCONSTS_H_'
         ])
 
 
 ################################################################################
 # underground code
 
 def getScriptDir():
--- a/image/test/crashtests/crashtests.list
+++ b/image/test/crashtests/crashtests.list
@@ -21,17 +21,17 @@ load 1210745-1.gif
 load 1212954-1.svg
 load 1235605.gif
 load 1241728-1.html
 load 1241729-1.html
 load 1242093-1.html
 load 1242778-1.png
 load 1249576-1.png
 load 1253362-1.html
-load 1355898-1.html
+skip-if(Android&&browserIsRemote) load 1355898-1.html # bug 1507207
 load 1375842-1.html
 load 1413762-1.gif
 pref(image.downscale-during-decode.enabled,true) load 1443232-1.html
 load colormap-range.gif
 HTTP load delayedframe.sjs # A 3-frame animated GIF with an inordinate delay between the second and third frame
 
 # Animated gifs with a very large canvas, but tiny actual content.
 load delaytest.html?523528-1.gif
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -5,16 +5,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "JavaScriptShared.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/CPOWManagerGetter.h"
 #include "mozilla/dom/TabChild.h"
 #include "jsfriendapi.h"
+#include "js/Symbol.h"
 #include "xpcprivate.h"
 #include "WrapperFactory.h"
 #include "mozilla/Preferences.h"
 
 using namespace js;
 using namespace JS;
 using namespace mozilla;
 using namespace mozilla::jsipc;
--- a/js/public/MemoryFunctions.h
+++ b/js/public/MemoryFunctions.h
@@ -3,23 +3,41 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Low-level memory-allocation functions. */
 
 #ifndef js_MemoryFunctions_h
 #define js_MemoryFunctions_h
 
+#include "mozilla/Assertions.h" // MOZ_ASSERT
 #include "mozilla/Attributes.h" // MOZ_MUST_USE
 
 #include <stddef.h> // size_t
 
 #include "jstypes.h" // JS_PUBLIC_API
 
 struct JSContext;
+struct JSRuntime;
+
+struct JSFreeOp
+{
+  protected:
+    JSRuntime* runtime_;
+
+    explicit JSFreeOp(JSRuntime* rt)
+      : runtime_(rt)
+    {}
+
+  public:
+    JSRuntime* runtime() const {
+        MOZ_ASSERT(runtime_);
+        return runtime_;
+    }
+};
 
 extern JS_PUBLIC_API void*
 JS_malloc(JSContext* cx, size_t nbytes);
 
 extern JS_PUBLIC_API void*
 JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes);
 
 /**
new file mode 100644
--- /dev/null
+++ b/js/public/Symbol.h
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Symbols. */
+
+#ifndef js_Symbol_h
+#define js_Symbol_h
+
+#include <stddef.h> // size_t
+#include <stdint.h> // uintptr_t, uint32_t
+
+#include "jstypes.h" // JS_PUBLIC_API
+
+#include "js/RootingAPI.h" // JS::Handle
+
+struct JSContext;
+class JSString;
+
+namespace JS {
+
+class Symbol;
+
+/**
+ * Create a new Symbol with the given description. This function never returns
+ * a Symbol that is in the Runtime-wide symbol registry.
+ *
+ * If description is null, the new Symbol's [[Description]] attribute is
+ * undefined.
+ */
+extern JS_PUBLIC_API Symbol*
+NewSymbol(JSContext* cx, Handle<JSString*> description);
+
+/**
+ * Symbol.for as specified in ES6.
+ *
+ * Get a Symbol with the description 'key' from the Runtime-wide symbol registry.
+ * If there is not already a Symbol with that description in the registry, a new
+ * Symbol is created and registered. 'key' must not be null.
+ */
+extern JS_PUBLIC_API Symbol*
+GetSymbolFor(JSContext* cx, Handle<JSString*> key);
+
+/**
+ * Get the [[Description]] attribute of the given symbol.
+ *
+ * This function is infallible. If it returns null, that means the symbol's
+ * [[Description]] is undefined.
+ */
+extern JS_PUBLIC_API JSString*
+GetSymbolDescription(Handle<Symbol*> symbol);
+
+/* Well-known symbols. */
+#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(MACRO) \
+    MACRO(isConcatSpreadable) \
+    MACRO(iterator) \
+    MACRO(match) \
+    MACRO(replace) \
+    MACRO(search) \
+    MACRO(species) \
+    MACRO(hasInstance) \
+    MACRO(split) \
+    MACRO(toPrimitive) \
+    MACRO(toStringTag) \
+    MACRO(unscopables) \
+    MACRO(asyncIterator)
+
+enum class SymbolCode : uint32_t
+{
+    // There is one SymbolCode for each well-known symbol.
+#define JS_DEFINE_SYMBOL_ENUM(name) name,
+    JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM)  // SymbolCode::iterator, etc.
+#undef JS_DEFINE_SYMBOL_ENUM
+    Limit,
+    WellKnownAPILimit = 0x80000000, // matches JS::shadow::Symbol::WellKnownAPILimit for inline use
+    InSymbolRegistry = 0xfffffffe,  // created by Symbol.for() or JS::GetSymbolFor()
+    UniqueSymbol = 0xffffffff       // created by Symbol() or JS::NewSymbol()
+};
+
+/* For use in loops that iterate over the well-known symbols. */
+const size_t WellKnownSymbolLimit = size_t(SymbolCode::Limit);
+
+/**
+ * Return the SymbolCode telling what sort of symbol `symbol` is.
+ *
+ * A symbol's SymbolCode never changes once it is created.
+ */
+extern JS_PUBLIC_API SymbolCode
+GetSymbolCode(Handle<Symbol*> symbol);
+
+/**
+ * Get one of the well-known symbols defined by ES6. A single set of well-known
+ * symbols is shared by all compartments in a JSRuntime.
+ *
+ * `which` must be in the range [0, WellKnownSymbolLimit).
+ */
+extern JS_PUBLIC_API Symbol*
+GetWellKnownSymbol(JSContext* cx, SymbolCode which);
+
+/**
+ * Return true if the given JSPropertySpec::name or JSFunctionSpec::name value
+ * is actually a symbol code and not a string. See JS_SYM_FN.
+ */
+inline bool
+PropertySpecNameIsSymbol(const char* name)
+{
+    uintptr_t u = reinterpret_cast<uintptr_t>(name);
+    return u != 0 && u - 1 < WellKnownSymbolLimit;
+}
+
+} // namespace JS
+
+#endif /* js_Symbol_h */
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -476,28 +476,16 @@ union alignas(8) Value
         MOZ_ASSERT(js::gc::IsCellPointerValid(bi));
         asBits_ = bitsFromTagAndPayload(JSVAL_TAG_BIGINT, PayloadType(bi));
     }
 #endif
 
     void setObject(JSObject& obj) {
         MOZ_ASSERT(js::gc::IsCellPointerValid(&obj));
 
-        // This should not be possible and is undefined behavior, but some
-        // ObjectValue(nullptr) are sneaking in. Try to catch them here, if
-        // indeed they are going through this code. I tested gcc, and it at
-        // least will *not* elide the null check even though it would be
-        // permitted according to the spec. The temporary is necessary to
-        // prevent gcc from helpfully pointing out that this code makes no
-        // sense.
-#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
-        JSObject* testObj = &obj;
-        MOZ_DIAGNOSTIC_ASSERT(testObj != nullptr);
-#endif
-
 #if defined(JS_PUNBOX64)
         // VisualStudio cannot contain parenthesized C++ style cast and shift
         // inside decltype in template parameter:
         //   AssertionConditionType<decltype((uintptr_t(x) >> 1))>
         // It throws syntax error.
         MOZ_ASSERT((((uintptr_t)&obj) >> JSVAL_TAG_SHIFT) == 0);
 #endif
         setObjectNoCheck(&obj);
@@ -619,17 +607,17 @@ union alignas(8) Value
     bool isInt32(int32_t i32) const {
         return asBits_ == bitsFromTagAndPayload(JSVAL_TAG_INT32, uint32_t(i32));
     }
 
     bool isDouble() const {
 #if defined(JS_NUNBOX32)
         return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
 #elif defined(JS_PUNBOX64)
-        return (asBits_ | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
+        return (asBits_ | mozilla::FloatingPoint<double>::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
 #endif
     }
 
     bool isNumber() const {
 #if defined(JS_NUNBOX32)
         MOZ_ASSERT(toTag() != JSVAL_TAG_CLEAR);
         return uint32_t(toTag()) <= uint32_t(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET);
 #elif defined(JS_PUNBOX64)
@@ -1001,17 +989,17 @@ static inline bool
 IsCanonicalized(double d)
 {
   if (mozilla::IsInfinite(d) || mozilla::IsFinite(d)) {
       return true;
   }
 
   uint64_t bits;
   mozilla::BitwiseCast<uint64_t>(d, &bits);
-  return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits;
+  return (bits & ~mozilla::FloatingPoint<double>::kSignBit) == detail::CanonicalizedNaNBits;
 }
 
 static inline Value
 DoubleNaNValue()
 {
     Value v;
     v.setNaN();
     return v;
--- a/js/src/builtin/Symbol.cpp
+++ b/js/src/builtin/Symbol.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "builtin/Symbol.h"
 
+#include "js/Symbol.h"
 #include "util/StringBuffer.h"
 #include "vm/SymbolType.h"
 
 #include "vm/JSObject-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using JS::Symbol;
 using namespace js;
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -6,16 +6,17 @@
 
 #include "ctypes/Library.h"
 
 #include "prerror.h"
 #include "prlink.h"
 
 #include "ctypes/CTypes.h"
 #include "js/CharacterEncoding.h"
+#include "js/MemoryFunctions.h"
 #include "js/StableStringChars.h"
 
 using JS::AutoStableStringChars;
 
 namespace js {
 namespace ctypes {
 
 /*******************************************************************************
--- a/js/src/gc/FreeOp.h
+++ b/js/src/gc/FreeOp.h
@@ -4,20 +4,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef gc_FreeOp_h
 #define gc_FreeOp_h
 
 #include "mozilla/Assertions.h" // MOZ_ASSERT
 
-#include "jsapi.h" // JSFreeOp
-
 #include "jit/ExecutableAllocator.h" // jit::JitPoisonRangeVector
 #include "js/AllocPolicy.h" // SystemAllocPolicy
+#include "js/MemoryFunctions.h" // JSFreeOp
 #include "js/Utility.h" // AutoEnterOOMUnsafeRegion, js_free
 #include "js/Vector.h" // js::Vector
 
 struct JSRuntime;
 
 namespace js {
 
 /*
--- a/js/src/gdb/run-tests.py
+++ b/js/src/gdb/run-tests.py
@@ -127,17 +127,17 @@ class Summary(object):
                             out.write(test.name + '\n')
                 except IOError as err:
                     sys.stderr.write("Error writing worklist file '%s': %s"
                                      % (OPTIONS.worklist, err))
                     sys.exit(1)
 
             if OPTIONS.write_failures:
                 try:
-                    with open(OPTIONS.write_failures) as out:
+                    with open(OPTIONS.write_failures, "w") as out:
                         for test in self.failures:
                             test.show(out)
                 except IOError as err:
                     sys.stderr.write("Error writing worklist file '%s': %s"
                                      % (OPTIONS.write_failures, err))
                     sys.exit(1)
 
         if self.timeouts:
--- a/js/src/gdb/tests/test-GCCellPtr.cpp
+++ b/js/src/gdb/tests/test-GCCellPtr.cpp
@@ -1,12 +1,13 @@
 #include "gdb-tests.h"
 #include "jsapi.h"
 
 #include "js/HeapAPI.h"
+#include "js/Symbol.h"
 
 FRAGMENT(GCCellPtr, simple) {
   JS::GCCellPtr nulll(nullptr);
 
   JS::Rooted<JSObject*> glob(cx, JS::CurrentGlobalOrNull(cx));
   JS::Rooted<JSString*> empty(cx, JS_NewStringCopyN(cx, nullptr, 0));
   JS::Rooted<JS::Symbol*> unique(cx, JS::NewSymbol(cx, nullptr));
 
--- a/js/src/gdb/tests/test-JSSymbol.cpp
+++ b/js/src/gdb/tests/test-JSSymbol.cpp
@@ -1,11 +1,13 @@
 #include "gdb-tests.h"
 #include "jsapi.h"
 
+#include "js/Symbol.h"
+
 FRAGMENT(JSSymbol, simple) {
   using namespace JS;
 
   RootedString hello(cx, JS_NewStringCopyZ(cx, "Hello!"));
 
   Rooted<Symbol*> unique(cx, NewSymbol(cx, nullptr));
   Rooted<Symbol*> unique_with_desc(cx, NewSymbol(cx, hello));
   Rooted<Symbol*> registry(cx, GetSymbolFor(cx, hello));
--- a/js/src/gdb/tests/test-jsid.cpp
+++ b/js/src/gdb/tests/test-jsid.cpp
@@ -1,11 +1,13 @@
 #include "gdb-tests.h"
 #include "jsapi.h"
 
+#include "js/Symbol.h"
+
 FRAGMENT(jsid, simple) {
   JS::Rooted<JSString*> string(cx, JS_NewStringCopyZ(cx, "moon"));
   JS::Rooted<JSString*> interned(cx, JS_AtomizeAndPinJSString(cx, string));
   JS::Rooted<jsid> string_id(cx, INTERNED_STRING_TO_JSID(cx, interned));
   jsid int_id = INT_TO_JSID(1729);
   JS::Rooted<jsid> unique_symbol_id(
       cx, SYMBOL_TO_JSID(JS::NewSymbol(cx, interned)));
   JS::Rooted<jsid> registry_symbol_id(
--- a/js/src/gdb/tests/test-jsval.cpp
+++ b/js/src/gdb/tests/test-jsval.cpp
@@ -1,11 +1,12 @@
 #include "gdb-tests.h"
 #include "jsapi.h"
 
+#include "js/Symbol.h"
 #ifdef ENABLE_BIGINT
 #include "vm/BigIntType.h"
 #endif
 
 FRAGMENT(jsval, simple) {
   using namespace JS;
 
   RootedValue fortytwo(cx, Int32Value(42));
--- a/js/src/jsapi-tests/testArrayBuffer.cpp
+++ b/js/src/jsapi-tests/testArrayBuffer.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  */
 
 #include "jsfriendapi.h"
+#include "js/MemoryFunctions.h"
 
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testArrayBuffer_bug720949_steal)
 {
     static const unsigned NUM_TEST_BUFFERS  = 2;
     static const unsigned MAGIC_VALUE_1 = 3;
     static const unsigned MAGIC_VALUE_2 = 17;
--- a/js/src/jsapi-tests/testInformalValueTypeName.cpp
+++ b/js/src/jsapi-tests/testInformalValueTypeName.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "js/Symbol.h"
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testInformalValueTypeName)
 {
     JS::RootedValue v1(cx, JS::ObjectOrNullValue(JS_NewPlainObject(cx)));
     CHECK(strcmp(JS::InformalValueTypeName(v1), "Object") == 0);
 
     JS::RootedValue v2(cx, JS::ObjectOrNullValue(JS_NewArrayObject(cx, 0)));
--- a/js/src/jsapi-tests/testParseJSON.cpp
+++ b/js/src/jsapi-tests/testParseJSON.cpp
@@ -6,16 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <limits>
 #include <string.h>
 
 #include "builtin/String.h"
 
 #include "js/JSON.h"
+#include "js/MemoryFunctions.h"
 #include "js/Printf.h"
 #include "jsapi-tests/tests.h"
 
 using namespace js;
 
 class AutoInflatedString {
     JSContext * const cx;
     char16_t* chars_;
--- a/js/src/jsapi-tests/testSourcePolicy.cpp
+++ b/js/src/jsapi-tests/testSourcePolicy.cpp
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "js/CompilationAndEvaluation.h"
+#include "js/MemoryFunctions.h"
 #include "jsapi-tests/tests.h"
 #include "vm/JSScript.h"
 
 BEGIN_TEST(testBug795104)
 {
     JS::RealmBehaviorsRef(cx->realm()).setDiscardSource(true);
 
     const size_t strLen = 60002;
--- a/js/src/jsapi-tests/testSymbol.cpp
+++ b/js/src/jsapi-tests/testSymbol.cpp
@@ -1,12 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "js/Symbol.h"
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testSymbol_New)
 {
     using namespace JS;
 
     RootedString desc(cx, nullptr);
     RootedSymbol sym1(cx);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -55,21 +55,23 @@
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/CompileOptions.h"
 #include "js/Conversions.h"
 #include "js/Date.h"
 #include "js/Initialization.h"
 #include "js/JSON.h"
 #include "js/LocaleSensitive.h"
+#include "js/MemoryFunctions.h"
 #include "js/Proxy.h"
 #include "js/SliceBudget.h"
 #include "js/SourceText.h"
 #include "js/StableStringChars.h"
 #include "js/StructuredClone.h"
+#include "js/Symbol.h"
 #include "js/Utility.h"
 #include "js/Wrapper.h"
 #include "util/CompleteFile.h"
 #include "util/StringBuffer.h"
 #include "util/Text.h"
 #include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
 #include "vm/DateObject.h"
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -29,31 +29,32 @@
 #include "js/CallArgs.h"
 #include "js/CharacterEncoding.h"
 #include "js/Class.h"
 #include "js/CompileOptions.h"
 #include "js/ErrorReport.h"
 #include "js/GCVector.h"
 #include "js/HashTable.h"
 #include "js/Id.h"
-#include "js/MemoryFunctions.h"
 #include "js/OffThreadScriptCompilation.h"
 #include "js/Principals.h"
 #include "js/Realm.h"
 #include "js/RefCounted.h"
 #include "js/RootingAPI.h"
 #include "js/TracingAPI.h"
 #include "js/Transcoding.h"
 #include "js/UniquePtr.h"
 #include "js/Utility.h"
 #include "js/Value.h"
 #include "js/Vector.h"
 
 /************************************************************************/
 
+struct JSFreeOp;
+
 namespace JS {
 
 template<typename UnitT> class SourceText;
 
 class TwoByteChars;
 
 /** AutoValueArray roots an internal fixed-size array of Values. */
 template <size_t N>
@@ -158,32 +159,16 @@ class HandleValueArray
     HandleValue operator[](size_t i) const {
         MOZ_ASSERT(i < length_);
         return HandleValue::fromMarkedLocation(&elements_[i]);
     }
 };
 
 }  /* namespace JS */
 
-/************************************************************************/
-
-struct JSFreeOp {
-  protected:
-    JSRuntime*  runtime_;
-
-    explicit JSFreeOp(JSRuntime* rt)
-      : runtime_(rt) { }
-
-  public:
-    JSRuntime* runtime() const {
-        MOZ_ASSERT(runtime_);
-        return runtime_;
-    }
-};
-
 /* Callbacks and their arguments. */
 
 /************************************************************************/
 
 typedef bool
 (* JSInterruptCallback)(JSContext* cx);
 
 typedef JSObject*
@@ -4033,109 +4018,18 @@ JS_GetStringEncodingLength(JSContext* cx
  * encoded into bytes with no error reported. Otherwise it returns the number
  * of bytes that are necessary to encode the string. If that exceeds the
  * length parameter, the string will be cut and only length bytes will be
  * written into the buffer.
  */
 MOZ_MUST_USE JS_PUBLIC_API bool
 JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length);
 
-/************************************************************************/
-/*
- * Symbols
- */
-
 namespace JS {
 
-/**
- * Create a new Symbol with the given description. This function never returns
- * a Symbol that is in the Runtime-wide symbol registry.
- *
- * If description is null, the new Symbol's [[Description]] attribute is
- * undefined.
- */
-JS_PUBLIC_API Symbol*
-NewSymbol(JSContext* cx, HandleString description);
-
-/**
- * Symbol.for as specified in ES6.
- *
- * Get a Symbol with the description 'key' from the Runtime-wide symbol registry.
- * If there is not already a Symbol with that description in the registry, a new
- * Symbol is created and registered. 'key' must not be null.
- */
-JS_PUBLIC_API Symbol*
-GetSymbolFor(JSContext* cx, HandleString key);
-
-/**
- * Get the [[Description]] attribute of the given symbol.
- *
- * This function is infallible. If it returns null, that means the symbol's
- * [[Description]] is undefined.
- */
-JS_PUBLIC_API JSString*
-GetSymbolDescription(HandleSymbol symbol);
-
-/* Well-known symbols. */
-#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(MACRO) \
-    MACRO(isConcatSpreadable) \
-    MACRO(iterator) \
-    MACRO(match) \
-    MACRO(replace) \
-    MACRO(search) \
-    MACRO(species) \
-    MACRO(hasInstance) \
-    MACRO(split) \
-    MACRO(toPrimitive) \
-    MACRO(toStringTag) \
-    MACRO(unscopables) \
-    MACRO(asyncIterator)
-
-enum class SymbolCode : uint32_t {
-    // There is one SymbolCode for each well-known symbol.
-#define JS_DEFINE_SYMBOL_ENUM(name) name,
-    JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM)  // SymbolCode::iterator, etc.
-#undef JS_DEFINE_SYMBOL_ENUM
-    Limit,
-    WellKnownAPILimit = 0x80000000, // matches JS::shadow::Symbol::WellKnownAPILimit for inline use
-    InSymbolRegistry = 0xfffffffe,  // created by Symbol.for() or JS::GetSymbolFor()
-    UniqueSymbol = 0xffffffff       // created by Symbol() or JS::NewSymbol()
-};
-
-/* For use in loops that iterate over the well-known symbols. */
-const size_t WellKnownSymbolLimit = size_t(SymbolCode::Limit);
-
-/**
- * Return the SymbolCode telling what sort of symbol `symbol` is.
- *
- * A symbol's SymbolCode never changes once it is created.
- */
-JS_PUBLIC_API SymbolCode
-GetSymbolCode(Handle<Symbol*> symbol);
-
-/**
- * Get one of the well-known symbols defined by ES6. A single set of well-known
- * symbols is shared by all compartments in a JSRuntime.
- *
- * `which` must be in the range [0, WellKnownSymbolLimit).
- */
-JS_PUBLIC_API Symbol*
-GetWellKnownSymbol(JSContext* cx, SymbolCode which);
-
-/**
- * Return true if the given JSPropertySpec::name or JSFunctionSpec::name value
- * is actually a symbol code and not a string. See JS_SYM_FN.
- */
-inline bool
-PropertySpecNameIsSymbol(const char* name)
-{
-    uintptr_t u = reinterpret_cast<uintptr_t>(name);
-    return u != 0 && u - 1 < WellKnownSymbolLimit;
-}
-
 JS_PUBLIC_API bool
 PropertySpecNameEqualsId(const char* name, HandleId id);
 
 /**
  * Create a jsid that does not need to be marked for GC.
  *
  * 'name' is a JSPropertySpec::name or JSFunctionSpec::name value. The
  * resulting jsid, on success, is either an interned string or a well-known
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -151,16 +151,17 @@ EXPORTS.js += [
     '../public/RootingAPI.h',
     '../public/SavedFrameAPI.h',
     '../public/SliceBudget.h',
     '../public/SourceText.h',
     '../public/StableStringChars.h',
     '../public/Stream.h',
     '../public/StructuredClone.h',
     '../public/SweepingAPI.h',
+    '../public/Symbol.h',
     '../public/TraceKind.h',
     '../public/TraceLoggerAPI.h',
     '../public/TracingAPI.h',
     '../public/TrackedOptimizationInfo.h',
     '../public/Transcoding.h',
     '../public/TypeDecls.h',
     '../public/UbiNode.h',
     '../public/UbiNodeBreadthFirst.h',
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -81,16 +81,17 @@
 #include "jit/shared/CodeGenerator-shared.h"
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/CompileOptions.h"
 #include "js/Debug.h"
 #include "js/GCVector.h"
 #include "js/Initialization.h"
 #include "js/JSON.h"
+#include "js/MemoryFunctions.h"
 #include "js/Printf.h"
 #include "js/SourceText.h"
 #include "js/StableStringChars.h"
 #include "js/StructuredClone.h"
 #include "js/SweepingAPI.h"
 #include "js/Wrapper.h"
 #include "perf/jsperf.h"
 #include "shell/jsoptparse.h"
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -30,16 +30,17 @@
 
 #include "builtin/String.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/SourceNotes.h"
 #include "gc/FreeOp.h"
 #include "gc/GCInternals.h"
 #include "js/CharacterEncoding.h"
 #include "js/Printf.h"
+#include "js/Symbol.h"
 #include "util/StringBuffer.h"
 #include "util/Text.h"
 #include "vm/CodeCoverage.h"
 #include "vm/EnvironmentObject.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSObject.h"
--- a/js/src/vm/JSAtom.cpp
+++ b/js/src/vm/JSAtom.cpp
@@ -17,16 +17,17 @@
 
 #include <string.h>
 
 #include "jstypes.h"
 
 #include "builtin/String.h"
 #include "gc/Marking.h"
 #include "js/CharacterEncoding.h"
+#include "js/Symbol.h"
 #include "util/Text.h"
 #include "vm/JSContext.h"
 #include "vm/SymbolType.h"
 #include "vm/Xdr.h"
 
 #include "gc/AtomMarking-inl.h"
 #include "vm/JSContext-inl.h"
 #include "vm/JSObject-inl.h"
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -32,16 +32,17 @@
 #include "irregexp/RegExpStack.h"
 #include "js/Debug.h"
 #include "js/GCVector.h"
 #include "js/HashTable.h"
 #ifdef DEBUG
 # include "js/Proxy.h" // For AutoEnterPolicy
 #endif
 #include "js/Stream.h"
+#include "js/Symbol.h"
 #include "js/UniquePtr.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 #include "threading/Thread.h"
 #include "vm/Caches.h"
 #include "vm/CodeCoverage.h"
 #include "vm/CommonPropertyNames.h"
 #include "vm/GeckoProfiler.h"
--- a/js/src/vm/StringType.cpp
+++ b/js/src/vm/StringType.cpp
@@ -22,16 +22,17 @@
 #include "jsfriendapi.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "gc/GCInternals.h"
 #include "gc/Marking.h"
 #include "gc/Nursery.h"
 #include "js/CharacterEncoding.h"
 #include "js/StableStringChars.h"
+#include "js/Symbol.h"
 #include "js/UbiNode.h"
 #include "util/StringBuffer.h"
 #include "vm/GeckoProfiler.h"
 
 #include "vm/GeckoProfiler-inl.h"
 #include "vm/JSContext-inl.h"
 #include "vm/JSObject-inl.h"
 #include "vm/Realm-inl.h"
--- a/js/src/vm/SymbolType.h
+++ b/js/src/vm/SymbolType.h
@@ -14,16 +14,17 @@
 #include "jsapi.h"
 
 #include "gc/Barrier.h"
 #include "gc/Tracer.h"
 #include "js/AllocPolicy.h"
 #include "js/GCHashTable.h"
 #include "js/HeapAPI.h"
 #include "js/RootingAPI.h"
+#include "js/Symbol.h"
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 #include "vm/Printer.h"
 #include "vm/StringType.h"
 
 namespace js {
 class AutoAccessAtomsZone;
 } // namespace js
--- a/js/src/wasm/cranelift/Cargo.toml
+++ b/js/src/wasm/cranelift/Cargo.toml
@@ -3,18 +3,18 @@ name = "baldrdash"
 version = "0.1.0"
 authors = ["The Spidermonkey and Cranelift developers"]
 
 [lib]
 crate-type = ["rlib"]
 name = "baldrdash"
 
 [dependencies]
-cranelift-codegen = "0.23.0"
-cranelift-wasm = "0.23.0"
+cranelift-codegen = "0.25.0"
+cranelift-wasm = "0.25.0"
 target-lexicon = "0.2.0"
 log = { version = "0.4.4", default-features = false, features = ["release_max_level_info"] }
 env_logger = "0.5.6"
 
 [build-dependencies]
 bindgen = {version = "0.43", default-features = false} # disable `logging` to reduce code size
 
 # Uncomment this to enable perf support in release mode.
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -18,16 +18,17 @@
 #include "nsScriptError.h"
 #include "WrapperFactory.h"
 
 #include "nsWrapperCacheInlines.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/CharacterEncoding.h"
+#include "js/MemoryFunctions.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 
 using namespace xpc;
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* An xpcom implementation of the JavaScript nsIID and nsCID objects. */
 
 #include "xpcprivate.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
+#include "js/Symbol.h"
 
 using namespace mozilla::dom;
 using namespace JS;
 
 namespace xpc {
 
 /******************************************************************************
  * # Generic IDs #
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -37,16 +37,17 @@
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 #include "nsContentUtils.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsCycleCollector.h"
 #include "jsapi.h"
+#include "js/MemoryFunctions.h"
 #include "js/MemoryMetrics.h"
 #include "js/UbiNode.h"
 #include "js/UbiNodeUtils.h"
 #include "mozilla/dom/GeneratedAtomList.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Wrapper object for reflecting native xpcom objects into JavaScript. */
 
 #include "xpcprivate.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsWrapperCacheInlines.h"
 #include "XPCLog.h"
+#include "js/MemoryFunctions.h"
 #include "js/Printf.h"
 #include "jsfriendapi.h"
 #include "AccessCheck.h"
 #include "WrapperFactory.h"
 #include "XrayWrapper.h"
 
 #include "nsContentUtils.h"
 #include "nsCycleCollectionNoteRootCallback.h"
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -8,16 +8,17 @@
 
 #include "xpcprivate.h"
 #include "xpc_make_class.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Preferences.h"
 #include "js/CharacterEncoding.h"
 #include "js/Class.h"
 #include "js/Printf.h"
+#include "js/Symbol.h"
 
 using namespace mozilla;
 using namespace JS;
 
 /***************************************************************************/
 
 // All of the exceptions thrown into JS from this file go through here.
 // That makes this a nice place to set a breakpoint.
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -7,16 +7,17 @@
 #include "FilteringWrapper.h"
 #include "AccessCheck.h"
 #include "ChromeObjectWrapper.h"
 #include "XrayWrapper.h"
 #include "nsJSUtils.h"
 #include "mozilla/ErrorResult.h"
 
 #include "jsapi.h"
+#include "js/Symbol.h"
 
 using namespace JS;
 using namespace js;
 
 namespace xpc {
 
 static JS::SymbolCode sCrossOriginWhitelistedSymbolCodes[] = {
     JS::SymbolCode::toStringTag,
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -6212,37 +6212,37 @@ nsCSSFrameConstructor::AppendFramesToPar
   if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
     // When we get here, our frame list might start with a block.  If it does
     // so, and aParentFrame is an inline, and it and all its previous
     // continuations have no siblings, then put the initial blocks from the
     // frame list into the previous block of the {ib} split.  Note that we
     // didn't want to stop at the block part of the split when figuring out
     // initial parent, because that could screw up float parenting; it's easier
     // to do this little fixup here instead.
-    if (aFrameList.NotEmpty() && !aFrameList.FirstChild()->IsInlineOutside()) {
+    if (aFrameList.NotEmpty() && aFrameList.FirstChild()->IsBlockOutside()) {
       // See whether our trailing inline is empty
       nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
       if (firstContinuation->PrincipalChildList().IsEmpty()) {
         // Our trailing inline is empty.  Collect our starting blocks from
         // aFrameList, get the right parent frame for them, and put them in.
         nsFrameList blockKids =
-          aFrameList.Split([](nsIFrame* f) { return f->IsInlineOutside();} );
+          aFrameList.Split([](nsIFrame* f) { return !f->IsBlockOutside();} );
         NS_ASSERTION(blockKids.NotEmpty(), "No blocks?");
 
         nsContainerFrame* prevBlock = GetIBSplitPrevSibling(firstContinuation);
         prevBlock = static_cast<nsContainerFrame*>(prevBlock->LastContinuation());
         NS_ASSERTION(prevBlock, "Should have previous block here");
 
         MoveChildrenTo(aParentFrame, prevBlock, blockKids);
       }
     }
 
     // We want to put some of the frames into this inline frame.
     nsFrameList inlineKids =
-      aFrameList.Split([](nsIFrame* f) { return !f->IsInlineOutside(); });
+      aFrameList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
 
     if (!inlineKids.IsEmpty()) {
       AppendFrames(aParentFrame, kPrincipalList, inlineKids);
     }
 
     if (!aFrameList.IsEmpty()) {
       nsFrameItems ibSiblings;
       CreateIBSiblings(aState, aParentFrame,
@@ -11582,17 +11582,17 @@ nsCSSFrameConstructor::ConstructInline(n
   nsFrameItems childItems;
   ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
                               /* aParentIsWrapperAnonBox = */ false,
                               childItems);
 
   nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childItems);
   if (!aItem.mIsAllInline) {
     firstBlockEnumerator.Find(
-      [](nsIFrame* aFrame) { return !aFrame->IsInlineOutside(); });
+      [](nsIFrame* aFrame) { return aFrame->IsBlockOutside(); });
   }
 
   if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) {
     // This part is easy.  We either already know we have no non-inline kids,
     // or haven't found any when constructing actual frames (the latter can
     // happen only if out-of-flows that we thought had no containing block
     // acquired one when ancestor inline frames and {ib} splits got
     // constructed).  Just put all the kids into the single inline frame and
@@ -11643,29 +11643,29 @@ nsCSSFrameConstructor::CreateIBSiblings(
                                        computedStyle);
 
   nsContainerFrame* lastNewInline =
     static_cast<nsContainerFrame*>(aInitialInline->FirstContinuation());
   do {
     // On entry to this loop aChildItems is not empty and the first frame in it
     // is block-level.
     MOZ_ASSERT(aChildItems.NotEmpty(), "Should have child items");
-    MOZ_ASSERT(!aChildItems.FirstChild()->IsInlineOutside(),
+    MOZ_ASSERT(aChildItems.FirstChild()->IsBlockOutside(),
                "Must have list starting with block");
 
     // The initial run of blocks belongs to an anonymous block that we create
     // right now. The anonymous block will be the parent of these block
     // children of the inline.
     nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
     InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
 
     // Find the first non-block child which defines the end of our block kids
     // and the start of our next inline's kids
     nsFrameList blockKids =
-      aChildItems.Split([](nsIFrame* f) { return f->IsInlineOutside(); });
+      aChildItems.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
 
     if (!StaticPrefs::layout_css_column_span_enabled() ||
         !aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
       MoveChildrenTo(aInitialInline, blockFrame, blockKids);
 
       SetFrameIsIBSplit(lastNewInline, blockFrame);
       aSiblings.AddChild(blockFrame);
     } else {
@@ -11697,17 +11697,17 @@ nsCSSFrameConstructor::CreateIBSiblings(
     InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
     inlineFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
     if (aIsAbsPosCB) {
       inlineFrame->MarkAsAbsoluteContainingBlock();
     }
 
     if (aChildItems.NotEmpty()) {
       nsFrameList inlineKids =
-        aChildItems.Split([](nsIFrame* f) { return !f->IsInlineOutside(); });
+        aChildItems.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
       MoveChildrenTo(aInitialInline, inlineFrame, inlineKids);
     }
 
     SetFrameIsIBSplit(blockFrame, inlineFrame);
     aSiblings.AddChild(inlineFrame);
     lastNewInline = inlineFrame;
   } while (aChildItems.NotEmpty());
 
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -564,17 +564,17 @@ load 893523.html
 asserts(0-3) load 898871.html # bug 479160 - mostly OSX, sometimes Windows
 asserts(0-3) load 914501.html # bug 1144852 - all platforms
 load 914891.html
 load 915475.xhtml
 load 927558.html
 load 943509-1.html
 load 944909-1.html
 load 946167-1.html
-load 947158.html
+skip-if(Android&&browserIsRemote) load 947158.html # bug 1507207
 load 949932.html
 load 963878.html
 load 964078.html
 load 970710.html
 load 973701-1.xhtml
 load 973701-2.xhtml
 load 986899.html
 load 1001233.html
--- a/layout/svg/SVGObserverUtils.cpp
+++ b/layout/svg/SVGObserverUtils.cpp
@@ -367,20 +367,16 @@ nsSVGRenderingObserverProperty::OnRender
 class SVGTextPathObserver final : public nsSVGRenderingObserverProperty
 {
 public:
   SVGTextPathObserver(URLAndReferrerInfo* aURI, nsIFrame* aFrame, bool aReferenceImage)
     : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage)
     , mValid(true)
   {}
 
-  bool ObservesReflow() override {
-    return false;
-  }
-
 protected:
   void OnRenderingChange() override;
 
 private:
   /**
    * Returns true if the target of the textPath is the frame of a 'path' element.
    */
   bool TargetIsValid() {
@@ -461,17 +457,17 @@ SVGMarkerObserver::OnRenderingChange()
     nsSVGUtils::ScheduleReflowSVG(frame);
   }
   frame->PresContext()->RestyleManager()->PostRestyleEvent(
     frame->GetContent()->AsElement(), nsRestyleHint(0),
     nsChangeHint_RepaintFrame);
 }
 
 
-class nsSVGPaintingProperty final : public nsSVGRenderingObserverProperty
+class nsSVGPaintingProperty : public nsSVGRenderingObserverProperty
 {
 public:
   nsSVGPaintingProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame, bool aReferenceImage)
     : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage)
   {}
 
 protected:
   void OnRenderingChange() override;
@@ -493,16 +489,34 @@ nsSVGPaintingProperty::OnRenderingChange
     for (nsIFrame* f = frame; f;
          f = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(f)) {
       f->InvalidateFrame();
     }
   }
 }
 
 
+class SVGMozElementObserver final : public nsSVGPaintingProperty
+{
+public:
+  SVGMozElementObserver(URLAndReferrerInfo* aURI, nsIFrame* aFrame,
+                        bool aReferenceImage)
+    : nsSVGPaintingProperty(aURI, aFrame, aReferenceImage)
+  {}
+
+  // We only return true here because GetAndObserveBackgroundImage uses us
+  // to implement observing of arbitrary elements (including HTML elements)
+  // that may require us to repaint if the referenced element is reflowed.
+  // Bug 1496065 has been filed to remove that support though.
+  bool ObservesReflow() override {
+    return true;
+  }
+};
+
+
 /**
  * In a filter chain, there can be multiple SVG reference filters.
  * e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
  *
  * This class keeps track of one SVG reference filter in a filter chain.
  * e.g. url(#svg-filter-1)
  *
  * It fires invalidations when the SVG filter element's id changes or when
@@ -1465,20 +1479,20 @@ SVGObserverUtils::GetAndObserveBackgroun
     base);
   RefPtr<URLAndReferrerInfo> url = new URLAndReferrerInfo(
     targetURI,
     aFrame->GetContent()->OwnerDoc()->GetDocumentURI(),
     aFrame->GetContent()->OwnerDoc()->GetReferrerPolicy());
 
   // XXXjwatt: this is broken - we're using the address of a new
   // URLAndReferrerInfo as the hash key every time!
-  nsSVGPaintingProperty* observer =
-    static_cast<nsSVGPaintingProperty*>(hashtable->GetWeak(url));
+  SVGMozElementObserver* observer =
+    static_cast<SVGMozElementObserver*>(hashtable->GetWeak(url));
   if (!observer) {
-    observer = new nsSVGPaintingProperty(url, aFrame, /* aWatchImage */ true);
+    observer = new SVGMozElementObserver(url, aFrame, /* aWatchImage */ true);
     hashtable->Put(url, observer);
   }
   return observer->GetAndObserveReferencedElement();
 }
 
 nsSVGPaintServerFrame *
 SVGObserverUtils::GetAndObservePaintServer(nsIFrame* aTargetFrame,
                                            nsStyleSVGPaint nsStyleSVG::* aPaint)
--- a/layout/svg/SVGObserverUtils.h
+++ b/layout/svg/SVGObserverUtils.h
@@ -140,17 +140,17 @@ public:
    * @param aOK this is only for the convenience of callers. We set *aOK to false
    * if the frame is the wrong type
    */
   nsIFrame* GetAndObserveReferencedFrame(mozilla::LayoutFrameType aFrameType,
                                          bool* aOK);
 
   Element* GetAndObserveReferencedElement();
 
-  virtual bool ObservesReflow() { return true; }
+  virtual bool ObservesReflow() { return false; }
 
 protected:
   void StartObserving();
   void StopObserving();
 
   /**
    * Called whenever the rendering of the observed element may have changed.
    *
@@ -398,16 +398,23 @@ public:
    * used as a callback to lazily get the href value, if necessary.
    */
   static nsIFrame*
   GetAndObserveTemplate(nsIFrame* aFrame, HrefToTemplateCallback aGetHref);
 
   static void
   RemoveTemplateObserver(nsIFrame* aFrame);
 
+  /**
+   * Gets an arbitrary element and starts observing it.  Used to implement
+   * '-moz-element'.
+   *
+   * Note that bug 1496065 has been filed to remove support for referencing
+   * arbitrary elements using '-moz-element'.
+   */
   static Element*
   GetAndObserveBackgroundImage(nsIFrame* aFrame,
                                const nsAtom* aHref);
 
   /**
    * A helper function to resolve filter URL.
    */
   static already_AddRefed<URLAndReferrerInfo>
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -1508,17 +1508,18 @@ TextNodeCorrespondenceRecorder::Traverse
                    "incorrect tracking of undisplayed characters in "
                    "text nodes");
       // Any trailing characters at the end of the previous nsTextNode are
       // undisplayed.
       undisplayed = mPreviousNode->TextLength() - mNodeCharIndex;
     }
     // Each whole nsTextNode we find before we get to the text node for
     // the current text frame must be undisplayed.
-    while (mNodeIterator.Current() != node) {
+    while (mNodeIterator.Current() &&
+           mNodeIterator.Current() != node) {
       undisplayed += mNodeIterator.Current()->TextLength();
       NextNode();
     }
     // If the current text frame starts at a non-zero content offset, then those
     // earlier characters are also undisplayed.
     undisplayed += frame->GetContentOffset();
     NextNode();
   }
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/1504918.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <style>textPath { display: contents; }</style>
+  <text>x<textPath><textPath><tspan>y</tspan></textPath></textPath></text>
+</svg>
\ No newline at end of file
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -213,8 +213,9 @@ load 1474982.html
 load conditional-outer-svg-nondirty-reflow-assert.xhtml
 load extref-test-1.xhtml
 load blob-merging-and-retained-display-list.html
 load empty-blob-merging.html
 load grouping-empty-bounds.html
 load 1480275.html
 load 1480224.html
 load 1502936.html
+load 1504918.svg
--- a/layout/tables/crashtests/crashtests.list
+++ b/layout/tables/crashtests/crashtests.list
@@ -136,17 +136,17 @@ load 563009-3.html
 load 573354-1.xhtml
 load 576890-1.html
 load 576890-2.html
 load 576890-3.html
 load 580481-1.xhtml
 asserts(1) load 595758-1.xhtml # Bug 714667
 load 595758-2.xhtml
 load 678447-1.html
-load 691824-1.xhtml
+skip-if(Android&&browserIsRemote) load 691824-1.xhtml # bug 1507207
 load 695430-1.html
 load 696640-1.html
 load 696640-2.html
 load 705996-1.html
 load 705996-2.html
 load 707622-1.html
 load 710098-1.html
 load 711864-1.html
--- a/layout/tools/reftest/mach_commands.py
+++ b/layout/tools/reftest/mach_commands.py
@@ -137,16 +137,20 @@ class ReftestRunner(MozbuildObject):
         args.printDeviceInfo = False
 
         from mozrunner.devices.android_device import grant_runtime_permissions, get_adb_path
         grant_runtime_permissions(self, args.app, device_serial=args.deviceSerial)
 
         if not args.adb_path:
             args.adb_path = get_adb_path(self)
 
+        if 'geckoview' not in args.app:
+            args.e10s = False
+            print("using e10s=False for non-geckoview app")
+
         # A symlink and some path manipulations are required so that test
         # manifests can be found both locally and remotely (via a url)
         # using the same relative path.
         if args.suite == "jstestbrowser":
             staged_js_dir = os.path.join(self.topobjdir, "dist", "test-stage", "jsreftest")
             tests = os.path.join(self.reftest_dir, 'jsreftest')
             if not os.path.isdir(tests):
                 os.symlink(staged_js_dir, tests)
--- a/layout/tools/reftest/reftestcommandline.py
+++ b/layout/tools/reftest/reftestcommandline.py
@@ -480,12 +480,9 @@ class RemoteArgumentsParser(ReftestArgum
 
         # httpd-path is specified by standard makefile targets and may be specified
         # on the command line to select a particular version of httpd.js. If not
         # specified, try to select the one from hostutils.zip, as required in
         # bug 882932.
         if not options.httpdPath:
             options.httpdPath = os.path.join(options.utilityPath, "components")
 
-        # Disable e10s by default on Android because we don't run Android
-        # e10s jobs anywhere yet.
-        options.e10s = False
         return options
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -171,19 +171,22 @@ class RemoteReftest(RefTest):
                            "please adjust to 1366x1050 or higher" % (
                             width, height))
 
         self._populate_logger(options)
         self.outputHandler = OutputHandler(self.log, options.utilityPath, options.symbolsPath)
         # RemoteAutomation.py's 'messageLogger' is also used by mochitest. Mimic a mochitest
         # MessageLogger object to re-use this code path.
         self.outputHandler.write = self.outputHandler.__call__
-        self.automation = RemoteAutomation(self.device, options.app, self.remoteProfile,
-                                           options.remoteLogFile, processArgs=None)
-        self.automation._processArgs['messageLogger'] = self.outputHandler
+        args = {'messageLogger': self.outputHandler}
+        self.automation = RemoteAutomation(self.device,
+                                           appName=options.app,
+                                           remoteProfile=self.remoteProfile,
+                                           remoteLog=options.remoteLogFile,
+                                           processArgs=args)
 
         self.environment = self.automation.environment
         if self.automation.IS_DEBUG_BUILD:
             self.SERVER_STARTUP_TIMEOUT = 180
         else:
             self.SERVER_STARTUP_TIMEOUT = 90
 
         self.remoteCache = os.path.join(options.remoteTestRoot, "cache/")
@@ -370,17 +373,18 @@ class RemoteReftest(RefTest):
         status, self.lastTestSeen = self.automation.runApp(None, env,
                                                            binary,
                                                            profile.profile,
                                                            cmdargs,
                                                            utilityPath=options.utilityPath,
                                                            xrePath=options.xrePath,
                                                            debuggerInfo=debuggerInfo,
                                                            symbolsPath=symbolsPath,
-                                                           timeout=timeout)
+                                                           timeout=timeout,
+                                                           e10s=options.e10s)
 
         self.cleanup(profile.profile)
         return status
 
     def cleanup(self, profileDir):
         self.device.rm(self.remoteTestRoot,  force=True, recursive=True)
         self.device.rm(self.remoteProfile, force=True, recursive=True)
         self.device.rm(self.remoteCache, force=True, recursive=True)
--- a/mfbt/FloatingPoint.h
+++ b/mfbt/FloatingPoint.h
@@ -32,43 +32,48 @@ namespace mozilla {
  * algorithms!  But with some care we've found algorithms that seem to not
  * trigger those compiler bugs.
  *
  * For the aforementioned reasons, be very wary of making changes to any of
  * these algorithms.  If you must make changes, keep a careful eye out for
  * compiler bustage, particularly PGO-specific bustage.
  */
 
-struct FloatTypeTraits
+namespace detail {
+
+/*
+ * These implementations assume float/double are 32/64-bit single/double
+ * format number types compatible with the IEEE-754 standard.  C++ doesn't
+ * require this, but we required it in implementations of these algorithms that
+ * preceded this header, so we shouldn't break anything to continue doing so.
+ */
+template<typename T>
+struct FloatingPointTrait;
+
+template<>
+struct FloatingPointTrait<float>
 {
+protected:
   using Bits = uint32_t;
 
-  static constexpr unsigned kExponentBias = 127;
-  static constexpr unsigned kExponentShift = 23;
-
-  static constexpr Bits kSignBit         = 0x80000000UL;
-  static constexpr Bits kExponentBits    = 0x7F800000UL;
-  static constexpr Bits kSignificandBits = 0x007FFFFFUL;
+  static constexpr unsigned kExponentWidth = 8;
+  static constexpr unsigned kSignificandWidth = 23;
 };
 
-struct DoubleTypeTraits
+template<>
+struct FloatingPointTrait<double>
 {
+protected:
   using Bits = uint64_t;
 
-  static constexpr unsigned kExponentBias = 1023;
-  static constexpr unsigned kExponentShift = 52;
-
-  static constexpr Bits kSignBit         = 0x8000000000000000ULL;
-  static constexpr Bits kExponentBits    = 0x7ff0000000000000ULL;
-  static constexpr Bits kSignificandBits = 0x000fffffffffffffULL;
+  static constexpr unsigned kExponentWidth = 11;
+  static constexpr unsigned kSignificandWidth = 52;
 };
 
-template<typename T> struct SelectTrait;
-template<> struct SelectTrait<float> : public FloatTypeTraits {};
-template<> struct SelectTrait<double> : public DoubleTypeTraits {};
+} // namespace detail
 
 /*
  *  This struct contains details regarding the encoding of floating-point
  *  numbers that can be useful for direct bit manipulation. As of now, the
  *  template parameter has to be float or double.
  *
  *  The nested typedef |Bits| is the unsigned integral type with the same size
  *  as T: uint32_t for float and uint64_t for double (static assertions
@@ -87,40 +92,75 @@ template<> struct SelectTrait<double> : 
  *  bits.
  *
  *  Full details of how floating point number formats are encoded are beyond
  *  the scope of this comment. For more information, see
  *  http://en.wikipedia.org/wiki/IEEE_floating_point
  *  http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
  */
 template<typename T>
-struct FloatingPoint : public SelectTrait<T>
+struct FloatingPoint final : private detail::FloatingPointTrait<T>
 {
-  using Base = SelectTrait<T>;
+private:
+  using Base = detail::FloatingPointTrait<T>;
+
+public:
+  /**
+   * An unsigned integral type suitable for accessing the bitwise representation
+   * of T.
+   */
   using Bits = typename Base::Bits;
 
-  static_assert((Base::kSignBit & Base::kExponentBits) == 0,
+  static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
+
+  /** The bit-width of the exponent component of T. */
+  using Base::kExponentWidth;
+
+  /** The bit-width of the significand component of T. */
+  using Base::kSignificandWidth;
+
+  static_assert(1 + kExponentWidth + kSignificandWidth ==
+                CHAR_BIT * sizeof(T),
+                "sign bit plus bit widths should sum to overall bit width");
+
+  /**
+   * The exponent field in an IEEE-754 floating point number consists of bits
+   * encoding an unsigned number.  The *actual* represented exponent (for all
+   * values finite and not denormal) is that value, minus a bias |kExponentBias|
+   * so that a useful range of numbers is represented.
+   */
+  static constexpr unsigned kExponentBias = (1U << (kExponentWidth - 1)) - 1;
+
+  /**
+   * The amount by which the bits of the exponent-field in an IEEE-754 floating
+   * point number are shifted from the LSB of the floating point type.
+   */
+  static constexpr unsigned kExponentShift = kSignificandWidth;
+
+  /** The sign bit in the floating point representation. */
+  static constexpr Bits kSignBit =
+    static_cast<Bits>(1) << (CHAR_BIT * sizeof(Bits) - 1);
+
+  /** The exponent bits in the floating point representation. */
+  static constexpr Bits kExponentBits =
+    ((static_cast<Bits>(1) << kExponentWidth) - 1) << kSignificandWidth;
+
+  /** The significand bits in the floating point representation. */
+  static constexpr Bits kSignificandBits =
+    (static_cast<Bits>(1) << kSignificandWidth) - 1;
+
+  static_assert((kSignBit & kExponentBits) == 0,
                 "sign bit shouldn't overlap exponent bits");
-  static_assert((Base::kSignBit & Base::kSignificandBits) == 0,
+  static_assert((kSignBit & kSignificandBits) == 0,
                 "sign bit shouldn't overlap significand bits");
-  static_assert((Base::kExponentBits & Base::kSignificandBits) == 0,
+  static_assert((kExponentBits & kSignificandBits) == 0,
                 "exponent bits shouldn't overlap significand bits");
 
-  static_assert((Base::kSignBit | Base::kExponentBits | Base::kSignificandBits) ==
-                ~Bits(0),
+  static_assert((kSignBit | kExponentBits | kSignificandBits) == ~Bits(0),
                 "all bits accounted for");
-
-  /*
-   * These implementations assume float/double are 32/64-bit single/double
-   * format number types compatible with the IEEE-754 standard.  C++ don't
-   * require this to be the case.  But we required this in implementations of
-   * these algorithms that preceded this header, so we shouldn't break anything
-   * if we keep doing so.
-   */
-  static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
 };
 
 /** Determines whether a float/double is NaN. */
 template<typename T>
 static MOZ_ALWAYS_INLINE bool
 IsNaN(T aValue)
 {
   /*
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -611,19 +611,16 @@ public class BrowserApp extends GeckoApp
         }
         return super.onKeyUp(keyCode, event);
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         final Context appContext = getApplicationContext();
 
-        final Intent killerIntent = new Intent(this, FennecKiller.class);
-        startService(killerIntent);
-
         showSplashScreen = true;
 
         safeStartingIntent = new SafeIntent(getIntent());
         isInAutomation = IntentUtils.getIsInAutomationFromEnvironment(safeStartingIntent);
 
         GeckoProfile.setIntentArgs(safeStartingIntent.getStringExtra("args"));
 
         if (!isInAutomation && AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
@@ -1021,16 +1018,19 @@ public class BrowserApp extends GeckoApp
     @Override
     public void onResume() {
         super.onResume();
 
         if (mIsAbortingAppLaunch) {
             return;
         }
 
+        final Intent killerIntent = new Intent(this, FennecKiller.class);
+        startService(killerIntent);
+
         if (!mHasResumed) {
             getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop");
             mHasResumed = true;
         }
 
         processTabQueue();
 
         for (BrowserAppDelegate delegate : delegates) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -987,17 +987,16 @@ pref("accessibility.tabfocus_applies_to_
 // "gtk-primary-button-warps-slider" property with GTK (since 2.24 / 3.6),
 // unless this preference is explicitly set.
 #if !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GTK)
 pref("ui.scrollToClick", 0);
 #endif
 
 // provide ability to turn on support for canvas focus rings
 pref("canvas.focusring.enabled", true);
-pref("canvas.customfocusring.enabled", false);
 pref("canvas.hitregions.enabled", false);
 pref("canvas.filters.enabled", true);
 // Add support for canvas path objects
 pref("canvas.path.enabled", true);
 pref("canvas.capturestream.enabled", true);
 
 // We want the ability to forcibly disable platform a11y, because
 // some non-a11y-related components attempt to bring it up.  See bug
--- a/netwerk/test/crashtests/crashtests.list
+++ b/netwerk/test/crashtests/crashtests.list
@@ -1,6 +1,6 @@
-load 675518.html
+skip-if(Android&&browserIsRemote) load 675518.html
 load 785753-1.html
 load 785753-2.html
 load 1274044-1.html
 skip-if(Android) pref(privacy.firstparty.isolate,true) load 1334468-1.html
 load 1399467-1.html
--- a/python/mozbuild/mozbuild/backend/test_manifest.py
+++ b/python/mozbuild/mozbuild/backend/test_manifest.py
@@ -73,16 +73,17 @@ class TestManifestBackend(PartialBackend
         t['flavor'] = flavor
 
         path = mozpath.normpath(t['path'])
         assert mozpath.basedir(path, [topsrcdir])
 
         key = path[len(topsrcdir)+1:]
         t['file_relpath'] = key
         t['dir_relpath'] = mozpath.dirname(key)
+        t['srcdir_relpath'] = key
 
         self.tests_by_path[key].append(t)
 
     def add_defaults(self, manifest):
         if not hasattr(manifest, 'manifest_defaults'):
             return
         for sub_manifest, defaults in manifest.manifest_defaults.items():
             self.manifest_defaults[sub_manifest] = defaults
--- a/taskcluster/taskgraph/actions/backfill.py
+++ b/taskcluster/taskgraph/actions/backfill.py
@@ -1,16 +1,17 @@
 # -*- coding: utf-8 -*-
 
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
+import json
 import logging
 
 import requests
 from requests.exceptions import HTTPError
 
 from .registry import register_callback_action
 from .util import find_decision_task, create_tasks, combine_task_graph_files
 from taskgraph.util.taskcluster import get_artifact_from_index
@@ -135,17 +136,20 @@ def backfill_action(parameters, graph_co
                                    '--this-chunk=1']
                     if is_android:
                         # no --e10s; todo, what about future geckoView?
                         verify_args.remove('--e10s')
 
                     if gpu_required:
                         verify_args.append('--gpu-required')
 
-                    task.task['payload']['env']['MOZHARNESS_TEST_PATHS'] = input.get('testPath')
+                    if 'testPath' in input:
+                        task.task['payload']['env']['MOZHARNESS_TEST_PATHS'] = json.dums({
+                            task.task['extra']['suite']['flavor']: input['testPath']
+                        })
 
                     cmd_parts = task.task['payload']['command']
                     keep_args = ['--installer-url', '--download-symbols', '--test-packages-url']
                     cmd_parts = remove_args_from_command(cmd_parts, preamble_length, keep_args)
                     cmd_parts = add_args_to_command(cmd_parts, verify_args)
                     task.task['payload']['command'] = cmd_parts
 
                     # morph the task label to a test-verify job
--- a/taskcluster/taskgraph/transforms/tests.py
+++ b/taskcluster/taskgraph/transforms/tests.py
@@ -200,17 +200,17 @@ test_description_schema = Schema({
     # Whether to run this task with the serviceworker e10s redesign enabled
     # (desktop-test only).  If 'both', run one task with and one task without.
     # Tasks with this enabled have have "-sw" appended to the test name and
     # treeherder group.
     Optional('serviceworker-e10s'): optionally_keyed_by(
         'test-platform', 'project',
         Any(bool, 'both')),
 
-    # Whether to run this task with e10s (desktop-test only).  If false, run
+    # Whether to run this task with e10s.  If false, run
     # without e10s; if true, run with e10s; if 'both', run one task with and
     # one task without e10s.  E10s tasks have "-e10s" appended to the test name
     # and treeherder group.
     Required('e10s'): optionally_keyed_by(
         'test-platform', 'project',
         Any(bool, 'both')),
 
     # Whether the task should run with WebRender enabled or not.
@@ -424,17 +424,17 @@ def handle_keyed_by_mozharness(config, t
 @transforms.add
 def set_defaults(config, tests):
     for test in tests:
         build_platform = test['build-platform']
         if build_platform.startswith('android'):
             # all Android test tasks download internal objects from tooltool
             test['mozharness']['tooltool-downloads'] = True
             test['mozharness']['actions'] = ['get-secrets']
-            # Android doesn't do e10s
+            # Fennec is non-e10s; geckoview handled in set_target
             test['e10s'] = False
             # loopback-video is always true for Android, but false for other
             # platform phyla
             test['loopback-video'] = True
         else:
             # all non-android tests want to run the bits that require node
             test['mozharness']['set-moz-node-path'] = True
             test.setdefault('e10s', True)
@@ -546,16 +546,18 @@ def handle_artifact_prefix(config, tests
 @transforms.add
 def set_target(config, tests):
     for test in tests:
         build_platform = test['build-platform']
         target = None
         if 'target' in test:
             resolve_keyed_by(test, 'target', item_name=test['test-name'])
             target = test['target']
+            if target and 'geckoview' in target:
+                test['e10s'] = True
         if not target:
             if build_platform.startswith('macosx'):
                 target = 'target.dmg'
             elif build_platform.startswith('android'):
                 target = 'target.apk'
             elif build_platform.startswith('win'):
                 target = 'target.zip'
             else:
--- a/taskcluster/taskgraph/util/perfile.py
+++ b/taskcluster/taskgraph/util/perfile.py
@@ -1,14 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
+import itertools
+import json
 import logging
 import math
 
 from mozbuild.util import memoize
 from mozpack.path import match as mozpackmatch
 from taskgraph import files_changed
 import taskgraph
 from .. import GECKO
@@ -42,27 +44,27 @@ def perfile_number_of_chunks(is_try, try
                          'js/src/tests/test/**',
                          'js/src/tests/non262/**',
                          'js/src/tests/test262/**']
     else:
         # Returning 0 means no tests to run, this captures non test-verify tasks
         return 1
 
     changed_files = set()
-    specified_files = []
     if try_task_config:
-        specified_files = try_task_config.split(":")
+        suite_to_paths = json.loads(try_task_config)
+        specified_files = itertools.chain.from_iterable(suite_to_paths.values())
+        changed_files.update(specified_files)
 
     if is_try:
         changed_files.update(files_changed.get_locally_changed_files(GECKO))
     else:
         changed_files.update(files_changed.get_changed_files(head_repository,
                                                              head_rev))
 
-    changed_files.update(specified_files)
     test_count = 0
     for pattern in file_patterns:
         for path in changed_files:
             # TODO: consider running tests if a manifest changes
             if path.endswith('.list') or path.endswith('.ini'):
                 continue
             if path.endswith('^headers^'):
                 continue
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py
@@ -117,18 +117,20 @@ class ScreenCaptureTestCase(MarionetteTe
                 int(rect[1] * self.device_pixel_ratio))
 
 
 class TestScreenCaptureChrome(WindowManagerMixin, ScreenCaptureTestCase):
 
     def setUp(self):
         super(TestScreenCaptureChrome, self).setUp()
         self.marionette.set_context("chrome")
+        self.marionette.set_pref("marionette.log.truncate", False)
 
     def tearDown(self):
+        self.marionette.clear_pref("marionette.log.truncate")
         self.close_all_windows()
         super(TestScreenCaptureChrome, self).tearDown()
 
     @property
     def window_dimensions(self):
         return tuple(self.marionette.execute_script("""
             let el = document.documentElement;
             let rect = el.getBoundingClientRect();
--- a/testing/mochitest/mach_commands.py
+++ b/testing/mochitest/mach_commands.py
@@ -172,16 +172,21 @@ class MochitestRunner(MozbuildObject):
         options = Namespace(**kwargs)
 
         from manifestparser import TestManifest
         if tests and not options.manifestFile:
             manifest = TestManifest()
             manifest.tests.extend(tests)
             options.manifestFile = manifest
 
+        # Firefox for Android doesn't use e10s
+        if options.app is None or 'geckoview' not in options.app:
+            options.e10s = False
+            print("using e10s=False for non-geckoview app")
+
         return runtestsremote.run_test_harness(parser, options)
 
     def run_geckoview_junit_test(self, context, **kwargs):
         host_ret = verify_host_bin()
         if host_ret != 0:
             return host_ret
 
         import runjunit
@@ -203,16 +208,20 @@ class MochitestRunner(MozbuildObject):
         options = Namespace(**kwargs)
 
         from manifestparser import TestManifest
         if tests and not options.manifestFile:
             manifest = TestManifest()
             manifest.tests.extend(tests)
             options.manifestFile = manifest
 
+        # robocop only used for Firefox for Android - non-e10s
+        options.e10s = False
+        print("using e10s=False for robocop")
+
         return runrobocop.run_test_harness(parser, options)
 
 # parser
 
 
 def setup_argument_parser():
     build_obj = MozbuildObject.from_environment(cwd=here)
 
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -992,21 +992,16 @@ class AndroidArguments(ArgumentContainer
                 parser.error(
                     "--coverage-output-dir must be specified when using --enable-coverage")
             parent_dir = os.path.dirname(options.coverage_output_dir)
             if not os.path.isdir(options.coverage_output_dir):
                 parser.error(
                     "The directory for the coverage output does not exist: %s" %
                     parent_dir)
 
-        # Disable e10s by default on Android because we don't run Android
-        # e10s jobs anywhere yet.
-        options.e10s = False
-        mozinfo.update({'e10s': options.e10s})
-
         # allow us to keep original application around for cleanup while
         # running robocop via 'am'
         options.remoteappname = options.app
         return options
 
 
 container_map = {
     'generic': [MochitestArguments],
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -2072,17 +2072,18 @@ toolbar#nav-bar {
                valgrindPath=None,
                valgrindArgs=None,
                valgrindSuppFiles=None,
                symbolsPath=None,
                timeout=-1,
                detectShutdownLeaks=False,
                screenshotOnFail=False,
                bisectChunk=None,
-               marionette_args=None):
+               marionette_args=None,
+               e10s=True):
         """
         Run the app, log the duration it took to execute, return the status code.
         Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing
         for |timeout| seconds.
         """
         # It can't be the case that both a with-debugger and an
         # on-Valgrind run have been requested.  doTests() should have
         # already excluded this possibility.
@@ -2774,16 +2775,17 @@ toolbar#nav-bar {
                     valgrindArgs=valgrindArgs,
                     valgrindSuppFiles=valgrindSuppFiles,
                     symbolsPath=options.symbolsPath,
                     timeout=timeout,
                     detectShutdownLeaks=detectShutdownLeaks,
                     screenshotOnFail=options.screenshotOnFail,
                     bisectChunk=options.bisectChunk,
                     marionette_args=marionette_args,
+                    e10s=options.e10s
                 )
                 status = ret or status
         except KeyboardInterrupt:
             self.log.info("runtests.py | Received keyboard interrupt.\n")
             status = -1
         except Exception as e:
             traceback.print_exc()
             self.log.error(
--- a/testing/mozbase/mozdevice/mozdevice/adb.py
+++ b/testing/mozbase/mozdevice/mozdevice/adb.py
@@ -1433,17 +1433,25 @@ class ADBDevice(ADBCommand):
 
     def get_logcat(self,
                    filter_specs=[
                        "dalvikvm:I",
                        "ConnectivityService:S",
                        "WifiMonitor:S",
                        "WifiStateTracker:S",
                        "wpa_supplicant:S",
-                       "NetworkStateTracker:S"],
+                       "NetworkStateTracker:S",
+                       "EmulatedCamera_Camera:S",
+                       "EmulatedCamera_Device:S",
+                       "EmulatedCamera_FakeCamera:S",
+                       "EmulatedCamera_FakeDevice:S",
+                       "EmulatedCamera_CallbackNotifier:S",
+                       "GnssLocationProvider:S",
+                       "Hyphenator:S",
+                       "BatteryStats:S"],
                    format="time",
                    filter_out_regexps=[],
                    timeout=None,
                    buffers=[]):
         """Returns the contents of the logcat file as a list of strings.
 
         :param list filter_specs: Optional logcat messages to
             be included.
--- a/testing/mozbase/moztest/moztest/resolve.py
+++ b/testing/mozbase/moztest/moztest/resolve.py
@@ -482,16 +482,17 @@ class TestMetadata(object):
                         "here": os.path.dirname(path),
                         "manifest": data["manifest_path"],
                         "name": test.id,
                         "file_relpath": path,
                         "head": "",
                         "support-files": "",
                         "subsuite": test_type,
                         "dir_relpath": os.path.dirname(src_path),
+                        "srcdir_relpath": src_path,
                         })
 
         self._wpt_loaded = True
 
 
 class TestResolver(MozbuildObject):
     """Helper to resolve tests from the current environment to test files."""
 
--- a/testing/mozharness/mozharness/mozilla/testing/android.py
+++ b/testing/mozharness/mozharness/mozilla/testing/android.py
@@ -323,19 +323,25 @@ class AndroidMixin(object):
         try:
             self.device.install_app(apk)
         except mozdevice.ADBError:
             self.fatal('INFRA-ERROR: Failed to install %s on %s' %
                        (self.installer_path, self.device_name),
                        EXIT_STATUS_DICT[TBPL_RETRY])
 
     def is_boot_completed(self):
-        out = self.device.get_prop('sys.boot_completed', timeout=30)
-        if out.strip() == '1':
-            return True
+        import mozdevice
+        try:
+            out = self.device.get_prop('sys.boot_completed', timeout=30)
+            if out.strip() == '1':
+                return True
+        except ValueError:
+            pass
+        except mozdevice.ADBError:
+            pass
         return False
 
     def shell_output(self, cmd):
         return self.device.shell_output(cmd, timeout=30)
 
     def device_screenshot(self, prefix):
         """
            On emulator, save a screenshot of the entire screen to the upload directory;
--- a/testing/mozharness/mozharness/mozilla/testing/per_test_base.py
+++ b/testing/mozharness/mozharness/mozilla/testing/per_test_base.py
@@ -1,15 +1,17 @@
 #!/usr/bin/env python
 # ***** BEGIN LICENSE BLOCK *****
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 
+import itertools
+import json
 import math
 import os
 import posixpath
 import re
 import sys
 import mozinfo
 from manifestparser import TestManifest
 
@@ -233,17 +235,18 @@ class SingleTestMixin(FetchesMixin):
         mozinfo.update({"headless": headless})
         # FIXME(emilio): Need to update test expectations.
         mozinfo.update({'stylo': True})
         mozinfo.update({'verify': True})
         self.info("Per-test run using mozinfo: %s" % str(mozinfo.info))
 
         changed_files = set()
         if os.environ.get('MOZHARNESS_TEST_PATHS', None) is not None:
-            changed_files |= set(os.environ['MOZHARNESS_TEST_PATHS'].split(':'))
+            suite_to_paths = json.loads(os.environ['MOZHARNESS_TEST_PATHS'])
+            changed_files |= itertools.chain.from_iterable(suite_to_paths.values())
             self.info("Per-test run found explicit request in MOZHARNESS_TEST_PATHS:")
             self.info(str(changed_files))
         else:
             # determine which files were changed on this push
             url = '%s/json-automationrelevance/%s' % (repository.rstrip('/'), revision)
             contents = self.retry(get_automationrelevance, attempts=2, sleeptime=10)
             for c in contents['changesets']:
                 self.info(" {cset} {desc}".format(
--- a/testing/mozharness/scripts/android_emulator_unittest.py
+++ b/testing/mozharness/scripts/android_emulator_unittest.py
@@ -2,16 +2,17 @@
 # ***** BEGIN LICENSE BLOCK *****
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 
 import copy
 import datetime
+import json
 import os
 import re
 import sys
 import subprocess
 
 # load modules from parent dir
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
@@ -20,16 +21,19 @@ from mozharness.base.script import BaseS
 from mozharness.mozilla.mozbase import MozbaseMixin
 from mozharness.mozilla.testing.android import AndroidMixin
 from mozharness.mozilla.testing.testbase import TestingMixin, testing_config_options
 from mozharness.mozilla.testing.codecoverage import (
     CodeCoverageMixin,
     code_coverage_config_options
 )
 
+SUITE_DEFAULT_E10S = ['geckoview-junit', 'mochitest', 'reftest']
+SUITE_NO_E10S = ['cppunittest', 'geckoview-junit', 'xpcshell']
+
 
 class AndroidEmulatorTest(TestingMixin, BaseScript, MozbaseMixin, CodeCoverageMixin,
                           AndroidMixin):
     """
        A mozharness script for Android functional tests (like mochitests and reftests)
        run on an Android emulator. This script starts and manages an Android emulator
        for the duration of the required tests. This is like desktop_unittest.py, but
        for Android emulator test platforms.
@@ -70,16 +74,23 @@ class AndroidEmulatorTest(TestingMixin, 
          }
     ], [
         ["--log-tbpl-level"],
         {"action": "store",
          "dest": "log_tbpl_level",
          "default": "info",
          "help": "Set log level (debug|info|warning|error|critical|fatal)",
          }
+    ], [
+        ['--e10s', ],
+        {"action": "store_true",
+         "dest": "e10s",
+         "default": False,
+         "help": "Run tests with multiple processes.",
+         }
     ]] + copy.deepcopy(testing_config_options) + \
         copy.deepcopy(code_coverage_config_options)
 
     def __init__(self, require_config_file=False):
         super(AndroidEmulatorTest, self).__init__(
             config_options=self.config_options,
             all_actions=['clobber',
                          'setup-avds',
@@ -116,16 +127,17 @@ class AndroidEmulatorTest(TestingMixin, 
             if m:
                 self.test_suite = m.group(1)
                 if self.this_chunk is None:
                     self.this_chunk = m.group(2)
         self.xre_path = None
         self.device_serial = 'emulator-5554'
         self.log_raw_level = c.get('log_raw_level')
         self.log_tbpl_level = c.get('log_tbpl_level')
+        self.e10s = c.get('e10s')
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
         abs_dirs = super(AndroidEmulatorTest, self).query_abs_dirs()
         dirs = {}
         dirs['abs_test_install_dir'] = os.path.join(
             abs_dirs['abs_work_dir'], 'tests')
@@ -209,35 +221,49 @@ class AndroidEmulatorTest(TestingMixin, 
             'marionette_extra': c.get('marionette_extra', ''),
             'xpcshell_extra': c.get('xpcshell_extra', ''),
             'test_manifest': os.path.join(
                 dirs['abs_marionette_tests_dir'],
                 self.config.get('marionette_test_manifest', '')
             ),
         }
 
-        user_paths = os.environ.get('MOZHARNESS_TEST_PATHS')
+        user_paths = json.loads(os.environ.get('MOZHARNESS_TEST_PATHS', '""'))
+
         for option in self.config["suite_definitions"][self.test_suite]["options"]:
             opt = option.split('=')[0]
             # override configured chunk options with script args, if specified
             if opt in ('--this-chunk', '--total-chunks'):
                 if user_paths or getattr(self, opt.replace('-', '_').strip('_'), None) is not None:
                     continue
 
             if '%(app)' in option:
                 # only query package name if requested
                 cmd.extend([option % {'app': self.query_package_name()}])
             else:
                 option = option % str_format_values
                 if option:
                     cmd.extend([option])
 
+        if 'mochitest' in self.test_suite:
+            category = 'mochitest'
+        elif 'reftest' in self.test_suite or 'crashtest' in self.test_suite:
+            category = 'reftest'
+        else:
+            category = self.test_suite
+        if category not in SUITE_NO_E10S:
+            if category in SUITE_DEFAULT_E10S and not self.e10s:
+                cmd.extend(['--disable-e10s'])
+            elif category not in SUITE_DEFAULT_E10S and self.e10s:
+                cmd.extend(['--e10s'])
+
         if not (self.verify_enabled or self.per_test_coverage):
             if user_paths:
-                cmd.extend(user_paths.split(':'))
+                if self.test_suite in user_paths:
+                    cmd.extend(user_paths[self.test_suite])
             elif not (self.verify_enabled or self.per_test_coverage):
                 if self.this_chunk is not None:
                     cmd.extend(['--this-chunk', self.this_chunk])
                 if self.total_chunks is not None:
                     cmd.extend(['--total-chunks', self.total_chunks])
 
         try_options, try_tests = self.try_args(self.test_suite)
         cmd.extend(try_options)
--- a/testing/mozharness/scripts/android_hardware_unittest.py
+++ b/testing/mozharness/scripts/android_hardware_unittest.py
@@ -2,31 +2,35 @@
 # ***** BEGIN LICENSE BLOCK *****
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 
 import copy
 import datetime
+import json
 import os
 import re
 import sys
 import subprocess
 
 # load modules from parent dir
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
 from mozharness.base.log import FATAL
 from mozharness.base.script import BaseScript, PreScriptAction
 from mozharness.mozilla.mozbase import MozbaseMixin
 from mozharness.mozilla.testing.android import AndroidMixin
 from mozharness.mozilla.testing.testbase import TestingMixin, testing_config_options
 from mozharness.mozilla.testing.codecoverage import CodeCoverageMixin
 
+SUITE_DEFAULT_E10S = ['geckoview-junit', 'mochitest', 'reftest']
+SUITE_NO_E10S = ['cppunittest', 'xpcshell']
+
 
 class AndroidHardwareTest(TestingMixin, BaseScript, MozbaseMixin,
                           CodeCoverageMixin, AndroidMixin):
     config_options = [[
         ["--test-suite"],
         {"action": "store",
          "dest": "test_suite",
          "default": None
@@ -61,16 +65,23 @@ class AndroidHardwareTest(TestingMixin, 
          }
     ], [
         ["--log-tbpl-level"],
         {"action": "store",
          "dest": "log_tbpl_level",
          "default": "info",
          "help": "Set log level (debug|info|warning|error|critical|fatal)",
          }
+    ], [
+        ['--e10s', ],
+        {"action": "store_true",
+         "dest": "e10s",
+         "default": False,
+         "help": "Run tests with multiple processes.",
+         }
     ]] + copy.deepcopy(testing_config_options)
 
     def __init__(self, require_config_file=False):
         super(AndroidHardwareTest, self).__init__(
             config_options=self.config_options,
             all_actions=['clobber',
                          'download-and-extract',
                          'create-virtualenv',
@@ -105,16 +116,17 @@ class AndroidHardwareTest(TestingMixin, 
             m = re.match("(.*)-(\d*)", self.test_suite)
             if m:
                 self.test_suite = m.group(1)
                 if self.this_chunk is None:
                     self.this_chunk = m.group(2)
         self.xre_path = None
         self.log_raw_level = c.get('log_raw_level')
         self.log_tbpl_level = c.get('log_tbpl_level')
+        self.e10s = c.get('e10s')
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
         abs_dirs = super(AndroidHardwareTest, self).query_abs_dirs()
         dirs = {}
         dirs['abs_test_install_dir'] = os.path.join(
             abs_dirs['abs_work_dir'], 'tests')
@@ -196,40 +208,54 @@ class AndroidHardwareTest(TestingMixin, 
             'marionette_extra': c.get('marionette_extra', ''),
             'xpcshell_extra': c.get('xpcshell_extra', ''),
             'test_manifest': os.path.join(
                 dirs['abs_marionette_tests_dir'],
                 self.config.get('marionette_test_manifest', '')
             ),
         }
 
-        user_paths = os.environ.get('MOZHARNESS_TEST_PATHS')
+        user_paths = json.loads(os.environ.get('MOZHARNESS_TEST_PATHS', '""'))
+
         for option in self.config["suite_definitions"][self.test_suite]["options"]:
             opt = option.split('=')[0]
             # override configured chunk options with script args, if specified
             if opt in ('--this-chunk', '--total-chunks'):
                 if user_paths or getattr(self, opt.replace('-', '_').strip('_'), None) is not None:
                     continue
 
             if '%(app)' in option:
                 # only query package name if requested
                 cmd.extend([option % {'app': self.query_package_name()}])
             else:
                 option = option % str_format_values
                 if option:
                     cmd.extend([option])
 
         if user_paths:
-            cmd.extend(user_paths.split(':'))
+            if self.test_suite in user_paths:
+                cmd.extend(user_paths[self.test_suite])
         elif not self.verify_enabled:
             if self.this_chunk is not None:
                 cmd.extend(['--this-chunk', self.this_chunk])
             if self.total_chunks is not None:
                 cmd.extend(['--total-chunks', self.total_chunks])
 
+        if 'mochitest' in self.test_suite:
+            category = 'mochitest'
+        elif 'reftest' in self.test_suite or 'crashtest' in self.test_suite:
+            category = 'reftest'
+        else:
+            category = self.test_suite
+        if category not in SUITE_NO_E10S:
+            if category in SUITE_DEFAULT_E10S and not self.e10s:
+                cmd.extend(['--disable-e10s'])
+            elif category not in SUITE_DEFAULT_E10S and self.e10s:
+                cmd.extend(['--e10s'])
+
         try_options, try_tests = self.try_args(self.test_suite)
         cmd.extend(try_options)
         if not self.verify_enabled and not self.per_test_coverage:
             cmd.extend(self.query_tests_args(
                 self.config["suite_definitions"][self.test_suite].get("tests"),
                 None,
                 try_tests))
 
--- a/testing/mozharness/scripts/desktop_unittest.py
+++ b/testing/mozharness/scripts/desktop_unittest.py
@@ -5,16 +5,17 @@
 
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 """desktop_unittest.py
 
 author: Jordan Lund
 """
 
+import json
 import os
 import re
 import sys
 import copy
 import shutil
 import glob
 import imp
 
@@ -353,16 +354,31 @@ class DesktopUnittest(TestingMixin, Merc
                 self.fatal("self.installer_url was found but symbols_url could \
                         not be determined")
         else:
             self.fatal("self.installer_url was not found in self.config")
         self.info("setting symbols_url as %s" % (symbols_url))
         self.symbols_url = symbols_url
         return self.symbols_url
 
+    def _get_mozharness_test_paths(self, suite_category, suite):
+        test_paths = json.loads(os.environ.get('MOZHARNESS_TEST_PATHS', '""'))
+
+        if not test_paths or suite not in test_paths:
+            return None
+
+        suite_test_paths = test_paths[suite]
+
+        if suite_category == 'reftest':
+            dirs = self.query_abs_dirs()
+            suite_test_paths = [os.path.join(dirs['abs_reftest_dir'], 'tests', p)
+                                for p in suite_test_paths]
+
+        return suite_test_paths
+
     def _query_abs_base_cmd(self, suite_category, suite):
         if self.binary_path:
             c = self.config
             dirs = self.query_abs_dirs()
             run_file = c['run_file_names'][suite_category]
             base_cmd = [self.query_python_path('python'), '-u']
             base_cmd.append(os.path.join(dirs["abs_%s_dir" % suite_category], run_file))
             abs_app_dir = self.query_abs_app_dir()
@@ -393,21 +409,18 @@ class DesktopUnittest(TestingMixin, Merc
             if suite_category not in SUITE_NO_E10S:
                 if suite_category in SUITE_DEFAULT_E10S and not c['e10s']:
                     base_cmd.append('--disable-e10s')
                 elif suite_category not in SUITE_DEFAULT_E10S and c['e10s']:
                     base_cmd.append('--e10s')
 
             # Ignore chunking if we have user specified test paths
             if not (self.verify_enabled or self.per_test_coverage):
-                if os.environ.get('MOZHARNESS_TEST_PATHS'):
-                    test_paths = os.environ['MOZHARNESS_TEST_PATHS'].split(':')
-                    if suite_category == 'reftest':
-                        test_paths = [os.path.join(dirs['abs_reftest_dir'], 'tests', p)
-                                      for p in test_paths]
+                test_paths = self._get_mozharness_test_paths(suite_category, suite)
+                if test_paths:
                     base_cmd.extend(test_paths)
                 elif c.get('total_chunks') and c.get('this_chunk'):
                     base_cmd.extend(['--total-chunks', c['total_chunks'],
                                      '--this-chunk', c['this_chunk']])
 
             if c['no_random']:
                 if suite_category == "mochitest":
                     base_cmd.append('--bisect-chunk=default')
@@ -795,17 +808,17 @@ class DesktopUnittest(TestingMixin, Merc
                 }
                 options_list = []
                 env = {
                     'TEST_SUITE': suite
                 }
                 if isinstance(suites[suite], dict):
                     options_list = suites[suite].get('options', [])
                     if (self.verify_enabled or self.per_test_coverage or
-                        os.environ.get('MOZHARNESS_TEST_PATHS')):
+                        self._get_mozharness_test_paths(suite_category, suite)):
                         # Ignore tests list in modes where we are running specific tests.
                         tests_list = []
                     else:
                         tests_list = suites[suite].get('tests', [])
                     env = copy.deepcopy(suites[suite].get('env', {}))
                 else:
                     options_list = suites[suite]
                     tests_list = []
--- a/testing/mozharness/scripts/marionette.py
+++ b/testing/mozharness/scripts/marionette.py
@@ -1,16 +1,17 @@
 #!/usr/bin/env python
 # ***** BEGIN LICENSE BLOCK *****
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 
 import copy
+import json
 import os
 import sys
 
 # load modules from parent dir
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
 from mozharness.base.errors import BaseErrorList, TarErrorList
 from mozharness.base.log import INFO
@@ -312,19 +313,21 @@ class MarionetteTest(TestingMixin, Mercu
 
         for arg in self.config["suite_definitions"][self.test_suite]["options"]:
             cmd.append(arg % config_fmt_args)
 
         if self.mkdir_p(dirs["abs_blob_upload_dir"]) == -1:
             # Make sure that the logging directory exists
             self.fatal("Could not create blobber upload directory")
 
-        if os.environ.get('MOZHARNESS_TEST_PATHS'):
+        test_paths = json.loads(os.environ.get('MOZHARNESS_TEST_PATHS', '""'))
+
+        if test_paths and 'marionette' in test_paths:
             paths = [os.path.join(dirs['abs_test_install_dir'], 'marionette', 'tests', p)
-                     for p in os.environ['MOZHARNESS_TEST_PATHS'].split(':')]
+                     for p in test_paths['marionette']]
             cmd.extend(paths)
         else:
             cmd.append(manifest)
 
         try_options, try_tests = self.try_args("marionette")
         cmd.extend(self.query_tests_args(try_tests,
                                          str_format_values=config_fmt_args))
 
--- a/testing/mozharness/scripts/web_platform_tests.py
+++ b/testing/mozharness/scripts/web_platform_tests.py
@@ -1,15 +1,16 @@
 #!/usr/bin/env python
 # ***** BEGIN LICENSE BLOCK *****
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 # ***** END LICENSE BLOCK *****
 import copy
+import json
 import os
 import sys
 
 from datetime import datetime, timedelta
 
 # load modules from parent dir
 sys.path.insert(1, os.path.dirname(sys.path[0]))
 
@@ -246,21 +247,22 @@ class WebPlatformTest(TestingMixin, Merc
             cmd.append("--disable-e10s")
 
         if c["single_stylo_traversal"]:
             cmd.append("--stylo-threads=1")
         else:
             cmd.append("--stylo-threads=4")
 
         if not (self.verify_enabled or self.per_test_coverage):
-            if os.environ.get('MOZHARNESS_TEST_PATHS'):
-                prefix = 'testing/web-platform'
-                paths = os.environ['MOZHARNESS_TEST_PATHS'].split(':')
-                paths = [os.path.join(dirs["abs_wpttest_dir"], os.path.relpath(p, prefix))
-                         for p in paths if p.startswith(prefix)]
+            test_paths = json.loads(os.environ.get('MOZHARNESS_TEST_PATHS', '""'))
+            if test_paths and 'web-platform-tests' in test_paths:
+                relpaths = [os.path.relpath(p, 'testing/web-platform')
+                            for p in test_paths['web-platform-tests']]
+                paths = [os.path.join(dirs["abs_wpttest_dir"], relpath)
+                         for relpath in relpaths]
                 cmd.extend(paths)
             else:
                 for opt in ["total_chunks", "this_chunk"]:
                     val = c.get(opt)
                     if val:
                         cmd.append("--%s=%s" % (opt.replace("_", "-"), val))
 
         options = list(c.get("options", []))
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/ui3/box-sizing-replaced-003.xht.ini
@@ -0,0 +1,3 @@
+[box-sizing-replaced-003.xht]
+  disabled:
+    if (os == "mac"): https://bugzilla.mozilla.org/show_bug.cgi?id=1383454
--- a/testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini
+++ b/testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini
@@ -10,8 +10,23 @@
 
   [Window method: print]
     expected:
       if os == "android": FAIL
 
   [Window method: queueMicrotask]
     expected: FAIL
 
+  [Window unforgeable attribute: window]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
+  [Window unforgeable attribute: document]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
+  [Window unforgeable attribute: location]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
+  [Window unforgeable attribute: top]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
--- a/testing/web-platform/meta/html/dom/interfaces.https.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.https.html.ini
@@ -356,16 +356,32 @@
   [Window interface: window must inherit property "print()" with the proper type]
     expected:
       if os == "android": FAIL
 
   [Window interface: operation print()]
     expected:
       if os == "android": FAIL
 
+  [Window interface: window must have own property "window"]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
+  [Window interface: window must have own property "document"]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
+  [Window interface: window must have own property "location"]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
+  [Window interface: window must have own property "top"]
+    expected: FAIL
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
+
 [interfaces.https.html?include=HTML.*]
   [HTMLAllCollection must be primary interface of document.all]
     expected: FAIL
 
   [Stringification of document.all]
     expected: FAIL
 
   [HTMLAllCollection interface: document.all must inherit property "length" with the proper type]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes-ref.html
@@ -0,0 +1,179 @@
+<!DOCTYPE HTML>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+  <meta charset="utf-8">
+  <title>CSS Ruby Reference: ruby content w. layout-internal 'display' values</title>
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <style>
+html,body {
+  color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+
+input {
+  width: 20px;
+  -webkit-appearance: none;
+  border: 1px solid black;
+  background: white;
+}
+
+.thg { display: table-header-group; }
+.trg { display: table-row-group; }
+.tfg { display: table-footer-group; }
+.tr  { display: table-row; }
+.tc  { display: table-cell; }
+.tcg { display: table-column-group; }
+.tco { display: table-column; }
+.tca { display: table-caption; }
+.t   { display: table; }
+
+.rb  { display: ruby-base; }
+.rt  { display: ruby-text; }
+.rbc { display: ruby-base-container; }
+.rtc { display: ruby-text-container; }
+
+.x { background: red}
+    </style>
+</head>
+<body>
+
+<ruby><rb><span>a<span><input class="thg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="thg"><input class="thg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="thg">b</div><input class="thg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="thg">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="trg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="trg"><input class="trg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="trg">b</div><input class="trg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="trg">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="tfg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="tfg"><input class="tfg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tfg">b</div><input class="tfg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tfg">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="tr"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="tr"><input class="tr"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tr">b</div><input class="tr"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tr">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="tc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="tc"><input class="tc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tc">b</div><input class="tc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tc">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="tcg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="tcg"><input class="tcg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tcg">b</div><input class="tcg"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tcg">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="tco"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="tco"><input class="tco"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tco">b</div><input class="tco"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tco">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="tca"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="tca"><input class="tca"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tca">b</div><input class="tca"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="tca">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="t"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="t"><input class="t"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="t">b</div><input class="t"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="t">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="rb"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="rb"><input class="rb"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rb">b</div><input class="rb"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rb">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="rt"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="rt"><input class="rt"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rt">b</div><input class="rt"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rt">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="rbc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="rbc"><input class="rbc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rbc">b</div><input class="rbc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rbc">b</div></span>c</span></rb></ruby>
+
+<ruby><rb><span>a<span><input class="rtc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><input class="rtc"><input class="rtc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rtc">b</div><input class="rtc"></span>b</span></rb></ruby>
+<ruby><rb><span>a<span><div class="rtc">b</div></span>c</span></rb></ruby>
+
+<br><hr>
+
+<!--  -->
+
+<ruby><rb><span><input class="thg"></span>b</rb></ruby>
+<ruby><rb><span><input class="thg"><input class="thg"></span>b</rb></ruby>
+<ruby><rb><span><div class="thg">b</div><input class="thg"></span>b</rb></ruby>
+<ruby><rb><span><div class="thg">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="trg"></span>b</rb></ruby>
+<ruby><rb><span><input class="trg"><input class="trg"></span>b</rb></ruby>
+<ruby><rb><span><div class="trg">b</div><input class="trg"></span>b</rb></ruby>
+<ruby><rb><span><div class="trg">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="tfg"></span>b</rb></ruby>
+<ruby><rb><span><input class="tfg"><input class="tfg"></span>b</rb></ruby>
+<ruby><rb><span><div class="tfg">b</div><input class="tfg"></span>b</rb></ruby>
+<ruby><rb><span><div class="tfg">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="tr"></span>b</rb></ruby>
+<ruby><rb><span><input class="tr"><input class="tr"></span>b</rb></ruby>
+<ruby><rb><span><div class="tr">b</div><input class="tr"></span>b</rb></ruby>
+<ruby><rb><span><div class="tr">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="tc"></span>b</rb></ruby>
+<ruby><rb><span><input class="tc"><input class="tc"></span>b</rb></ruby>
+<ruby><rb><span><div class="tc">b</div><input class="tc"></span>b</rb></ruby>
+<ruby><rb><span><div class="tc">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="tcg"></span>b</rb></ruby>
+<ruby><rb><span><input class="tcg"><input class="tcg"></span>b</rb></ruby>
+<ruby><rb><span><div class="tcg">b</div><input class="tcg"></span>b</rb></ruby>
+<ruby><rb><span><div class="tcg">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="tco"></span>b</rb></ruby>
+<ruby><rb><span><input class="tco"><input class="tco"></span>b</rb></ruby>
+<ruby><rb><span><div class="tco">b</div><input class="tco"></span>b</rb></ruby>
+<ruby><rb><span><div class="tco">b</div></span>c</rb></ruby>
+
+<!-- bug NNNNNN
+<ruby><rb><span><input class="tca"></span>b</rb></ruby>
+<ruby><rb><span><input class="tca"><input class="tca"></span>b</rb></ruby>
+<ruby><rb><span><div class="tca">b</div><input class="tca"></span>b</rb></ruby>
+<ruby><rb><span><div class="tca">b</div></span>c</rb></ruby>
+-->
+
+<ruby><rb><span><input class="t"></span>b</rb></ruby>
+<ruby><rb><span><input class="t"><input class="t"></span>b</rb></ruby>
+<ruby><rb><span><div class="t">b</div><input class="t"></span>b</rb></ruby>
+<ruby><rb><span><div class="t">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="rb"></span>b</rb></ruby>
+<ruby><rb><span><input class="rb"><input class="rb"></span>b</rb></ruby>
+<ruby><rb><span><div class="rb">b</div><input class="rb"></span>b</rb></ruby>
+<ruby><rb><span><div class="rb">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="rt"></span>b</rb></ruby>
+<ruby><rb><span><input class="rt"><input class="rt"></span>b</rb></ruby>
+<ruby><rb><span><div class="rt">b</div><input class="rt"></span>b</rb></ruby>
+<ruby><rb><span><div class="rt">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="rbc"></span>b</rb></ruby>
+<ruby><rb><span><input class="rbc"><input class="rbc"></span>b</rb></ruby>
+<ruby><rb><span><div class="rbc">b</div><input class="rbc"></span>b</rb></ruby>
+<ruby><rb><span><div class="rbc">b</div></span>c</rb></ruby>
+
+<ruby><rb><span><input class="rtc"></span>b</rb></ruby>
+<ruby><rb><span><input class="rtc"><input class="rtc"></span>b</rb></ruby>
+<ruby><rb><span><div class="rtc">b</div><input class="rtc"></span>b</rb></ruby>
+<ruby><rb><span><div class="rtc">b</div></span>c</rb></ruby>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes.html
@@ -0,0 +1,181 @@
+<!DOCTYPE HTML>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+  <meta charset="utf-8">
+  <title>CSS Ruby Test: ruby content w. layout-internal 'display' values</title>
+  <link rel="help" href="https://drafts.csswg.org/css-ruby-1/#box-fixup">
+  <link rel="help" href="https://drafts.csswg.org/css-display-3/#inlinify">
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <link rel="match" href="ruby-layout-internal-boxes-ref.html">
+  <style>
+html,body {
+  color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+
+input {
+  width: 20px;
+  -webkit-appearance: none;
+  border: 1px solid black;
+  background: white;
+}
+
+.thg { display: table-header-group; }
+.trg { display: table-row-group; }
+.tfg { display: table-footer-group; }
+.tr  { display: table-row; }
+.tc  { display: table-cell; }
+.tcg { display: table-column-group; }
+.tco { display: table-column; }
+.tca { display: table-caption; }
+.t   { display: table; }
+
+.rb  { display: ruby-base; }
+.rt  { display: ruby-text; }
+.rbc { display: ruby-base-container; }
+.rtc { display: ruby-text-container; }
+
+    </style>
+</head>
+<body>
+
+<ruby><rb><span>a<input class="thg">b</span></rb></ruby>
+<ruby><rb><span>a<input class="thg"><input class="thg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="thg">b</div><input class="thg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="thg">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="trg">b</span></rb></ruby>
+<ruby><rb><span>a<input class="trg"><input class="trg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="trg">b</div><input class="trg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="trg">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="tfg">b</span></rb></ruby>
+<ruby><rb><span>a<input class="tfg"><input class="tfg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tfg">b</div><input class="tfg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tfg">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="tr">b</span></rb></ruby>
+<ruby><rb><span>a<input class="tr"><input class="tr">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tr">b</div><input class="tr">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tr">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="tc">b</span></rb></ruby>
+<ruby><rb><span>a<input class="tc"><input class="tc">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tc">b</div><input class="tc">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tc">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="tcg">b</span></rb></ruby>
+<ruby><rb><span>a<input class="tcg"><input class="tcg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tcg">b</div><input class="tcg">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tcg">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="tco">b</span></rb></ruby>
+<ruby><rb><span>a<input class="tco"><input class="tco">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tco">b</div><input class="tco">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tco">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="tca">b</span></rb></ruby>
+<ruby><rb><span>a<input class="tca"><input class="tca">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tca">b</div><input class="tca">b</span></rb></ruby>
+<ruby><rb><span>a<div class="tca">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="t">b</span></rb></ruby>
+<ruby><rb><span>a<input class="t"><input class="t">b</span></rb></ruby>
+<ruby><rb><span>a<div class="t">b</div><input class="t">b</span></rb></ruby>
+<ruby><rb><span>a<div class="t">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="rb">b</span></rb></ruby>
+<ruby><rb><span>a<input class="rb"><input class="rb">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rb">b</div><input class="rb">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rb">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="rt">b</span></rb></ruby>
+<ruby><rb><span>a<input class="rt"><input class="rt">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rt">b</div><input class="rt">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rt">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="rbc">b</span></rb></ruby>
+<ruby><rb><span>a<input class="rbc"><input class="rbc">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rbc">b</div><input class="rbc">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rbc">b</div>c</span></rb></ruby>
+
+<ruby><rb><span>a<input class="rtc">b</span></rb></ruby>
+<ruby><rb><span>a<input class="rtc"><input class="rtc">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rtc">b</div><input class="rtc">b</span></rb></ruby>
+<ruby><rb><span>a<div class="rtc">b</div>c</span></rb></ruby>
+
+<br><hr>
+
+<!-- same as above but without the SPAN wrapper -->
+
+<ruby><rb><input class="thg">b</rb></ruby>
+<ruby><rb><input class="thg"><input class="thg">b</rb></ruby>
+<ruby><rb><div class="thg">b</div><input class="thg">b</rb></ruby>
+<ruby><rb><div class="thg">b</div>c</rb></ruby>
+
+<ruby><rb><input class="trg">b</rb></ruby>
+<ruby><rb><input class="trg"><input class="trg">b</rb></ruby>
+<ruby><rb><div class="trg">b</div><input class="trg">b</rb></ruby>
+<ruby><rb><div class="trg">b</div>c</rb></ruby>
+
+<ruby><rb><input class="tfg">b</rb></ruby>
+<ruby><rb><input class="tfg"><input class="tfg">b</rb></ruby>
+<ruby><rb><div class="tfg">b</div><input class="tfg">b</rb></ruby>
+<ruby><rb><div class="tfg">b</div>c</rb></ruby>
+
+<ruby><rb><input class="tr">b</rb></ruby>
+<ruby><rb><input class="tr"><input class="tr">b</rb></ruby>
+<ruby><rb><div class="tr">b</div><input class="tr">b</rb></ruby>
+<ruby><rb><div class="tr">b</div>c</rb></ruby>
+
+<ruby><rb><input class="tc">b</rb></ruby>
+<ruby><rb><input class="tc"><input class="tc">b</rb></ruby>
+<ruby><rb><div class="tc">b</div><input class="tc">b</rb></ruby>
+<ruby><rb><div class="tc">b</div>c</rb></ruby>
+
+<ruby><rb><input class="tcg">b</rb></ruby>
+<ruby><rb><input class="tcg"><input class="tcg">b</rb></ruby>
+<ruby><rb><div class="tcg">b</div><input class="tcg">b</rb></ruby>
+<ruby><rb><div class="tcg">b</div>c</rb></ruby>
+
+<ruby><rb><input class="tco">b</rb></ruby>
+<ruby><rb><input class="tco"><input class="tco">b</rb></ruby>
+<ruby><rb><div class="tco">b</div><input class="tco">b</rb></ruby>
+<ruby><rb><div class="tco">b</div>c</rb></ruby>
+
+<!-- FIXME after https://bugzilla.mozilla.org/show_bug.cgi?id=1510299
+<ruby><rb><input class="tca">b</rb></ruby>
+<ruby><rb><input class="tca"><input class="tca">b</rb></ruby>
+<ruby><rb><div class="tca">b</div><input class="tca">b</rb></ruby>
+<ruby><rb><div class="tca">b</div>c</rb></ruby>
+-->
+
+<ruby><rb><input class="t">b</rb></ruby>
+<ruby><rb><input class="t"><input class="t">b</rb></ruby>
+<ruby><rb><div class="t">b</div><input class="t">b</rb></ruby>
+<ruby><rb><div class="t">b</div>c</rb></ruby>
+
+<ruby><rb><input class="rb">b</rb></ruby>
+<ruby><rb><input class="rb"><input class="rb">b</rb></ruby>
+<ruby><rb><div class="rb">b</div><input class="rb">b</rb></ruby>
+<ruby><rb><div class="rb">b</div>c</rb></ruby>
+
+<ruby><rb><input class="rt">b</rb></ruby>
+<ruby><rb><input class="rt"><input class="rt">b</rb></ruby>
+<ruby><rb><div class="rt">b</div><input class="rt">b</rb></ruby>
+<ruby><rb><div class="rt">b</div>c</rb></ruby>
+
+<ruby><rb><input class="rbc">b</rb></ruby>
+<ruby><rb><input class="rbc"><input class="rbc">b</rb></ruby>
+<ruby><rb><div class="rbc">b</div><input class="rbc">b</rb></ruby>
+<ruby><rb><div class="rbc">b</div>c</rb></ruby>
+
+<ruby><rb><input class="rtc">b</rb></ruby>
+<ruby><rb><input class="rtc"><input class="rtc">b</rb></ruby>
+<ruby><rb><div class="rtc">b</div><input class="rtc">b</rb></ruby>
+<ruby><rb><div class="rtc">b</div>c</rb></ruby>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-ui/text-overflow-ruby-ref.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+  <meta charset="utf-8">
+  <title>Reference: text-overflow:ellipsis and ruby</title>
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <style>
+html,body {
+  color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+
+.clip {
+    overflow: hidden;
+    width: 40px;
+    text-overflow: ellipsis;
+}
+
+input { width: 40px; -webkit-appearance: none; border: 1px solid black; }
+span { white-space: pre; }
+.thg { display: inline-table; }
+.tc { display: inline-table; }
+.t { display: inline-table; }
+
+    </style>
+</head>
+<body>
+
+<div style="float:left; width:300px">
+<div class="clip">
+<span><span><span>aa<input class="thg">bb</span></span></span>
+<br>
+<span><span><span>aa<div class="thg">bbbbbb</div>cc</span></span></span>
+<br>
+<span><span><span>aa<span>bbbbbb</span>cc</span></span></span>
+<br>
+<span><span><span>aa<input class="tc">bb</span></span></span>
+<br>
+<span><span><span>aa<div class="tc">bbbbbb</div>cc</span></span></span>
+<br>
+<span><span><span>aa<input class="t">bb</span></span></span>
+<br>
+<span><span><span>aa<div class="t">bbbbbb</div>cc</span></span></span>
+
+<br>
+<span><span><span><input class="thg">bb</span></span></span>
+<br>
+<span><span><span><div class="thg">bbbbbb</div>cc</span></span></span>
+<br>
+<span><span><span><span>bbbbbb</span>cc</span></span></span>
+<br>
+<span><span><span><input class="tc">bb</span></span></span>
+<br>
+<span><span><span><div class="tc">bbbbbb</div>cc</span></span></span>
+<br>
+<span><span><span><input class="t">bb</span></span></span>
+<br>
+<span><span><span><div class="t">bbbbbb</div>cc</span></span></span>
+</div>
+</div>
+
+<div style="float:left; width:300px">
+<div class="clip">
+<span><span><input class="thg">bb</span></span>
+<br>
+<span><span><div class="thg">bbbbbb</div>cc</span></span>
+<br>
+<span><span>bbbbbbcc</span></span>
+<br>
+<span><span><input class="tc">bb</span></span>
+<br>
+<span><span><div class="tc">bbbbbb</div>cc</span></span>
+<br>
+<span><span><input class="t">bb</span></span>
+<br>
+<span><span><div class="t">bbbbbb</div>cc</span></span>
+</div>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-ui/text-overflow-ruby.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+  <meta charset="utf-8">
+  <title>CSS Basic User Interface Test: text-overflow:ellipsis and ruby</title>
+  <link rel="help" href="http://www.w3.org/TR/css3-ui/#text-overflow">
+  <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+  <link rel="match" href="text-overflow-ruby-ref.html">
+  <style>
+html,body {
+  color:black; background-color:white; font:14px/1 monospace; padding:0; margin:0;
+}
+
+.clip {
+    overflow: hidden;
+    width: 40px;
+    text-overflow: ellipsis;
+}
+
+input { width: 40px; -webkit-appearance: none; border: 1px solid black; }
+
+.thg { display: table-header-group; }
+.tc { display: table-cell; }
+.t { display: table; }
+
+    </style>
+</head>
+<body>
+
+<div style="float:left; width:300px">
+<div class="clip">
+<ruby><rb><span>aa<input class="thg">bb</span></rb></ruby>
+<br>
+<ruby><rb><span>aa<div class="thg">bbbbbb</div>cc</span></rb></ruby>
+<br>
+<ruby><rb><span>aa<span>bbbbbb</span>cc</span></rb></ruby>
+<br>
+<ruby><rb><span>aa<input class="tc">bb</span></rb></ruby>
+<br>
+<ruby><rb><span>aa<div class="tc">bbbbbb</div>cc</span></rb></ruby>
+<br>
+<ruby><rb><span>aa<input class="t">bb</span></rb></ruby>
+<br>
+<ruby><rb><span>aa<div class="t">bbbbbb</div>cc</span></rb></ruby>
+
+<br>
+<ruby><rb><span><input class="thg">bb</span></rb></ruby>
+<br>
+<ruby><rb><span><div class="thg">bbbbbb</div>cc</span></rb></ruby>
+<br>
+<ruby><rb><span><span>bbbbbb</span>cc</span></rb></ruby>
+<br>
+<ruby><rb><span><input class="tc">bb</span></rb></ruby>
+<br>
+<ruby><rb><span><div class="tc">bbbbbb</div>cc</span></rb></ruby>
+<br>
+<ruby><rb><span><input class="t">bb</span></rb></ruby>
+<br>
+<ruby><rb><span><div class="t">bbbbbb</div>cc</span></rb></ruby>
+</div>
+</div>
+
+<div style="float:left; width:300px">
+<div class="clip">
+<ruby><rb><input class="thg">bb</rb></ruby>
+<br>
+<ruby><rb><div class="thg">bbbbbb</div>cc</rb></ruby>
+<br>
+<ruby><rb>bbbbbbcc</rb></ruby>
+<br>
+<ruby><rb><input class="tc">bb</rb></ruby>
+<br>
+<ruby><rb><div class="tc">bbbbbb</div>cc</rb></ruby>
+<br>
+<ruby><rb><input class="t">bb</rb></ruby>
+<br>
+<ruby><rb><div class="t">bbbbbb</div>cc</rb></ruby>
+</div>
+</div>
+
+</body>
+</html>
--- a/third_party/rust/cranelift-bforest/.cargo-checksum.json
+++ b/third_party/rust/cranelift-bforest/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"a9d64466eee85b2f607e61ad354cb7b08cc17b925395fb2ec08eec61726773e9","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"01f8c9b8a077975c8f0803f793b8c20b583aaef2dc1f4400b9d90ba132ff4133","src/map.rs":"77eb9fd2ffdaafaf4daea609602a0c775c5012efae21c03547f63653271da163","src/node.rs":"309609acc70f1ce6be2f3c964430d23c0680bd7a647afab837a2aedc06235531","src/path.rs":"25326bacbb99189e873cb70e770f21c13fdef0fb2cd20f484830386fc4c75c6a","src/pool.rs":"196216124922dc42708a3aa944e98b6a57ef9bb770dab7e01f154b6382cab021","src/set.rs":"d4ff99fe51de9eefb4c774e919259d952ab5dde4dd3b99bd9974e4eedbb28938"},"package":"8c5f8e1ab4f73b59a98531a8013d8ed3ca7edb4e36984cb301d9c06f6892787b"}
\ No newline at end of file
+{"files":{"Cargo.toml":"8c219cb955621bfeb89eb1175dc9d810dc98323ccb54360e623425308c970e72","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"af367c67340fa7f6fb9a35b0aa637dcf303957f7ae7427a5f4f6356801c8bb04","src/lib.rs":"01f8c9b8a077975c8f0803f793b8c20b583aaef2dc1f4400b9d90ba132ff4133","src/map.rs":"77eb9fd2ffdaafaf4daea609602a0c775c5012efae21c03547f63653271da163","src/node.rs":"309609acc70f1ce6be2f3c964430d23c0680bd7a647afab837a2aedc06235531","src/path.rs":"25326bacbb99189e873cb70e770f21c13fdef0fb2cd20f484830386fc4c75c6a","src/pool.rs":"196216124922dc42708a3aa944e98b6a57ef9bb770dab7e01f154b6382cab021","src/set.rs":"d4ff99fe51de9eefb4c774e919259d952ab5dde4dd3b99bd9974e4eedbb28938"},"package":"7b2d527b241af388ff017d72f2b0b323929a70cf97342c6ec1534e3b0f4dfaa0"}
\ No newline at end of file
--- a/third_party/rust/cranelift-bforest/Cargo.toml
+++ b/third_party/rust/cranelift-bforest/Cargo.toml
@@ -7,27 +7,27 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-bforest"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "A forest of B+-trees"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 keywords = ["btree", "forest", "set", "map"]
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [features]
 default = ["std"]
 std = ["cranelift-entity/std"]
 [badges.maintenance]
 status = "experimental"
 
--- a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
+++ b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"56d43cc835cbea830d3659c9f32062f3413c85a0eba618acc633fe0f6640445d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"9320dfed2250bdb0347e01862b2ff7bf7db78920dae1719834b374de11131e87","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"52ab00f489acbf00ebda8e2866de6495f3ed0f57d06896418dc7a2e8def902d2","src/cdsl/mod.rs":"311726d7e4ad9278eab301fd4f6e31e697b7d4260733c6a00fe39cd61db977d3","src/cdsl/regs.rs":"fe24d2ea67d7eec9912c2f9c85bbec98a12c43c9a1dd12f219795abf2e8d962a","src/cdsl/types.rs":"f9756e483329f00a1d8a15e30bc05e8d4c8fa71ff1f649b808528ddeb5fbdfea","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"3d38ff5b0c6183209d4ba84bd1f14b1d84bea697c0589471aa5ce4abc209f20b","src/gen_types.rs":"5eb4e9bd0fda7f7644bb2428045f0bf16f2b698ff32cadcbbf7f2c7669f18de3","src/isa/arm32/mod.rs":"2a1aef09ead88fac19ca65f0ca01b5b38761001f7816984300d640001d818f33","src/isa/arm64/mod.rs":"5b034bcdcef2ab161c43afa860c7f176c81647f076c47cc4315917e13aa47810","src/isa/mod.rs":"927e5543dbe5c22bd6356b252318942ca16e3cbce466641a4f494a8a492443d9","src/isa/riscv/mod.rs":"f691fd37f2770919b32725ae0a2b523bc231aebb4aada4f9a591fc2acbbb2dc7","src/isa/x86/mod.rs":"0821384e048456475061c69f94a2f96868311114c18c758b841720c76f6daa71","src/lib.rs":"dd97d73d41ffee2d2cc62705f9f6f7ed6b9af982aff8d1fafb72590e097c513c","src/srcgen.rs":"abe118fb41a643ffc63577cc4b62de9a2286e1eeb34b95bff79648d0ea582886"},"package":"4eac16097b96e9f609df735555f2d1658531750fbc3805bca1daca7671aef9eb"}
\ No newline at end of file
+{"files":{"Cargo.toml":"0e4050095c283d025e30ccba0e3d9753b63340604b6373e4ea06d221eb3a97e1","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"b123f056d0d458396679c5f7f2a16d2762af0258fcda4ac14b6655a95e5a0022","src/base/mod.rs":"9320dfed2250bdb0347e01862b2ff7bf7db78920dae1719834b374de11131e87","src/base/types.rs":"a3e449db1f515d268f3ad21301740ba415444d399f8433dbc48979f78557f66a","src/cdsl/isa.rs":"b34150e2658dd7ab30e9846dece89f56a0acbfff0341927cec06bf0de1d9b419","src/cdsl/mod.rs":"311726d7e4ad9278eab301fd4f6e31e697b7d4260733c6a00fe39cd61db977d3","src/cdsl/regs.rs":"41cca844b390bba3ceefa147e7b0dec170aba2b5759a41ecb5b9cd7f2cc59f60","src/cdsl/types.rs":"f9756e483329f00a1d8a15e30bc05e8d4c8fa71ff1f649b808528ddeb5fbdfea","src/error.rs":"5110a4e3c1e97396ba02d9f5abbb8af4b586f0cc4d33a5c2473f1718cc4bef05","src/gen_registers.rs":"3d38ff5b0c6183209d4ba84bd1f14b1d84bea697c0589471aa5ce4abc209f20b","src/gen_types.rs":"5eb4e9bd0fda7f7644bb2428045f0bf16f2b698ff32cadcbbf7f2c7669f18de3","src/isa/arm32/mod.rs":"ceb8290344a245f11eb541d60c2678ddfe7beaf60cde491c22fd48090fa210ba","src/isa/arm64/mod.rs":"db7f828940372a21c62cf6f5aefca7cc05c974ba731b8db602da0a336e29ea1e","src/isa/mod.rs":"36c001f8ecdea4aaf8cadcad4f91fe79a82806e4f43182e216c2fa99cecf55dc","src/isa/riscv/mod.rs":"aecb127f8c06970a00dde8ad772fdebe5497b6e7f342fa2a0e859355ae027055","src/isa/x86/mod.rs":"2b3a181a226d66a8faf855d517fb4a13554a31020f6b8875ba75a2fe650f378a","src/lib.rs":"dd97d73d41ffee2d2cc62705f9f6f7ed6b9af982aff8d1fafb72590e097c513c","src/srcgen.rs":"abe118fb41a643ffc63577cc4b62de9a2286e1eeb34b95bff79648d0ea582886"},"package":"963262697a05d9aa63ca40f4670a7243e4525f4a098e10d654c3f5143fcef686"}
\ No newline at end of file
--- a/third_party/rust/cranelift-codegen-meta/Cargo.toml
+++ b/third_party/rust/cranelift-codegen-meta/Cargo.toml
@@ -7,21 +7,21 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-codegen-meta"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Metaprogram for cranelift-codegen code generator library"
 readme = "README.md"
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 [badges.maintenance]
 status = "experimental"
 
 [badges.travis-ci]
 repository = "CraneStation/cranelift"
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
@@ -1,109 +1,134 @@
 use cranelift_entity::PrimaryMap;
 
 use super::regs::{
-    RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex,
+    RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, RegClassProto,
 };
 
 pub struct TargetIsa {
     pub name: &'static str,
     pub reg_banks: PrimaryMap<RegBankIndex, RegBank>,
     pub reg_classes: PrimaryMap<RegClassIndex, RegClass>,
 }
 
 impl TargetIsa {
     pub fn new(name: &'static str) -> Self {
         Self {
             name,
             reg_banks: PrimaryMap::new(),
             reg_classes: PrimaryMap::new(),
         }
     }
+}
+
+pub struct TargetIsaBuilder {
+    isa: TargetIsa,
+}
+
+impl TargetIsaBuilder {
+    pub fn new(name: &'static str) -> Self {
+        Self {
+            isa: TargetIsa::new(name),
+        }
+    }
 
     pub fn add_reg_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
-        let first_unit = if self.reg_banks.len() == 0 {
+        let first_unit = if self.isa.reg_banks.len() == 0 {
             0
         } else {
-            let last = &self.reg_banks.last().unwrap();
+            let last = &self.isa.reg_banks.last().unwrap();
             let first_available_unit = (last.first_unit + last.units) as i8;
             let units = builder.units;
             let align = if units.is_power_of_two() {
                 units
             } else {
                 units.next_power_of_two()
             } as i8;
             (first_available_unit + align - 1) & -align
         } as u8;
 
-        self.reg_banks.push(RegBank::new(
+        self.isa.reg_banks.push(RegBank::new(
             builder.name,
             first_unit,
             builder.units,
             builder.names,
             builder.prefix,
             builder
                 .pressure_tracking
                 .expect("Pressure tracking must be explicitly set"),
         ))
     }
 
     pub fn add_reg_class(&mut self, builder: RegClassBuilder) -> RegClassIndex {
-        let reg_bank_units = self.reg_banks.get(builder.bank).unwrap().units;
+        let class_index = self.isa.reg_classes.next_key();
 
-        let start = builder.start;
+        // Finish delayed construction of RegClass.
+        let (bank, toprc, start, width) = match builder.proto {
+            RegClassProto::TopLevel(bank_index) => {
+                self.isa
+                    .reg_banks
+                    .get_mut(bank_index)
+                    .unwrap()
+                    .toprcs
+                    .push(class_index);
+                (bank_index, class_index, builder.start, builder.width)
+            }
+            RegClassProto::SubClass(parent_class_index) => {
+                assert!(builder.width == 0);
+                let (bank, toprc, start, width) = {
+                    let parent = self.isa.reg_classes.get(parent_class_index).unwrap();
+                    (parent.bank, parent.toprc, parent.start, parent.width)
+                };
+                for reg_class in self.isa.reg_classes.values_mut() {
+                    if reg_class.toprc == toprc {
+                        reg_class.subclasses.push(class_index);
+                    }
+                }
+                let subclass_start = start + builder.start * width;
+                (bank, toprc, subclass_start, width)
+            }
+        };
+
+        let reg_bank_units = self.isa.reg_banks.get(bank).unwrap().units;
         assert!(start < reg_bank_units);
 
         let count = if builder.count != 0 {
             builder.count
         } else {
-            reg_bank_units / builder.width
+            reg_bank_units / width
         };
 
-        let reg_class_index = builder.index;
-        assert!(
-            self.reg_classes.next_key() == reg_class_index,
-            "should have inserted RegClass where expected"
-        );
+        let reg_class = RegClass::new(builder.name, class_index, width, bank, toprc, count, start);
+        self.isa.reg_classes.push(reg_class);
 
-        let reg_class = RegClass::new(
-            builder.name,
-            reg_class_index,
-            builder.width,
-            builder.bank,
-            builder.toprc,
-            count,
-            start,
-        );
-        self.reg_classes.push(reg_class);
+        let reg_bank = self.isa.reg_banks.get_mut(bank).unwrap();
+        reg_bank.classes.push(class_index);
 
-        let reg_bank = self.reg_banks.get_mut(builder.bank).unwrap();
-        reg_bank.classes.push(reg_class_index);
-
-        reg_class_index
+        class_index
     }
 
     /// Checks that the set of register classes satisfies:
     ///
     /// 1. Closed under intersection: The intersection of any two register
     ///    classes in the set is either empty or identical to a member of the
     ///    set.
     /// 2. There are no identical classes under different names.
     /// 3. Classes are sorted topologically such that all subclasses have a
     ///    higher index that the superclass.
-    pub fn check(&self) {
-        for reg_bank in self.reg_banks.values() {
+    pub fn finish(self) -> TargetIsa {
+        for reg_bank in self.isa.reg_banks.values() {
             for i1 in reg_bank.classes.iter() {
                 for i2 in reg_bank.classes.iter() {
                     if i1 >= i2 {
                         continue;
                     }
 
-                    let rc1 = self.reg_classes.get(*i1).unwrap();
-                    let rc2 = self.reg_classes.get(*i2).unwrap();
+                    let rc1 = self.isa.reg_classes.get(*i1).unwrap();
+                    let rc2 = self.isa.reg_classes.get(*i2).unwrap();
 
                     let rc1_mask = rc1.mask(0);
                     let rc2_mask = rc2.mask(0);
 
                     assert!(
                         rc1.width != rc2.width || rc1_mask != rc2_mask,
                         "no duplicates"
                     );
@@ -121,22 +146,44 @@ impl TargetIsa {
 
                     // Classes must be topologically ordered, so the intersection can't be the
                     // superclass.
                     assert!(intersect != rc1_mask);
 
                     // If the intersection is the second one, then it must be a subclass.
                     if intersect == rc2_mask {
                         assert!(
-                            self.reg_classes
+                            self.isa
+                                .reg_classes
                                 .get(*i1)
                                 .unwrap()
                                 .subclasses
                                 .iter()
                                 .find(|x| **x == *i2)
                                 .is_some()
                         );
                     }
                 }
             }
         }
+
+        // This limit should be coordinated with the `RegClassMask` and `RegClassIndex` types in
+        // isa/registers.rs of the non-meta code.
+        assert!(
+            self.isa.reg_classes.len() <= 32,
+            "Too many register classes"
+        );
+
+        // The maximum number of top-level register classes which have pressure tracking should be
+        // kept in sync with the MAX_TRACKED_TOPRCS constant in isa/registers.rs of the non-meta
+        // code.
+        let num_toplevel = self
+            .isa
+            .reg_classes
+            .values()
+            .filter(|x| {
+                x.toprc == x.index && self.isa.reg_banks.get(x.bank).unwrap().pressure_tracking
+            }).count();
+        assert!(num_toplevel <= 4, "Too many top-level register classes");
+
+        self.isa
     }
 }
--- a/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs
@@ -1,12 +1,10 @@
 use cranelift_entity::EntityRef;
 
-use super::isa::TargetIsa;
-
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct RegBankIndex(u32);
 entity_impl!(RegBankIndex);
 
 pub struct RegBank {
     pub name: &'static str,
     pub first_unit: u8,
     pub units: u8,
@@ -92,81 +90,63 @@ impl RegClass {
         for _ in 0..self.count {
             out_mask[u / 32] |= 1 << (u % 32);
             u += self.width as usize;
         }
         out_mask
     }
 }
 
+pub enum RegClassProto {
+    TopLevel(RegBankIndex),
+    SubClass(RegClassIndex),
+}
+
 pub struct RegClassBuilder {
     pub name: &'static str,
-    pub index: RegClassIndex,
     pub width: u8,
-    pub bank: RegBankIndex,
-    pub toprc: RegClassIndex,
     pub count: u8,
     pub start: u8,
+    pub proto: RegClassProto,
 }
 
 impl RegClassBuilder {
-    pub fn new_toplevel(isa: &mut TargetIsa, name: &'static str, bank: RegBankIndex) -> Self {
-        let index = isa.reg_classes.next_key();
-
-        // Add it to the top-level register classes of the register bank.
-        isa.reg_banks.get_mut(bank).unwrap().toprcs.push(index);
-
+    pub fn new_toplevel(name: &'static str, bank: RegBankIndex) -> Self {
         Self {
             name,
-            index,
             width: 1,
-            bank,
-            toprc: index,
             count: 0,
             start: 0,
+            proto: RegClassProto::TopLevel(bank),
         }
     }
-
     pub fn subclass_of(
-        isa: &mut TargetIsa,
         name: &'static str,
         parent_index: RegClassIndex,
         start: u8,
         stop: u8,
     ) -> Self {
         assert!(stop >= start);
-
-        let index = isa.reg_classes.next_key();
-
-        let toprc = isa.reg_classes.get(parent_index).unwrap().toprc;
-        for reg_class in isa.reg_classes.values_mut() {
-            if reg_class.toprc == toprc {
-                reg_class.subclasses.push(index);
-            }
-        }
-
-        let parent = &isa.reg_classes.get(parent_index).unwrap();
         Self {
             name,
+            width: 0,
             count: stop - start,
-            width: parent.width,
-            start: parent.start + start * parent.width,
-            bank: parent.bank,
-            toprc: parent.toprc,
-            index,
+            start: start,
+            proto: RegClassProto::SubClass(parent_index),
         }
     }
-
     pub fn count(mut self, count: u8) -> Self {
         self.count = count;
         self
     }
-
     pub fn width(mut self, width: u8) -> Self {
-        self.width = width;
+        match self.proto {
+            RegClassProto::TopLevel(_) => self.width = width,
+            RegClassProto::SubClass(_) => panic!("Subclasses inherit their parent's width."),
+        }
         self
     }
 }
 
 pub struct RegBankBuilder {
     pub name: &'static str,
     pub units: u8,
     pub names: Vec<&'static str>,
--- a/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs
@@ -1,13 +1,13 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("arm32");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("arm32");
 
     let builder = RegBankBuilder::new("FloatRegs", "s")
         .units(64)
         .track_pressure(true);
     let float_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("IntRegs", "r")
         .units(16)
@@ -15,25 +15,25 @@ pub fn define() -> isa::TargetIsa {
     let int_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FlagRegs", "")
         .units(1)
         .names(vec!["nzcv"])
         .track_pressure(false);
     let flag_reg = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "S", float_regs).count(32);
+    let builder = RegClassBuilder::new_toplevel("S", float_regs).count(32);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "D", float_regs).width(2);
+    let builder = RegClassBuilder::new_toplevel("D", float_regs).width(2);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "Q", float_regs).width(4);
+    let builder = RegClassBuilder::new_toplevel("Q", float_regs).width(4);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
+    let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs
@@ -1,13 +1,13 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("arm64");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("arm64");
 
     // The `x31` regunit serves as the stack pointer / zero register depending on context. We
     // reserve it and don't model the difference.
     let builder = RegBankBuilder::new("IntRegs", "x")
         .units(32)
         .track_pressure(true);
     let int_regs = isa.add_reg_bank(builder);
 
@@ -17,19 +17,19 @@ pub fn define() -> isa::TargetIsa {
     let float_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FlagRegs", "")
         .units(1)
         .names(vec!["nzcv"])
         .track_pressure(false);
     let flag_reg = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
+    let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
+    let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs
@@ -57,19 +57,15 @@ impl fmt::Display for Isa {
             Isa::X86 => write!(f, "x86"),
             Isa::Arm32 => write!(f, "arm32"),
             Isa::Arm64 => write!(f, "arm64"),
         }
     }
 }
 
 pub fn define_all() -> Vec<TargetIsa> {
-    let isas = vec![
+    vec![
         riscv::define(),
         arm32::define(),
         arm64::define(),
         x86::define(),
-    ];
-    for isa in isas.iter() {
-        isa.check();
-    }
-    isas
+    ]
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs
@@ -1,24 +1,24 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("riscv");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("riscv");
 
     let builder = RegBankBuilder::new("IntRegs", "x")
         .units(32)
         .track_pressure(true);
     let int_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FloatRegs", "f")
         .units(32)
         .track_pressure(true);
     let float_regs = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
+    let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
+++ b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs
@@ -1,13 +1,13 @@
+use cdsl::isa::{TargetIsa, TargetIsaBuilder};
 use cdsl::regs::{RegBankBuilder, RegClassBuilder};
-use isa;
 
-pub fn define() -> isa::TargetIsa {
-    let mut isa = isa::TargetIsa::new("x86");
+pub fn define() -> TargetIsa {
+    let mut isa = TargetIsaBuilder::new("x86");
 
     let builder = RegBankBuilder::new("IntRegs", "r")
         .units(16)
         .names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
         .track_pressure(true);
     let int_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FloatRegs", "xmm")
@@ -16,28 +16,28 @@ pub fn define() -> isa::TargetIsa {
     let float_regs = isa.add_reg_bank(builder);
 
     let builder = RegBankBuilder::new("FlagRegs", "")
         .units(1)
         .names(vec!["rflags"])
         .track_pressure(false);
     let flag_reg = isa.add_reg_bank(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "GPR", int_regs);
+    let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
     let gpr = isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FPR", float_regs);
+    let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
     let fpr = isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::new_toplevel(&mut isa, "FLAG", flag_reg);
+    let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::subclass_of(&mut isa, "GPR8", gpr, 0, 8);
+    let builder = RegClassBuilder::subclass_of("GPR8", gpr, 0, 8);
     let gpr8 = isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::subclass_of(&mut isa, "ABCD", gpr8, 0, 4);
+    let builder = RegClassBuilder::subclass_of("ABCD", gpr8, 0, 4);
     isa.add_reg_class(builder);
 
-    let builder = RegClassBuilder::subclass_of(&mut isa, "FPR8", fpr, 0, 8);
+    let builder = RegClassBuilder::subclass_of("FPR8", fpr, 0, 8);
     isa.add_reg_class(builder);
 
-    isa
+    isa.finish()
 }
--- a/third_party/rust/cranelift-codegen/.cargo-checksum.json
+++ b/third_party/rust/cranelift-codegen/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"0b0ed9a5aee750b88bed0d2a120fc9ca0a8dcf3a92a03582f08e7287ce3fbb4a","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"513cfea9d05e69a1f3b596f91f40dd380ab0368931e5dc869dbd3959192b6792","meta-python/base/__init__.py":"4fac8bb055541dc964383bb04223bae6dfbfe348abf5e23f83655966cbb4aa8f","meta-python/base/entities.py":"0e146dd56dfb93cac88f9557a3501c9804cff584c2723db27435842bb5e2a1b7","meta-python/base/formats.py":"f9fb41210bc1f99a78cb7a60ee9f01c603412c6b1db7e69abbcc0f573cf9fb40","meta-python/base/immediates.py":"f42682d86bda7b569ec2fc2debd9036355999e61caaa9fbf8307e0be8a164814","meta-python/base/instructions.py":"4c3f8ee6c29e8cc9e19172f707890d613ed4173bda9b9de7857dae2b28babcbd","meta-python/base/legalize.py":"57b71ec3599fbf998c1926e4b48566661b7feec01dbd8bd177d0d2aaa26a44c2","meta-python/base/predicates.py":"53a5a9a37021a9762f0faec9f9e3c5b713411d47dd9192423cfe0f7a61916809","meta-python/base/semantics.py":"b90cbca9a143676ac37496c83634a66a83360248e4505ff7bda12b0d454efd92","meta-python/base/settings.py":"97fca9ddaab347f50f1594c93283f8f474e53a7232eae65949f56a6a702c2bba","meta-python/base/types.py":"9616d6fe4cab050827ab02eeb9843eacebbb8f7555521f504b5ee2ddf7214fdb","meta-python/build.py":"b72a80a54e09366878e92dca3a1508af394bf71a0c4b07a05e54058901373d34","meta-python/cdsl/__init__.py":"b531693b8228553ca8bd07e1dcd1aa5855f1ad3741b431d758fc27fdd162b024","meta-python/cdsl/ast.py":"b7c09f69b28b5754f494912ca5b77722dbd4ee416d5fad79cb48322eb544ea9f","meta-python/cdsl/formats.py":"fedfeaec754b40d6a9cc92b827976782c615d8eab1c7f47f6b47510cbef585f4","meta-python/cdsl/instructions.py":"b0ddfd8fd22889bd1e610c103d47087c9c6ae5882862ed44921dafc2ae0463a0","meta-python/cdsl/isa.py":"96e31674d699cfc846f65ee2ab62a199215e7ce012c6d43ea36ea5d2f839402e","meta-python/cdsl/operands.py":"e24914eae4059b88781bf5a5d7a14ecf98b10a701ed6cf6e88d15981b2ccbfdf","meta-python/cdsl/predicates.py":"def3f91712744671df9cf3d4f9c255a2061f341198689e31addf7db4efb63e36","meta-python/cdsl/registers.py":"939dafd1b8976a6cd456c9a5e4b374af81fafb9da979ea3a1f6d14e4645914a6","meta-python/cdsl/settings.py":"18dc27dd98a82c814c6aeb2686b40d1fed23661bef5e8b4cbf0fb4e7d39f4755","meta-python/cdsl/test_ast.py":"947e934e2862445a158bf266dff58a8c88aae31fb34a7f823309ee58a15c5393","meta-python/cdsl/test_package.py":"ffa53d20e023ecb89137294bb13614f4de9b09e1bf05d9772131570bf78f7987","meta-python/cdsl/test_ti.py":"57966c9eb027fa73bbc7ad81094ff55232053fbb2e16d78849ae3b6e9b1c2989","meta-python/cdsl/test_typevar.py":"714b2d564af1a843629279501436d681cd6590d1988b59e9f50ec940506538bb","meta-python/cdsl/test_xform.py":"ddb6633c7941bbf68570701cb887a81d6b4b27f4bc45eabccf2ce287ad9b77e9","meta-python/cdsl/ti.py":"a1a7ff79f8a2196aee491a3aafbd4f1b231004bbb5281992fc8f4e43f4fb951f","meta-python/cdsl/types.py":"adee4bbc1a9478288fa4b53ee1edeb5ee3296dba2c70bfbe01e923895064999e","meta-python/cdsl/typevar.py":"b5669934eddaf5b9cc0c27b966e2566b5f669f1c5a345f005960930fb499097e","meta-python/cdsl/xform.py":"5cdad80f12d50aa9491cd3d39797e6c0444936bb0874199d7c34e6d735658b34","meta-python/check.sh":"9e2f70f2d762c840f1d49519b024b4c1b93168137184b5e3e605e55813c62ea5","meta-python/constant_hash.py":"c752e6dadf3a9a5bd00c978e85ab27a20c49138a1ccdc6fc9a1904797a4bfe48","meta-python/gen_binemit.py":"76472fb199a330b934ba9ad0a1bbacfb52f0eae7c9a66d83f0d7890970323a2d","meta-python/gen_build_deps.py":"3920c5c89451c26102f7d87c61de64c94e915a545bc8a35d2e49106aecf019ec","meta-python/gen_encoding.py":"0b57d9d74a72a1b3b11721166fdbaa8b8c4b2d7493fc10b88736ac330b83256f","meta-python/gen_instr.py":"7ccd6a6bb1ce1800ea9c2c37e462ac7ded4f908e311d708080f7d21d92578316","meta-python/gen_legalizer.py":"187a47f1702e07487fb8a13076aadcf9c2de3e801d367424dc847ff7b0ed70f1","meta-python/gen_settings.py":"44c231ab8d2aa4f18cbe4fb5a33fb72103503d58f5af22c7b545eeffbf97da79","meta-python/isa/__init__.py":"e499c1206cd095a926fa0ca7eb9d0a50a802ed71c8eb7598e5d3a0f939c8ada5","meta-python/isa/arm32/__init__.py":"eecba73231aa398ded7304690bdba3450dc163afd4360f1b0ad02a28e2380363","meta-python/isa/arm32/defs.py":"01c41dbd7406c624e26229df6befa0992194bddcc7d11e8f6174abfe2b33bf61","meta-python/isa/arm32/registers.py":"c03ca6435828ad5f262049e42f1f71bcf74903831f85daa92c3f322a6c1050ea","meta-python/isa/arm32/settings.py":"afd5a04a9d029f578d6f62dc7c539191886cc9f9dea15d65fc66bf37a63b8814","meta-python/isa/arm64/__init__.py":"f6877253cf786d7ee972881e7d9b3c78c11e6b024e4e227487340dd01d0c44e4","meta-python/isa/arm64/defs.py":"797c5bb6d11fc7a44afe67476136dbd11c40f5e13a1c8f52f9f96be4441677b2","meta-python/isa/arm64/registers.py":"9bdd06edaa382be96042e1ac36d63137e73292292b61dcf4becb7d1428130317","meta-python/isa/arm64/settings.py":"f7b1f8733e775ea8005372ee35f1c2a627b3a69d722e837295599e4cf1f5eb43","meta-python/isa/riscv/__init__.py":"c11607c9eef0bc2707daa3edd4174e934c7a0dcc8ce90cee2c9292a85b1ac596","meta-python/isa/riscv/defs.py":"e73740055c4fb123c45453fc149a807e9720466de848022d5375049bdcfc311c","meta-python/isa/riscv/encodings.py":"ecaad5ea98273ade1cb10606354e893342c495bb48771df50121f789566d7be6","meta-python/isa/riscv/recipes.py":"3852e5b7aa6995fa721ba91744a0470343ce1834651e7b9cc97b5d69af7dfdc5","meta-python/isa/riscv/registers.py":"ef9aca3a6ec2b08ee8f5952186d232861b64a919b671b41911a365e7672b01bd","meta-python/isa/riscv/settings.py":"dfe29722d67be0620a70e08cfb802829a26f5fd339a9342a8ac2dd419daf8a85","meta-python/isa/x86/__init__.py":"ad579de68ea7bf5dc2bce0e3a6f09e7978b1697f1afec8a5ce5dc591136e590d","meta-python/isa/x86/defs.py":"b5eb7889b6f5e5b221ed3923d0137bbb1566c55b5961448cc39e4ea2f13cf4b7","meta-python/isa/x86/encodings.py":"dc758c5bf95b9271e70203c481df0dc9b3363c4f730cfc564e4e3f5f275a6433","meta-python/isa/x86/instructions.py":"530cde78e6b9f6e4ea2192985f4c5c77a987cdc19001d50fb47fa8e36a62f52e","meta-python/isa/x86/legalize.py":"1375ded072c29459e7c0e40ecb02f28d5395d9d8c603eb70e338b2bf2991c9cd","meta-python/isa/x86/recipes.py":"edc60f964816026e27136cb284eec28220f088b472a54e1bd90b3e8ccfe0648d","meta-python/isa/x86/registers.py":"ff934491d07ec6b51fbfd454b865a7c7c191ffbd31b1804615735266b120f4b2","meta-python/isa/x86/settings.py":"d779a768475cf00c2a8d3ddb5cd0a70ce34662e0ebb52ee26a7e1a495ec41aa2","meta-python/mypy.ini":"5ec2f7cc0bbc4fd0435643d6b72e715bd9568a3a0fe14c043f9e559c405b66fb","meta-python/semantics/__init__.py":"e8a25a111f2d9cc9fc7aa498a572a86403d31fe50a7ba59dd2e2560a17804e92","meta-python/semantics/elaborate.py":"3a3fbba83a6818c2d1ce236fd0413111380875a0307f7a5f4b5dd66d8ef714b1","meta-python/semantics/macros.py":"b218c52e1bd4f019dc14a27d315b4f3405a10e5bdc6f2523fe709c8faf91b418","meta-python/semantics/primitives.py":"4e5eb0c90fcc295686732c8c66ad7a793997645c9a676c97babf06823fd2b60d","meta-python/semantics/smtlib.py":"825edfbb9221bf59c02fea26e55d17cf32194da7a9f56ed0e035c44353481055","meta-python/semantics/test_elaborate.py":"3a4c850a7385007422c7549661b211903cd1dd1606dad7a86262ae27e697bca6","meta-python/srcgen.py":"999557d683e808a2ca90688c489ec4aff65798f44ac321ecf7de34d307261913","meta-python/stubs/z3/__init__.pyi":"6aaeb80f783b29c4364dee21da45f6df041c0a4807189a15777ee5447f6515dc","meta-python/stubs/z3/z3core.pyi":"c01a41d468e07cc4f8b405c292ed7f8c82bc1077f8b82dfde1e474577ade3335","meta-python/stubs/z3/z3types.pyi":"30009c951af99b9028d47cd4cabae95ff9742b77b690bd8dd63f6b7dba580759","meta-python/test_constant_hash.py":"157cf4f8964e0f04c041ffd349e889ce565b144453436690578c5d03c3a60216","meta-python/test_gen_legalizer.py":"f16edce7cb2ce53e55b1fc56b6f5ba6a0fc61b291ee4513ec859e36d69f0e285","meta-python/test_srcgen.py":"d6d7775e19a5b2621360c00eb6d92dfcb4568e49220993e0ceaac9628dbfd661","meta-python/unique_table.py":"5bd500667430c15f6ae586603d8612fb3bda07b072e40d86286e08392bdc3127","src/abi.rs":"29f505fdfcb6ec14e561bb408b99ab30ab69b96d1e283a1dcd55db9aff02dbe4","src/binemit/memorysink.rs":"8437e5f5c1b3e68b8e2d0de6fb3a4982f7a06390a0f8820b6379492408df8964","src/binemit/mod.rs":"2f95ea5f6ee20b8d56bdedcacdd41a609c5b999c02affca341d6a71eb59bc113","src/binemit/relaxation.rs":"5facfa8e15a26cba42210102a6fd735df1ba291adf512dabc85c0951239291f8","src/binemit/shrink.rs":"428679a02e44a7b3621a43c7d2e8d2f3b2cb50a36179a4d9862205c0ba34ae50","src/bitset.rs":"67fd02dd2acb9af73e45426e5cab1d2a74d568a11d11ee17ae6a4421f96cf741","src/cfg_printer.rs":"8c0fda88060c204985a6406ba46d7f0a69be96bb18c9fcfc70055d50986068ab","src/constant_hash.rs":"493cdf8f607eab01bb52f93d616fb6190c7c86d3a02e530b0ced30993d4bfda0","src/context.rs":"bfb491dc9c99c05cb906caec4a198a962ae4733ac32eda8f4aad127735511488","src/cursor.rs":"523899307d471f63e9ca35ee4b3340cf55041561a05b199e11cc60f6ad2714f4","src/dbg.rs":"bae915e1f7544f725817b368aed00a6aaa9e394a454dc847d65ad44e54d78cb9","src/dce.rs":"6d015824ae0325f01bb523606d7e15dd5feeb72a75b947f40385feeba94555c8","src/divconst_magic_numbers.rs":"eac50e2353e17ab6f7d1da3bd8e0e8dc9e3122a160efba594d407eb6a8936cc7","src/dominator_tree.rs":"73032e0e7a0ab694aa3181222bccb40630bd6fbda33885a391fd662f7de7d540","src/flowgraph.rs":"fccfade2b24038e18d469e273976f418757159fde140642b5faeb3c664a756ce","src/fx.rs":"2fb53f141b3e6be1882a1e4afac4bc607ce694f045d9329ee823e0aca415898e","src/ir/builder.rs":"19aa7cef76b7577bdd9d769fb1260080a959f9bfdbac569fb1e38307a721a03c","src/ir/condcodes.rs":"5456a25798516245b0923c9e12ae0af5cc98c097fc6f3bc0bf2d7af5008667f7","src/ir/dfg.rs":"bc975909538056b9f1dc1dacf4f6078d93f2983ad7de1c8fba3c4bee028dcc85","src/ir/entities.rs":"1505347c2baa256b04f69384d1391f52e007d533cb4319d3826cf3046ec1df27","src/ir/extfunc.rs":"9a3535730a39a6b71ca9f1ed679f588e6c3fa48ee7a50489d90803f3134db4a6","src/ir/extname.rs":"839e3d694e5c109bb594fe31c7d9dfe4f156bbc2eb695f3412fd39c325374b91","src/ir/function.rs":"55feb0b0a2bf4a0d194a4d11fc297616c78d5edfa41504795742fd25e7af1399","src/ir/globalvalue.rs":"bf9b76430f6ba564d4e5db85dbebfddf952678be6914326a5549b569c064d03d","src/ir/heap.rs":"dc9d4f0eade20d58b3e2678c329452fbd5965c46d6121cbf5889f2588ae88772","src/ir/immediates.rs":"5f57bc2a46b7ca11e1e495e657cedbf493194025eceb6591ba8792aff6910f88","src/ir/instructions.rs":"be6493d0a507f1a9a9ec37a3bb976998ee8e1355c44ae7c656c82a6edacfbec7","src/ir/jumptable.rs":"3fc108096e5404c4c30220cfaa4e359caa83bad747268bea88bbc0ac4b1bcd13","src/ir/layout.rs":"77210d256e39d339736ced5518c8d666da6359f656b972d6b6b19581ccaec329","src/ir/libcall.rs":"b35c8d0c90e686a176f9bd157ef6ab3819e8a0b974d0d24007a910ffb0d15f51","src/ir/memflags.rs":"5819e1171c620f171020bf26df9513eb6bee9890da8a7ebabbd1506b1d123f91","src/ir/mod.rs":"16566fb92fc16498d5a2699fa76dfdbc39665a4e8bae3040c03e4f3d2f07e3cb","src/ir/progpoint.rs":"d5191447f82bb612ae25ebceb5ecc2099a902be5aaecd5b9d418dcbd8a2747a5","src/ir/sourceloc.rs":"79eb71609b844839994fc735cd72edf53179eb659303a4150634928e207cee4f","src/ir/stackslot.rs":"d5d0c61555bf7060c58603047356b7db53b5b296497daed8eac356b9e724902d","src/ir/table.rs":"810e92631257e1e54577563df1da9709134438d0eab3db5e540500e69437a16b","src/ir/trapcode.rs":"233d73e4a2abbfc767aac7868d4adbb24cedaf8e7e42a640d590bda2e776784a","src/ir/types.rs":"1f93f886dba75f6bc267b35e2fc6ed1564074a8885af13d6c85c28574acf8436","src/ir/valueloc.rs":"5055897d9acba6d9c396b126889f9b2c7ff3f54a27c1ec5fe70d1a059d633b36","src/isa/arm32/abi.rs":"50ca3161a0f11ba1c2d5b0ff7523d332503cb6a6182695246e4284a486e18cab","src/isa/arm32/binemit.rs":"3197df7b15c223f3a9f2708311375ff423bb247381cf21e26da079f7933f5279","src/isa/arm32/enc_tables.rs":"dacb50bdacfa2085a6283818563e19874590d223e5decb5c91b968e0348e2bf7","src/isa/arm32/mod.rs":"798049325ca439444a5508f63ebb53bf2e0ab16b128c43417017bbdb2fd95742","src/isa/arm32/registers.rs":"0e5c32a218d685c6d37fb46788baedf6bede6be7d4f715808c13620636dfc472","src/isa/arm32/settings.rs":"145f59227c6087e7872f66a6d2183c66e061c40466e7b427a733136e41e41207","src/isa/arm64/abi.rs":"bfd0065a6c26eb407872959c9d7f64169591afa4d69816370e0900aa1ad4e46f","src/isa/arm64/binemit.rs":"159ab9eca03ac4aa7f55d51ab20585a5971d95a74c61953d1899ac863b06e2ec","src/isa/arm64/enc_tables.rs":"00ec8f53402f6cb73716db1adb3aca564574833cab58dc12b4dc6ba8c4529a73","src/isa/arm64/mod.rs":"4eef5f904f2219262c59dae7056af5adb7764074309dffc0be5b2357781dd1a6","src/isa/arm64/registers.rs":"7a8b207ed28737efc737e8e65ce79e7e7d3eecd23599890230dca8474c985026","src/isa/arm64/settings.rs":"7b466fcc2c58bc1846a72f08ec58900b3cf622ab2922ee9128e6dfe254907bf5","src/isa/call_conv.rs":"4bc8f8cc540ed54cf1e4c4688a1a8a975ed49a039a48d44a2c6b97f847b65ea8","src/isa/constraints.rs":"324d7c8655565f13b90a6c9587c9fb6c545ab3086201f434e1324fc5d6e5b3c7","src/isa/enc_tables.rs":"c8e9b1293917d061fcb26899cc21bd6f6c99f29ef5d1da8e2c537f343cf4ec64","src/isa/encoding.rs":"032347d4e624449af7a35f7ba012339bc49fabae97b971818e922d6ca4510e59","src/isa/mod.rs":"e3cbdf52862ac052292965dc399d832e9684a42099df5d5fd06f5fcdf5781cba","src/isa/registers.rs":"c0014dc940e8a6da628c60e49f6261cebaee1e06e0ea1c172de5f797e600535c","src/isa/riscv/abi.rs":"1de6d0070126e0127ca6a63551a14d1b5c030cf9628538fd732301fd2bd34b5e","src/isa/riscv/binemit.rs":"3bdad2791447f51bfe5ecedb73b1aed8a6a8809790b1f26e3ff624a89163a026","src/isa/riscv/enc_tables.rs":"6bc179f95ef5634b64fb42ab67929c0aeb70ac8efccfc47dd8c9b1dbfe64a446","src/isa/riscv/mod.rs":"de0dd32005f6b0510e3c8a31bb7e58ab7e7cffb674169a08558794950db87126","src/isa/riscv/registers.rs":"794ac61343a8db66dc99b2ca964ea3986b47b37fe8b72575c644c1cdaabd2991","src/isa/riscv/settings.rs":"78ced69b82d89f83b5612a91d0acdac2616f9091b380ee3e4715adb31f95b232","src/isa/stack.rs":"ec96130c446cd7d637722f1603e38d5164498368b652f4b0454baf3227385ad4","src/isa/x86/abi.rs":"82d592bfae4810813f7d1328e172376f7679f077834c0150d776d0d08842d089","src/isa/x86/binemit.rs":"f90820a1f9c4ad02f3507625d35f014f644d8cea93b0216bcc60cc05cc84eacc","src/isa/x86/enc_tables.rs":"06c625ceef65e395d8134597b20496f3ea0874e13ecf84fa2ff2a8e9e623b2b6","src/isa/x86/mod.rs":"bc83c0e619e8603885359c472b4113bc83b8867dd2d8e83b27f798301c6df93c","src/isa/x86/registers.rs":"783ebbe4c3b4711fe1eac2cfd3bbea7c31a53c15c6028397c038ef4eb0b2aa06","src/isa/x86/settings.rs":"dcce098045c1115cd55f256dcd3e0ccaa5a0c9ad93b14fb8a4c680e95caf2b73","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"ff36220e78d9639046b1c9741c93f5333aa412256949b8842b6c31f97a6e441b","src/legalizer/call.rs":"12f380d126765f0bc2da1cf298088fa98451e2d6bf56c34b755ff7077d14a4f1","src/legalizer/globalvalue.rs":"be6fc6e310dedde48e172453eccaa7cb416baa92e1adfc55f565d51159c930cc","src/legalizer/heap.rs":"c44a0845254187dfe7456b0b9efbfea25ae566772bc64b41ed93dd32a71f8e8a","src/legalizer/libcall.rs":"bf18267f502bf9bfbc3ff51bc05df480293a84422ea7f4c37dd0c75e97952766","src/legalizer/mod.rs":"f516c4e22fb66099678f753121dfa92128f2c4524ea4196e1b400e06e6649d44","src/legalizer/split.rs":"ae07854aad2ff2aa83a6ba08276b49a462dda0591faa9a61bdc7ca787451078f","src/legalizer/table.rs":"2aca27ea564c2ef02ed833c495156b9e1ddcee3c8a1b1e70347ab5907a381605","src/lib.rs":"1542f5cae0d80c408f190d225890da959e0b4033687b6c2480e83254341cba83","src/licm.rs":"9657ccfdcf7a52eca1ba201d455f1d538f17aaa6295b9651282de9f7c79a53b9","src/loop_analysis.rs":"ab74f702649ddd16d3d91400c3c2aafed4f09d9af210f5e180dff15a82caf8ac","src/nan_canonicalization.rs":"e2b1f9935d14af9abe553de1eda5483cffdaa7098dd1a17ba9a98fa04280b22c","src/partition_slice.rs":"55b9e857f452baf4d6312779861f9ef93b3d5300467e752230ec6af14943efe3","src/postopt.rs":"f1fe06398c644cad19fd427323c74acdb237b5853ffb72148a2b2012b906e2a3","src/predicates.rs":"8e4c4afde65420d33621aedd80e4ce270d334c1b62a17d7879273a1719d49b41","src/print_errors.rs":"60f9ba4ca69a0c307915d9e7290dbf15c6622e688a3c02911b67f9e8568b4111","src/ref_slice.rs":"9be914b705eefcc6b4e38db573f56ad7b978f4b65c2f6f8f5516df78fb2206a4","src/regalloc/affinity.rs":"47e28f9ae7cebfc9b1006480143a3a5ab1b118ec761a163c4a670b63fdc47d0a","src/regalloc/coalescing.rs":"253e3fb916c37453f0fa4f963caf5336712d60447e39f63a6696c2ad22cb102f","src/regalloc/coloring.rs":"baf4861cabfc897755bef0b25a8367148bd2468717b3571763a5cc599407e5c2","src/regalloc/context.rs":"794f9f0fb3b980feb3be57b95c152767cb318b81aca48c27197b01b7d529c48d","src/regalloc/diversion.rs":"cbb942a197081f9e537f3fed71a7ec6d6d1edc18b8536fa46a1dda316f46c776","src/regalloc/live_value_tracker.rs":"054efd9e8da0f33a158082f67a7c2c14f7c8632b1fc28d54941ca7bc9d5a46d6","src/regalloc/liveness.rs":"6886e52e68aee5b2e26fb0b6e073905e7fa963eb597657fc966e5758cda4c254","src/regalloc/liverange.rs":"3c6a34e35a912dce48fa9a579e82e14a7e64334d5572b0d74dbfbf42dd380804","src/regalloc/mod.rs":"6254df639f9289fd578e01b7dca99bc9c9e3c6680c6d031405e8df8d0cff31ad","src/regalloc/pressure.rs":"7c73ca1f54559b1d9f8ce587bdc067e74f3d47901058f7ae1e9277516624236f","src/regalloc/register_set.rs":"e1554d01a3a5a13acc4e0092681eb3fc090d9c68eb71f8a9985c01c7a3f2e3e2","src/regalloc/reload.rs":"82040d3a3115f9117e11a77ee4e6d2437c1af84e0ee0b541ca286c5434c10e98","src/regalloc/solver.rs":"853c6f16f68e75add56981b132d92e556a94d8cbd13fed311df2d75da08de03a","src/regalloc/spilling.rs":"8ca113a149090c864df63e70a7f3a6c68c2edc655a5dd057724d63fc6319a8de","src/regalloc/virtregs.rs":"af5a0604557760a469f4aafd1047b73a8aaf5a1c19f6914a989a1a71662627a4","src/result.rs":"d43abf9b22c5ad772200889bba339bcc4455c7abb9f2f3a2af65fbbaf1130009","src/scoped_hash_map.rs":"102797c380a588f7c16d26bf3b6c9cff28d37c2d8168a382b265194cd8969212","src/settings.rs":"18f3b43b5ec916b5969a62a6bbf0b7b8f039a5f7930e406bb7e8f181f2dc0d2d","src/simple_gvn.rs":"fae3d71f7ab684044d8710e2193f26bf81e4b8a6f28de87b5caf1ca95eedc7ff","src/simple_preopt.rs":"cfafd0398bba0b3e2b91b5bf10617bd4048ba2b22345b3e5bfc403239903960a","src/stack_layout.rs":"ce0b4b188cc46fa5070139124ffb2d263d44acd08703e7043a40b5c1afa952fb","src/timing.rs":"79acc12600ace2b144f1d7d82e01c023596e418a84042cf70ef93df928cdcabf","src/topo_order.rs":"73ec442db1cc9a282cf9c5b715ad2f60c4d2872080c16fd04ef7091d56816fbd","src/unreachable_code.rs":"6fdea8f9afe9fbffe411bfef48fec7937cb41d51036fd190a3d0a5f0cc2894c6","src/verifier/cssa.rs":"8f41765d18474575faa7c44a0345549dabe0af07141e2f004a7db1c67486ce77","src/verifier/flags.rs":"0665b4cbeef762c3871ba3cc55b0b1a27c513e25cbd3f93a725aa3d636a23c72","src/verifier/liveness.rs":"6e827f05461bd6fb21b0ce99f02fae374f2d6ea6e7e14ba61e88983a1c6fac4b","src/verifier/locations.rs":"a83f7d58118a838651c80f55e2455736e79235691692488d8431b77be8093a58","src/verifier/mod.rs":"88e89da3a893a2c31c56596f49a0b5e4f4c92766115d661eb1f770d562454ac0","src/write.rs":"02995cbc87e2b15ed4021b88bcb36782975bedacc89282c5129923d20b4abc37"},"package":"4437ec8212686e6cdacfea75aaedb4ab8b013869be1e8693a4cb97a60f135035"}
\ No newline at end of file
+{"files":{"Cargo.toml":"d6b246e5928dba1141afc7402f2ac29dfd6e467640efc77282e5cb9080f1bf99","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"e5127227a7db4a8aa92fa6613ed71801025790e696bb41b0323fb7f3c6f7495a","build.rs":"dc816beb002843cd9fcdb47dae9a0a8e3612882411f18bed34d7fda1aa108d90","meta-python/base/__init__.py":"4fac8bb055541dc964383bb04223bae6dfbfe348abf5e23f83655966cbb4aa8f","meta-python/base/entities.py":"0e146dd56dfb93cac88f9557a3501c9804cff584c2723db27435842bb5e2a1b7","meta-python/base/formats.py":"f9fb41210bc1f99a78cb7a60ee9f01c603412c6b1db7e69abbcc0f573cf9fb40","meta-python/base/immediates.py":"f42682d86bda7b569ec2fc2debd9036355999e61caaa9fbf8307e0be8a164814","meta-python/base/instructions.py":"4c3f8ee6c29e8cc9e19172f707890d613ed4173bda9b9de7857dae2b28babcbd","meta-python/base/legalize.py":"57b71ec3599fbf998c1926e4b48566661b7feec01dbd8bd177d0d2aaa26a44c2","meta-python/base/predicates.py":"53a5a9a37021a9762f0faec9f9e3c5b713411d47dd9192423cfe0f7a61916809","meta-python/base/semantics.py":"b90cbca9a143676ac37496c83634a66a83360248e4505ff7bda12b0d454efd92","meta-python/base/settings.py":"97fca9ddaab347f50f1594c93283f8f474e53a7232eae65949f56a6a702c2bba","meta-python/base/types.py":"9616d6fe4cab050827ab02eeb9843eacebbb8f7555521f504b5ee2ddf7214fdb","meta-python/build.py":"b72a80a54e09366878e92dca3a1508af394bf71a0c4b07a05e54058901373d34","meta-python/cdsl/__init__.py":"b531693b8228553ca8bd07e1dcd1aa5855f1ad3741b431d758fc27fdd162b024","meta-python/cdsl/ast.py":"b7c09f69b28b5754f494912ca5b77722dbd4ee416d5fad79cb48322eb544ea9f","meta-python/cdsl/formats.py":"fedfeaec754b40d6a9cc92b827976782c615d8eab1c7f47f6b47510cbef585f4","meta-python/cdsl/instructions.py":"b0ddfd8fd22889bd1e610c103d47087c9c6ae5882862ed44921dafc2ae0463a0","meta-python/cdsl/isa.py":"dc530a4dd5642e3379398dfc8a90ad6ae1692302de63851370bdfa8abf4cdce0","meta-python/cdsl/operands.py":"e24914eae4059b88781bf5a5d7a14ecf98b10a701ed6cf6e88d15981b2ccbfdf","meta-python/cdsl/predicates.py":"def3f91712744671df9cf3d4f9c255a2061f341198689e31addf7db4efb63e36","meta-python/cdsl/registers.py":"939dafd1b8976a6cd456c9a5e4b374af81fafb9da979ea3a1f6d14e4645914a6","meta-python/cdsl/settings.py":"18dc27dd98a82c814c6aeb2686b40d1fed23661bef5e8b4cbf0fb4e7d39f4755","meta-python/cdsl/test_ast.py":"947e934e2862445a158bf266dff58a8c88aae31fb34a7f823309ee58a15c5393","meta-python/cdsl/test_package.py":"ffa53d20e023ecb89137294bb13614f4de9b09e1bf05d9772131570bf78f7987","meta-python/cdsl/test_ti.py":"57966c9eb027fa73bbc7ad81094ff55232053fbb2e16d78849ae3b6e9b1c2989","meta-python/cdsl/test_typevar.py":"714b2d564af1a843629279501436d681cd6590d1988b59e9f50ec940506538bb","meta-python/cdsl/test_xform.py":"ddb6633c7941bbf68570701cb887a81d6b4b27f4bc45eabccf2ce287ad9b77e9","meta-python/cdsl/ti.py":"a1a7ff79f8a2196aee491a3aafbd4f1b231004bbb5281992fc8f4e43f4fb951f","meta-python/cdsl/types.py":"adee4bbc1a9478288fa4b53ee1edeb5ee3296dba2c70bfbe01e923895064999e","meta-python/cdsl/typevar.py":"b5669934eddaf5b9cc0c27b966e2566b5f669f1c5a345f005960930fb499097e","meta-python/cdsl/xform.py":"5cdad80f12d50aa9491cd3d39797e6c0444936bb0874199d7c34e6d735658b34","meta-python/check.sh":"9e2f70f2d762c840f1d49519b024b4c1b93168137184b5e3e605e55813c62ea5","meta-python/constant_hash.py":"c752e6dadf3a9a5bd00c978e85ab27a20c49138a1ccdc6fc9a1904797a4bfe48","meta-python/gen_binemit.py":"76472fb199a330b934ba9ad0a1bbacfb52f0eae7c9a66d83f0d7890970323a2d","meta-python/gen_build_deps.py":"3920c5c89451c26102f7d87c61de64c94e915a545bc8a35d2e49106aecf019ec","meta-python/gen_encoding.py":"0b57d9d74a72a1b3b11721166fdbaa8b8c4b2d7493fc10b88736ac330b83256f","meta-python/gen_instr.py":"7ccd6a6bb1ce1800ea9c2c37e462ac7ded4f908e311d708080f7d21d92578316","meta-python/gen_legalizer.py":"187a47f1702e07487fb8a13076aadcf9c2de3e801d367424dc847ff7b0ed70f1","meta-python/gen_settings.py":"44c231ab8d2aa4f18cbe4fb5a33fb72103503d58f5af22c7b545eeffbf97da79","meta-python/isa/__init__.py":"e499c1206cd095a926fa0ca7eb9d0a50a802ed71c8eb7598e5d3a0f939c8ada5","meta-python/isa/arm32/__init__.py":"eecba73231aa398ded7304690bdba3450dc163afd4360f1b0ad02a28e2380363","meta-python/isa/arm32/defs.py":"01c41dbd7406c624e26229df6befa0992194bddcc7d11e8f6174abfe2b33bf61","meta-python/isa/arm32/registers.py":"c03ca6435828ad5f262049e42f1f71bcf74903831f85daa92c3f322a6c1050ea","meta-python/isa/arm32/settings.py":"afd5a04a9d029f578d6f62dc7c539191886cc9f9dea15d65fc66bf37a63b8814","meta-python/isa/arm64/__init__.py":"f6877253cf786d7ee972881e7d9b3c78c11e6b024e4e227487340dd01d0c44e4","meta-python/isa/arm64/defs.py":"797c5bb6d11fc7a44afe67476136dbd11c40f5e13a1c8f52f9f96be4441677b2","meta-python/isa/arm64/registers.py":"9bdd06edaa382be96042e1ac36d63137e73292292b61dcf4becb7d1428130317","meta-python/isa/arm64/settings.py":"f7b1f8733e775ea8005372ee35f1c2a627b3a69d722e837295599e4cf1f5eb43","meta-python/isa/riscv/__init__.py":"c11607c9eef0bc2707daa3edd4174e934c7a0dcc8ce90cee2c9292a85b1ac596","meta-python/isa/riscv/defs.py":"e73740055c4fb123c45453fc149a807e9720466de848022d5375049bdcfc311c","meta-python/isa/riscv/encodings.py":"ecaad5ea98273ade1cb10606354e893342c495bb48771df50121f789566d7be6","meta-python/isa/riscv/recipes.py":"3852e5b7aa6995fa721ba91744a0470343ce1834651e7b9cc97b5d69af7dfdc5","meta-python/isa/riscv/registers.py":"ef9aca3a6ec2b08ee8f5952186d232861b64a919b671b41911a365e7672b01bd","meta-python/isa/riscv/settings.py":"dfe29722d67be0620a70e08cfb802829a26f5fd339a9342a8ac2dd419daf8a85","meta-python/isa/x86/__init__.py":"ad579de68ea7bf5dc2bce0e3a6f09e7978b1697f1afec8a5ce5dc591136e590d","meta-python/isa/x86/defs.py":"b5eb7889b6f5e5b221ed3923d0137bbb1566c55b5961448cc39e4ea2f13cf4b7","meta-python/isa/x86/encodings.py":"dc758c5bf95b9271e70203c481df0dc9b3363c4f730cfc564e4e3f5f275a6433","meta-python/isa/x86/instructions.py":"530cde78e6b9f6e4ea2192985f4c5c77a987cdc19001d50fb47fa8e36a62f52e","meta-python/isa/x86/legalize.py":"1375ded072c29459e7c0e40ecb02f28d5395d9d8c603eb70e338b2bf2991c9cd","meta-python/isa/x86/recipes.py":"ca56edb2bb87389e2db95d0f0e0fdbf9b27242192de764d60971828bb9a02e60","meta-python/isa/x86/registers.py":"ff934491d07ec6b51fbfd454b865a7c7c191ffbd31b1804615735266b120f4b2","meta-python/isa/x86/settings.py":"d779a768475cf00c2a8d3ddb5cd0a70ce34662e0ebb52ee26a7e1a495ec41aa2","meta-python/mypy.ini":"5ec2f7cc0bbc4fd0435643d6b72e715bd9568a3a0fe14c043f9e559c405b66fb","meta-python/semantics/__init__.py":"e8a25a111f2d9cc9fc7aa498a572a86403d31fe50a7ba59dd2e2560a17804e92","meta-python/semantics/elaborate.py":"3a3fbba83a6818c2d1ce236fd0413111380875a0307f7a5f4b5dd66d8ef714b1","meta-python/semantics/macros.py":"b218c52e1bd4f019dc14a27d315b4f3405a10e5bdc6f2523fe709c8faf91b418","meta-python/semantics/primitives.py":"4e5eb0c90fcc295686732c8c66ad7a793997645c9a676c97babf06823fd2b60d","meta-python/semantics/smtlib.py":"825edfbb9221bf59c02fea26e55d17cf32194da7a9f56ed0e035c44353481055","meta-python/semantics/test_elaborate.py":"3a4c850a7385007422c7549661b211903cd1dd1606dad7a86262ae27e697bca6","meta-python/srcgen.py":"999557d683e808a2ca90688c489ec4aff65798f44ac321ecf7de34d307261913","meta-python/stubs/z3/__init__.pyi":"6aaeb80f783b29c4364dee21da45f6df041c0a4807189a15777ee5447f6515dc","meta-python/stubs/z3/z3core.pyi":"c01a41d468e07cc4f8b405c292ed7f8c82bc1077f8b82dfde1e474577ade3335","meta-python/stubs/z3/z3types.pyi":"30009c951af99b9028d47cd4cabae95ff9742b77b690bd8dd63f6b7dba580759","meta-python/test_constant_hash.py":"157cf4f8964e0f04c041ffd349e889ce565b144453436690578c5d03c3a60216","meta-python/test_gen_legalizer.py":"f16edce7cb2ce53e55b1fc56b6f5ba6a0fc61b291ee4513ec859e36d69f0e285","meta-python/test_srcgen.py":"d6d7775e19a5b2621360c00eb6d92dfcb4568e49220993e0ceaac9628dbfd661","meta-python/unique_table.py":"5bd500667430c15f6ae586603d8612fb3bda07b072e40d86286e08392bdc3127","src/abi.rs":"29f505fdfcb6ec14e561bb408b99ab30ab69b96d1e283a1dcd55db9aff02dbe4","src/binemit/memorysink.rs":"8437e5f5c1b3e68b8e2d0de6fb3a4982f7a06390a0f8820b6379492408df8964","src/binemit/mod.rs":"2f95ea5f6ee20b8d56bdedcacdd41a609c5b999c02affca341d6a71eb59bc113","src/binemit/relaxation.rs":"5facfa8e15a26cba42210102a6fd735df1ba291adf512dabc85c0951239291f8","src/binemit/shrink.rs":"428679a02e44a7b3621a43c7d2e8d2f3b2cb50a36179a4d9862205c0ba34ae50","src/bitset.rs":"67fd02dd2acb9af73e45426e5cab1d2a74d568a11d11ee17ae6a4421f96cf741","src/cfg_printer.rs":"8c0fda88060c204985a6406ba46d7f0a69be96bb18c9fcfc70055d50986068ab","src/constant_hash.rs":"493cdf8f607eab01bb52f93d616fb6190c7c86d3a02e530b0ced30993d4bfda0","src/context.rs":"a44197bd5e05599b643c420d87ca4ad218a8c3ab2fb7b88655b2479014b117b2","src/cursor.rs":"523899307d471f63e9ca35ee4b3340cf55041561a05b199e11cc60f6ad2714f4","src/dbg.rs":"bae915e1f7544f725817b368aed00a6aaa9e394a454dc847d65ad44e54d78cb9","src/dce.rs":"6d015824ae0325f01bb523606d7e15dd5feeb72a75b947f40385feeba94555c8","src/divconst_magic_numbers.rs":"eac50e2353e17ab6f7d1da3bd8e0e8dc9e3122a160efba594d407eb6a8936cc7","src/dominator_tree.rs":"73032e0e7a0ab694aa3181222bccb40630bd6fbda33885a391fd662f7de7d540","src/flowgraph.rs":"fccfade2b24038e18d469e273976f418757159fde140642b5faeb3c664a756ce","src/fx.rs":"2fb53f141b3e6be1882a1e4afac4bc607ce694f045d9329ee823e0aca415898e","src/ir/builder.rs":"19aa7cef76b7577bdd9d769fb1260080a959f9bfdbac569fb1e38307a721a03c","src/ir/condcodes.rs":"5456a25798516245b0923c9e12ae0af5cc98c097fc6f3bc0bf2d7af5008667f7","src/ir/dfg.rs":"cf44ceda665e32d5bd4563d90094fdf519937adbd29096c7291065a2ebdcfbfe","src/ir/entities.rs":"1505347c2baa256b04f69384d1391f52e007d533cb4319d3826cf3046ec1df27","src/ir/extfunc.rs":"9a3535730a39a6b71ca9f1ed679f588e6c3fa48ee7a50489d90803f3134db4a6","src/ir/extname.rs":"5b50dddd0801dfe736433191502e405c879221a6e362be0e2919176b90b4d74c","src/ir/function.rs":"55feb0b0a2bf4a0d194a4d11fc297616c78d5edfa41504795742fd25e7af1399","src/ir/globalvalue.rs":"bf9b76430f6ba564d4e5db85dbebfddf952678be6914326a5549b569c064d03d","src/ir/heap.rs":"dc9d4f0eade20d58b3e2678c329452fbd5965c46d6121cbf5889f2588ae88772","src/ir/immediates.rs":"5f57bc2a46b7ca11e1e495e657cedbf493194025eceb6591ba8792aff6910f88","src/ir/instructions.rs":"2dd2ad70947122e791f41f6cbc7879fd201d4f96d19c138b56559428ba655dab","src/ir/jumptable.rs":"3fc108096e5404c4c30220cfaa4e359caa83bad747268bea88bbc0ac4b1bcd13","src/ir/layout.rs":"77210d256e39d339736ced5518c8d666da6359f656b972d6b6b19581ccaec329","src/ir/libcall.rs":"b35c8d0c90e686a176f9bd157ef6ab3819e8a0b974d0d24007a910ffb0d15f51","src/ir/memflags.rs":"5819e1171c620f171020bf26df9513eb6bee9890da8a7ebabbd1506b1d123f91","src/ir/mod.rs":"16566fb92fc16498d5a2699fa76dfdbc39665a4e8bae3040c03e4f3d2f07e3cb","src/ir/progpoint.rs":"d5191447f82bb612ae25ebceb5ecc2099a902be5aaecd5b9d418dcbd8a2747a5","src/ir/sourceloc.rs":"79eb71609b844839994fc735cd72edf53179eb659303a4150634928e207cee4f","src/ir/stackslot.rs":"d5d0c61555bf7060c58603047356b7db53b5b296497daed8eac356b9e724902d","src/ir/table.rs":"810e92631257e1e54577563df1da9709134438d0eab3db5e540500e69437a16b","src/ir/trapcode.rs":"233d73e4a2abbfc767aac7868d4adbb24cedaf8e7e42a640d590bda2e776784a","src/ir/types.rs":"1f93f886dba75f6bc267b35e2fc6ed1564074a8885af13d6c85c28574acf8436","src/ir/valueloc.rs":"5055897d9acba6d9c396b126889f9b2c7ff3f54a27c1ec5fe70d1a059d633b36","src/isa/arm32/abi.rs":"50ca3161a0f11ba1c2d5b0ff7523d332503cb6a6182695246e4284a486e18cab","src/isa/arm32/binemit.rs":"3197df7b15c223f3a9f2708311375ff423bb247381cf21e26da079f7933f5279","src/isa/arm32/enc_tables.rs":"dacb50bdacfa2085a6283818563e19874590d223e5decb5c91b968e0348e2bf7","src/isa/arm32/mod.rs":"798049325ca439444a5508f63ebb53bf2e0ab16b128c43417017bbdb2fd95742","src/isa/arm32/registers.rs":"0e5c32a218d685c6d37fb46788baedf6bede6be7d4f715808c13620636dfc472","src/isa/arm32/settings.rs":"145f59227c6087e7872f66a6d2183c66e061c40466e7b427a733136e41e41207","src/isa/arm64/abi.rs":"bfd0065a6c26eb407872959c9d7f64169591afa4d69816370e0900aa1ad4e46f","src/isa/arm64/binemit.rs":"159ab9eca03ac4aa7f55d51ab20585a5971d95a74c61953d1899ac863b06e2ec","src/isa/arm64/enc_tables.rs":"00ec8f53402f6cb73716db1adb3aca564574833cab58dc12b4dc6ba8c4529a73","src/isa/arm64/mod.rs":"4eef5f904f2219262c59dae7056af5adb7764074309dffc0be5b2357781dd1a6","src/isa/arm64/registers.rs":"7a8b207ed28737efc737e8e65ce79e7e7d3eecd23599890230dca8474c985026","src/isa/arm64/settings.rs":"7b466fcc2c58bc1846a72f08ec58900b3cf622ab2922ee9128e6dfe254907bf5","src/isa/call_conv.rs":"4bc8f8cc540ed54cf1e4c4688a1a8a975ed49a039a48d44a2c6b97f847b65ea8","src/isa/constraints.rs":"324d7c8655565f13b90a6c9587c9fb6c545ab3086201f434e1324fc5d6e5b3c7","src/isa/enc_tables.rs":"946a9fcdf7d0541e7e65aeafdf18b6a5cb9e3ea29a1ce3bf05c155f910acca3a","src/isa/encoding.rs":"032347d4e624449af7a35f7ba012339bc49fabae97b971818e922d6ca4510e59","src/isa/mod.rs":"a7f966ec68dd709f685157812c7cb40ed012b175666509b9d05fec57b60fdb37","src/isa/registers.rs":"c0014dc940e8a6da628c60e49f6261cebaee1e06e0ea1c172de5f797e600535c","src/isa/riscv/abi.rs":"1de6d0070126e0127ca6a63551a14d1b5c030cf9628538fd732301fd2bd34b5e","src/isa/riscv/binemit.rs":"3bdad2791447f51bfe5ecedb73b1aed8a6a8809790b1f26e3ff624a89163a026","src/isa/riscv/enc_tables.rs":"6bc179f95ef5634b64fb42ab67929c0aeb70ac8efccfc47dd8c9b1dbfe64a446","src/isa/riscv/mod.rs":"de0dd32005f6b0510e3c8a31bb7e58ab7e7cffb674169a08558794950db87126","src/isa/riscv/registers.rs":"794ac61343a8db66dc99b2ca964ea3986b47b37fe8b72575c644c1cdaabd2991","src/isa/riscv/settings.rs":"78ced69b82d89f83b5612a91d0acdac2616f9091b380ee3e4715adb31f95b232","src/isa/stack.rs":"ec96130c446cd7d637722f1603e38d5164498368b652f4b0454baf3227385ad4","src/isa/x86/abi.rs":"6a9f8a3c9ee0f09118be1f962c473f8f5269cc4eba25519ca84df25b8835cceb","src/isa/x86/binemit.rs":"f90820a1f9c4ad02f3507625d35f014f644d8cea93b0216bcc60cc05cc84eacc","src/isa/x86/enc_tables.rs":"aa4bd2992d08ad97e94aafa022cafd853e0978c7c139558885715f57bfcf49e7","src/isa/x86/mod.rs":"bc83c0e619e8603885359c472b4113bc83b8867dd2d8e83b27f798301c6df93c","src/isa/x86/registers.rs":"783ebbe4c3b4711fe1eac2cfd3bbea7c31a53c15c6028397c038ef4eb0b2aa06","src/isa/x86/settings.rs":"dcce098045c1115cd55f256dcd3e0ccaa5a0c9ad93b14fb8a4c680e95caf2b73","src/iterators.rs":"f85f52d3fa707a0eb974c92215b3e976923ce8f9481219f7812e0f2869c2bd37","src/legalizer/boundary.rs":"e86400b42ef60d42e05ed7d2c24dc815f16652b49ab0ee9048edadd460bd411d","src/legalizer/call.rs":"12f380d126765f0bc2da1cf298088fa98451e2d6bf56c34b755ff7077d14a4f1","src/legalizer/globalvalue.rs":"be6fc6e310dedde48e172453eccaa7cb416baa92e1adfc55f565d51159c930cc","src/legalizer/heap.rs":"c44a0845254187dfe7456b0b9efbfea25ae566772bc64b41ed93dd32a71f8e8a","src/legalizer/libcall.rs":"bf18267f502bf9bfbc3ff51bc05df480293a84422ea7f4c37dd0c75e97952766","src/legalizer/mod.rs":"f516c4e22fb66099678f753121dfa92128f2c4524ea4196e1b400e06e6649d44","src/legalizer/split.rs":"6869c2cc436215ed22abffa85c783ae205374eb74f6ec0fc0ddec2b983e799fe","src/legalizer/table.rs":"2aca27ea564c2ef02ed833c495156b9e1ddcee3c8a1b1e70347ab5907a381605","src/lib.rs":"1542f5cae0d80c408f190d225890da959e0b4033687b6c2480e83254341cba83","src/licm.rs":"dcdf4744a01489939955dd02d43be3522cfbc448d92b30796d512b10e784c503","src/loop_analysis.rs":"ab74f702649ddd16d3d91400c3c2aafed4f09d9af210f5e180dff15a82caf8ac","src/nan_canonicalization.rs":"e2b1f9935d14af9abe553de1eda5483cffdaa7098dd1a17ba9a98fa04280b22c","src/partition_slice.rs":"55b9e857f452baf4d6312779861f9ef93b3d5300467e752230ec6af14943efe3","src/postopt.rs":"f1fe06398c644cad19fd427323c74acdb237b5853ffb72148a2b2012b906e2a3","src/predicates.rs":"8e4c4afde65420d33621aedd80e4ce270d334c1b62a17d7879273a1719d49b41","src/print_errors.rs":"54282bd8480b0bab29cbf3c257cdb3faafb566f0c40f88e1ff6c41e742f99ff6","src/ref_slice.rs":"9be914b705eefcc6b4e38db573f56ad7b978f4b65c2f6f8f5516df78fb2206a4","src/regalloc/affinity.rs":"47e28f9ae7cebfc9b1006480143a3a5ab1b118ec761a163c4a670b63fdc47d0a","src/regalloc/coalescing.rs":"5ffab5529e5840e0dc3f13930788caf75ae9e15ce90d4f64f9f625b2ee495605","src/regalloc/coloring.rs":"baf4861cabfc897755bef0b25a8367148bd2468717b3571763a5cc599407e5c2","src/regalloc/context.rs":"794f9f0fb3b980feb3be57b95c152767cb318b81aca48c27197b01b7d529c48d","src/regalloc/diversion.rs":"cbb942a197081f9e537f3fed71a7ec6d6d1edc18b8536fa46a1dda316f46c776","src/regalloc/live_value_tracker.rs":"054efd9e8da0f33a158082f67a7c2c14f7c8632b1fc28d54941ca7bc9d5a46d6","src/regalloc/liveness.rs":"6886e52e68aee5b2e26fb0b6e073905e7fa963eb597657fc966e5758cda4c254","src/regalloc/liverange.rs":"3c6a34e35a912dce48fa9a579e82e14a7e64334d5572b0d74dbfbf42dd380804","src/regalloc/mod.rs":"6254df639f9289fd578e01b7dca99bc9c9e3c6680c6d031405e8df8d0cff31ad","src/regalloc/pressure.rs":"7c73ca1f54559b1d9f8ce587bdc067e74f3d47901058f7ae1e9277516624236f","src/regalloc/register_set.rs":"294a66b676189e4da3cbb9c66474e0dd1a86a00b8cc71d03762994ae0654e11f","src/regalloc/reload.rs":"6525e9488e797b49b7892ac7596d6100793bb1db97c5025b17e6b32546fbe2fe","src/regalloc/solver.rs":"853c6f16f68e75add56981b132d92e556a94d8cbd13fed311df2d75da08de03a","src/regalloc/spilling.rs":"aae3faab22dcd8704179941a5b9b8e2b160d43a7daa02cebca1d31b9d368794b","src/regalloc/virtregs.rs":"23447a8e6196681cfb2388e0204626a0ac992735eb01f3eed4781c1cdfb688e4","src/result.rs":"d43abf9b22c5ad772200889bba339bcc4455c7abb9f2f3a2af65fbbaf1130009","src/scoped_hash_map.rs":"102797c380a588f7c16d26bf3b6c9cff28d37c2d8168a382b265194cd8969212","src/settings.rs":"18f3b43b5ec916b5969a62a6bbf0b7b8f039a5f7930e406bb7e8f181f2dc0d2d","src/simple_gvn.rs":"05576f7e90555c668c91df0b63a0468fbf2ed1aee9bc4118b73461f8719ead1a","src/simple_preopt.rs":"cfafd0398bba0b3e2b91b5bf10617bd4048ba2b22345b3e5bfc403239903960a","src/stack_layout.rs":"ce0b4b188cc46fa5070139124ffb2d263d44acd08703e7043a40b5c1afa952fb","src/timing.rs":"79acc12600ace2b144f1d7d82e01c023596e418a84042cf70ef93df928cdcabf","src/topo_order.rs":"73ec442db1cc9a282cf9c5b715ad2f60c4d2872080c16fd04ef7091d56816fbd","src/unreachable_code.rs":"6fdea8f9afe9fbffe411bfef48fec7937cb41d51036fd190a3d0a5f0cc2894c6","src/verifier/cssa.rs":"8f41765d18474575faa7c44a0345549dabe0af07141e2f004a7db1c67486ce77","src/verifier/flags.rs":"0665b4cbeef762c3871ba3cc55b0b1a27c513e25cbd3f93a725aa3d636a23c72","src/verifier/liveness.rs":"6e827f05461bd6fb21b0ce99f02fae374f2d6ea6e7e14ba61e88983a1c6fac4b","src/verifier/locations.rs":"a83f7d58118a838651c80f55e2455736e79235691692488d8431b77be8093a58","src/verifier/mod.rs":"4e17623e454bf115661ddaf0be0c2554e87dd4fc83a0a7a18dc8337d66ee5de5","src/write.rs":"1e810d79ff90aa37c76e16df8d6e69af6e35f5d7c6fae325243d8e2d0568ac4d"},"package":"e92fa0fa287cf00a6739c46aba114957e0a8eeeb4f0d1aa65d6ed0699c34ca6b"}
\ No newline at end of file
--- a/third_party/rust/cranelift-codegen/Cargo.toml
+++ b/third_party/rust/cranelift-codegen/Cargo.toml
@@ -7,32 +7,32 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-codegen"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 build = "build.rs"
 description = "Low-level code generator library"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 keywords = ["compile", "compiler", "jit"]
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-bforest]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.failure]
 version = "0.1.1"
 features = ["derive"]
 default-features = false
 
 [dependencies.failure_derive]
@@ -46,17 +46,17 @@ optional = true
 [dependencies.log]
 version = "0.4.4"
 default-features = false
 
 [dependencies.target-lexicon]
 version = "0.2.0"
 default-features = false
 [build-dependencies.cranelift-codegen-meta]
-version = "0.23.0"
+version = "0.25.0"
 
 [features]
 core = ["hashmap_core"]
 default = ["std"]
 std = ["cranelift-entity/std", "cranelift-bforest/std", "target-lexicon/std"]
 testing_hooks = []
 [badges.maintenance]
 status = "experimental"
--- a/third_party/rust/cranelift-codegen/build.rs
+++ b/third_party/rust/cranelift-codegen/build.rs
@@ -19,21 +19,17 @@
 // current directory is used to find the sources.
 
 extern crate cranelift_codegen_meta as meta;
 
 use meta::isa::Isa;
 use std::env;
 use std::process;
 
-use std::time::Instant;
-
 fn main() {
-    let start_time = Instant::now();
-
     let out_dir = env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set");
     let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set");
     let cranelift_targets = env::var("CRANELIFT_TARGETS").ok();
     let cranelift_targets = cranelift_targets.as_ref().map(|s| s.as_ref());
     let python = identify_python();
 
     // Configure isa targets cfg.
     match isa_targets(cranelift_targets, &target_triple) {
@@ -91,25 +87,16 @@ fn main() {
     }
 
     for isa in isas {
         if let Err(err) = meta::gen_registers::generate(isa, "registers", &out_dir) {
             eprintln!("Error: {}", err);
             process::exit(1);
         }
     }
-
-    println!(
-        "cargo:warning=Cranelift meta-build step took {:?}",
-        Instant::now() - start_time
-    );
-    println!(
-        "cargo:warning=Meta-build script generated files in {}",
-        out_dir
-    );
 }
 
 fn identify_python() -> &'static str {
     for python in &["python", "python3", "python2.7"] {
         if process::Command::new(python)
             .arg("--version")
             .status()
             .is_ok()
--- a/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
+++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py
@@ -43,17 +43,16 @@ class TargetISA(object):
 
     def __init__(self, name, instruction_groups):
         # type: (str, Sequence[InstructionGroup]) -> None
         self.name = name
         self.settings = None  # type: SettingGroup
         self.instruction_groups = instruction_groups
         self.cpumodes = list()  # type: List[CPUMode]
         self.regbanks = list()  # type: List[RegBank]
-        self.regclasses = list()  # type: List[RegClass]
         self.legalize_codes = OrderedDict()  # type: OrderedDict[XFormGroup, int]  # noqa
         # Unique copies of all predicates.
         self._predicates = dict()  # type: Dict[PredKey, PredNode]
 
         assert InstructionGroup._current is None,\
             "InstructionGroup {} is still open"\
             .format(InstructionGroup._current.name)
 
@@ -69,17 +68,16 @@ class TargetISA(object):
 
         This computes some derived properties that are used in multiple
         places.
 
         :returns self:
         """
         self._collect_encoding_recipes()
         self._collect_predicates()
-        self._collect_regclasses()
         self._collect_legalize_codes()
         return self
 
     def _collect_encoding_recipes(self):
         # type: () -> None
         """
         Collect and number all encoding recipes in use.
         """
@@ -117,59 +115,16 @@ class TargetISA(object):
                     self.instp_number[instp] = n
 
                 # All referenced ISA predicates must have a number in
                 # `self.settings`. This may cause some parent predicates to be
                 # replicated here, which is OK.
                 if enc.isap:
                     self.settings.number_predicate(enc.isap)
 
-    def _collect_regclasses(self):
-        # type: () -> None
-        """
-        Collect and number register classes.
-
-        Every register class needs a unique index, and the classes need to be
-        topologically ordered.
-
-        We also want all the top-level register classes to be first.
-        """
-        # Compute subclasses and top-level classes in each bank.
-        # Collect the top-level classes so they get numbered consecutively.
-        for bank in self.regbanks:
-            bank.finish_regclasses()
-            # Always get the pressure tracking classes in first.
-            if bank.pressure_tracking:
-                self.regclasses.extend(bank.toprcs)
-
-        # The limit on the number of top-level register classes can be raised.
-        # This should be coordinated with the `MAX_TRACKED_TOPRCS` constant in
-        # `isa/registers.rs`.
-        assert len(self.regclasses) <= 4, "Too many top-level register classes"
-
-        # Get the remaining top-level register classes which may exceed
-        # `MAX_TRACKED_TOPRCS`.
-        for bank in self.regbanks:
-            if not bank.pressure_tracking:
-                self.regclasses.extend(bank.toprcs)
-
-        # Collect all of the non-top-level register classes.
-        # They are numbered strictly after the top-level classes.
-        for bank in self.regbanks:
-            self.regclasses.extend(
-                    rc for rc in bank.classes if not rc.is_toprc())
-
-        for idx, rc in enumerate(self.regclasses):
-            rc.index = idx
-
-        # The limit on the number of register classes can be changed. It should
-        # be coordinated with the `RegClassMask` and `RegClassIndex` types in
-        # `isa/registers.rs`.
-        assert len(self.regclasses) <= 32, "Too many register classes"
-
     def _collect_legalize_codes(self):
         # type: () -> None
         """
         Make sure all legalization transforms have been assigned a code.
         """
         for cpumode in self.cpumodes:
             self.legalize_code(cpumode.default_legalize)
             for x in cpumode.type_legalize.values():
--- a/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
+++ b/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py
@@ -801,23 +801,26 @@ spaddr8_id = TailRecipe(
 # Store recipes.
 #
 
 # XX /r register-indirect store with no offset.
 st = TailRecipe(
         'st', Store, base_size=1, ins=(GPR, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_1",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        if needs_offset(in_reg1) {
+        if needs_sib_byte(in_reg1) {
+            modrm_sib(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else if needs_offset(in_reg1) {
             modrm_disp8(in_reg1, in_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg1, in_reg0, sink);
         }
         ''')
 
 # XX /r register-indirect store with index and no offset.
@@ -828,16 +831,17 @@ stWithIndex = TailRecipe(
     instp=IsEqual(StoreComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_1",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg1) {
         modrm_sib_disp8(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
         sink.put1(0);
     } else {
         modrm_sib(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
     }
@@ -845,60 +849,73 @@ stWithIndex = TailRecipe(
 
 # XX /r register-indirect store with no offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 st_abcd = TailRecipe(
         'st_abcd', Store, base_size=1, ins=(ABCD, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         when_prefixed=st,
         clobbers_flags=False,
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        modrm_rm(in_reg1, in_reg0, sink);
+        if needs_sib_byte(in_reg1) {
+            modrm_sib(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else if needs_offset(in_reg1) {
+            modrm_disp8(in_reg1, in_reg0, sink);
+            sink.put1(0);
+        } else {
+            modrm_rm(in_reg1, in_reg0, sink);
+        }
         ''')
 
 # XX /r register-indirect store with index and no offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stWithIndex_abcd = TailRecipe(
     'stWithIndex_abcd', StoreComplex, base_size=2,
     ins=(ABCD, GPR, GPR),
     outs=(),
     instp=IsEqual(StoreComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_1",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg1) {
         modrm_sib_disp8(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
         sink.put1(0);
     } else {
         modrm_sib(in_reg0, sink);
         sib(0, in_reg2, in_reg1, sink);
     }
     ''')
 
 # XX /r register-indirect store of FPR with no offset.
 fst = TailRecipe(
         'fst', Store, base_size=1, ins=(FPR, GPR), outs=(),
         instp=IsEqual(Store.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_1",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        if needs_offset(in_reg1) {
+        if needs_sib_byte(in_reg1) {
+            modrm_sib(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else if needs_offset(in_reg1) {
             modrm_disp8(in_reg1, in_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg1, in_reg0, sink);
         }
         ''')
 # XX /r register-indirect store with index and no offset of FPR.
 fstWithIndex = TailRecipe(
@@ -907,16 +924,17 @@ fstWithIndex = TailRecipe(
         instp=IsEqual(StoreComplex.offset, 0),
         clobbers_flags=False,
         compute_size="size_plus_maybe_offset_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex3(in_reg1, in_reg0, in_reg2), sink);
+        // The else branch always inserts an SIB byte.
         if needs_offset(in_reg1) {
             modrm_sib_disp8(in_reg0, sink);
             sib(0, in_reg2, in_reg1, sink);
             sink.put1(0);
         } else {
             modrm_sib(in_reg0, sink);
             sib(0, in_reg2, in_reg1, sink);
         }
@@ -963,22 +981,28 @@ stWithIndexDisp8 = TailRecipe(
 
 # XX /r register-indirect store with 8-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stDisp8_abcd = TailRecipe(
         'stDisp8_abcd', Store, base_size=2, ins=(ABCD, GPR), outs=(),
         instp=IsSignedInt(Store.offset, 8),
         when_prefixed=stDisp8,
         clobbers_flags=False,
+        compute_size="size_plus_maybe_sib_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        modrm_disp8(in_reg1, in_reg0, sink);
+        if needs_sib_byte(in_reg1) {
+            modrm_sib_disp8(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else {
+            modrm_disp8(in_reg1, in_reg0, sink);
+        }
         let offset: i32 = offset.into();
         sink.put1(offset as u8);
         ''')
 
 # XX /r register-indirect store with index and 8-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stWithIndexDisp8_abcd = TailRecipe(
     'stWithIndexDisp8_abcd', StoreComplex, base_size=3,
@@ -1075,22 +1099,28 @@ stWithIndexDisp32 = TailRecipe(
     ''')
 
 # XX /r register-indirect store with 32-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stDisp32_abcd = TailRecipe(
         'stDisp32_abcd', Store, base_size=5, ins=(ABCD, GPR), outs=(),
         when_prefixed=stDisp32,
         clobbers_flags=False,
+        compute_size="size_plus_maybe_sib_for_in_reg_1",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg1, in_reg0), sink);
-        modrm_disp32(in_reg1, in_reg0, sink);
+        if needs_sib_byte(in_reg1) {
+            modrm_sib_disp32(in_reg0, sink);
+            sib_noindex(in_reg1, sink);
+        } else {
+            modrm_disp32(in_reg1, in_reg0, sink);
+        }
         let offset: i32 = offset.into();
         sink.put4(offset as u32);
         ''')
 
 # XX /r register-indirect store with index and 32-bit offset.
 # Only ABCD allowed for stored value. This is for byte stores with no REX.
 stWithIndexDisp32_abcd = TailRecipe(
     'stWithIndexDisp32_abcd', StoreComplex, base_size=6,
@@ -1205,23 +1235,26 @@ fregspill32 = TailRecipe(
 # Load recipes
 #
 
 # XX /r load with no offset.
 ld = TailRecipe(
         'ld', Load, base_size=1, ins=(GPR), outs=(GPR),
         instp=IsEqual(Load.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_0",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_0",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
-        if needs_offset(in_reg0) {
+        if needs_sib_byte(in_reg0) {
+            modrm_sib(out_reg0, sink);
+            sib_noindex(in_reg0, sink);
+        } else if needs_offset(in_reg0) {
             modrm_disp8(in_reg0, out_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg0, out_reg0, sink);
         }
         ''')
 
 # XX /r load with index and no offset.
@@ -1232,38 +1265,42 @@ ldWithIndex = TailRecipe(
     instp=IsEqual(LoadComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_0",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg0) {
         modrm_sib_disp8(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
         sink.put1(0);
     } else {
         modrm_sib(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
     }
     ''')
 
 # XX /r float load with no offset.
 fld = TailRecipe(
         'fld', Load, base_size=1, ins=(GPR), outs=(FPR),
         instp=IsEqual(Load.offset, 0),
         clobbers_flags=False,
-        compute_size="size_plus_maybe_offset_for_in_reg_0",
+        compute_size="size_plus_maybe_sib_or_offset_for_in_reg_0",
         emit='''
         if !flags.notrap() {
             sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
         }
         PUT_OP(bits, rex2(in_reg0, out_reg0), sink);
-        if needs_offset(in_reg0) {
+        if needs_sib_byte(in_reg0) {
+            modrm_sib(out_reg0, sink);
+            sib_noindex(in_reg0, sink);
+        } else if needs_offset(in_reg0) {
             modrm_disp8(in_reg0, out_reg0, sink);
             sink.put1(0);
         } else {
             modrm_rm(in_reg0, out_reg0, sink);
         }
         ''')
 
 # XX /r float load with index and no offset.
@@ -1274,16 +1311,17 @@ fldWithIndex = TailRecipe(
     instp=IsEqual(LoadComplex.offset, 0),
     clobbers_flags=False,
     compute_size="size_plus_maybe_offset_for_in_reg_0",
     emit='''
     if !flags.notrap() {
         sink.trap(TrapCode::HeapOutOfBounds, func.srclocs[inst]);
     }
     PUT_OP(bits, rex3(in_reg0, out_reg0, in_reg1), sink);
+    // The else branch always inserts an SIB byte.
     if needs_offset(in_reg0) {
         modrm_sib_disp8(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
         sink.put1(0);
     } else {
         modrm_sib(out_reg0, sink);
         sib(0, in_reg1, in_reg0, sink);
     }
--- a/third_party/rust/cranelift-codegen/src/context.rs
+++ b/third_party/rust/cranelift-codegen/src/context.rs
@@ -270,24 +270,25 @@ impl Context {
 
     /// Perform simple GVN on the function.
     pub fn simple_gvn<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CodegenResult<()> {
         do_simple_gvn(&mut self.func, &mut self.domtree);
         self.verify_if(fisa)
     }
 
     /// Perform LICM on the function.
-    pub fn licm<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CodegenResult<()> {
+    pub fn licm(&mut self, isa: &TargetIsa) -> CodegenResult<()> {
         do_licm(
+            isa,
             &mut self.func,
             &mut self.cfg,
             &mut self.domtree,
             &mut self.loop_analysis,
         );
-        self.verify_if(fisa)
+        self.verify_if(isa)
     }
 
     /// Perform unreachable code elimination.
     pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CodegenResult<()>
     where
         FOI: Into<FlagsOrIsa<'a>>,
     {
         eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
--- a/third_party/rust/cranelift-codegen/src/ir/dfg.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/dfg.rs
@@ -425,36 +425,48 @@ impl DataFlowGraph {
 
     /// Get all value arguments on `inst` as a mutable slice.
     pub fn inst_args_mut(&mut self, inst: Inst) -> &mut [Value] {
         self.insts[inst].arguments_mut(&mut self.value_lists)
     }
 
     /// Get the fixed value arguments on `inst` as a slice.
     pub fn inst_fixed_args(&self, inst: Inst) -> &[Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &self.inst_args(inst)[..fixed_args]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &self.inst_args(inst)[..num_fixed_args]
     }
 
     /// Get the fixed value arguments on `inst` as a mutable slice.
     pub fn inst_fixed_args_mut(&mut self, inst: Inst) -> &mut [Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &mut self.inst_args_mut(inst)[..fixed_args]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &mut self.inst_args_mut(inst)[..num_fixed_args]
     }
 
     /// Get the variable value arguments on `inst` as a slice.
     pub fn inst_variable_args(&self, inst: Inst) -> &[Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &self.inst_args(inst)[fixed_args..]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &self.inst_args(inst)[num_fixed_args..]
     }
 
     /// Get the variable value arguments on `inst` as a mutable slice.
     pub fn inst_variable_args_mut(&mut self, inst: Inst) -> &mut [Value] {
-        let fixed_args = self[inst].opcode().constraints().fixed_value_arguments();
-        &mut self.inst_args_mut(inst)[fixed_args..]
+        let num_fixed_args = self[inst]
+            .opcode()
+            .constraints()
+            .num_fixed_value_arguments();
+        &mut self.inst_args_mut(inst)[num_fixed_args..]
     }
 
     /// Create result values for an instruction that produces multiple results.
     ///
     /// Instructions that produce no result values only need to be created with `make_inst`,
     /// otherwise call `make_inst_results` to allocate value table entries for the results.
     ///
     /// The result value types are determined from the instruction's value type constraints and the
@@ -484,32 +496,35 @@ impl DataFlowGraph {
     {
         let mut reuse = reuse.fuse();
 
         self.results[inst].clear(&mut self.value_lists);
 
         // Get the call signature if this is a function call.
         if let Some(sig) = self.call_signature(inst) {
             // Create result values corresponding to the call return types.
-            debug_assert_eq!(self.insts[inst].opcode().constraints().fixed_results(), 0);
+            debug_assert_eq!(
+                self.insts[inst].opcode().constraints().num_fixed_results(),
+                0
+            );
             let num_results = self.signatures[sig].returns.len();
             for res_idx in 0..num_results {
                 let ty = self.signatures[sig].returns[res_idx].value_type;
                 if let Some(Some(v)) = reuse.next() {
                     debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
                     self.attach_result(inst, v);
                 } else {
                     self.append_result(inst, ty);
                 }
             }
             num_results
         } else {
             // Create result values corresponding to the opcode's constraints.
             let constraints = self.insts[inst].opcode().constraints();
-            let num_results = constraints.fixed_results();
+            let num_results = constraints.num_fixed_results();
             for res_idx in 0..num_results {
                 let ty = constraints.result_type(res_idx, ctrl_typevar);
                 if let Some(Some(v)) = reuse.next() {
                     debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
                     self.attach_result(inst, v);
                 } else {
                     self.append_result(inst, ty);
                 }
@@ -657,27 +672,27 @@ impl DataFlowGraph {
     /// Returns `None` if asked about a result index that is too large.
     pub fn compute_result_type(
         &self,
         inst: Inst,
         result_idx: usize,
         ctrl_typevar: Type,
     ) -> Option<Type> {
         let constraints = self.insts[inst].opcode().constraints();
-        let fixed_results = constraints.fixed_results();
+        let num_fixed_results = constraints.num_fixed_results();
 
-        if result_idx < fixed_results {
+        if result_idx < num_fixed_results {
             return Some(constraints.result_type(result_idx, ctrl_typevar));
         }
 
         // Not a fixed result, try to extract a return type from the call signature.
         self.call_signature(inst).and_then(|sigref| {
             self.signatures[sigref]
                 .returns
-                .get(result_idx - fixed_results)
+                .get(result_idx - num_fixed_results)
                 .map(|&arg| arg.value_type)
         })
     }
 
     /// Get the controlling type variable, or `INVALID` if `inst` isn't polymorphic.
     pub fn ctrl_typevar(&self, inst: Inst) -> Type {
         let constraints = self[inst].opcode().constraints();
 
@@ -929,26 +944,29 @@ impl DataFlowGraph {
     pub fn make_inst_results_for_parser(
         &mut self,
         inst: Inst,
         ctrl_typevar: Type,
         reuse: &[Value],
     ) -> usize {
         // Get the call signature if this is a function call.
         if let Some(sig) = self.call_signature(inst) {
-            assert_eq!(self.insts[inst].opcode().constraints().fixed_results(), 0);
+            assert_eq!(
+                self.insts[inst].opcode().constraints().num_fixed_results(),
+                0
+            );
             for res_idx in 0..self.signatures[sig].returns.len() {
                 let ty = self.signatures[sig].returns[res_idx].value_type;
                 if let Some(v) = reuse.get(res_idx) {
                     self.set_value_type_for_parser(*v, ty);
                 }
             }
         } else {
             let constraints = self.insts[inst].opcode().constraints();
-            for res_idx in 0..constraints.fixed_results() {
+            for res_idx in 0..constraints.num_fixed_results() {
                 let ty = constraints.result_type(res_idx, ctrl_typevar);
                 if let Some(v) = reuse.get(res_idx) {
                     self.set_value_type_for_parser(*v, ty);
                 }
             }
         }
 
         self.make_inst_results_reusing(inst, ctrl_typevar, reuse.iter().map(|x| Some(*x)))
--- a/third_party/rust/cranelift-codegen/src/ir/extname.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/extname.rs
@@ -8,17 +8,17 @@ use ir::LibCall;
 use std::cmp;
 use std::fmt::{self, Write};
 use std::str::FromStr;
 
 const TESTCASE_NAME_LENGTH: usize = 16;
 
 /// The name of an external is either a reference to a user-defined symbol
 /// table, or a short sequence of ascii bytes so that test cases do not have
-/// to keep track of a sy mbol table.
+/// to keep track of a symbol table.
 ///
 /// External names are primarily used as keys by code using Cranelift to map
 /// from a `cranelift_codegen::ir::FuncRef` or similar to additional associated
 /// data.
 ///
 /// External names can also serve as a primitive testing and debugging tool.
 /// In particular, many `.clif` test files use function names to identify
 /// functions.
@@ -63,22 +63,22 @@ impl ExternalName {
         bytes[0..len].copy_from_slice(&vec[0..len]);
 
         ExternalName::TestCase {
             length: len as u8,
             ascii: bytes,
         }
     }
 
-    /// Create a new external name from user-provided integer indicies.
+    /// Create a new external name from user-provided integer indices.
     ///
     /// # Examples
     /// ```rust
     /// # use cranelift_codegen::ir::ExternalName;
-    /// // Create `ExternalName` from integer indicies
+    /// // Create `ExternalName` from integer indices
     /// let name = ExternalName::user(123, 456);
     /// assert_eq!(name.to_string(), "u123:456");
     /// ```
     pub fn user(namespace: u32, index: u32) -> Self {
         ExternalName::User { namespace, index }
     }
 }
 
--- a/third_party/rust/cranelift-codegen/src/ir/instructions.rs
+++ b/third_party/rust/cranelift-codegen/src/ir/instructions.rs
@@ -330,18 +330,18 @@ pub struct OpcodeConstraints {
     /// Bits 5-7:
     ///     Number of fixed value arguments. The minimum required number of value operands.
     flags: u8,
 
     /// Permitted set of types for the controlling type variable as an index into `TYPE_SETS`.
     typeset_offset: u8,
 
     /// Offset into `OPERAND_CONSTRAINT` table of the descriptors for this opcode. The first
-    /// `fixed_results()` entries describe the result constraints, then follows constraints for the
-    /// fixed `Value` input operands. (`fixed_value_arguments()` of them).
+    /// `num_fixed_results()` entries describe the result constraints, then follows constraints for the
+    /// fixed `Value` input operands. (`num_fixed_value_arguments()` of them).
     constraint_offset: u16,
 }
 
 impl OpcodeConstraints {
     /// Can the controlling type variable for this opcode be inferred from the designated value
     /// input operand?
     /// This also implies that this opcode is polymorphic.
     pub fn use_typevar_operand(self) -> bool {
@@ -355,28 +355,28 @@ impl OpcodeConstraints {
     /// variable. A few polymorphic instructions either don't produce any results, or produce
     /// results with a fixed type. These instructions return `true`.
     pub fn requires_typevar_operand(self) -> bool {
         (self.flags & 0x10) != 0
     }
 
     /// Get the number of *fixed* result values produced by this opcode.
     /// This does not include `variable_args` produced by calls.
-    pub fn fixed_results(self) -> usize {
+    pub fn num_fixed_results(self) -> usize {
         (self.flags & 0x7) as usize
     }
 
     /// Get the number of *fixed* input values required by this opcode.
     ///
     /// This does not include `variable_args` arguments on call and branch instructions.
     ///
     /// The number of fixed input values is usually implied by the instruction format, but
     /// instruction formats that use a `ValueList` put both fixed and variable arguments in the
     /// list. This method returns the *minimum* number of values required in the value list.
-    pub fn fixed_value_arguments(self) -> usize {
+    pub fn num_fixed_value_arguments(self) -> usize {
         ((self.flags >> 5) & 0x7) as usize
     }
 
     /// Get the offset into `TYPE_SETS` for the controlling type variable.
     /// Returns `None` if the instruction is not polymorphic.
     fn typeset_offset(self) -> Option<usize> {
         let offset = usize::from(self.typeset_offset);
         if offset < TYPE_SETS.len() {
@@ -389,37 +389,37 @@ impl OpcodeConstraints {
     /// Get the offset into OPERAND_CONSTRAINTS where the descriptors for this opcode begin.
     fn constraint_offset(self) -> usize {
         self.constraint_offset as usize
     }
 
     /// Get the value type of result number `n`, having resolved the controlling type variable to
     /// `ctrl_type`.
     pub fn result_type(self, n: usize, ctrl_type: Type) -> Type {
-        debug_assert!(n < self.fixed_results(), "Invalid result index");
+        debug_assert!(n < self.num_fixed_results(), "Invalid result index");
         if let ResolvedConstraint::Bound(t) =
             OPERAND_CONSTRAINTS[self.constraint_offset() + n].resolve(ctrl_type)
         {
             t
         } else {
             panic!("Result constraints can't be free");
         }
     }
 
     /// Get the value type of input value number `n`, having resolved the controlling type variable
     /// to `ctrl_type`.
     ///
     /// Unlike results, it is possible for some input values to vary freely within a specific
     /// `ValueTypeSet`. This is represented with the `ArgumentConstraint::Free` variant.
     pub fn value_argument_constraint(self, n: usize, ctrl_type: Type) -> ResolvedConstraint {
         debug_assert!(
-            n < self.fixed_value_arguments(),
+            n < self.num_fixed_value_arguments(),
             "Invalid value argument index"
         );
-        let offset = self.constraint_offset() + self.fixed_results();
+        let offset = self.constraint_offset() + self.num_fixed_results();
         OPERAND_CONSTRAINTS[offset + n].resolve(ctrl_type)
     }
 
     /// Get the typeset of allowed types for the controlling type variable in a polymorphic
     /// instruction.
     pub fn ctrl_typeset(self) -> Option<ValueTypeSet> {
         self.typeset_offset().map(|offset| TYPE_SETS[offset])
     }
@@ -598,54 +598,54 @@ mod tests {
         assert_eq!(mem::size_of::<InstructionData>(), 16);
     }
 
     #[test]
     fn constraints() {
         let a = Opcode::Iadd.constraints();
         assert!(a.use_typevar_operand());
         assert!(!a.requires_typevar_operand());
-        assert_eq!(a.fixed_results(), 1);
-        assert_eq!(a.fixed_value_arguments(), 2);
+        assert_eq!(a.num_fixed_results(), 1);
+        assert_eq!(a.num_fixed_value_arguments(), 2);
         assert_eq!(a.result_type(0, types::I32), types::I32);
         assert_eq!(a.result_type(0, types::I8), types::I8);
         assert_eq!(
             a.value_argument_constraint(0, types::I32),
             ResolvedConstraint::Bound(types::I32)
         );
         assert_eq!(
             a.value_argument_constraint(1, types::I32),
             ResolvedConstraint::Bound(types::I32)
         );
 
         let b = Opcode::Bitcast.constraints();
         assert!(!b.use_typevar_operand());
         assert!(!b.requires_typevar_operand());
-        assert_eq!(b.fixed_results(), 1);
-        assert_eq!(b.fixed_value_arguments(), 1);
+        assert_eq!(b.num_fixed_results(), 1);
+        assert_eq!(b.num_fixed_value_arguments(), 1);
         assert_eq!(b.result_type(0, types::I32), types::I32);
         assert_eq!(b.result_type(0, types::I8), types::I8);
         match b.value_argument_constraint(0, types::I32) {
             ResolvedConstraint::Free(vts) => assert!(vts.contains(types::F32)),
             _ => panic!("Unexpected constraint from value_argument_constraint"),
         }
 
         let c = Opcode::Call.constraints();
-        assert_eq!(c.fixed_results(), 0);
-        assert_eq!(c.fixed_value_arguments(), 0);
+        assert_eq!(c.num_fixed_results(), 0);
+        assert_eq!(c.num_fixed_value_arguments(), 0);
 
         let i = Opcode::CallIndirect.constraints();
-        assert_eq!(i.fixed_results(), 0);
-        assert_eq!(i.fixed_value_arguments(), 1);
+        assert_eq!(i.num_fixed_results(), 0);
+        assert_eq!(i.num_fixed_value_arguments(), 1);
 
         let cmp = Opcode::Icmp.constraints();
         assert!(cmp.use_typevar_operand());
         assert!(cmp.requires_typevar_operand());
-        assert_eq!(cmp.fixed_results(), 1);
-        assert_eq!(cmp.fixed_value_arguments(), 2);
+        assert_eq!(cmp.num_fixed_results(), 1);
+        assert_eq!(cmp.num_fixed_value_arguments(), 2);
     }
 
     #[test]
     fn value_set() {
         use ir::types::*;
 
         let vts = ValueTypeSet {
             lanes: BitSet16::from_range(0, 8),
--- a/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs
@@ -35,17 +35,17 @@ pub type LegalizeCode = u8;
 /// The hash table values are references to level 2 hash tables, encoded as an offset in `LEVEL2`
 /// where the table begins, and the binary logarithm of its length. All the level 2 hash tables
 /// have a power-of-two size.
 ///
 /// Entries are generic over the offset type. It will typically be `u32` or `u16`, depending on the
 /// size of the `LEVEL2` table.
 ///
 /// Empty entries are encoded with a `!0` value for `log2len` which will always be out of range.
-/// Entries that have a `legalize` value but no level 2 table have an `offset` field that is out f
+/// Entries that have a `legalize` value but no level 2 table have an `offset` field that is out of
 /// bounds.
 pub struct Level1Entry<OffT: Into<u32> + Copy> {
     pub ty: Type,
     pub log2len: u8,
     pub legalize: LegalizeCode,
     pub offset: OffT,
 }
 
--- a/third_party/rust/cranelift-codegen/src/isa/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/mod.rs
@@ -191,17 +191,17 @@ impl TargetFrontendConfig {
     /// Get the width of pointers on this target, in units of bytes.
     pub fn pointer_bytes(self) -> u8 {
         self.pointer_width.bytes()
     }
 }
 
 /// Methods that are specialized to a target ISA. Implies a Display trait that shows the
 /// shared flags, as well as any isa-specific flags.
-pub trait TargetIsa: fmt::Display {
+pub trait TargetIsa: fmt::Display + Sync {
     /// Get the name of this ISA.
     fn name(&self) -> &'static str;
 
     /// Get the target triple that was used to make this trait object.
     fn triple(&self) -> &Triple;
 
     /// Get the ISA-independent flags that were used to make this trait object.
     fn flags(&self) -> &settings::Flags;
--- a/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs
@@ -265,17 +265,17 @@ pub fn prologue_epilogue(func: &mut ir::
             system_v_prologue_epilogue(func, isa)
         }
         CallConv::WindowsFastcall => fastcall_prologue_epilogue(func, isa),
         CallConv::Baldrdash => baldrdash_prologue_epilogue(func, isa),
         CallConv::Probestack => unimplemented!("probestack calling convention"),
     }
 }
 
-pub fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
+fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
     debug_assert!(
         !isa.flags().probestack_enabled(),
         "baldrdash does not expect cranelift to emit stack probes"
     );
 
     // Baldrdash on 32-bit x86 always aligns its stack pointer to 16 bytes.
     let stack_align = 16;
     let word_size = StackSize::from(isa.pointer_bytes());
@@ -286,17 +286,17 @@ pub fn baldrdash_prologue_epilogue(func:
     func.stack_slots.push(ss);
 
     layout_stack(&mut func.stack_slots, stack_align)?;
     Ok(())
 }
 
 /// Implementation of the fastcall-based Win64 calling convention described at [1]
 /// [1] https://msdn.microsoft.com/en-us/library/ms235286.aspx
-pub fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
+fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
     if isa.triple().pointer_width().unwrap() != PointerWidth::U64 {
         panic!("TODO: windows-fastcall: x86-32 not implemented yet");
     }
 
     // [1] "The primary exceptions are the stack pointer and malloc or alloca memory,
     // which are aligned to 16 bytes in order to aid performance"
     let stack_align = 16;
 
@@ -358,17 +358,17 @@ pub fn fastcall_prologue_epilogue(func: 
     // Reset the cursor and insert the epilogue
     let mut pos = pos.at_position(CursorPosition::Nowhere);
     insert_common_epilogues(&mut pos, local_stack_size, reg_type, &csrs);
 
     Ok(())
 }
 
 /// Insert a System V-compatible prologue and epilogue.
-pub fn system_v_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
+fn system_v_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenResult<()> {
     // The original 32-bit x86 ELF ABI had a 4-byte aligned stack pointer, but
     // newer versions use a 16-byte aligned stack pointer.
     let stack_align = 16;
     let pointer_width = isa.triple().pointer_width().unwrap();
     let word_size = pointer_width.bytes() as usize;
     let reg_type = ir::Type::int(u16::from(pointer_width.bits())).unwrap();
 
     let csrs = callee_saved_gprs_used(isa, func);
--- a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs
@@ -18,16 +18,19 @@ include!(concat!(env!("OUT_DIR"), "/enco
 include!(concat!(env!("OUT_DIR"), "/legalize-x86.rs"));
 
 pub fn needs_sib_byte(reg: RegUnit) -> bool {
     reg == RU::r12 as RegUnit || reg == RU::rsp as RegUnit
 }
 pub fn needs_offset(reg: RegUnit) -> bool {
     reg == RU::r13 as RegUnit || reg == RU::rbp as RegUnit
 }
+pub fn needs_sib_byte_or_offset(reg: RegUnit) -> bool {
+    needs_sib_byte(reg) || needs_offset(reg)
+}
 
 fn additional_size_if(
     op_index: usize,
     inst: Inst,
     divert: &RegDiversions,
     func: &Function,
     condition_func: fn(RegUnit) -> bool,
 ) -> u8 {
@@ -66,16 +69,32 @@ fn size_plus_maybe_sib_for_in_reg_0(
 fn size_plus_maybe_sib_for_in_reg_1(
     sizing: &RecipeSizing,
     inst: Inst,
     divert: &RegDiversions,
     func: &Function,
 ) -> u8 {
     sizing.base_size + additional_size_if(1, inst, divert, func, needs_sib_byte)
 }
+fn size_plus_maybe_sib_or_offset_for_in_reg_0(
+    sizing: &RecipeSizing,
+    inst: Inst,
+    divert: &RegDiversions,
+    func: &Function,
+) -> u8 {
+    sizing.base_size + additional_size_if(0, inst, divert, func, needs_sib_byte_or_offset)
+}
+fn size_plus_maybe_sib_or_offset_for_in_reg_1(
+    sizing: &RecipeSizing,
+    inst: Inst,
+    divert: &RegDiversions,
+    func: &Function,
+) -> u8 {
+    sizing.base_size + additional_size_if(1, inst, divert, func, needs_sib_byte_or_offset)
+}
 
 /// Expand the `sdiv` and `srem` instructions using `x86_sdivmodx`.
 fn expand_sdivrem(
     inst: ir::Inst,
     func: &mut ir::Function,
     cfg: &mut ControlFlowGraph,
     isa: &isa::TargetIsa,
 ) {
--- a/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs
+++ b/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs
@@ -196,18 +196,24 @@ where
     ResType: FnMut(&Function, usize) -> AbiParam,
 {
     let call = pos
         .current_inst()
         .expect("Cursor must point to a call instruction");
 
     // We theoretically allow for call instructions that return a number of fixed results before
     // the call return values. In practice, it doesn't happen.
-    let fixed_results = pos.func.dfg[call].opcode().constraints().fixed_results();
-    debug_assert_eq!(fixed_results, 0, "Fixed results on calls not supported");
+    debug_assert_eq!(
+        pos.func.dfg[call]
+            .opcode()
+            .constraints()
+            .num_fixed_results(),
+        0,
+        "Fixed results on calls not supported"
+    );
 
     let results = pos.func.dfg.detach_results(call);
     let mut next_res = 0;
     let mut abi_res = 0;
 
     // Point immediately after the call.
     pos.next_inst();
 
@@ -435,21 +441,21 @@ fn legalize_inst_arguments<ArgType>(
     // Lift the value list out of the call instruction so we modify it.
     let mut vlist = pos.func.dfg[inst]
         .take_value_list()
         .expect("Call must have a value list");
 
     // The value list contains all arguments to the instruction, including the callee on an
     // indirect call which isn't part of the call arguments that must match the ABI signature.
     // Figure out how many fixed values are at the front of the list. We won't touch those.
-    let fixed_values = pos.func.dfg[inst]
+    let num_fixed_values = pos.func.dfg[inst]
         .opcode()
         .constraints()
-        .fixed_value_arguments();
-    let have_args = vlist.len(&pos.func.dfg.value_lists) - fixed_values;
+        .num_fixed_value_arguments();
+    let have_args = vlist.len(&pos.func.dfg.value_lists) - num_fixed_values;
 
     // Grow the value list to the right size and shift all the existing arguments to the right.
     // This lets us write the new argument values into the list without overwriting the old
     // arguments.
     //
     // Before:
     //
     //    <-->              fixed_values
@@ -467,32 +473,32 @@ fn legalize_inst_arguments<ArgType>(
     //
     // After writing the new arguments:
     //
     //    <-->                     fixed_values
     //        <------------------> abi_args
     //   [FFFFNNNNNNNNNNNNNNNNNNNN]
     //
     vlist.grow_at(
-        fixed_values,
+        num_fixed_values,
         abi_args - have_args,
         &mut pos.func.dfg.value_lists,
     );
-    let old_arg_offset = fixed_values + abi_args - have_args;
+    let old_arg_offset = num_fixed_values + abi_args - have_args;
 
     let mut abi_arg = 0;
     for old_arg in 0..have_args {
         let old_value = vlist
             .get(old_arg_offset + old_arg, &pos.func.dfg.value_lists)
             .unwrap();
         let mut put_arg = |func: &mut Function, arg| {
             let abi_type = get_abi_type(func, abi_arg);
             if func.dfg.value_type(arg) == abi_type.value_type {
                 // This is the argument type we need.
-                vlist.as_mut_slice(&mut func.dfg.value_lists)[fixed_values + abi_arg] = arg;
+                vlist.as_mut_slice(&mut func.dfg.value_lists)[num_fixed_values + abi_arg] = arg;
                 abi_arg += 1;
                 Ok(())
             } else {
                 Err(abi_type)
             }
         };
         convert_to_abi(pos, cfg, old_value, &mut put_arg);
     }
--- a/third_party/rust/cranelift-codegen/src/legalizer/split.rs
+++ b/third_party/rust/cranelift-codegen/src/legalizer/split.rs
@@ -128,53 +128,55 @@ fn split_any(
     while let Some(repair) = repairs.pop() {
         for BasicBlock { inst, .. } in cfg.pred_iter(repair.ebb) {
             let branch_opc = pos.func.dfg[inst].opcode();
             debug_assert!(
                 branch_opc.is_branch(),
                 "Predecessor not a branch: {}",
                 pos.func.dfg.display_inst(inst, None)
             );
-            let fixed_args = branch_opc.constraints().fixed_value_arguments();
+            let num_fixed_args = branch_opc.constraints().num_fixed_value_arguments();
             let mut args = pos.func.dfg[inst]
                 .take_value_list()
                 .expect("Branches must have value lists.");
             let num_args = args.len(&pos.func.dfg.value_lists);
             // Get the old value passed to the EBB argument we're repairing.
             let old_arg = args
-                .get(fixed_args + repair.num, &pos.func.dfg.value_lists)
+                .get(num_fixed_args + repair.num, &pos.func.dfg.value_lists)
                 .expect("Too few branch arguments");
 
             // It's possible that the CFG's predecessor list has duplicates. Detect them here.
             if pos.func.dfg.value_type(old_arg) == repair.split_type {
                 pos.func.dfg[inst].put_value_list(args);
                 continue;
             }
 
             // Split the old argument, possibly causing more repairs to be scheduled.
             pos.goto_inst(inst);
             let (lo, hi) = split_value(pos, old_arg, repair.concat, &mut repairs);
 
             // The `lo` part replaces the original argument.
             *args
-                .get_mut(fixed_args + repair.num, &mut pos.func.dfg.value_lists)
+                .get_mut(num_fixed_args + repair.num, &mut pos.func.dfg.value_lists)
                 .unwrap() = lo;
 
             // The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
             // same EBB, there could be multiple arguments missing.
-            if num_args > fixed_args + repair.hi_num {
+            if num_args > num_fixed_args + repair.hi_num {
                 *args
-                    .get_mut(fixed_args + repair.hi_num, &mut pos.func.dfg.value_lists)
-                    .unwrap() = hi;
+                    .get_mut(
+                        num_fixed_args + repair.hi_num,
+                        &mut pos.func.dfg.value_lists,
+                    ).unwrap() = hi;
             } else {
                 // We need to append one or more arguments. If we're adding more than one argument,
                 // there must be pending repairs on the stack that will fill in the correct values
                 // instead of `hi`.
                 args.extend(
-                    iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
+                    iter::repeat(hi).take(1 + num_fixed_args + repair.hi_num - num_args),
                     &mut pos.func.dfg.value_lists,
                 );
             }
 
             // Put the value list back after manipulating it.
             pos.func.dfg[inst].put_value_list(args);
         }
     }
--- a/third_party/rust/cranelift-codegen/src/licm.rs
+++ b/third_party/rust/cranelift-codegen/src/licm.rs
@@ -1,24 +1,26 @@
 //! A Loop Invariant Code Motion optimization pass
 
-use cursor::{Cursor, FuncCursor};
+use cursor::{Cursor, EncCursor, FuncCursor};
 use dominator_tree::DominatorTree;
 use entity::{EntityList, ListPool};
 use flowgraph::{BasicBlock, ControlFlowGraph};
 use fx::FxHashSet;
 use ir::{DataFlowGraph, Ebb, Function, Inst, InstBuilder, Layout, Opcode, Type, Value};
+use isa::TargetIsa;
 use loop_analysis::{Loop, LoopAnalysis};
 use std::vec::Vec;
 use timing;
 
 /// Performs the LICM pass by detecting loops within the CFG and moving
 /// loop-invariant instructions out of them.
 /// Changes the CFG and domtree in-place during the operation.
 pub fn do_licm(
+    isa: &TargetIsa,
     func: &mut Function,
     cfg: &mut ControlFlowGraph,
     domtree: &mut DominatorTree,
     loop_analysis: &mut LoopAnalysis,
 ) {
     let _tt = timing::licm();
     debug_assert!(cfg.is_valid());
     debug_assert!(domtree.is_valid());
@@ -31,17 +33,17 @@ pub fn do_licm(
         // Then we create the loop's pre-header and fill it with the invariant instructions
         // Then we remove the invariant instructions from the loop body
         if !invariant_insts.is_empty() {
             // If the loop has a natural pre-header we use it, otherwise we create it.
             let mut pos;
             match has_pre_header(&func.layout, cfg, domtree, loop_analysis.loop_header(lp)) {
                 None => {
                     let pre_header =
-                        create_pre_header(loop_analysis.loop_header(lp), func, cfg, domtree);
+                        create_pre_header(isa, loop_analysis.loop_header(lp), func, cfg, domtree);
                     pos = FuncCursor::new(func).at_last_inst(pre_header);
                 }
                 // If there is a natural pre-header we insert new instructions just before the
                 // related jumping instruction (which is not necessarily at the end).
                 Some((_, last_inst)) => {
                     pos = FuncCursor::new(func).at_inst(last_inst);
                 }
             };
@@ -55,16 +57,17 @@ pub fn do_licm(
     // We have to recompute the domtree to account for the changes
     cfg.compute(func);
     domtree.compute(func, cfg);
 }
 
 // Insert a pre-header before the header, modifying the function layout and CFG to reflect it.
 // A jump instruction to the header is placed at the end of the pre-header.
 fn create_pre_header(
+    isa: &TargetIsa,
     header: Ebb,
     func: &mut Function,
     cfg: &mut ControlFlowGraph,
     domtree: &DominatorTree,
 ) -> Ebb {
     let pool = &mut ListPool::<Value>::new();
     let header_args_values: Vec<Value> = func.dfg.ebb_params(header).into_iter().cloned().collect();
     let header_args_types: Vec<Type> = header_args_values
@@ -82,17 +85,17 @@ fn create_pre_header(
     } in cfg.pred_iter(header)
     {
         // We only follow normal edges (not the back edges)
         if !domtree.dominates(header, last_inst, &func.layout) {
             change_branch_jump_destination(last_inst, pre_header, func);
         }
     }
     {
-        let mut pos = FuncCursor::new(func).at_top(header);
+        let mut pos = EncCursor::new(func, isa).at_top(header);
         // Inserts the pre-header at the right place in the layout.
         pos.insert_ebb(pre_header);
         pos.next_inst();
         pos.ins().jump(header, pre_header_args_value.as_slice(pool));
     }
     pre_header
 }
 
@@ -103,31 +106,34 @@ fn create_pre_header(
 // Returns the pre-header Ebb and the instruction jumping to the header.
 fn has_pre_header(
     layout: &Layout,
     cfg: &ControlFlowGraph,
     domtree: &DominatorTree,
     header: Ebb,
 ) -> Option<(Ebb, Inst)> {
     let mut result = None;
-    let mut found = false;
     for BasicBlock {
         ebb: pred_ebb,
-        inst: last_inst,
+        inst: branch_inst,
     } in cfg.pred_iter(header)
     {
         // We only count normal edges (not the back edges)
-        if !domtree.dominates(header, last_inst, layout) {
-            if found {
+        if !domtree.dominates(header, branch_inst, layout) {
+            if result.is_some() {
                 // We have already found one, there are more than one
                 return None;
-            } else {
-                result = Some((pred_ebb, last_inst));
-                found = true;
             }
+            if branch_inst != layout.last_inst(pred_ebb).unwrap()
+                || cfg.succ_iter(pred_ebb).nth(1).is_some()
+            {
+                // It's along a critical edge, so don't use it.
+                return None;
+            }
+            result = Some((pred_ebb, branch_inst));
         }
     }
     result
 }
 
 // Change the destination of a jump or branch instruction. Does nothing if called with a non-jump
 // or non-branch instruction.
 fn change_branch_jump_destination(inst: Inst, new_ebb: Ebb, func: &mut Function) {
--- a/third_party/rust/cranelift-codegen/src/print_errors.rs
+++ b/third_party/rust/cranelift-codegen/src/print_errors.rs
@@ -1,13 +1,13 @@
 //! Utility routines for pretty-printing error messages.
 
 use entity::SecondaryMap;
 use ir;
-use ir::entities::{AnyEntity, Inst, Value};
+use ir::entities::{AnyEntity, Ebb, Inst, Value};
 use ir::function::Function;
 use isa::TargetIsa;
 use result::CodegenError;
 use std::boxed::Box;
 use std::fmt;
 use std::fmt::Write;
 use std::string::{String, ToString};
 use std::vec::Vec;
@@ -18,29 +18,49 @@ use write::{decorate_function, FuncWrite
 pub fn pretty_verifier_error<'a>(
     func: &ir::Function,
     isa: Option<&TargetIsa>,
     func_w: Option<Box<FuncWriter + 'a>>,
     errors: VerifierErrors,
 ) -> String {
     let mut errors = errors.0;
     let mut w = String::new();
+    let num_errors = errors.len();
 
     decorate_function(
         &mut PrettyVerifierError(func_w.unwrap_or_else(|| Box::new(PlainWriter)), &mut errors),
         &mut w,
         func,
         isa,
     ).unwrap();
+
+    writeln!(
+        w,
+        "\n; {} verifier error{} detected (see above). Compilation aborted.",
+        num_errors,
+        if num_errors == 1 { "" } else { "s" }
+    ).unwrap();
+
     w
 }
 
 struct PrettyVerifierError<'a>(Box<FuncWriter + 'a>, &'a mut Vec<VerifierError>);
 
 impl<'a> FuncWriter for PrettyVerifierError<'a> {
+    fn write_ebb_header(
+        &mut self,
+        w: &mut Write,
+        func: &Function,
+        isa: Option<&TargetIsa>,
+        ebb: Ebb,
+        indent: usize,
+    ) -> fmt::Result {
+        pretty_ebb_header_error(w, func, isa, ebb, indent, &mut *self.0, self.1)
+    }
+
     fn write_instruction(
         &mut self,
         w: &mut Write,
         func: &Function,
         aliases: &SecondaryMap<Value, Vec<Value>>,
         isa: Option<&TargetIsa>,
         inst: Inst,
         indent: usize,
@@ -54,110 +74,149 @@ impl<'a> FuncWriter for PrettyVerifierEr
         func: &Function,
         entity: AnyEntity,
         value: &fmt::Display,
     ) -> fmt::Result {
         pretty_preamble_error(w, func, entity, value, &mut *self.0, self.1)
     }
 }
 
-/// Pretty-print a function verifier error.
+/// Pretty-print a function verifier error for a given EBB.
+fn pretty_ebb_header_error(
+    w: &mut Write,
+    func: &Function,
+    isa: Option<&TargetIsa>,
+    cur_ebb: Ebb,
+    indent: usize,
+    func_w: &mut FuncWriter,
+    errors: &mut Vec<VerifierError>,
+) -> fmt::Result {
+    let mut s = String::new();
+    func_w.write_ebb_header(&mut s, func, isa, cur_ebb, indent)?;
+    write!(w, "{}", s)?;
+
+    // TODO: Use drain_filter here when it gets stabilized
+    let mut i = 0;
+    let mut printed_error = false;
+    while i != errors.len() {
+        match errors[i].location {
+            ir::entities::AnyEntity::Ebb(ebb) if ebb == cur_ebb => {
+                if !printed_error {
+                    print_arrow(w, &s)?;
+                    printed_error = true;
+                }
+                let err = errors.remove(i);
+                print_error(w, err)?;
+            }
+            _ => i += 1,
+        }
+    }
+
+    if printed_error {
+        w.write_char('\n')?;
+    }
+
+    Ok(())
+}
+
+/// Pretty-print a function verifier error for a given instruction.
 fn pretty_instruction_error(
     w: &mut Write,
     func: &Function,
     aliases: &SecondaryMap<Value, Vec<Value>>,
     isa: Option<&TargetIsa>,
     cur_inst: Inst,
     indent: usize,
     func_w: &mut FuncWriter,
     errors: &mut Vec<VerifierError>,
 ) -> fmt::Result {
+    let mut s = String::new();
+    func_w.write_instruction(&mut s, func, aliases, isa, cur_inst, indent)?;
+    write!(w, "{}", s)?;
+
     // TODO: Use drain_filter here when it gets stabilized
     let mut i = 0;
-    let mut printed_instr = false;
-
+    let mut printed_error = false;
     while i != errors.len() {
         match errors[i].location {
             ir::entities::AnyEntity::Inst(inst) if inst == cur_inst => {
-                let err = errors.remove(i);
-
-                if !printed_instr {
-                    func_w.write_instruction(w, func, aliases, isa, cur_inst, indent)?;
-                    printed_instr = true;
+                if !printed_error {
+                    print_arrow(w, &s)?;
+                    printed_error = true;
                 }
-
-                print_error(w, indent, cur_inst.to_string(), err)?;
+                let err = errors.remove(i);
+                print_error(w, err)?;
             }
-            ir::entities::AnyEntity::Inst(_) => i += 1,
-            _ => unreachable!(),
+            _ => i += 1,
         }
     }
 
-    if printed_instr {
+    if printed_error {
         w.write_char('\n')?;
-    } else {
-        writeln!(
-            w,
-            "{1:0$}{2}",
-            indent,
-            "",
-            func.dfg.display_inst(cur_inst, isa)
-        )?;
     }
 
     Ok(())
 }
 
 fn pretty_preamble_error(
     w: &mut Write,
     func: &Function,
     entity: AnyEntity,
     value: &fmt::Display,
     func_w: &mut FuncWriter,
     errors: &mut Vec<VerifierError>,
 ) -> fmt::Result {
-    // TODO: Use drain_filter here when it gets stabilized
-    let indent = 4;
+    let mut s = String::new();
+    func_w.write_entity_definition(&mut s, func, entity, value)?;
+    write!(w, "{}", s)?;
 
+    // TODO: Use drain_filter here when it gets stabilized
     let mut i = 0;
-    let mut printed_entity = false;
-
+    let mut printed_error = false;
     while i != errors.len() {
         if entity == errors[i].location {
+            if !printed_error {
+                print_arrow(w, &s)?;
+                printed_error = true;
+            }
             let err = errors.remove(i);
-
-            if !printed_entity {
-                func_w.write_entity_definition(w, func, entity, value)?;
-                printed_entity = true;
-            }
-
-            print_error(w, indent, entity.to_string(), err)?;
+            print_error(w, err)?;
         } else {
             i += 1
         }
     }
 
-    if printed_entity {
+    if printed_error {
         w.write_char('\n')?;
-    } else {
-        func_w.write_entity_definition(w, func, entity, value)?;
     }
 
     Ok(())
 }
 
-/// Prints ;   ^~~~~~ verifier [ERROR BODY]
-fn print_error(w: &mut Write, indent: usize, s: String, err: VerifierError) -> fmt::Result {
-    let indent = if indent < 1 { 0 } else { indent - 1 };
+/// Prints:
+///    ;   ^~~~~~
+fn print_arrow(w: &mut Write, entity: &str) -> fmt::Result {
+    write!(w, ";")?;
 
-    write!(w, ";{1:0$}^", indent, "")?;
-    for _c in s.chars() {
+    let indent = entity.len() - entity.trim_start().len();
+    if indent != 0 {
+        write!(w, "{1:0$}^", indent - 1, "")?;
+    }
+
+    for _ in 0..entity.trim().len() - 1 {
         write!(w, "~")?;
     }
-    writeln!(w, " verifier {}", err.to_string())?;
+
+    writeln!(w)
+}
+
+/// Prints:
+///    ; error: [ERROR BODY]
+fn print_error(w: &mut Write, err: VerifierError) -> fmt::Result {
+    writeln!(w, "; error: {}", err.to_string())?;
     Ok(())
 }
 
 /// Pretty-print a Cranelift error.
 pub fn pretty_error(func: &ir::Function, isa: Option<&TargetIsa>, err: CodegenError) -> String {
     if let CodegenError::Verifier(e) = err {
         pretty_verifier_error(func, isa, None, e)
     } else {
--- a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs
@@ -370,17 +370,17 @@ impl<'a> Context<'a> {
             pred_ebb,
             pos.display_inst(pred_inst)
         );
 
         copy
     }
 
     /// Finish the union-find part of the coalescing algorithm.
-    ///     ///
+    ///
     /// This builds the initial set of virtual registers as the transitive/reflexive/symmetric
     /// closure of the relation formed by EBB parameter-argument pairs found by `union_find_ebb()`.
     fn finish_union_find(&mut self) {
         self.virtregs.finish_union_find(None);
         debug!("After union-find phase:{}", self.virtregs);
     }
 }
 
--- a/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs
@@ -67,17 +67,17 @@ impl RegisterSet {
         self.avail[idx] &= !bits;
     }
 
     /// Return `reg` and all of its register units to the set of available registers.
     pub fn free(&mut self, rc: RegClass, reg: RegUnit) {
         let (idx, bits) = bitmask(rc, reg);
         debug_assert!(
             (self.avail[idx] & bits) == 0,
-            "{}:{} not allocated in {}",
+            "{}:{} is already free in {}",
             rc,
             rc.info.display_regunit(reg),
             self.display(rc.info)
         );
         self.avail[idx] |= bits;
     }
 
     /// Return an iterator over all available registers belonging to the register class `rc`.
--- a/third_party/rust/cranelift-codegen/src/regalloc/reload.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/reload.rs
@@ -261,17 +261,17 @@ impl<'a> Context<'a> {
                 }
             }
         }
 
         // Same thing for spilled call return values.
         let retvals = &defs[self.cur.func.dfg[inst]
                                 .opcode()
                                 .constraints()
-                                .fixed_results()..];
+                                .num_fixed_results()..];
         if !retvals.is_empty() {
             let sig = self
                 .cur
                 .func
                 .dfg
                 .call_signature(inst)
                 .expect("Extra results on non-call instruction");
             for (i, lv) in retvals.iter().enumerate() {
@@ -362,17 +362,17 @@ impl<'a> Context<'a> {
                 }
             }
         }
 
         // If we only have the fixed arguments, we're done now.
         let offset = self.cur.func.dfg[inst]
             .opcode()
             .constraints()
-            .fixed_value_arguments();
+            .num_fixed_value_arguments();
         if args.len() == offset {
             return;
         }
         let var_args = &args[offset..];
 
         // Handle ABI arguments.
         if let Some(sig) = self.cur.func.dfg.call_signature(inst) {
             handle_abi_args(
--- a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs
@@ -129,21 +129,18 @@ impl<'a> Context<'a> {
     fn visit_ebb(&mut self, ebb: Ebb, tracker: &mut LiveValueTracker) {
         debug!("Spilling {}:", ebb);
         self.cur.goto_top(ebb);
         self.visit_ebb_header(ebb, tracker);
         tracker.drop_dead_params();
         self.process_spills(tracker);
 
         while let Some(inst) = self.cur.next_inst() {
-            if let Some(constraints) = self
-                .encinfo
-                .operand_constraints(self.cur.func.encodings[inst])
-            {
-                self.visit_inst(inst, ebb, constraints, tracker);
+            if !self.cur.func.dfg[inst].opcode().is_ghost() {
+                self.visit_inst(inst, ebb, tracker);
             } else {
                 let (_throughs, kills) = tracker.process_ghost(inst);
                 self.free_regs(kills);
             }
             tracker.drop_dead(inst);
             self.process_spills(tracker);
         }
     }
@@ -232,27 +229,25 @@ impl<'a> Context<'a> {
             }
         }
 
         // The transient pressure counts for the EBB arguments are accurate. Just preserve them.
         self.pressure.preserve_transient();
         self.free_dead_regs(params);
     }
 
-    fn visit_inst(
-        &mut self,
-        inst: Inst,
-        ebb: Ebb,
-        constraints: &RecipeConstraints,
-        tracker: &mut LiveValueTracker,
-    ) {
+    fn visit_inst(&mut self, inst: Inst, ebb: Ebb, tracker: &mut LiveValueTracker) {
         debug!("Inst {}, {}", self.cur.display_inst(inst), self.pressure);
         debug_assert_eq!(self.cur.current_inst(), Some(inst));
         debug_assert_eq!(self.cur.current_ebb(), Some(ebb));
 
+        let constraints = self
+            .encinfo
+            .operand_constraints(self.cur.func.encodings[inst]);
+
         // We may need to resolve register constraints if there are any noteworthy uses.
         debug_assert!(self.reg_uses.is_empty());
         self.collect_reg_uses(inst, ebb, constraints);
 
         // Calls usually have fixed register uses.
         let call_sig = self.cur.func.dfg.call_signature(inst);
         if let Some(sig) = call_sig {
             self.collect_abi_reg_uses(inst, sig);
@@ -277,91 +272,100 @@ impl<'a> Context<'a> {
                     self.spill_reg(lv.value);
                 }
             }
         }
 
         // Make sure we have enough registers for the register defs.
         // Dead defs are included here. They need a register too.
         // No need to process call return values, they are in fixed registers.
-        for op in constraints.outs {
-            if op.kind != ConstraintKind::Stack {
-                // Add register def to pressure, spill if needed.
-                while let Err(mask) = self.pressure.take_transient(op.regclass) {
-                    debug!("Need {} reg from {} throughs", op.regclass, throughs.len());
-                    match self.spill_candidate(mask, throughs) {
-                        Some(cand) => self.spill_reg(cand),
-                        None => panic!(
-                            "Ran out of {} registers for {}",
-                            op.regclass,
-                            self.cur.display_inst(inst)
-                        ),
+        if let Some(constraints) = constraints {
+            for op in constraints.outs {
+                if op.kind != ConstraintKind::Stack {
+                    // Add register def to pressure, spill if needed.
+                    while let Err(mask) = self.pressure.take_transient(op.regclass) {
+                        debug!("Need {} reg from {} throughs", op.regclass, throughs.len());
+                        match self.spill_candidate(mask, throughs) {
+                            Some(cand) => self.spill_reg(cand),
+                            None => panic!(
+                                "Ran out of {} registers for {}",
+                                op.regclass,
+                                self.cur.display_inst(inst)
+                            ),
+                        }
                     }
                 }
             }
+            self.pressure.reset_transient();
         }
-        self.pressure.reset_transient();
 
         // Restore pressure state, compute pressure with affinities from `defs`.
         // Exclude dead defs. Includes call return values.
         // This won't cause spilling.
         self.take_live_regs(defs);
     }
 
     // Collect register uses that are noteworthy in one of the following ways:
     //
     // 1. It's a fixed register constraint.
     // 2. It's a use of a spilled value.
     // 3. It's a tied register constraint and the value isn't killed.
     //
     // We are assuming here that if a value is used both by a fixed register operand and a register
     // class operand, they two are compatible. We are also assuming that two register class
     // operands are always compatible.
-    fn collect_reg_uses(&mut self, inst: Inst, ebb: Ebb, constraints: &RecipeConstraints) {
+    fn collect_reg_uses(&mut self, inst: Inst, ebb: Ebb, constraints: Option<&RecipeConstraints>) {
         let args = self.cur.func.dfg.inst_args(inst);
-        for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() {
-            let mut reguse = RegUse::new(arg, idx, op.regclass.into());
-            let lr = &self.liveness[arg];
-            let ctx = self.liveness.context(&self.cur.func.layout);
-            match op.kind {
-                ConstraintKind::Stack => continue,
-                ConstraintKind::FixedReg(_) => reguse.fixed = true,
-                ConstraintKind::Tied(_) => {
-                    // A tied operand must kill the used value.
-                    reguse.tied = !lr.killed_at(inst, ebb, ctx);
+        let num_fixed_ins = if let Some(constraints) = constraints {
+            for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() {
+                let mut reguse = RegUse::new(arg, idx, op.regclass.into());
+                let lr = &self.liveness[arg];
+                let ctx = self.liveness.context(&self.cur.func.layout);
+                match op.kind {
+                    ConstraintKind::Stack => continue,
+                    ConstraintKind::FixedReg(_) => reguse.fixed = true,
+                    ConstraintKind::Tied(_) => {
+                        // A tied operand must kill the used value.
+                        reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                    }
+                    ConstraintKind::FixedTied(_) => {
+                        reguse.fixed = true;
+                        reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                    }
+                    ConstraintKind::Reg => {}
                 }
-                ConstraintKind::FixedTied(_) => {
-                    reguse.fixed = true;
-                    reguse.tied = !lr.killed_at(inst, ebb, ctx);
+                if lr.affinity.is_stack() {
+                    reguse.spilled = true;
                 }
-                ConstraintKind::Reg => {}
+
+                // Only collect the interesting register uses.
+                if reguse.fixed || reguse.tied || reguse.spilled {
+                    debug!("  reguse: {}", reguse);
+                    self.reg_uses.push(reguse);
+                }
             }
-            if lr.affinity.is_stack() {
-                reguse.spilled = true;
-            }
-
-            // Only collect the interesting register uses.
-            if reguse.fixed || reguse.tied || reguse.spilled {
-                debug!("  reguse: {}", reguse);
-                self.reg_uses.push(reguse);
-            }
-        }
+            constraints.ins.len()
+        } else {
+            // A non-ghost instruction with no constraints can't have any
+            // fixed operands.
+            0
+        };
 
         // Similarly, for return instructions, collect uses of ABI-defined
         // return values.
         if self.cur.func.dfg[inst].opcode().is_return() {
             debug_assert_eq!(
                 self.cur.func.dfg.inst_variable_args(inst).len(),
                 self.cur.func.signature.returns.len(),
                 "The non-fixed arguments in a return should follow the function's signature."
             );
             for (ret_idx, (ret, &arg)) in
                 self.cur.func.signature.returns.iter().zip(args).enumerate()
             {
-                let idx = constraints.ins.len() + ret_idx;
+                let idx = num_fixed_ins + ret_idx;
                 let unit = match ret.location {
                     ArgumentLoc::Unassigned => {
                         panic!("function return signature should be legalized")
                     }
                     ArgumentLoc::Reg(unit) => unit,
                     ArgumentLoc::Stack(_) => continue,
                 };
                 let toprc = toprc_containing_regunit(unit, &self.reginfo);
@@ -371,37 +375,37 @@ impl<'a> Context<'a> {
                 debug!("  reguse: {}", reguse);
                 self.reg_uses.push(reguse);
             }
         }
     }
 
     // Collect register uses from the ABI input constraints.
     fn collect_abi_reg_uses(&mut self, inst: Inst, sig: SigRef) {
-        let fixed_args = self.cur.func.dfg[inst]
+        let num_fixed_args = self.cur.func.dfg[inst]
             .opcode()
             .constraints()
-            .fixed_value_arguments();
+            .num_fixed_value_arguments();
         let args = self.cur.func.dfg.inst_variable_args(inst);
         for (idx, (abi, &arg)) in self.cur.func.dfg.signatures[sig]
             .params
             .iter()
             .zip(args)
             .enumerate()
         {
             if abi.location.is_reg() {
                 let (rci, spilled) = match self.liveness[arg].affinity {
                     Affinity::Reg(rci) => (rci, false),
                     Affinity::Stack => (
                         self.cur.isa.regclass_for_abi_type(abi.value_type).into(),
                         true,
                     ),
                     Affinity::Unassigned => panic!("Missing affinity for {}", arg),
                 };
-                let mut reguse = RegUse::new(arg, fixed_args + idx, rci);
+                let mut reguse = RegUse::new(arg, num_fixed_args + idx, rci);
                 reguse.fixed = true;
                 reguse.spilled = spilled;
                 self.reg_uses.push(reguse);
             }
         }
     }
 
     // Process multiple register uses to resolve potential conflicts.
--- a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
+++ b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs
@@ -286,30 +286,32 @@ impl UFEntry {
 /// For more information on the algorithm implemented here, see Chapter 21 "Data Structures for
 /// Disjoint Sets" of Cormen, Leiserson, Rivest, Stein, "Introduction to algorithms", 3rd Ed.
 ///
 /// The [Wikipedia entry on disjoint-set data
 /// structures](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) is also good.
 impl VirtRegs {
     /// Find the leader value and rank of the set containing `v`.
     /// Compress the path if needed.
-    fn find(&mut self, val: Value) -> (Value, u32) {
-        match UFEntry::decode(self.union_find[val]) {
-            UFEntry::Rank(rank) => (val, rank),
-            UFEntry::Link(parent) => {
-                // TODO: This recursion would be more efficient as an iteration that pushes
-                // elements onto a SmallVector.
-                let found = self.find(parent);
-                // Compress the path if needed.
-                if found.0 != parent {
-                    self.union_find[val] = UFEntry::encode_link(found.0);
+    fn find(&mut self, mut val: Value) -> (Value, u32) {
+        let mut val_stack = vec![];
+        let found = loop {
+            match UFEntry::decode(self.union_find[val]) {
+                UFEntry::Rank(rank) => break (val, rank),
+                UFEntry::Link(parent) => {
+                    val_stack.push(val);
+                    val = parent;
                 }
-                found
             }
+        };
+        // Compress the path
+        while let Some(val) = val_stack.pop() {
+            self.union_find[val] = UFEntry::encode_link(found.0);
         }
+        found
     }
 
     /// Union the two sets containing `a` and `b`.
     ///
     /// This ensures that `a` and `b` will belong to the same virtual register after calling
     /// `finish_union_find()`.
     pub fn union(&mut self, a: Value, b: Value) {
         let (leader_a, rank_a) = self.find(a);
--- a/third_party/rust/cranelift-codegen/src/simple_gvn.rs
+++ b/third_party/rust/cranelift-codegen/src/simple_gvn.rs
@@ -105,32 +105,29 @@ pub fn do_simple_gvn(func: &mut Function
                 scope_stack.push(func.layout.next_inst(inst).unwrap());
                 visible_values.increment_depth();
             }
 
             if trivially_unsafe_for_gvn(opcode) {
                 continue;
             }
 
-            let inst_data = func.dfg[inst].clone();
-
             // These are split up to separate concerns.
-            if is_load_and_not_readonly(&inst_data) {
+            if is_load_and_not_readonly(&func.dfg[inst]) {
                 continue;
             }
 
             let ctrl_typevar = func.dfg.ctrl_typevar(inst);
             let key = HashKey {
                 inst: func.dfg[inst].clone(),
                 ty: ctrl_typevar,
                 pos: &pos,
             };
-            let entry = visible_values.entry(key);
             use scoped_hash_map::Entry::*;
-            match entry {
+            match visible_values.entry(key) {
                 Occupied(entry) => {
                     debug_assert!(domtree.dominates(*entry.get(), inst, &func.layout));
                     // If the redundant instruction is representing the current
                     // scope, pick a new representative.
                     let old = scope_stack.last_mut().unwrap();
                     if *old == inst {
                         *old = func.layout.next_inst(inst).unwrap();
                     }
--- a/third_party/rust/cranelift-codegen/src/verifier/mod.rs
+++ b/third_party/rust/cranelift-codegen/src/verifier/mod.rs
@@ -519,22 +519,22 @@ impl<'a> Verifier<'a> {
         if inst_data.opcode().format() != InstructionFormat::from(inst_data) {
             return fatal!(
                 errors,
                 inst,
                 "instruction opcode doesn't match instruction format"
             );
         }
 
-        let fixed_results = inst_data.opcode().constraints().fixed_results();
+        let num_fixed_results = inst_data.opcode().constraints().num_fixed_results();
         // var_results is 0 if we aren't a call instruction
         let var_results = dfg
             .call_signature(inst)
             .map_or(0, |sig| dfg.signatures[sig].returns.len());
-        let total_results = fixed_results + var_results;
+        let total_results = num_fixed_results + var_results;
 
         // All result values for multi-valued instructions are created
         let got_results = dfg.inst_results(inst).len();
         if got_results != total_results {
             return fatal!(
                 errors,
                 inst,
                 "expected {} result values, found {}",
@@ -856,28 +856,23 @@ impl<'a> Verifier<'a> {
                 if is_reachable {
                     if !self
                         .expected_domtree
                         .dominates(def_inst, loc_inst, &self.func.layout)
                     {
                         return fatal!(
                             errors,
                             loc_inst,
-                            "uses value from non-dominating {}",
+                            "uses value {} from non-dominating {}",
+                            v,
                             def_inst
                         );
                     }
                     if def_inst == loc_inst {
-                        return fatal!(
-                            errors,
-                            loc_inst,
-                            "uses value from itself {},  {}",
-                            def_inst,
-                            loc_inst
-                        );
+                        return fatal!(errors, loc_inst, "uses value {} from itself", v);
                     }
                 }
             }
             ValueDef::Param(ebb, _) => {
                 // Value is defined by an existing EBB.
                 if !dfg.ebb_is_valid(ebb) {
                     return fatal!(errors, loc_inst, "{} is defined by invalid EBB {}", v, ebb);
                 }
--- a/third_party/rust/cranelift-codegen/src/write.rs
+++ b/third_party/rust/cranelift-codegen/src/write.rs
@@ -9,25 +9,35 @@ use ir::{DataFlowGraph, Ebb, Function, I
 use isa::{RegInfo, TargetIsa};
 use packed_option::ReservedValue;
 use std::fmt::{self, Write};
 use std::string::String;
 use std::vec::Vec;
 
 /// A `FuncWriter` used to decorate functions during printing.
 pub trait FuncWriter {
+    /// Write the extended basic block header for the current function.
+    fn write_ebb_header(
+        &mut self,
+        w: &mut Write,
+        func: &Function,
+        isa: Option<&TargetIsa>,
+        ebb: Ebb,
+        indent: usize,
+    ) -> fmt::Result;
+
     /// Write the given `inst` to `w`.
     fn write_instruction(
         &mut self,
         w: &mut Write,
         func: &Function,
         aliases: &SecondaryMap<Value, Vec<Value>>,
         isa: Option<&TargetIsa>,
         inst: Inst,
-        ident: usize,
+        indent: usize,
     ) -> fmt::Result;
 
     /// Write the preamble to `w`. By default, this uses `write_entity_definition`.
     fn write_preamble(
         &mut self,
         w: &mut Write,
         func: &Function,
         regs: Option<&RegInfo>,
@@ -103,16 +113,27 @@ impl FuncWriter for PlainWriter {
         func: &Function,
         aliases: &SecondaryMap<Value, Vec<Value>>,
         isa: Option<&TargetIsa>,
         inst: Inst,
         indent: usize,
     ) -> fmt::Result {
         write_instruction(w, func, aliases, isa, inst, indent)
     }
+
+    fn write_ebb_header(
+        &mut self,
+        w: &mut Write,
+        func: &Function,
+        isa: Option<&TargetIsa>,
+        ebb: Ebb,
+        indent: usize,
+    ) -> fmt::Result {
+        write_ebb_header(w, func, isa, ebb, indent)
+    }
 }
 
 /// Write `func` to `w` as equivalent text.
 /// Use `isa` to emit ISA-dependent annotations.
 pub fn write_function(w: &mut Write, func: &Function, isa: Option<&TargetIsa>) -> fmt::Result {
     decorate_function(&mut PlainWriter, w, func, isa)
 }
 
@@ -222,17 +243,17 @@ fn decorate_ebb<FW: FuncWriter>(
 ) -> fmt::Result {
     // Indent all instructions if any encodings are present.
     let indent = if func.encodings.is_empty() && func.srclocs.is_empty() {
         4
     } else {
         36
     };
 
-    write_ebb_header(w, func, isa, ebb, indent)?;
+    func_w.write_ebb_header(w, func, isa, ebb, indent)?;
     for a in func.dfg.ebb_params(ebb).iter().cloned() {
         write_value_aliases(w, aliases, a, indent)?;
     }
     for inst in func.layout.ebb_insts(ebb) {
         func_w.write_instruction(w, func, aliases, isa, inst, indent)?;
     }
 
     Ok(())
--- a/third_party/rust/cranelift-entity/.cargo-checksum.json
+++ b/third_party/rust/cranelift-entity/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"1e808860e82183786baf0f34301d7de848ddc5932ddc2ff2f7ccc56a7c94cd61","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/iter.rs":"cd2336dc29891e4e5060fb24f1d2f885a4606ea6580e9bd0f261843f12e31a1b","src/keys.rs":"5eca885b3e7ba19936c24066253bf47ebbd9d0a808a84dc910041e8e7be86349","src/lib.rs":"ccbf78e58d56ef1cb811e5ba451d6e8aa69a84c95f5cfe89c0d1f7ecdd26d15b","src/list.rs":"15d9762396439eb2e835401a7b85e190e097fa5eb863decfb67fb677f1093335","src/map.rs":"bcf7a78077056e4194581cbeb4b9d6bdd263ae1c6b261a0fc011ccda5f39bb4f","src/packed_option.rs":"19b2d49e0233e05e3dc39424187644af546934fe92b7200543fe10728ec831f6","src/primary.rs":"0954bbae2dcbd4cc173f15be473ecece94af278917f0f94e5dd289ccbfac66da","src/set.rs":"fd687531bb01db9a22ed09486e378fdfe5842c84b603620f83fe8a42109df3cb","src/sparse.rs":"d2b7bd25c7e2b5ef2194feb08c635447953a4548d42ae26d080bb4ca44dfcc20"},"package":"9be3f82369346201c2e0cff720522e6eb55459e51c916b2199f25cff2058ca96"}
\ No newline at end of file
+{"files":{"Cargo.toml":"18b45cd5e51eaa9c5591e303a4fcdb759e740be967d02aaa154aaafc25281daa","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"96ceffbfd88fb06e3b41aa4d3087cffbbf8441d04eba7ab09662a72ab600a321","src/iter.rs":"cd2336dc29891e4e5060fb24f1d2f885a4606ea6580e9bd0f261843f12e31a1b","src/keys.rs":"5eca885b3e7ba19936c24066253bf47ebbd9d0a808a84dc910041e8e7be86349","src/lib.rs":"ccbf78e58d56ef1cb811e5ba451d6e8aa69a84c95f5cfe89c0d1f7ecdd26d15b","src/list.rs":"15d9762396439eb2e835401a7b85e190e097fa5eb863decfb67fb677f1093335","src/map.rs":"bcf7a78077056e4194581cbeb4b9d6bdd263ae1c6b261a0fc011ccda5f39bb4f","src/packed_option.rs":"19b2d49e0233e05e3dc39424187644af546934fe92b7200543fe10728ec831f6","src/primary.rs":"457f72222869abfc06109473d8a7435cf8acaef3888b4bd559608e135aa96395","src/set.rs":"fd687531bb01db9a22ed09486e378fdfe5842c84b603620f83fe8a42109df3cb","src/sparse.rs":"d2b7bd25c7e2b5ef2194feb08c635447953a4548d42ae26d080bb4ca44dfcc20"},"package":"fc9a0329208e5e0d7d4d6e64cd50985d4c4cbfdbeeb594ae2157a094b98e8dcc"}
\ No newline at end of file
--- a/third_party/rust/cranelift-entity/Cargo.toml
+++ b/third_party/rust/cranelift-entity/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-entity"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Data structures using entity references as mapping keys"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 keywords = ["entity", "set", "map"]
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
--- a/third_party/rust/cranelift-entity/src/primary.rs
+++ b/third_party/rust/cranelift-entity/src/primary.rs
@@ -106,16 +106,26 @@ where
         self.elems.push(v);
         k
     }
 
     /// Returns the last element that was inserted in the map.
     pub fn last(&self) -> Option<&V> {
         self.elems.last()
     }
+
+    /// Reserves capacity for at least `additional` more elements to be inserted.
+    pub fn reserve(&mut self, additional: usize) {
+        self.elems.reserve(additional)
+    }
+
+    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted.
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.elems.reserve_exact(additional)
+    }
 }
 
 /// Immutable indexing into an `PrimaryMap`.
 /// The indexed value must be in the map.
 impl<K, V> Index<K> for PrimaryMap<K, V>
 where
     K: EntityRef,
 {
--- a/third_party/rust/cranelift-frontend/.cargo-checksum.json
+++ b/third_party/rust/cranelift-frontend/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"86e80c8ba33f01a87083d8abf7de8ebcf2e8c065aa5c3a4276e5154d3e02af35","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"32c32130a988cf636a26abd6ddeb993f6c11f3c259c5c0b21997a72ab7f8c90b","src/lib.rs":"9c223914fb7530a669a7487b3b1cf3138df0aed79d152da3d3e03012382244f2","src/ssa.rs":"2b03fd5c88cda8a318827282ed960a61192d6685881ebd8b3d6e8fa92ca6bdc6","src/switch.rs":"bda005663d7976353250c8016ec1f46d0aa03ef289542e4db1b87a071387f7a4","src/variable.rs":"b8de0a43f72ca45bfa0833aee312f3c3f396cf3920545bbdcb9da98fb0de26df"},"package":"7d5d18ab2bc89a09b4275442a9559dc0f947b9a8ad9ae9ee89452a057df54ced"}
\ No newline at end of file
+{"files":{"Cargo.toml":"597db8d588c5ed61feb5d54e82f9750575f41211de66c965241186694aec244f","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"dea43e8044284df50f8b8772e9b48ba8b109b45c74111ff73619775d57ad8d67","src/frontend.rs":"98fed7c08319790af423c40498ed8dd856a52b3535d2ecaf4a835392bd951996","src/lib.rs":"9c223914fb7530a669a7487b3b1cf3138df0aed79d152da3d3e03012382244f2","src/ssa.rs":"2b03fd5c88cda8a318827282ed960a61192d6685881ebd8b3d6e8fa92ca6bdc6","src/switch.rs":"bda005663d7976353250c8016ec1f46d0aa03ef289542e4db1b87a071387f7a4","src/variable.rs":"b8de0a43f72ca45bfa0833aee312f3c3f396cf3920545bbdcb9da98fb0de26df"},"package":"98d9eb4a2343435d520499236c805725c88d6d55eefb9a6ad0819b7970c76bdd"}
\ No newline at end of file
--- a/third_party/rust/cranelift-frontend/Cargo.toml
+++ b/third_party/rust/cranelift-frontend/Cargo.toml
@@ -7,26 +7,26 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-frontend"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Cranelift IR builder helper"
 documentation = "https://cranelift.readthedocs.io/"
 readme = "README.md"
 categories = ["no-std"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-codegen]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.hashmap_core]
 version = "0.1.9"
 optional = true
 
 [dependencies.log]
 version = "0.4.4"
--- a/third_party/rust/cranelift-frontend/src/frontend.rs
+++ b/third_party/rust/cranelift-frontend/src/frontend.rs
@@ -600,22 +600,22 @@ impl<'a> FunctionBuilder<'a> {
         let load_and_store_amount = size / access_size;
 
         if load_and_store_amount > THRESHOLD {
             let size_value = self.ins().iconst(config.pointer_type(), size as i64);
             self.call_memcpy(config, dest, src, size_value);
             return;
         }
 
+        let int_type = Type::int((access_size * 8) as u16).unwrap();
         let mut flags = MemFlags::new();
         flags.set_aligned();
 
         for i in 0..load_and_store_amount {
             let offset = (access_size * i) as i32;
-            let int_type = Type::int(access_size as u16).unwrap();
             let value = self.ins().load(int_type, flags, src, offset);
             self.ins().store(flags, value, dest, offset);
         }
     }
 
     /// Calls libc.memset
     ///
     /// Writes `size` bytes of value `ch` to memory starting at `buffer`.
@@ -674,17 +674,17 @@ impl<'a> FunctionBuilder<'a> {
             let ch = self.ins().iconst(types::I32, ch as i64);
             let size = self.ins().iconst(config.pointer_type(), size as i64);
             self.call_memset(config, buffer, ch, size);
         } else {
             let mut flags = MemFlags::new();
             flags.set_aligned();
 
             let ch = ch as u64;
-            let int_type = Type::int(access_size as u16).unwrap();
+            let int_type = Type::int((access_size * 8) as u16).unwrap();
             let raw_value = if int_type == types::I64 {
                 (ch << 32) | (ch << 16) | (ch << 8) | ch
             } else if int_type == types::I32 {
                 (ch << 16) | (ch << 8) | ch
             } else if int_type == types::I16 {
                 (ch << 8) | ch
             } else {
                 assert_eq!(int_type, types::I8);
@@ -760,17 +760,20 @@ impl<'a> FunctionBuilder<'a> {
 
         let mut flags = MemFlags::new();
         flags.set_aligned();
 
         // Load all of the memory first in case `dest` overlaps.
         let registers: Vec<_> = (0..load_and_store_amount)
             .map(|i| {
                 let offset = (access_size * i) as i32;
-                (self.ins().load(types::I8, flags, src, offset), offset)
+                (
+                    self.ins().load(config.pointer_type(), flags, src, offset),
+                    offset,
+                )
             }).collect();
 
         for (value, offset) in registers {
             self.ins().store(flags, value, dest, offset);
         }
     }
 }
 
@@ -983,15 +986,72 @@ ebb0:
     call fn0(v1, v0, v1)
     return v1
 }
 "
         );
     }
 
     #[test]
+    fn small_memcpy() {
+        use cranelift_codegen::{isa, settings};
+        use std::str::FromStr;
+
+        let shared_builder = settings::builder();
+        let shared_flags = settings::Flags::new(shared_builder);
+
+        let triple = ::target_lexicon::Triple::from_str("arm").expect("Couldn't create arm triple");
+
+        let target = isa::lookup(triple)
+            .ok()
+            .map(|b| b.finish(shared_flags))
+            .expect("This test requires arm support.");
+
+        let mut sig = Signature::new(target.default_call_conv());
+        sig.returns.push(AbiParam::new(I32));
+
+        let mut fn_ctx = FunctionBuilderContext::new();
+        let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
+        {
+            let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
+
+            let block0 = builder.create_ebb();
+            let x = Variable::new(0);
+            let y = Variable::new(16);
+            builder.declare_var(x, target.pointer_type());
+            builder.declare_var(y, target.pointer_type());
+            builder.append_ebb_params_for_function_params(block0);
+            builder.switch_to_block(block0);
+
+            let src = builder.use_var(x);
+            let dest = builder.use_var(y);
+            let size = 8;
+            builder.emit_small_memcpy(target.frontend_config(), dest, src, size, 8, 8);
+            builder.ins().return_(&[dest]);
+
+            builder.seal_all_blocks();
+            builder.finalize();
+        }
+
+        assert_eq!(
+            func.display(None).to_string(),
+            "function %sample() -> i32 system_v {
+ebb0:
+    v4 = iconst.i32 0
+    v1 -> v4
+    v3 = iconst.i32 0
+    v0 -> v3
+    v2 = load.i64 aligned v0
+    store aligned v2, v1
+    return v1
+}
+"
+        );
+    }
+
+    #[test]
     fn test_greatest_divisible_power_of_two() {
         assert_eq!(64, greatest_divisible_power_of_two(64));
         assert_eq!(16, greatest_divisible_power_of_two(48));
         assert_eq!(8, greatest_divisible_power_of_two(24));
         assert_eq!(1, greatest_divisible_power_of_two(25));
     }
 }
--- a/third_party/rust/cranelift-wasm/.cargo-checksum.json
+++ b/third_party/rust/cranelift-wasm/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"1a769c7a06aca3d88b4792a2ac46c6416902f0fa1176bf0fbdec4b4ebc29be6c","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"046f81212a5705bfaa925b6de195652141b727d63ef602af57d5073659deea64","src/code_translator.rs":"36bf4010cbd89774fd8f8ba75c3535887585b11624ae2f20b05ec60d43e2954d","src/environ/dummy.rs":"1eafb40cc09f04cc673c387ff960c373ad15ff091d14638799ad12ab1e3fc6ba","src/environ/mod.rs":"8c5287366c354acb144593fadbbe45c14106e0b7ec101077c4f3f213901c584d","src/environ/spec.rs":"49e43ff35083f87d518ee02b4a18c1c2079552069eeaa4c2f7c9776a2f5ba5a6","src/func_translator.rs":"1c6b7d0d3da14c1ff7df1c22d2ade14da5d87d0be70f647145ea180da762aa2f","src/lib.rs":"5db10cae9fb9c792fa278a1795b4f5ec412ad481f52391e481d688c2e55533ce","src/module_translator.rs":"8e441cc4cb05d6bdd7be41f2ba937390f85f3e3b07578e03a0f9e642f963bc02","src/sections_translator.rs":"799754ccdd0e8572b8c0d775193ce1b279c89c92a284687dce86268ee316b83b","src/state.rs":"4523d611d2c4889eb809ee6c2bfbf29d4d83230580be3c724009ba8988cc25b6","src/translation_utils.rs":"3e8d486c7acccad5e269628add77338702e43464780945c8767559d836d72a10","tests/wasm_testsuite.rs":"9ea05ab8d188f047f3307e5ca0c1ea10784d65d338f7ea3544d59e6fa6a202f2"},"package":"e5906a111814d43d84002ef974eb0c023804fd4d1866b34f43c1bb588a759ad8"}
\ No newline at end of file
+{"files":{"Cargo.toml":"aca5579a3fbaa96d6cfda23012215879f7df0a07313e2e9acdc49e167d31e1c3","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"046f81212a5705bfaa925b6de195652141b727d63ef602af57d5073659deea64","src/code_translator.rs":"474d07684fee27fcbd48997a7772458d8eff0a69a31b74293066a892c87067f9","src/environ/dummy.rs":"aafca1a2cda88cb67d4c082f7ccb6296812586216f417c501224b6790d345446","src/environ/mod.rs":"8c5287366c354acb144593fadbbe45c14106e0b7ec101077c4f3f213901c584d","src/environ/spec.rs":"a627a1a92a2a652d037f63a9def019ebbf4c953de1cb194f2e73095744d07476","src/func_translator.rs":"1c6b7d0d3da14c1ff7df1c22d2ade14da5d87d0be70f647145ea180da762aa2f","src/lib.rs":"b94abdc2fe638aff7b5fc00ffb2fc4812590a68241b8462b82888aa9114c2f64","src/module_translator.rs":"8e441cc4cb05d6bdd7be41f2ba937390f85f3e3b07578e03a0f9e642f963bc02","src/sections_translator.rs":"62d7d53abc88060c4d63721a99530d26a3ed09cb99e1f19238bcefd8b86b958a","src/state.rs":"4523d611d2c4889eb809ee6c2bfbf29d4d83230580be3c724009ba8988cc25b6","src/translation_utils.rs":"363d75509bca5d87548881dcbb3c52642980be8fa6d62c2ea4b39524560ac65c","tests/wasm_testsuite.rs":"9ea05ab8d188f047f3307e5ca0c1ea10784d65d338f7ea3544d59e6fa6a202f2"},"package":"5022a3a3d1044fdc8c97909b5e8d701884982dcfb43885034d004cfdd9b7d577"}
\ No newline at end of file
--- a/third_party/rust/cranelift-wasm/Cargo.toml
+++ b/third_party/rust/cranelift-wasm/Cargo.toml
@@ -7,34 +7,34 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cranelift-wasm"
-version = "0.23.0"
+version = "0.25.0"
 authors = ["The Cranelift Project Developers"]
 description = "Translator from WebAssembly to Cranelift IR"
 readme = "README.md"
 keywords = ["webassembly", "wasm"]
 categories = ["no-std", "wasm"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/CraneStation/cranelift"
 [dependencies.cranelift-codegen]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.cranelift-entity]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.cranelift-frontend]
-version = "0.23.0"
+version = "0.25.0"
 default-features = false
 
 [dependencies.failure]
 version = "0.1.1"
 features = ["derive"]
 default-features = false
 
 [dependencies.failure_derive]
@@ -45,17 +45,17 @@ default-features = false
 version = "0.1.9"
 optional = true
 
 [dependencies.log]
 version = "0.4.4"
 default-features = false
 
 [dependencies.wasmparser]
-version = "0.21.4"
+version = "0.22.0"
 default-features = false
 [dev-dependencies.target-lexicon]
 version = "0.2.0"
 
 [dev-dependencies.wabt]
 version = "0.7.0"
 
 [features]
--- a/third_party/rust/cranelift-wasm/src/code_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/code_translator.rs
@@ -248,17 +248,17 @@ pub fn translate_operator<FE: FuncEnviro
             builder
                 .ins()
                 .jump(br_destination, state.peekn(return_count));
             state.popn(return_count);
             state.reachable = false;
         }
         Operator::BrIf { relative_depth } => translate_br_if(relative_depth, builder, state),
         Operator::BrTable { table } => {
-            let (depths, default) = table.read_table();
+            let (depths, default) = table.read_table()?;
             let mut min_depth = default;
             for depth in &*depths {
                 if *depth < min_depth {
                     min_depth = *depth;
                 }
             }
             let jump_args_count = {
                 let i = state.control_stack.len() - 1 - (min_depth as usize);
--- a/third_party/rust/cranelift-wasm/src/environ/dummy.rs
+++ b/third_party/rust/cranelift-wasm/src/environ/dummy.rs
@@ -47,16 +47,25 @@ pub struct DummyModuleInfo {
     config: TargetFrontendConfig,
 
     /// Signatures as provided by `declare_signature`.
     pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
 
     /// Module and field names of imported functions as provided by `declare_func_import`.
     pub imported_funcs: Vec<(String, String)>,
 
+    /// Module and field names of imported globals as provided by `declare_global_import`.
+    pub imported_globals: Vec<(String, String)>,
+
+    /// Module and field names of imported tables as provided by `declare_table_import`.
+    pub imported_tables: Vec<(String, String)>,
+
+    /// Module and field names of imported memories as provided by `declare_memory_import`.
+    pub imported_memories: Vec<(String, String)>,
+
     /// Functions, imported and local.
     pub functions: PrimaryMap<FuncIndex, Exportable<SignatureIndex>>,
 
     /// Function bodies.
     pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
 
     /// Tables as provided by `declare_table`.
     pub tables: PrimaryMap<TableIndex, Exportable<Table>>,
@@ -73,16 +82,19 @@ pub struct DummyModuleInfo {
 
 impl DummyModuleInfo {
     /// Creates a new `DummyModuleInfo` instance.
     pub fn new(config: TargetFrontendConfig) -> Self {
         Self {
             config,
             signatures: PrimaryMap::new(),
             imported_funcs: Vec::new(),
+            imported_globals: Vec::new(),
+            imported_tables: Vec::new(),
+            imported_memories: Vec::new(),
             functions: PrimaryMap::new(),
             function_bodies: PrimaryMap::new(),
             tables: PrimaryMap::new(),
             memories: PrimaryMap::new(),
             globals: PrimaryMap::new(),
             start_func: None,
         }
     }
@@ -321,18 +333,18 @@ impl<'dummy_environment> FuncEnvironment
     }
 
     fn return_mode(&self) -> ReturnMode {
         self.return_mode
     }
 }
 
 impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
-    fn target_config(&self) -> &TargetFrontendConfig {
-        &self.info.config
+    fn target_config(&self) -> TargetFrontendConfig {
+        self.info.config
     }
 
     fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName {
         get_func_name(func_index)
     }
 
     fn declare_signature(&mut self, sig: &ir::Signature) {
         self.info.signatures.push(sig.clone());
@@ -370,35 +382,59 @@ impl<'data> ModuleEnvironment<'data> for
     fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex {
         self.info.functions[func_index].entity
     }
 
     fn declare_global(&mut self, global: Global) {
         self.info.globals.push(Exportable::new(global));
     }
 
+    fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str) {
+        self.info.globals.push(Exportable::new(global));
+        self.info
+            .imported_globals
+            .push((String::from(module), String::from(field)));
+    }
+
     fn get_global(&self, global_index: GlobalIndex) -> &Global {
         &self.info.globals[global_index].entity
     }
 
     fn declare_table(&mut self, table: Table) {
         self.info.tables.push(Exportable::new(table));
     }
+
+    fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str) {
+        self.info.tables.push(Exportable::new(table));
+        self.info
+            .imported_tables
+            .push((String::from(module), String::from(field)));
+    }
+
     fn declare_table_elements(
         &mut self,
         _table_index: TableIndex,
         _base: Option<GlobalIndex>,
         _offset: usize,
         _elements: Vec<FuncIndex>,
     ) {
         // We do nothing
     }
+
     fn declare_memory(&mut self, memory: Memory) {
         self.info.memories.push(Exportable::new(memory));
     }
+
+    fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str) {
+        self.info.memories.push(Exportable::new(memory));
+        self.info
+            .imported_memories
+            .push((String::from(module), String::from(field)));
+    }
+
     fn declare_data_initialization(
         &mut self,
         _memory_index: MemoryIndex,
         _base: Option<GlobalIndex>,
         _offset: usize,
         _data: &'data [u8],
     ) {
         // We do nothing
--- a/third_party/rust/cranelift-wasm/src/environ/spec.rs
+++ b/third_party/rust/cranelift-wasm/src/environ/spec.rs
@@ -232,17 +232,17 @@ pub trait FuncEnvironment {
     }
 }
 
 /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the
 /// [`translate_module`](fn.translate_module.html) function. These methods should not be called
 /// by the user, they are only for `cranelift-wasm` internal use.
 pub trait ModuleEnvironment<'data> {
     /// Get the information needed to produce Cranelift IR for the current target.
-    fn target_config(&self) -> &TargetFrontendConfig;
+    fn target_config(&self) -> TargetFrontendConfig;
 
     /// Return the name for the given function index.
     fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName;
 
     /// Declares a function signature to the environment.
     fn declare_signature(&mut self, sig: &ir::Signature);
 
     /// Return the signature with the given index.
@@ -263,31 +263,42 @@ pub trait ModuleEnvironment<'data> {
     fn declare_func_type(&mut self, sig_index: SignatureIndex);
 
     /// Return the signature index for the given function index.
     fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex;
 
     /// Declares a global to the environment.
     fn declare_global(&mut self, global: Global);
 
+    /// Declares a global import to the environment.
+    fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str);
+
     /// Return the global for the given global index.
     fn get_global(&self, global_index: GlobalIndex) -> &Global;
 
     /// Declares a table to the environment.
     fn declare_table(&mut self, table: Table);
+
+    /// Declares a table import to the environment.
+    fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str);
+
     /// Fills a declared table with references to functions in the module.
     fn declare_table_elements(
         &mut self,
         table_index: TableIndex,
         base: Option<GlobalIndex>,
         offset: usize,
         elements: Vec<FuncIndex>,
     );
     /// Declares a memory to the environment
     fn declare_memory(&mut self, memory: Memory);
+
+    /// Declares a memory import to the environment.
+    fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str);
+
     /// Fills a declared memory with bytes at module instantiation.
     fn declare_data_initialization(
         &mut self,
         memory_index: MemoryIndex,
         base: Option<GlobalIndex>,
         offset: usize,
         data: &'data [u8],
     );
--- a/third_party/rust/cranelift-wasm/src/lib.rs
+++ b/third_party/rust/cranelift-wasm/src/lib.rs
@@ -61,18 +61,18 @@ mod translation_utils;
 
 pub use environ::{
     DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmError,
     WasmResult,
 };
 pub use func_translator::FuncTranslator;
 pub use module_translator::translate_module;
 pub use translation_utils::{
-    DefinedFuncIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex,
-    SignatureIndex, Table, TableIndex,
+    DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global,
+    GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
 };
 
 #[cfg(not(feature = "std"))]
 mod std {
     extern crate alloc;
 
     pub use self::alloc::string;
     pub use self::alloc::vec;
--- a/third_party/rust/cranelift-wasm/src/sections_translator.rs
+++ b/third_party/rust/cranelift-wasm/src/sections_translator.rs
@@ -14,18 +14,18 @@ use std::str::from_utf8;
 use std::vec::Vec;
 use translation_utils::{
     type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex,
     Table, TableElementType, TableIndex,
 };
 use wasmparser::{
     self, CodeSectionReader, Data, DataSectionReader, Element, ElementSectionReader, Export,
     ExportSectionReader, ExternalKind, FuncType, FunctionSectionReader, GlobalSectionReader,
-    GlobalType, Import, ImportSectionEntryType, ImportSectionReader, MemorySectionReader,
-    MemoryType, Operator, TableSectionReader, TypeSectionReader,
+    GlobalType, ImportSectionEntryType, ImportSectionReader, MemorySectionReader, MemoryType,
+    Operator, TableSectionReader, TypeSectionReader,
 };
 
 /// Parses the Type section of the wasm module.
 pub fn parse_type_section(
     types: TypeSectionReader,
     environ: &mut ModuleEnvironment,
 ) -> WasmResult<()> {
     for entry in types {
@@ -55,68 +55,71 @@ pub fn parse_type_section(
 }
 
 /// Parses the Import section of the wasm module.
 pub fn parse_import_section<'data>(
     imports: ImportSectionReader<'data>,
     environ: &mut ModuleEnvironment<'data>,
 ) -> WasmResult<()> {
     for entry in imports {
-        match entry? {
-            Import {
-                module,
-                field,
-                ty: ImportSectionEntryType::Function(sig),
-            } => {
-                // The input has already been validated, so we should be able to
-                // assume valid UTF-8 and use `from_utf8_unchecked` if performance
-                // becomes a concern here.
-                let module_name = from_utf8(module).unwrap();
-                let field_name = from_utf8(field).unwrap();
+        let import = entry?;
+
+        // The input has already been validated, so we should be able to
+        // assume valid UTF-8 and use `from_utf8_unchecked` if performance
+        // becomes a concern here.
+        let module_name = from_utf8(import.module).unwrap();
+        let field_name = from_utf8(import.field).unwrap();
+
+        match import.ty {
+            ImportSectionEntryType::Function(sig) => {
                 environ.declare_func_import(
                     SignatureIndex::new(sig as usize),
                     module_name,
                     field_name,
                 );
             }
-            Import {
-                ty:
-                    ImportSectionEntryType::Memory(MemoryType {
-                        limits: ref memlimits,
+            ImportSectionEntryType::Memory(MemoryType {
+                limits: ref memlimits,
+                shared,
+            }) => {
+                environ.declare_memory_import(
+                    Memory {
+                        pages_count: memlimits.initial as usize,
+                        maximum: memlimits.maximum.map(|x| x as usize),
                         shared,
-                    }),
-                ..
-            } => {
-                environ.declare_memory(Memory {
-                    pages_count: memlimits.initial as usize,
-                    maximum: memlimits.maximum.map(|x| x as usize),
-                    shared,
-                });
+                    },
+                    module_name,
+                    field_name,
+                );
             }
-            Import {
-                ty: ImportSectionEntryType::Global(ref ty),
-                ..
-            } => {
-                environ.declare_global(Global {
-                    ty: type_to_type(ty.content_type).unwrap(),
-                    mutability: ty.mutable,
-                    initializer: GlobalInit::Import(),
-                });
+            ImportSectionEntryType::Global(ref ty) => {
+                environ.declare_global_import(
+                    Global {
+                        ty: type_to_type(ty.content_type).unwrap(),
+                        mutability: ty.mutable,
+                        initializer: GlobalInit::Import(),
+                    },
+                    module_name,
+                    field_name,
+                );
             }
-            Import {
-                ty: ImportSectionEntryType::Table(ref tab),
-                ..
-            } => environ.declare_table(Table {
-                ty: match type_to_type(tab.element_type) {
-                    Ok(t) => TableElementType::Val(t),
-                    Err(()) => TableElementType::Func(),
-                },
-                size: tab.limits.initial as usize,
-                maximum: tab.limits.maximum.map(|x| x as usize),
-            }),
+            ImportSectionEntryType::Table(ref tab) => {
+                environ.declare_table_import(
+                    Table {
+                        ty: match type_to_type(tab.element_type) {
+                            Ok(t) => TableElementType::Val(t),
+                            Err(()) => TableElementType::Func(),
+                        },
+                        size: tab.limits.initial as usize,
+                        maximum: tab.limits.maximum.map(|x| x as usize),
+                    },
+                    module_name,
+                    field_name,
+                );
+            }
         }
     }
     Ok(())
 }
 
 /// Parses the Function section of the wasm module.
 pub fn parse_function_section(
     functions: FunctionSectionReader,
--- a/third_party/rust/cranelift-wasm/src/translation_utils.rs
+++ b/third_party/rust/cranelift-wasm/src/translation_utils.rs
@@ -8,16 +8,31 @@ use wasmparser;
 pub struct FuncIndex(u32);
 entity_impl!(FuncIndex);
 
 /// Index type of a defined function inside the WebAssembly module.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
 pub struct DefinedFuncIndex(u32);
 entity_impl!(DefinedFuncIndex);
 
+/// Index type of a defined table inside the WebAssembly module.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub struct DefinedTableIndex(u32);
+entity_impl!(DefinedTableIndex);
+
+/// Index type of a defined memory inside the WebAssembly module.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub struct DefinedMemoryIndex(u32);
+entity_impl!(DefinedMemoryIndex);
+
+/// Index type of a defined global inside the WebAssembly module.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub struct DefinedGlobalIndex(u32);
+entity_impl!(DefinedGlobalIndex);
+
 /// Index type of a table (imported or defined) inside the WebAssembly module.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
 pub struct TableIndex(u32);
 entity_impl!(TableIndex);
 
 /// Index type of a global variable (imported or defined) inside the WebAssembly module.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
 pub struct GlobalIndex(u32);
--- a/third_party/rust/wasmparser/.cargo-checksum.json
+++ b/third_party/rust/wasmparser/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"bfb9c0686d78c97a864c39d8d5015e779547ce2c15188fa849a6d9b6a552a5e7","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"4d883e8917a348973ce29f668182d9443d6ef61c258e5e37107609d20e9adeb6","examples/dump.rs":"b0a4fbc3dd85df85f5eca39861b09f89716c55ff97657e7a32cf6fdee7a88e60","examples/simple.rs":"9726621cd8314ed3c7e293913b06847208ff98e43e1b4d5c79708a7b71c7a768","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"ef4abddea226c624b50cd892ca16fad0423f7af99112deb7ba4f7ae18c3b6f94","src/lib.rs":"04185314f9e61975eb507638c85b0f399f87bc4cf994dd91fd9e73a569dddfb3","src/limits.rs":"2cf22e266c2828d68bb521485b8bd604a2ecb7a023204d7874b3da5837ec44f9","src/parser.rs":"ffb9a83926b8d8f2837d295b4ef0c5c51a3fa905c5b9e80a0b3bd1da50eb612c","src/primitives.rs":"32d3662d7473bc770bcb14a2878ce9d21a00635d928ee142ae4bdbfbb741b159","src/readers/code_section.rs":"7ded16c3e703d71d71b384629488aaa050d0f9b4d419a78eaef8ef481be4b4f3","src/readers/data_section.rs":"74e751ea3cecbe29eb6d6b1b0119f859a5aec1a3240c4a71c381e7409378fa45","src/readers/element_section.rs":"b8f2e367b08f0a7097a9eece6a27e7170c175a13c007b7c4cb3517fa81250ff4","src/readers/export_section.rs":"dc11c96c4955cf18d1fdd50c2a6dddabd915c0ee8fc998e12130b534c9c2b621","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"4dc8ec40c237c30b951bb31a7150a5159430e01d62c91d58ef4922bec65b0f6a","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"15d15305ba1c3cfee3107c5119b12853803a2257ac533be9b58adcf51623d4b8","src/readers/module.rs":"8eb1d05e7cf7393f5c10272123e3aa3fd18fb4ada648014ff519555d08450915","src/readers/name_section.rs":"e61633a3a43f4626f15cd85d53f66a5e2bab0f016658ca792b0c94574f84b57c","src/readers/operators.rs":"f9f5fee7405c332439b4bd3b594f7fd58b08842a9db8752a7734023bfe4dec4a","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"742602c2537ba3ed50f830b1929fe2d19bb68ea04ddb59f77dc47109e84f262a","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"1f6353bd3fdd6f0e004ce440bfbe454bec0c6cffa8bacf1b777cdca690cbdd6a","src/validator.rs":"51410deced9a051767b98891ac304c300ec651f4848df6d02985b3b329b505c3","test-all.sh":"ff894f4e5e34389ad6ef697bd4ade28a2483dd456eabba8b757945546568f4c9","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"202e4cd4d99aa8adb8fe6280e099fdd2e5003c8d09c27de6969ff04dba60ef39"}
\ No newline at end of file
+{"files":{"Cargo.toml":"4c26a23166e9aedf319c9e0175e2be495718d44dd78816582d429377b63c6dc5","LICENSE":"a6c48161a09acc75a0e25503bab66a731eb5fba5392ed4bb4743e4ba5085327a","README.md":"13ea373a411dfa7371cd994736289bb000db51957da92315fecbcc9fe7dcab92","examples/dump.rs":"b0a4fbc3dd85df85f5eca39861b09f89716c55ff97657e7a32cf6fdee7a88e60","examples/simple.rs":"9726621cd8314ed3c7e293913b06847208ff98e43e1b4d5c79708a7b71c7a768","format-all.sh":"6b02a40629ef3d2c0b9671222582a6217d526317a41262ae06c7a95de53bcbeb","src/binary_reader.rs":"d6b0dd34c2a97babae84d1758df75515de372c5228450267141ebbad402c8acd","src/lib.rs":"44d30e30e2b844bcb1d048c5adcaf1057326f7b9b042824631020fbf128d0669","src/limits.rs":"2cf22e266c2828d68bb521485b8bd604a2ecb7a023204d7874b3da5837ec44f9","src/parser.rs":"8f29497795ef8b93134680ff9cb38dbb4f0520ceba270c1d6cee22694362b270","src/primitives.rs":"32d3662d7473bc770bcb14a2878ce9d21a00635d928ee142ae4bdbfbb741b159","src/readers/code_section.rs":"d71a798dce497838c8d6b3aa9744a2cae818b7aff99d45a31a4accb892985fd1","src/readers/data_section.rs":"74e751ea3cecbe29eb6d6b1b0119f859a5aec1a3240c4a71c381e7409378fa45","src/readers/element_section.rs":"b8f2e367b08f0a7097a9eece6a27e7170c175a13c007b7c4cb3517fa81250ff4","src/readers/export_section.rs":"dc11c96c4955cf18d1fdd50c2a6dddabd915c0ee8fc998e12130b534c9c2b621","src/readers/function_section.rs":"57c0479ba8d7f61908ed74e86cbc26553fdd6d2d952f032ce29385a39f82efd3","src/readers/global_section.rs":"5fa18bed0fffadcc2dbdcbaedbe4e4398992fd1ce9e611b0319333a7681082ac","src/readers/import_section.rs":"4dc8ec40c237c30b951bb31a7150a5159430e01d62c91d58ef4922bec65b0f6a","src/readers/init_expr.rs":"7020c80013dad4518a5f969c3ab4d624b46d778f03e632871cf343964f63441c","src/readers/linking_section.rs":"9df71f3ee5356f0d273c099212213353080001e261ca697caddf6b847fb5af09","src/readers/memory_section.rs":"83212f86cfc40d18fb392e9234c880afdf443f4af38a727ba346f9c740ef8718","src/readers/mod.rs":"9de31285cded591651108f16b9463cee7289536c722dbcf49a33847047a82bd1","src/readers/module.rs":"31329dabf177f29b40fa53fa44b19ab545c47bae8bc1e29ef995f413f572e303","src/readers/name_section.rs":"e61633a3a43f4626f15cd85d53f66a5e2bab0f016658ca792b0c94574f84b57c","src/readers/operators.rs":"da43ee8afcb0c1d6e7f1e19e8a10143101f0c598b1e533a394c7397f43881a82","src/readers/reloc_section.rs":"0ef818a8b83a4542c4c29c23642436a92d3e7c37bc0248e817ed5a9d65ec38ce","src/readers/section_reader.rs":"3d2260449fa0455d710ba6d97810372ec36cba70722c10dd236c3a18ca0eb56f","src/readers/sourcemappingurl_section.rs":"742602c2537ba3ed50f830b1929fe2d19bb68ea04ddb59f77dc47109e84f262a","src/readers/start_section.rs":"3eeae00e1aa0fcb2e0d93b7b0eaac30a60d3f1431c71c589cd3f73adb363d532","src/readers/table_section.rs":"e564876825a7b31df2b5dc850279b523e26dc50a08da935cc8d635a49e809951","src/readers/type_section.rs":"2fa33a7b793f3bfa01c259b5dbc38633b7343931886ab41f0cb96dd78db3bf6e","src/tests.rs":"1f6353bd3fdd6f0e004ce440bfbe454bec0c6cffa8bacf1b777cdca690cbdd6a","src/validator.rs":"e55cdabb44689fa780ca639c5e287be99eef9dd203f523b769842df6310f3eb4","test-all.sh":"ff894f4e5e34389ad6ef697bd4ade28a2483dd456eabba8b757945546568f4c9","test-no_std.sh":"f8bc939b378fe618b7ec6297152708e7c8740858eb94e5756464934a38796b8c"},"package":"1b4e0f66e314a8e63ff5c3cc5103f7d0a3de9ee98bb61a960adcf7f1d9debd2f"}
\ No newline at end of file
--- a/third_party/rust/wasmparser/Cargo.toml
+++ b/third_party/rust/wasmparser/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "wasmparser"
-version = "0.21.8"
+version = "0.22.0"
 authors = ["Yury Delendik <ydelendik@mozilla.com>"]
 exclude = ["fuzz/**/*", "tests/**/*"]
 description = "A simple event-driven library for parsing WebAssembly binary files.\n"
 keywords = ["parser", "WebAssembly", "wasm"]
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/yurydelendik/wasmparser.rs"
 [dependencies.hashmap_core]
 version = "0.1.9"
--- a/third_party/rust/wasmparser/README.md
+++ b/third_party/rust/wasmparser/README.md
@@ -1,15 +1,25 @@
-# Simple wasm parser in Rust
+# The WebAssembly binary file decoder in Rust
 
 [![Build Status](https://travis-ci.org/yurydelendik/wasmparser.rs.svg?branch=master)](https://travis-ci.org/yurydelendik/wasmparser.rs)
 [![crates.io link](https://img.shields.io/crates/v/wasmparser.svg)](https://crates.io/crates/wasmparser)
 
+The decoder library provides lightwight and fast decoding/parsing of WebAssembly binary files.
+
+The other goal is minimal memory footprint. For this reason, there is no AST or IR of WebAssembly data.
+
 See also its sibling at https://github.com/wasdk/wasmparser
 
+
+## Documentation
+
+The documentation and examples can be found at the https://docs.rs/wasmparser/
+
+
 ## Example
 
 ```rust
 use wasmparser::WasmDecoder;
 use wasmparser::Parser;
 use wasmparser::ParserState;
 
 fn get_name(bytes: &[u8]) -> &str {
@@ -33,16 +43,17 @@ fn main() {
         }
         ParserState::EndWasm => break,
         _ => ( /* println!(" Other {:?}", state) */ )
     }
   }
 }
 ```
 
+
 ## Fuzzing
 
 To fuzz test wasmparser.rs, switch to a nightly Rust compiler and install [cargo-fuzz]:
 
 ```
 cargo install cargo-fuzz
 ```
 
--- a/third_party/rust/wasmparser/src/binary_reader.rs
+++ b/third_party/rust/wasmparser/src/binary_reader.rs
@@ -18,17 +18,17 @@ use std::vec::Vec;
 
 use limits::{
     MAX_WASM_FUNCTION_LOCALS, MAX_WASM_FUNCTION_PARAMS, MAX_WASM_FUNCTION_RETURNS,
     MAX_WASM_FUNCTION_SIZE, MAX_WASM_STRING_SIZE,
 };
 
 use primitives::{
     BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32,
-    Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Naming, Operator, RelocType,
+    Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType,
     ResizableLimits, Result, SectionCode, TableType, Type,
 };
 
 const MAX_WASM_BR_TABLE_SIZE: usize = MAX_WASM_FUNCTION_SIZE;
 
 fn is_name(name: &[u8], expected: &'static str) -> bool {
     if name.len() != expected.len() {
         return false;
@@ -60,16 +60,34 @@ const WASM_EXPERIMENTAL_VERSION: u32 = 0
 const WASM_SUPPORTED_VERSION: u32 = 0x1;
 
 pub struct SectionHeader<'a> {
     pub code: SectionCode<'a>,
     pub payload_start: usize,
     pub payload_len: usize,
 }
 
+/// Bytecode range in the WebAssembly module.
+#[derive(Debug, Copy, Clone)]
+pub struct Range {
+    pub start: usize,
+    pub end: usize,
+}
+
+impl Range {
+    pub fn new(start: usize, end: usize) -> Range {
+        assert!(start <= end);
+        Range { start, end }
+    }
+
+    pub fn slice<'a>(&self, data: &'a [u8]) -> &'a [u8] {
+        &data[self.start..self.end]
+    }
+}
+
 /// A binary reader of the WebAssembly structures and types.
 #[derive(Clone)]
 pub struct BinaryReader<'a> {
     pub(crate) buffer: &'a [u8],
     pub(crate) position: usize,
     pub(crate) original_offset: usize,
 }
 
@@ -356,33 +374,16 @@ impl<'a> BinaryReader<'a> {
             self.skip_var_32()?;
         }
         self.skip_var_32()?;
         Ok(BrTable {
             buffer: &self.buffer[start..self.position],
         })
     }
 
-    pub(crate) fn read_name_map(&mut self, limit: usize) -> Result<Box<[Naming<'a>]>> {
-        let count = self.read_var_u32()? as usize;
-        if count > limit {
-            return Err(BinaryReaderError {
-                message: "name map size is out of bound",
-                offset: self.original_position() - 1,
-            });
-        }
-        let mut result = Vec::with_capacity(count);
-        for _ in 0..count {
-            let index = self.read_var_u32()?;
-            let name = self.read_string()?;
-            result.push(Naming { index, name });
-        }
-        Ok(result.into_boxed_slice())
-    }
-
     pub fn eof(&self) -> bool {
         self.position >= self.buffer.len()
     }
 
     pub fn current_position(&self) -> usize {
         self.position
     }
 
@@ -1183,31 +1184,34 @@ impl<'a> BrTable<'a> {
     /// Reads br_table entries.
     ///
     /// # Examples
     /// ```rust
     /// let buf = vec![0x0e, 0x02, 0x01, 0x02, 0x00];
     /// let mut reader = wasmparser::BinaryReader::new(&buf);
     /// let op = reader.read_operator().unwrap();
     /// if let wasmparser::Operator::BrTable { ref table } = op {