diff --git a/Cargo.lock b/Cargo.lock index daccf0fa7b3a..65e09fd3840e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,8 +161,8 @@ 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)", @@ -457,20 +457,20 @@ dependencies = [ [[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)", @@ -479,39 +479,39 @@ dependencies = [ [[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]] @@ -2900,7 +2900,7 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.21.8" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3163,12 +3163,12 @@ dependencies = [ "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" @@ -3393,7 +3393,7 @@ dependencies = [ "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" diff --git a/browser/components/extensions/schemas/menus.json b/browser/components/extensions/schemas/menus.json index 2831bb594fd5..df5e1373c07a 100644 --- a/browser/components/extensions/schemas/menus.json +++ b/browser/components/extensions/schemas/menus.json @@ -113,6 +113,12 @@ "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, diff --git a/browser/components/payments/res/containers/address-form.js b/browser/components/payments/res/containers/address-form.js index 4c48e01ce277..fb0fc8a6e9fb 100644 --- a/browser/components/payments/res/containers/address-form.js +++ b/browser/components/payments/res/containers/address-form.js @@ -412,12 +412,12 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ 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"); diff --git a/browser/components/payments/res/debugging.js b/browser/components/payments/res/debugging.js index a80a1e728427..4a56623ce14c 100644 --- a/browser/components/payments/res/debugging.js +++ b/browser/components/payments/res/debugging.js @@ -53,8 +53,8 @@ let REQUEST_1 = { }, }, ], - payer: {}, - paymentMethod: {}, + payerErrors: {}, + paymentMethodErrors: {}, shippingAddressErrors: {}, shippingOptions: [ { @@ -135,8 +135,8 @@ let REQUEST_2 = { }, }, ], - payer: {}, - paymentMethod: {}, + payerErrors: {}, + paymentMethoErrors: {}, shippingAddressErrors: {}, shippingOptions: [ { @@ -487,7 +487,7 @@ let buttonActions = { 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: "", @@ -530,7 +530,7 @@ let buttonActions = { 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", diff --git a/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js b/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js index a33a4422d6b8..c035401f4f28 100644 --- a/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js +++ b/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js @@ -46,8 +46,8 @@ export let requestStore = new PaymentsStore({ id: null, totalItem: {label: null, amount: {currency: null, value: 0}}, displayItems: [], - payer: {}, - paymentMethod: null, + payerErrors: {}, + paymentMethodErrors: null, shippingAddressErrors: {}, shippingOptions: [], modifiers: null, diff --git a/browser/components/payments/test/mochitest/test_address_form.html b/browser/components/payments/test/mochitest/test_address_form.html index 3ecee5b30d1e..f87d87d8a3a7 100644 --- a/browser/components/payments/test/mochitest/test_address_form.html +++ b/browser/components/payments/test/mochitest/test_address_form.html @@ -708,7 +708,7 @@ add_task(async function test_customMerchantValidity_billingAddressForm() { 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", @@ -753,7 +753,7 @@ add_task(async function test_merchantPayerAddressErrors() { }, 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", @@ -771,7 +771,7 @@ add_task(async function test_merchantPayerAddressErrors() { 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); } @@ -786,7 +786,7 @@ add_task(async function test_merchantPayerAddressErrors() { await form.requestStore.setState({ request: { paymentDetails: { - payer: {}, + payerErrors: {}, }, paymentOptions: {}, }, diff --git a/browser/components/payments/test/mochitest/test_address_picker.html b/browser/components/payments/test/mochitest/test_address_picker.html index 1c2ad514a20e..7667d5d1aae7 100644 --- a/browser/components/payments/test/mochitest/test_address_picker.html +++ b/browser/components/payments/test/mochitest/test_address_picker.html @@ -256,10 +256,10 @@ add_task(async function test_merchantError() { 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", }, diff --git a/browser/components/urlbar/tests/browser/browser.ini b/browser/components/urlbar/tests/browser/browser.ini index d27448db7dd0..afedb3b1e4b8 100644 --- a/browser/components/urlbar/tests/browser/browser.ini +++ b/browser/components/urlbar/tests/browser/browser.ini @@ -9,6 +9,7 @@ support-files = [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] diff --git a/browser/modules/AsyncTabSwitcher.jsm b/browser/modules/AsyncTabSwitcher.jsm index 20123451304d..82f6b5dc3411 100644 --- a/browser/modules/AsyncTabSwitcher.jsm +++ b/browser/modules/AsyncTabSwitcher.jsm @@ -748,6 +748,7 @@ class AsyncTabSwitcher { 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"); diff --git a/build/automation.py.in b/build/automation.py.in index 84d1fde19e13..1e8e87587021 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -504,7 +504,7 @@ class Automation(object): 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. diff --git a/build/mobile/remoteautomation.py b/build/mobile/remoteautomation.py index 00993899ec8d..7f3bdb4eb016 100644 --- a/build/mobile/remoteautomation.py +++ b/build/mobile/remoteautomation.py @@ -28,24 +28,59 @@ 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' @@ -75,56 +110,54 @@ class RemoteAutomation(Automation): 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: @@ -133,12 +166,11 @@ class RemoteAutomation(Automation): # 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 @@ -147,10 +179,10 @@ class RemoteAutomation(Automation): 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 @@ -166,11 +198,11 @@ class RemoteAutomation(Automation): 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( @@ -185,8 +217,8 @@ class RemoteAutomation(Automation): 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 @@ -194,7 +226,7 @@ class RemoteAutomation(Automation): 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( @@ -210,8 +242,8 @@ class RemoteAutomation(Automation): 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 @@ -226,251 +258,235 @@ class RemoteAutomation(Automation): 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 - 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 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 + + 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 - - if app and self.device.process_exist(app): - print("remoteautomation.py %s is already running. Stopping...") - self.device.stop_application(app, root=True) - - self.counts = counts - if self.counts is not None: - self.counts['pass'] = 0 - self.counts['fail'] = 0 - self.counts['todo'] = 0 - - 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) + 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 = 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) + 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 + # 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 = "" + # 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]] + @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] + 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 - try: - newLogContent = self.device.get_file( - self.proc, offset=self.stdoutlen) - except ADBTimeoutError: - raise - except Exception: - return False - if not newLogContent: - return False + 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 - 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: - # 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 + 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 - @property - def getLastTestSeen(self): - return self.lastTestSeen + self.logBuffer += newLogContent + lines = self.logBuffer.split('\n') + lines = [l for l in lines if l] - # 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) - try: - self.device.pkill(self.procName, sig=3, 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) + if lines: + if self.logBuffer.endswith('\n'): + # all lines are complete; no need to buffer + self.logBuffer = "" 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) + # 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 + + # 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. + # 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: + self.device.pkill(self.procName, sig=3, 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(crashreporter, root=True) + self.device.pkill(self.procName, sig=9, attempts=1, root=True) except ADBTimeoutError: raise except: # NOQA: E722 - pass - if self.device.process_exist(crashreporter): - print("ERROR: %s still running!!" % crashreporter) + print("%s still alive after SIGKILL!" % self.procName) + if self.device.process_exist(self.procName): + self.device.stop_application(self.procName) + 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) diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index a5f10096da66..b2c64681b27b 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -498,6 +498,27 @@ nsOuterWindowProxy::getPropertyDescriptor(JSContext* cx, 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 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 proxy, @@ -515,7 +536,18 @@ nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx, } // 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 @@ -532,7 +564,68 @@ nsOuterWindowProxy::defineProperty(JSContext* cx, 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 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 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 diff --git a/dom/base/test/test_window_define_nonconfigurable.html b/dom/base/test/test_window_define_nonconfigurable.html index d1051b7dbc30..439e7bfe694e 100644 --- a/dom/base/test/test_window_define_nonconfigurable.html +++ b/dom/base/test/test_window_define_nonconfigurable.html @@ -18,12 +18,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443 */ 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"); @@ -32,8 +32,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443 "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"); @@ -48,17 +48,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443 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"); @@ -68,8 +65,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443 "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"); diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 454e32360a61..e07e5d51cf78 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -20,6 +20,7 @@ #include "AccessCheck.h" #include "js/JSON.h" #include "js/StableStringChars.h" +#include "js/Symbol.h" #include "jsfriendapi.h" #include "nsContentCreatorFunctions.h" #include "nsContentUtils.h" diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index ac28d91fae1d..e2ad599e74e3 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -9,8 +9,9 @@ #include "jsfriendapi.h" #include "js/CharacterEncoding.h" -#include "js/Wrapper.h" #include "js/Conversions.h" +#include "js/MemoryFunctions.h" +#include "js/Wrapper.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Alignment.h" #include "mozilla/Array.h" diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index cdccc22a5830..2957f4cdc565 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -13958,6 +13958,13 @@ class CGBindingRoot(CGThing): 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]) diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index c2a1e170074c..99e0c97218da 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -2043,6 +2043,7 @@ ScopedUnpackReset::ScopedUnpackReset(const WebGLContext* const webgl) : ScopedGLWrapper(webgl->gl) , mWebGL(webgl) { + // clang-format off if (mWebGL->mPixelStore_UnpackAlignment != 4) mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4); if (mWebGL->IsWebGL2()) { @@ -2054,11 +2055,13 @@ ScopedUnpackReset::ScopedUnpackReset(const WebGLContext* const webgl) 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()) { @@ -2075,6 +2078,7 @@ ScopedUnpackReset::UnwrapImpl() mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, pbo); } + // clang-format on } //////////////////// diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index b690fd620d6e..a469157aa83b 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -48,15 +48,15 @@ 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; diff --git a/dom/canvas/WebGLFormats.cpp b/dom/canvas/WebGLFormats.cpp index d9fb59dbd364..bbf8a2b6eadf 100644 --- a/dom/canvas/WebGLFormats.cpp +++ b/dom/canvas/WebGLFormats.cpp @@ -118,6 +118,8 @@ AddCompressedFormatInfo(EffectiveFormat format, uint16_t bitsPerBlock, uint8_t b 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); @@ -194,6 +196,8 @@ InitCompressedFormatInfo() // OES_compressed_ETC1_RGB8_texture AddCompressedFormatInfo(EffectiveFormat::ETC1_RGB8_OES, 64, 4, 4, CompressionFamily::ETC1); + + // clang-format on } ////////////////////////////////////////////////////////////////////////////////////////// @@ -272,6 +276,9 @@ AddFormatInfo(EffectiveFormat format, const char* name, GLenum sizedFormat, 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 @@ -489,6 +496,7 @@ InitFormatInfo() #undef SET_BY_SUFFIX + ////// #define SET_BY_SUFFIX(X) \ @@ -521,6 +529,8 @@ InitFormatInfo() SET_COPY_DECAY(R11F_G11F_B10F, R16F, RG16F, R11F_G11F_B10F, MAX, Luminance16F, MAX, MAX) #undef SET_COPY_DECAY + + // clang-format on } ////////////////////////////////////////////////////////////////////////////////////////// @@ -767,9 +777,11 @@ AddLegacyFormats_LA8(FormatUsageAuthority* fua, gl::GLContext* gl) 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; @@ -778,6 +790,8 @@ AddLegacyFormats_LA8(FormatUsageAuthority* fua, gl::GLContext* gl) 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 ); @@ -787,6 +801,8 @@ AddUnsizedFormats(FormatUsageAuthority* fua, gl::GLContext* gl) // L, A, LA return AddLegacyFormats_LA8(fua, gl); + + // clang-format on } void @@ -894,6 +910,7 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl) ptr->AddTexUnpack(usage, pi, dui); }; + // clang-format off #define FOO(x) EffectiveFormat::x, LOCAL_GL_ ## x // RGBA @@ -984,6 +1001,7 @@ FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl) fnAddSizedUnpack(FOO(DEPTH32F_STENCIL8), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV); #undef FOO + // clang-format on //////////////////////////////////////////////////////////////////////////// diff --git a/dom/canvas/crashtests/crashtests.list b/dom/canvas/crashtests/crashtests.list index 5ad909166f27..50836c4d23f8 100644 --- a/dom/canvas/crashtests/crashtests.list +++ b/dom/canvas/crashtests/crashtests.list @@ -4,7 +4,7 @@ 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 diff --git a/dom/canvas/test/reftest/drawCustomFocusRing.html b/dom/canvas/test/reftest/drawCustomFocusRing.html deleted file mode 100644 index acb18b083997..000000000000 --- a/dom/canvas/test/reftest/drawCustomFocusRing.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - diff --git a/dom/canvas/test/reftest/reftest.list b/dom/canvas/test/reftest/reftest.list index 272b0dae2ec5..f88cef600378 100644 --- a/dom/canvas/test/reftest/reftest.list +++ b/dom/canvas/test/reftest/reftest.list @@ -157,7 +157,6 @@ fuzzy-if(skiaContent,0-1,0-150) == clip-multiple-move-2.html clip-multiple-move- # 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 diff --git a/dom/canvas/test/test_canvas_focusring.html b/dom/canvas/test/test_canvas_focusring.html index 9e2e832b3e9e..ef7cddd2e895 100644 --- a/dom/canvas/test/test_canvas_focusring.html +++ b/dom/canvas/test/test_canvas_focusring.html @@ -9,26 +9,6 @@ SimpleTest.waitForExplicitFinish(); const Cc = SpecialPowers.Cc; const Cr = SpecialPowers.Cr; SpecialPowers.setBoolPref("canvas.focusring.enabled", true); -SpecialPowers.setBoolPref("canvas.customfocusring.enabled", true); - - -

Canvas test: drawCustomFocusRing

-+ - - - -

Canvas test: drawFocusIfNeeded

@@ -78,12 +58,6 @@ function test_drawFocusIfNeeded_canvas() { 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; @@ -91,7 +65,6 @@ function runTests() { } SpecialPowers.setBoolPref("canvas.focusring.enabled", false); - SpecialPowers.setBoolPref("canvas.customfocusring.enabled", false); SimpleTest.finish(); } diff --git a/dom/indexedDB/Key.cpp b/dom/indexedDB/Key.cpp index 430ee0ce3c07..3a58ba077739 100644 --- a/dom/indexedDB/Key.cpp +++ b/dom/indexedDB/Key.cpp @@ -11,6 +11,7 @@ #include // 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" diff --git a/dom/interfaces/payments/nsIPaymentRequest.idl b/dom/interfaces/payments/nsIPaymentRequest.idl index 84453719e789..01de878550d6 100644 --- a/dom/interfaces/payments/nsIPaymentRequest.idl +++ b/dom/interfaces/payments/nsIPaymentRequest.idl @@ -63,9 +63,9 @@ interface nsIPaymentDetails : nsISupports [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)] diff --git a/dom/media/webaudio/MediaBufferDecoder.cpp b/dom/media/webaudio/MediaBufferDecoder.cpp index 5c21cce99c35..1417338e91f9 100644 --- a/dom/media/webaudio/MediaBufferDecoder.cpp +++ b/dom/media/webaudio/MediaBufferDecoder.cpp @@ -19,6 +19,7 @@ #include "DecoderTraits.h" #include "AudioContext.h" #include "AudioBuffer.h" +#include "js/MemoryFunctions.h" #include "MediaContainerType.h" #include "nsContentUtils.h" #include "nsIScriptObjectPrincipal.h" diff --git a/dom/payments/PaymentRequestData.cpp b/dom/payments/PaymentRequestData.cpp index eea6c8c083f0..456fe091badd 100644 --- a/dom/payments/PaymentRequestData.cpp +++ b/dom/payments/PaymentRequestData.cpp @@ -481,7 +481,7 @@ PaymentDetails::GetShippingAddressErrors(JSContext* aCx, JS::MutableHandleValue } NS_IMETHODIMP -PaymentDetails::GetPayer(JSContext* aCx, JS::MutableHandleValue aErrors) +PaymentDetails::GetPayerErrors(JSContext* aCx, JS::MutableHandleValue aErrors) { PayerErrors errors; errors.Init(mPayerErrors); @@ -492,7 +492,7 @@ PaymentDetails::GetPayer(JSContext* aCx, JS::MutableHandleValue aErrors) } NS_IMETHODIMP -PaymentDetails::GetPaymentMethod(JSContext* aCx, JS::MutableHandleValue aErrors) +PaymentDetails::GetPaymentMethodErrors(JSContext* aCx, JS::MutableHandleValue aErrors) { if (mPaymentMethodErrors.IsEmpty()) { aErrors.set(JS::NullValue()); @@ -558,8 +558,8 @@ PaymentDetails::Update(nsIPaymentDetails* aDetails, const bool aRequestShipping) PaymentDetails* rowDetails = static_cast(aDetails); MOZ_ASSERT(rowDetails); mShippingAddressErrors = rowDetails->GetShippingAddressErrors(); - mPayerErrors = rowDetails->GetPayer(); - mPaymentMethodErrors = rowDetails->GetPaymentMethod(); + mPayerErrors = rowDetails->GetPayerErrors(); + mPaymentMethodErrors = rowDetails->GetPaymentMethodErrors(); return NS_OK; @@ -572,13 +572,13 @@ PaymentDetails::GetShippingAddressErrors() const } const nsString& -PaymentDetails::GetPayer() const +PaymentDetails::GetPayerErrors() const { return mPayerErrors; } const nsString& -PaymentDetails::GetPaymentMethod() const +PaymentDetails::GetPaymentMethodErrors() const { return mPaymentMethodErrors; } diff --git a/dom/payments/PaymentRequestData.h b/dom/payments/PaymentRequestData.h index a5a618266666..8eb6d05ec568 100644 --- a/dom/payments/PaymentRequestData.h +++ b/dom/payments/PaymentRequestData.h @@ -131,8 +131,8 @@ public: 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, diff --git a/dom/payments/test/BasicCardErrorsChromeScript.js b/dom/payments/test/BasicCardErrorsChromeScript.js index 81cb1d55b34f..61963b3d03dd 100644 --- a/dom/payments/test/BasicCardErrorsChromeScript.js +++ b/dom/payments/test/BasicCardErrorsChromeScript.js @@ -99,7 +99,7 @@ const TestingUIService = { 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) { diff --git a/dom/payments/test/PayerDetailsChromeScript.js b/dom/payments/test/PayerDetailsChromeScript.js index 317cd61a0f0e..db5e0e8f3fbf 100644 --- a/dom/payments/test/PayerDetailsChromeScript.js +++ b/dom/payments/test/PayerDetailsChromeScript.js @@ -35,7 +35,7 @@ const TestingUIService = { 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) { diff --git a/dom/payments/test/RetryPaymentChromeScript.js b/dom/payments/test/RetryPaymentChromeScript.js index 4317279842b8..c85eeea33872 100644 --- a/dom/payments/test/RetryPaymentChromeScript.js +++ b/dom/payments/test/RetryPaymentChromeScript.js @@ -112,7 +112,7 @@ function checkPayerErrors(testName, errors) { 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)) { @@ -148,8 +148,8 @@ const DummyUIService = { 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 { diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index bba4a90e4c58..e791ed04efe9 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -25,6 +25,7 @@ #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" diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index c6781eaeebf0..abc213a61a08 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -15,6 +15,7 @@ #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" diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl index 13f61d4fe240..e25671eb0e25 100644 --- a/dom/webidl/CanvasRenderingContext2D.webidl +++ b/dom/webidl/CanvasRenderingContext2D.webidl @@ -243,9 +243,6 @@ interface CanvasDrawPath { [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); }; diff --git a/dom/workers/ChromeWorkerScope.cpp b/dom/workers/ChromeWorkerScope.cpp index 668130c301be..c90bfea0d158 100644 --- a/dom/workers/ChromeWorkerScope.cpp +++ b/dom/workers/ChromeWorkerScope.cpp @@ -7,6 +7,7 @@ #include "ChromeWorkerScope.h" #include "jsapi.h" +#include "js/MemoryFunctions.h" #include "nsXPCOM.h" #include "nsNativeCharsetUtils.h" diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index fc990735e7eb..09a44c3e165c 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -76,6 +76,7 @@ #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" diff --git a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic index c524eccd1df0..9ed94501c288 100644 --- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic +++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic @@ -1,4 +1,4 @@ -52944 +52951 0/nm 0th/pt 1/n1 @@ -2790,7 +2790,7 @@ Congolese/M Congregational Congregationalist/MS Congress/MS -Congressional +Congressional/Y Congreve/M Conley/M Conn/MR @@ -20673,7 +20673,7 @@ congregational congregationalism/M congregationalist/MS congress/MS -congressional +congressional/Y congressman/M congressmen congresspeople @@ -23779,6 +23779,7 @@ dowry/SM dowse/DRSZG dowser/M dox/SDG +doxastic doxology/SM doxx/SDG doyen/SM @@ -30059,6 +30060,7 @@ horde/DSMG horehound/SM horizon/SM horizontal/SMY +hormesis hormonal hormone/SM horn/MDS @@ -49607,6 +49609,8 @@ transfinite transfix/DSG transform/BSZGMDR transformation/SM +transformational +transformative transformer/M transfuse/DSXGN transfusion/M @@ -50827,6 +50831,7 @@ uptempo upthrust/GSM uptick/SM uptight +uptime uptown/M uptrend upturn/GSMD @@ -50919,9 +50924,11 @@ vacationer/M vacationist/SM vaccinate/GNDSX vaccination/M +vaccinator/S vaccine/SM vacillate/XGNDS vacillation/M +vacinal vacuity/M vacuole/MS vacuous/YP diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp index d93f8d9bc994..f714f833a6b1 100644 --- a/gfx/gl/GLBlitHelper.cpp +++ b/gfx/gl/GLBlitHelper.cpp @@ -481,12 +481,14 @@ DrawBlitProg::Draw(const BaseArgs& args, const YUVArgs* const argsYUV) const oldVAO = gl->GetIntAs(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); diff --git a/gfx/gl/GLConsts.h b/gfx/gl/GLConsts.h index 8a69f776356a..9ee02c61b4d1 100644 --- a/gfx/gl/GLConsts.h +++ b/gfx/gl/GLConsts.h @@ -5,6 +5,8 @@ #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 @@ -6999,6 +7001,6 @@ #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_ diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index a95211a43dc9..332ccca44468 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -63,11 +63,13 @@ 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[] = { @@ -383,6 +385,7 @@ 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 } }, @@ -511,6 +514,7 @@ GLContext::InitWithPrefixImpl(const char* prefix, bool trygl) END_SYMBOLS }; + // clang-format on if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL")) return false; @@ -587,9 +591,9 @@ GLContext::InitWithPrefixImpl(const char* prefix, bool trygl) // 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 }; @@ -597,27 +601,27 @@ GLContext::InitWithPrefixImpl(const char* prefix, bool trygl) 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 }; @@ -1040,13 +1044,13 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) 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); @@ -1063,7 +1067,7 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) if (IsExtensionSupported(APPLE_texture_range)) { const SymLoadStruct symbols[] = { - { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } }, + CORE_SYMBOL(TextureRangeAPPLE), END_SYMBOLS }; fnLoadForExt(symbols, APPLE_texture_range); @@ -1071,13 +1075,15 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) 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 } }, @@ -1500,6 +1506,8 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) fnLoadForExt(symbols, NV_fence); } +// clang-format off + if (IsExtensionSupported(NV_texture_barrier)) { const SymLoadStruct symbols[] = { { (PRFuncPtr*) &mSymbols.fTextureBarrier, { "TextureBarrierNV", nullptr } }, @@ -1510,7 +1518,7 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) if (IsSupported(GLFeature::read_buffer)) { const SymLoadStruct symbols[] = { - { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } }, + CORE_SYMBOL(ReadBuffer), END_SYMBOLS }; fnLoadForFeature(symbols, GLFeature::read_buffer); @@ -1518,7 +1526,7 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) if (IsExtensionSupported(APPLE_framebuffer_multisample)) { const SymLoadStruct symbols[] = { - { (PRFuncPtr*) &mSymbols.fResolveMultisampleFramebufferAPPLE, { "ResolveMultisampleFramebufferAPPLE", nullptr } }, + CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS }; fnLoadForExt(symbols, APPLE_framebuffer_multisample); @@ -1526,8 +1534,8 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl) // 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(); diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h index f0c59c6d0f60..14cc115058bf 100644 --- a/gfx/gl/GLDefs.h +++ b/gfx/gl/GLDefs.h @@ -20,6 +20,8 @@ bool CheckContextLost(const GLContext* gl); // - +// clang-format off + // TODO: use official constant names instead of followed ones. // IMG_texture_compression_pvrtc @@ -93,4 +95,6 @@ bool CheckContextLost(const GLContext* gl); #define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 #define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +// clang-format on + #endif diff --git a/gfx/gl/GLParseRegistryXML.py b/gfx/gl/GLParseRegistryXML.py index 6503a15b50b4..3b0a0f097d4b 100755 --- a/gfx/gl/GLParseRegistryXML.py +++ b/gfx/gl/GLParseRegistryXML.py @@ -55,6 +55,8 @@ class GLConstHeader: '#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', @@ -88,6 +90,8 @@ class GLConstHeader: def formatFileEnd(self): self.write([ + '', + '// clang-format on', '', '#endif // GLCONSTS_H_' ]) diff --git a/image/test/crashtests/crashtests.list b/image/test/crashtests/crashtests.list index 7af27b4b089d..c390bec1a435 100644 --- a/image/test/crashtests/crashtests.list +++ b/image/test/crashtests/crashtests.list @@ -26,7 +26,7 @@ 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 diff --git a/js/ipc/JavaScriptShared.cpp b/js/ipc/JavaScriptShared.cpp index 1fdda5d809aa..fe87a0f0a341 100644 --- a/js/ipc/JavaScriptShared.cpp +++ b/js/ipc/JavaScriptShared.cpp @@ -10,6 +10,7 @@ #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" diff --git a/js/public/MemoryFunctions.h b/js/public/MemoryFunctions.h index 6dd31c58c244..c6aafbc946f2 100644 --- a/js/public/MemoryFunctions.h +++ b/js/public/MemoryFunctions.h @@ -8,6 +8,7 @@ #ifndef js_MemoryFunctions_h #define js_MemoryFunctions_h +#include "mozilla/Assertions.h" // MOZ_ASSERT #include "mozilla/Attributes.h" // MOZ_MUST_USE #include // size_t @@ -15,6 +16,23 @@ #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); diff --git a/js/public/Symbol.h b/js/public/Symbol.h new file mode 100644 index 000000000000..c83a1589644f --- /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 // size_t +#include // 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 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 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); + +/* 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); + +/** + * 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(name); + return u != 0 && u - 1 < WellKnownSymbolLimit; +} + +} // namespace JS + +#endif /* js_Symbol_h */ diff --git a/js/public/Value.h b/js/public/Value.h index 801450196e9c..e32c6170490d 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -481,18 +481,6 @@ union alignas(8) Value 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: @@ -624,7 +612,7 @@ union alignas(8) Value #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::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE; #endif } @@ -1006,7 +994,7 @@ IsCanonicalized(double d) uint64_t bits; mozilla::BitwiseCast(d, &bits); - return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits; + return (bits & ~mozilla::FloatingPoint::kSignBit) == detail::CanonicalizedNaNBits; } static inline Value diff --git a/js/src/builtin/Symbol.cpp b/js/src/builtin/Symbol.cpp index 7269ef7c434b..70fff22a9a8d 100644 --- a/js/src/builtin/Symbol.cpp +++ b/js/src/builtin/Symbol.cpp @@ -6,6 +6,7 @@ #include "builtin/Symbol.h" +#include "js/Symbol.h" #include "util/StringBuffer.h" #include "vm/SymbolType.h" diff --git a/js/src/ctypes/Library.cpp b/js/src/ctypes/Library.cpp index 979d85d93c73..5ad68ef0ed35 100644 --- a/js/src/ctypes/Library.cpp +++ b/js/src/ctypes/Library.cpp @@ -11,6 +11,7 @@ #include "ctypes/CTypes.h" #include "js/CharacterEncoding.h" +#include "js/MemoryFunctions.h" #include "js/StableStringChars.h" using JS::AutoStableStringChars; diff --git a/js/src/gc/FreeOp.h b/js/src/gc/FreeOp.h index 4ae41aa0f258..e0459d7d5a06 100644 --- a/js/src/gc/FreeOp.h +++ b/js/src/gc/FreeOp.h @@ -9,10 +9,9 @@ #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 diff --git a/js/src/gdb/run-tests.py b/js/src/gdb/run-tests.py index 39383c9e8612..0b83cf315f51 100644 --- a/js/src/gdb/run-tests.py +++ b/js/src/gdb/run-tests.py @@ -132,7 +132,7 @@ class Summary(object): 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: diff --git a/js/src/gdb/tests/test-GCCellPtr.cpp b/js/src/gdb/tests/test-GCCellPtr.cpp index 44f151025d27..df20f1c7db72 100644 --- a/js/src/gdb/tests/test-GCCellPtr.cpp +++ b/js/src/gdb/tests/test-GCCellPtr.cpp @@ -2,6 +2,7 @@ #include "jsapi.h" #include "js/HeapAPI.h" +#include "js/Symbol.h" FRAGMENT(GCCellPtr, simple) { JS::GCCellPtr nulll(nullptr); diff --git a/js/src/gdb/tests/test-JSSymbol.cpp b/js/src/gdb/tests/test-JSSymbol.cpp index 45baac65fa55..29695731e377 100644 --- a/js/src/gdb/tests/test-JSSymbol.cpp +++ b/js/src/gdb/tests/test-JSSymbol.cpp @@ -1,6 +1,8 @@ #include "gdb-tests.h" #include "jsapi.h" +#include "js/Symbol.h" + FRAGMENT(JSSymbol, simple) { using namespace JS; diff --git a/js/src/gdb/tests/test-jsid.cpp b/js/src/gdb/tests/test-jsid.cpp index d7af4caec925..f5fcc840107a 100644 --- a/js/src/gdb/tests/test-jsid.cpp +++ b/js/src/gdb/tests/test-jsid.cpp @@ -1,6 +1,8 @@ #include "gdb-tests.h" #include "jsapi.h" +#include "js/Symbol.h" + FRAGMENT(jsid, simple) { JS::Rooted string(cx, JS_NewStringCopyZ(cx, "moon")); JS::Rooted interned(cx, JS_AtomizeAndPinJSString(cx, string)); diff --git a/js/src/gdb/tests/test-jsval.cpp b/js/src/gdb/tests/test-jsval.cpp index 7d4da4c02a73..37d25abd3b85 100644 --- a/js/src/gdb/tests/test-jsval.cpp +++ b/js/src/gdb/tests/test-jsval.cpp @@ -1,6 +1,7 @@ #include "gdb-tests.h" #include "jsapi.h" +#include "js/Symbol.h" #ifdef ENABLE_BIGINT #include "vm/BigIntType.h" #endif diff --git a/js/src/jsapi-tests/testArrayBuffer.cpp b/js/src/jsapi-tests/testArrayBuffer.cpp index 50490a01080b..858d81b66ad4 100644 --- a/js/src/jsapi-tests/testArrayBuffer.cpp +++ b/js/src/jsapi-tests/testArrayBuffer.cpp @@ -3,6 +3,7 @@ */ #include "jsfriendapi.h" +#include "js/MemoryFunctions.h" #include "jsapi-tests/tests.h" diff --git a/js/src/jsapi-tests/testInformalValueTypeName.cpp b/js/src/jsapi-tests/testInformalValueTypeName.cpp index e360f1334178..3182526c1394 100644 --- a/js/src/jsapi-tests/testInformalValueTypeName.cpp +++ b/js/src/jsapi-tests/testInformalValueTypeName.cpp @@ -5,6 +5,7 @@ * 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) diff --git a/js/src/jsapi-tests/testParseJSON.cpp b/js/src/jsapi-tests/testParseJSON.cpp index 91d3cdf6fdc9..17f764821dae 100644 --- a/js/src/jsapi-tests/testParseJSON.cpp +++ b/js/src/jsapi-tests/testParseJSON.cpp @@ -11,6 +11,7 @@ #include "builtin/String.h" #include "js/JSON.h" +#include "js/MemoryFunctions.h" #include "js/Printf.h" #include "jsapi-tests/tests.h" diff --git a/js/src/jsapi-tests/testSourcePolicy.cpp b/js/src/jsapi-tests/testSourcePolicy.cpp index 32f30cf5cd67..49425841a4bd 100644 --- a/js/src/jsapi-tests/testSourcePolicy.cpp +++ b/js/src/jsapi-tests/testSourcePolicy.cpp @@ -3,6 +3,7 @@ * 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" diff --git a/js/src/jsapi-tests/testSymbol.cpp b/js/src/jsapi-tests/testSymbol.cpp index 28c6f7a0ccbe..c538386576d9 100644 --- a/js/src/jsapi-tests/testSymbol.cpp +++ b/js/src/jsapi-tests/testSymbol.cpp @@ -2,6 +2,7 @@ * 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) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index e7859573e24d..8b14a92be172 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -60,11 +60,13 @@ #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" diff --git a/js/src/jsapi.h b/js/src/jsapi.h index a445da05cf9e..2e0e80d16904 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -34,7 +34,6 @@ #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" @@ -49,6 +48,8 @@ /************************************************************************/ +struct JSFreeOp; + namespace JS { template class SourceText; @@ -163,22 +164,6 @@ class HandleValueArray } /* 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. */ /************************************************************************/ @@ -4038,99 +4023,8 @@ JS_GetStringEncodingLength(JSContext* cx, JSString* str); 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); - -/** - * 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(name); - return u != 0 && u - 1 < WellKnownSymbolLimit; -} - JS_PUBLIC_API bool PropertySpecNameEqualsId(const char* name, HandleId id); diff --git a/js/src/moz.build b/js/src/moz.build index d1d36e0ff350..a4f8c87d35ed 100755 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -156,6 +156,7 @@ EXPORTS.js += [ '../public/Stream.h', '../public/StructuredClone.h', '../public/SweepingAPI.h', + '../public/Symbol.h', '../public/TraceKind.h', '../public/TraceLoggerAPI.h', '../public/TracingAPI.h', diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index ff39cdcf830d..0ccdb8f66411 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -86,6 +86,7 @@ #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" diff --git a/js/src/vm/BytecodeUtil.cpp b/js/src/vm/BytecodeUtil.cpp index 6c72644b1699..c8adbe906a3a 100644 --- a/js/src/vm/BytecodeUtil.cpp +++ b/js/src/vm/BytecodeUtil.cpp @@ -35,6 +35,7 @@ #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" diff --git a/js/src/vm/JSAtom.cpp b/js/src/vm/JSAtom.cpp index 31ec317416c9..7479c416d564 100644 --- a/js/src/vm/JSAtom.cpp +++ b/js/src/vm/JSAtom.cpp @@ -22,6 +22,7 @@ #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" diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 0c4a3dbd02f9..346cabe28970 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -37,6 +37,7 @@ # 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" diff --git a/js/src/vm/StringType.cpp b/js/src/vm/StringType.cpp index 5d3b56f82e3b..5c66138b0421 100644 --- a/js/src/vm/StringType.cpp +++ b/js/src/vm/StringType.cpp @@ -27,6 +27,7 @@ #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" diff --git a/js/src/vm/SymbolType.h b/js/src/vm/SymbolType.h index e3f72326f62e..1888db972486 100644 --- a/js/src/vm/SymbolType.h +++ b/js/src/vm/SymbolType.h @@ -19,6 +19,7 @@ #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" diff --git a/js/src/wasm/cranelift/Cargo.toml b/js/src/wasm/cranelift/Cargo.toml index d8bc6fdb531c..de68595076d9 100644 --- a/js/src/wasm/cranelift/Cargo.toml +++ b/js/src/wasm/cranelift/Cargo.toml @@ -8,8 +8,8 @@ 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" diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp index d3a42137bd3a..cb080800a8d0 100644 --- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -23,6 +23,7 @@ #include "jsapi.h" #include "jsfriendapi.h" #include "js/CharacterEncoding.h" +#include "js/MemoryFunctions.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/DOMException.h" diff --git a/js/xpconnect/src/XPCJSID.cpp b/js/xpconnect/src/XPCJSID.cpp index c1aee833381a..30e83c775739 100644 --- a/js/xpconnect/src/XPCJSID.cpp +++ b/js/xpconnect/src/XPCJSID.cpp @@ -10,6 +10,7 @@ #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; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 2427e978fd82..922f96ea5159 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -42,6 +42,7 @@ #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" diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index cfade897313e..cfaf5d2b9878 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -10,6 +10,7 @@ #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" diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp index c6ec25c3fc44..83280698a4fc 100644 --- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -13,6 +13,7 @@ #include "js/CharacterEncoding.h" #include "js/Class.h" #include "js/Printf.h" +#include "js/Symbol.h" using namespace mozilla; using namespace JS; diff --git a/js/xpconnect/wrappers/FilteringWrapper.cpp b/js/xpconnect/wrappers/FilteringWrapper.cpp index e50f741d3e1e..47e53612e189 100644 --- a/js/xpconnect/wrappers/FilteringWrapper.cpp +++ b/js/xpconnect/wrappers/FilteringWrapper.cpp @@ -12,6 +12,7 @@ #include "mozilla/ErrorResult.h" #include "jsapi.h" +#include "js/Symbol.h" using namespace JS; using namespace js; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index d13d51e0763c..6127c729f5e6 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -6217,14 +6217,14 @@ nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState& aStat // 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); @@ -6237,7 +6237,7 @@ nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState& aStat // 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); @@ -11587,7 +11587,7 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState, nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childItems); if (!aItem.mIsAllInline) { firstBlockEnumerator.Find( - [](nsIFrame* aFrame) { return !aFrame->IsInlineOutside(); }); + [](nsIFrame* aFrame) { return aFrame->IsBlockOutside(); }); } if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) { @@ -11648,7 +11648,7 @@ nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState, // 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 @@ -11660,7 +11660,7 @@ nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState, // 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)) { @@ -11702,7 +11702,7 @@ nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState, if (aChildItems.NotEmpty()) { nsFrameList inlineKids = - aChildItems.Split([](nsIFrame* f) { return !f->IsInlineOutside(); }); + aChildItems.Split([](nsIFrame* f) { return f->IsBlockOutside(); }); MoveChildrenTo(aInitialInline, inlineFrame, inlineKids); } diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index d1a22326f30f..65cfa8ffd754 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -569,7 +569,7 @@ 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 diff --git a/layout/svg/SVGObserverUtils.cpp b/layout/svg/SVGObserverUtils.cpp index dd9a7eb3286a..6130f164e869 100644 --- a/layout/svg/SVGObserverUtils.cpp +++ b/layout/svg/SVGObserverUtils.cpp @@ -372,10 +372,6 @@ public: , mValid(true) {} - bool ObservesReflow() override { - return false; - } - protected: void OnRenderingChange() override; @@ -466,7 +462,7 @@ SVGMarkerObserver::OnRenderingChange() } -class nsSVGPaintingProperty final : public nsSVGRenderingObserverProperty +class nsSVGPaintingProperty : public nsSVGRenderingObserverProperty { public: nsSVGPaintingProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame, bool aReferenceImage) @@ -498,6 +494,24 @@ nsSVGPaintingProperty::OnRenderingChange() } +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); @@ -1470,10 +1484,10 @@ SVGObserverUtils::GetAndObserveBackgroundImage(nsIFrame* aFrame, // XXXjwatt: this is broken - we're using the address of a new // URLAndReferrerInfo as the hash key every time! - nsSVGPaintingProperty* observer = - static_cast(hashtable->GetWeak(url)); + SVGMozElementObserver* observer = + static_cast(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(); diff --git a/layout/svg/SVGObserverUtils.h b/layout/svg/SVGObserverUtils.h index de8587649c2b..4297424b31eb 100644 --- a/layout/svg/SVGObserverUtils.h +++ b/layout/svg/SVGObserverUtils.h @@ -145,7 +145,7 @@ public: Element* GetAndObserveReferencedElement(); - virtual bool ObservesReflow() { return true; } + virtual bool ObservesReflow() { return false; } protected: void StartObserving(); @@ -403,6 +403,13 @@ public: 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); diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 2effe40b8a30..2ed02eba9413 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -1513,7 +1513,8 @@ TextNodeCorrespondenceRecorder::TraverseAndRecord(nsIFrame* aFrame) } // 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(); } diff --git a/layout/svg/crashtests/1504918.svg b/layout/svg/crashtests/1504918.svg new file mode 100644 index 000000000000..63cd3a08e018 --- /dev/null +++ b/layout/svg/crashtests/1504918.svg @@ -0,0 +1,4 @@ + + + xy + \ No newline at end of file diff --git a/layout/svg/crashtests/crashtests.list b/layout/svg/crashtests/crashtests.list index cfaa1baa9ce8..7f195b28a8fe 100644 --- a/layout/svg/crashtests/crashtests.list +++ b/layout/svg/crashtests/crashtests.list @@ -218,3 +218,4 @@ load grouping-empty-bounds.html load 1480275.html load 1480224.html load 1502936.html +load 1504918.svg diff --git a/layout/tables/crashtests/crashtests.list b/layout/tables/crashtests/crashtests.list index b9fdc37add04..35e761c906b7 100644 --- a/layout/tables/crashtests/crashtests.list +++ b/layout/tables/crashtests/crashtests.list @@ -141,7 +141,7 @@ 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 diff --git a/layout/tools/reftest/mach_commands.py b/layout/tools/reftest/mach_commands.py index f91d274dcf90..5318fdb0ed57 100644 --- a/layout/tools/reftest/mach_commands.py +++ b/layout/tools/reftest/mach_commands.py @@ -142,6 +142,10 @@ class ReftestRunner(MozbuildObject): 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. diff --git a/layout/tools/reftest/reftestcommandline.py b/layout/tools/reftest/reftestcommandline.py index 96727b43c6fa..e8f09348149f 100644 --- a/layout/tools/reftest/reftestcommandline.py +++ b/layout/tools/reftest/reftestcommandline.py @@ -485,7 +485,4 @@ class RemoteArgumentsParser(ReftestArgumentsParser): 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 diff --git a/layout/tools/reftest/remotereftest.py b/layout/tools/reftest/remotereftest.py index e806f3366d9d..5f26ebe18a30 100644 --- a/layout/tools/reftest/remotereftest.py +++ b/layout/tools/reftest/remotereftest.py @@ -176,9 +176,12 @@ class RemoteReftest(RefTest): # 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: @@ -375,7 +378,8 @@ class RemoteReftest(RefTest): xrePath=options.xrePath, debuggerInfo=debuggerInfo, symbolsPath=symbolsPath, - timeout=timeout) + timeout=timeout, + e10s=options.e10s) self.cleanup(profile.profile) return status diff --git a/mfbt/FloatingPoint.h b/mfbt/FloatingPoint.h index 60e621b8ea6f..3f306fab638b 100644 --- a/mfbt/FloatingPoint.h +++ b/mfbt/FloatingPoint.h @@ -37,33 +37,38 @@ namespace mozilla { * 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 +struct FloatingPointTrait; + +template<> +struct FloatingPointTrait { +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 { +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 struct SelectTrait; -template<> struct SelectTrait : public FloatTypeTraits {}; -template<> struct SelectTrait : public DoubleTypeTraits {}; +} // namespace detail /* * This struct contains details regarding the encoding of floating-point @@ -92,30 +97,65 @@ template<> struct SelectTrait : public DoubleTypeTraits {}; * http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers */ template -struct FloatingPoint : public SelectTrait +struct FloatingPoint final : private detail::FloatingPointTrait { - using Base = SelectTrait; +private: + using Base = detail::FloatingPointTrait; + +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(1) << (CHAR_BIT * sizeof(Bits) - 1); + + /** The exponent bits in the floating point representation. */ + static constexpr Bits kExponentBits = + ((static_cast(1) << kExponentWidth) - 1) << kSignificandWidth; + + /** The significand bits in the floating point representation. */ + static constexpr Bits kSignificandBits = + (static_cast(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. */ diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java index c91a7df39cd9..723670c58698 100644 --- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java +++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java @@ -616,9 +616,6 @@ public class BrowserApp extends GeckoApp 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()); @@ -1026,6 +1023,9 @@ public class BrowserApp extends GeckoApp return; } + final Intent killerIntent = new Intent(this, FennecKiller.class); + startService(killerIntent); + if (!mHasResumed) { getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop"); mHasResumed = true; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 1eb05679c666..68bd1e98c4e2 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -992,7 +992,6 @@ pref("ui.scrollToClick", 0); // 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 diff --git a/netwerk/test/crashtests/crashtests.list b/netwerk/test/crashtests/crashtests.list index 4837a356fcf6..db96b5bc1f07 100644 --- a/netwerk/test/crashtests/crashtests.list +++ b/netwerk/test/crashtests/crashtests.list @@ -1,4 +1,4 @@ -load 675518.html +skip-if(Android&&browserIsRemote) load 675518.html load 785753-1.html load 785753-2.html load 1274044-1.html diff --git a/python/mozbuild/mozbuild/backend/test_manifest.py b/python/mozbuild/mozbuild/backend/test_manifest.py index 0cfa59fb7772..218d81a83575 100644 --- a/python/mozbuild/mozbuild/backend/test_manifest.py +++ b/python/mozbuild/mozbuild/backend/test_manifest.py @@ -78,6 +78,7 @@ class TestManifestBackend(PartialBackend): 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) diff --git a/taskcluster/taskgraph/actions/backfill.py b/taskcluster/taskgraph/actions/backfill.py index 01cbc54f07c6..b8e1a1001b0c 100644 --- a/taskcluster/taskgraph/actions/backfill.py +++ b/taskcluster/taskgraph/actions/backfill.py @@ -6,6 +6,7 @@ from __future__ import absolute_import, print_function, unicode_literals +import json import logging import requests @@ -140,7 +141,10 @@ def backfill_action(parameters, graph_config, input, task_group_id, task_id, tas 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'] diff --git a/taskcluster/taskgraph/transforms/tests.py b/taskcluster/taskgraph/transforms/tests.py index 6940657e3bef..1065b840bd8d 100644 --- a/taskcluster/taskgraph/transforms/tests.py +++ b/taskcluster/taskgraph/transforms/tests.py @@ -205,7 +205,7 @@ test_description_schema = Schema({ '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. @@ -429,7 +429,7 @@ def set_defaults(config, tests): # 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 @@ -551,6 +551,8 @@ def set_target(config, tests): 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' diff --git a/taskcluster/taskgraph/util/perfile.py b/taskcluster/taskgraph/util/perfile.py index 6f16cdeb9b3b..e2d966c80fbf 100644 --- a/taskcluster/taskgraph/util/perfile.py +++ b/taskcluster/taskgraph/util/perfile.py @@ -4,6 +4,8 @@ from __future__ import absolute_import, print_function, unicode_literals +import itertools +import json import logging import math @@ -47,9 +49,10 @@ def perfile_number_of_chunks(is_try, try_task_config, head_repository, head_rev, 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)) @@ -57,7 +60,6 @@ def perfile_number_of_chunks(is_try, try_task_config, head_repository, head_rev, 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: diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py b/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py index 27ab50232b80..afb2d929404e 100644 --- a/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py @@ -122,8 +122,10 @@ 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() diff --git a/testing/mochitest/mach_commands.py b/testing/mochitest/mach_commands.py index 511ed70a998d..b4b6e7cd6c4c 100644 --- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -177,6 +177,11 @@ class MochitestRunner(MozbuildObject): 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): @@ -208,6 +213,10 @@ class MochitestRunner(MozbuildObject): 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 diff --git a/testing/mochitest/mochitest_options.py b/testing/mochitest/mochitest_options.py index 2f8ee1b59bf6..7526abcf90cc 100644 --- a/testing/mochitest/mochitest_options.py +++ b/testing/mochitest/mochitest_options.py @@ -997,11 +997,6 @@ class AndroidArguments(ArgumentContainer): "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 diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py index 2cbbe18b4220..e3025f60c3bb 100644 --- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -2077,7 +2077,8 @@ toolbar#nav-bar { 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 @@ -2779,6 +2780,7 @@ toolbar#nav-bar { screenshotOnFail=options.screenshotOnFail, bisectChunk=options.bisectChunk, marionette_args=marionette_args, + e10s=options.e10s ) status = ret or status except KeyboardInterrupt: diff --git a/testing/mozbase/mozdevice/mozdevice/adb.py b/testing/mozbase/mozdevice/mozdevice/adb.py index e70578ddf8f7..de97eb476e49 100644 --- a/testing/mozbase/mozdevice/mozdevice/adb.py +++ b/testing/mozbase/mozdevice/mozdevice/adb.py @@ -1438,7 +1438,15 @@ class ADBDevice(ADBCommand): "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, diff --git a/testing/mozbase/moztest/moztest/resolve.py b/testing/mozbase/moztest/moztest/resolve.py index 087b74bff897..309c5697b485 100644 --- a/testing/mozbase/moztest/moztest/resolve.py +++ b/testing/mozbase/moztest/moztest/resolve.py @@ -487,6 +487,7 @@ class TestMetadata(object): "support-files": "", "subsuite": test_type, "dir_relpath": os.path.dirname(src_path), + "srcdir_relpath": src_path, }) self._wpt_loaded = True diff --git a/testing/mozharness/mozharness/mozilla/testing/android.py b/testing/mozharness/mozharness/mozilla/testing/android.py index 689dec8e2526..55cd1ff0f0ca 100644 --- a/testing/mozharness/mozharness/mozilla/testing/android.py +++ b/testing/mozharness/mozharness/mozilla/testing/android.py @@ -328,9 +328,15 @@ class AndroidMixin(object): 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): diff --git a/testing/mozharness/mozharness/mozilla/testing/per_test_base.py b/testing/mozharness/mozharness/mozilla/testing/per_test_base.py index 72f98c947e12..4326d4664fa6 100644 --- a/testing/mozharness/mozharness/mozilla/testing/per_test_base.py +++ b/testing/mozharness/mozharness/mozilla/testing/per_test_base.py @@ -5,6 +5,8 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. # ***** END LICENSE BLOCK ***** +import itertools +import json import math import os import posixpath @@ -238,7 +240,8 @@ class SingleTestMixin(FetchesMixin): 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: diff --git a/testing/mozharness/scripts/android_emulator_unittest.py b/testing/mozharness/scripts/android_emulator_unittest.py index f5999f02e3c7..7636e656aeb4 100644 --- a/testing/mozharness/scripts/android_emulator_unittest.py +++ b/testing/mozharness/scripts/android_emulator_unittest.py @@ -7,6 +7,7 @@ import copy import datetime +import json import os import re import sys @@ -25,6 +26,9 @@ from mozharness.mozilla.testing.codecoverage import ( 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): @@ -75,6 +79,13 @@ class AndroidEmulatorTest(TestingMixin, BaseScript, MozbaseMixin, CodeCoverageMi "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) @@ -121,6 +132,7 @@ class AndroidEmulatorTest(TestingMixin, BaseScript, MozbaseMixin, CodeCoverageMi 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: @@ -214,7 +226,8 @@ class AndroidEmulatorTest(TestingMixin, BaseScript, MozbaseMixin, CodeCoverageMi ), } - 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 @@ -230,9 +243,22 @@ class AndroidEmulatorTest(TestingMixin, BaseScript, MozbaseMixin, CodeCoverageMi 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]) diff --git a/testing/mozharness/scripts/android_hardware_unittest.py b/testing/mozharness/scripts/android_hardware_unittest.py index f42701494451..9a682c9d5753 100644 --- a/testing/mozharness/scripts/android_hardware_unittest.py +++ b/testing/mozharness/scripts/android_hardware_unittest.py @@ -7,6 +7,7 @@ import copy import datetime +import json import os import re import sys @@ -22,6 +23,9 @@ 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): @@ -66,6 +70,13 @@ class AndroidHardwareTest(TestingMixin, BaseScript, MozbaseMixin, "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): @@ -110,6 +121,7 @@ class AndroidHardwareTest(TestingMixin, BaseScript, MozbaseMixin, 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: @@ -201,7 +213,8 @@ class AndroidHardwareTest(TestingMixin, BaseScript, MozbaseMixin, ), } - 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 @@ -218,13 +231,26 @@ class AndroidHardwareTest(TestingMixin, BaseScript, MozbaseMixin, 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: diff --git a/testing/mozharness/scripts/desktop_unittest.py b/testing/mozharness/scripts/desktop_unittest.py index 9f0e6515adcb..a18e51d8058f 100755 --- a/testing/mozharness/scripts/desktop_unittest.py +++ b/testing/mozharness/scripts/desktop_unittest.py @@ -10,6 +10,7 @@ author: Jordan Lund """ +import json import os import re import sys @@ -358,6 +359,21 @@ class DesktopUnittest(TestingMixin, MercurialScript, MozbaseMixin, 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 @@ -398,11 +414,8 @@ class DesktopUnittest(TestingMixin, MercurialScript, MozbaseMixin, # 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'], @@ -800,7 +813,7 @@ class DesktopUnittest(TestingMixin, MercurialScript, MozbaseMixin, 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: diff --git a/testing/mozharness/scripts/marionette.py b/testing/mozharness/scripts/marionette.py index 33ccd86471ad..979ebcdd2972 100755 --- a/testing/mozharness/scripts/marionette.py +++ b/testing/mozharness/scripts/marionette.py @@ -6,6 +6,7 @@ # ***** END LICENSE BLOCK ***** import copy +import json import os import sys @@ -317,9 +318,11 @@ class MarionetteTest(TestingMixin, MercurialScript, TransferMixin, # 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) diff --git a/testing/mozharness/scripts/web_platform_tests.py b/testing/mozharness/scripts/web_platform_tests.py index 996aa96299c3..393d7d1ddf43 100755 --- a/testing/mozharness/scripts/web_platform_tests.py +++ b/testing/mozharness/scripts/web_platform_tests.py @@ -5,6 +5,7 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. # ***** END LICENSE BLOCK ***** import copy +import json import os import sys @@ -251,11 +252,12 @@ class WebPlatformTest(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidM 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"]: diff --git a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/ui3/box-sizing-replaced-003.xht.ini b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/ui3/box-sizing-replaced-003.xht.ini new file mode 100644 index 000000000000..081bfbc09851 --- /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 diff --git 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 index 2ad549f54fb7..06a428eb5a56 100644 --- 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 @@ -15,3 +15,18 @@ [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 diff --git a/testing/web-platform/meta/html/dom/interfaces.https.html.ini b/testing/web-platform/meta/html/dom/interfaces.https.html.ini index 7e1e21854d2c..0fda4e2e5cb2 100644 --- a/testing/web-platform/meta/html/dom/interfaces.https.html.ini +++ b/testing/web-platform/meta/html/dom/interfaces.https.html.ini @@ -361,6 +361,22 @@ 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 diff --git a/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes-ref.html b/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes-ref.html new file mode 100644 index 000000000000..7c89ee60e980 --- /dev/null +++ b/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes-ref.html @@ -0,0 +1,179 @@ + + + + + CSS Ruby Reference: ruby content w. layout-internal 'display' values + + + + + +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +

+ + + +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ + + +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ + + diff --git a/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes.html b/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes.html new file mode 100644 index 000000000000..cfd271233e20 --- /dev/null +++ b/testing/web-platform/tests/css/css-ruby/ruby-layout-internal-boxes.html @@ -0,0 +1,181 @@ + + + + + CSS Ruby Test: ruby content w. layout-internal 'display' values + + + + + + + + +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +ab +ab +a
b
b
+a
b
c
+ +

+ + + +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ + + +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ +b +b +
b
b
+
b
c
+ + + diff --git a/testing/web-platform/tests/css/css-ui/text-overflow-ruby-ref.html b/testing/web-platform/tests/css/css-ui/text-overflow-ruby-ref.html new file mode 100644 index 000000000000..ae5267aa9ef6 --- /dev/null +++ b/testing/web-platform/tests/css/css-ui/text-overflow-ruby-ref.html @@ -0,0 +1,83 @@ + + + + + Reference: text-overflow:ellipsis and ruby + + + + + +
+
+aabb +
+aa
bbbbbb
cc
+
+aabbbbbbcc +
+aabb +
+aa
bbbbbb
cc
+
+aabb +
+aa
bbbbbb
cc
+ +
+bb +
+
bbbbbb
cc
+
+bbbbbbcc +
+bb +
+
bbbbbb
cc
+
+bb +
+
bbbbbb
cc
+
+
+ +
+
+bb +
+
bbbbbb
cc
+
+bbbbbbcc +
+bb +
+
bbbbbb
cc
+
+bb +
+
bbbbbb
cc
+
+
+ + + diff --git a/testing/web-platform/tests/css/css-ui/text-overflow-ruby.html b/testing/web-platform/tests/css/css-ui/text-overflow-ruby.html new file mode 100644 index 000000000000..c8abebb7206b --- /dev/null +++ b/testing/web-platform/tests/css/css-ui/text-overflow-ruby.html @@ -0,0 +1,85 @@ + + + + + CSS Basic User Interface Test: text-overflow:ellipsis and ruby + + + + + + + +
+
+aabb +
+aa
bbbbbb
cc
+
+aabbbbbbcc +
+aabb +
+aa
bbbbbb
cc
+
+aabb +
+aa
bbbbbb
cc
+ +
+bb +
+
bbbbbb
cc
+
+bbbbbbcc +
+bb +
+
bbbbbb
cc
+
+bb +
+
bbbbbb
cc
+
+
+ +
+
+bb +
+
bbbbbb
cc
+
+bbbbbbcc +
+bb +
+
bbbbbb
cc
+
+bb +
+
bbbbbb
cc
+
+
+ + + diff --git a/third_party/rust/cranelift-bforest/.cargo-checksum.json b/third_party/rust/cranelift-bforest/.cargo-checksum.json index 5ab80b58a17e..65ee78922be3 100644 --- a/third_party/rust/cranelift-bforest/.cargo-checksum.json +++ b/third_party/rust/cranelift-bforest/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/cranelift-bforest/Cargo.toml b/third_party/rust/cranelift-bforest/Cargo.toml index 1e546fa9e327..cc8cdb8445a1 100644 --- a/third_party/rust/cranelift-bforest/Cargo.toml +++ b/third_party/rust/cranelift-bforest/Cargo.toml @@ -12,7 +12,7 @@ [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/" @@ -22,7 +22,7 @@ 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] diff --git a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json index 8c65a0e88422..c01b00aeb271 100644 --- a/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json +++ b/third_party/rust/cranelift-codegen-meta/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/cranelift-codegen-meta/Cargo.toml b/third_party/rust/cranelift-codegen-meta/Cargo.toml index ef90f5c8e590..f320035aac04 100644 --- a/third_party/rust/cranelift-codegen-meta/Cargo.toml +++ b/third_party/rust/cranelift-codegen-meta/Cargo.toml @@ -12,14 +12,14 @@ [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" diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs index 4a6a819683ef..7168d32c8525 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs @@ -1,7 +1,7 @@ use cranelift_entity::PrimaryMap; use super::regs::{ - RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, + RegBank, RegBankBuilder, RegBankIndex, RegClass, RegClassBuilder, RegClassIndex, RegClassProto, }; pub struct TargetIsa { @@ -18,12 +18,24 @@ impl TargetIsa { 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() { @@ -34,7 +46,7 @@ impl TargetIsa { (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, @@ -47,38 +59,51 @@ impl TargetIsa { } 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: @@ -89,16 +114,16 @@ impl TargetIsa { /// 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); @@ -126,7 +151,8 @@ impl TargetIsa { // 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 @@ -138,5 +164,26 @@ impl TargetIsa { } } } + + // 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 } } diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs index bc40ffaf69ef..4e8a34001b30 100644 --- a/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs +++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/regs.rs @@ -1,7 +1,5 @@ use cranelift_entity::EntityRef; -use super::isa::TargetIsa; - #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct RegBankIndex(u32); entity_impl!(RegBankIndex); @@ -97,71 +95,53 @@ impl RegClass { } } +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 } } diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/arm32/mod.rs index ce3342227693..e0e47c2e2e17 100644 --- 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,8 +1,8 @@ +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) @@ -20,20 +20,20 @@ pub fn define() -> isa::TargetIsa { .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() } diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/arm64/mod.rs index 8e13d2832112..2435f3676e39 100644 --- 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,8 +1,8 @@ +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. @@ -22,14 +22,14 @@ pub fn define() -> isa::TargetIsa { .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() } diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs index ffb13fb15100..18f75c42e527 100644 --- a/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs +++ b/third_party/rust/cranelift-codegen-meta/src/isa/mod.rs @@ -62,14 +62,10 @@ impl fmt::Display for Isa { } pub fn define_all() -> Vec { - let isas = vec![ + vec![ riscv::define(), arm32::define(), arm64::define(), x86::define(), - ]; - for isa in isas.iter() { - isa.check(); - } - isas + ] } diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/riscv/mod.rs index 315ee42233c0..67f504c0f866 100644 --- 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,8 +1,8 @@ +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) @@ -14,11 +14,11 @@ pub fn define() -> isa::TargetIsa { .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() } diff --git a/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen-meta/src/isa/x86/mod.rs index 43fd4ed67d29..7970ea06db70 100644 --- 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,8 +1,8 @@ +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) @@ -21,23 +21,23 @@ pub fn define() -> isa::TargetIsa { .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() } diff --git a/third_party/rust/cranelift-codegen/.cargo-checksum.json b/third_party/rust/cranelift-codegen/.cargo-checksum.json index 907c007ac099..8734455166d6 100644 --- a/third_party/rust/cranelift-codegen/.cargo-checksum.json +++ b/third_party/rust/cranelift-codegen/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/cranelift-codegen/Cargo.toml b/third_party/rust/cranelift-codegen/Cargo.toml index f6c8c45d5474..362d8870b5c1 100644 --- a/third_party/rust/cranelift-codegen/Cargo.toml +++ b/third_party/rust/cranelift-codegen/Cargo.toml @@ -12,7 +12,7 @@ [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" @@ -23,11 +23,11 @@ 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] @@ -51,7 +51,7 @@ default-features = false version = "0.2.0" default-features = false [build-dependencies.cranelift-codegen-meta] -version = "0.23.0" +version = "0.25.0" [features] core = ["hashmap_core"] diff --git a/third_party/rust/cranelift-codegen/build.rs b/third_party/rust/cranelift-codegen/build.rs index f5dc65427314..1faedddd0602 100644 --- a/third_party/rust/cranelift-codegen/build.rs +++ b/third_party/rust/cranelift-codegen/build.rs @@ -24,11 +24,7 @@ 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(); @@ -96,15 +92,6 @@ fn main() { 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 { diff --git a/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py b/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py index 90a9610d6215..3e3ac0b4fe27 100644 --- a/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py +++ b/third_party/rust/cranelift-codegen/meta-python/cdsl/isa.py @@ -48,7 +48,6 @@ class TargetISA(object): 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] @@ -74,7 +73,6 @@ class TargetISA(object): """ self._collect_encoding_recipes() self._collect_predicates() - self._collect_regclasses() self._collect_legalize_codes() return self @@ -122,49 +120,6 @@ class TargetISA(object): 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 """ diff --git a/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py b/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py index 4c495807b784..534804e0e2fd 100644 --- a/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py +++ b/third_party/rust/cranelift-codegen/meta-python/isa/x86/recipes.py @@ -806,13 +806,16 @@ 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 { @@ -833,6 +836,7 @@ stWithIndex = TailRecipe( 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); @@ -850,12 +854,21 @@ st_abcd = TailRecipe( 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. @@ -872,6 +885,7 @@ stWithIndex_abcd = TailRecipe( 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); @@ -887,13 +901,16 @@ 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 { @@ -912,6 +929,7 @@ fstWithIndex = TailRecipe( 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); @@ -968,12 +986,18 @@ stDisp8_abcd = TailRecipe( 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); ''') @@ -1080,12 +1104,18 @@ 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); ''') @@ -1210,13 +1240,16 @@ 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 { @@ -1237,6 +1270,7 @@ ldWithIndex = TailRecipe( 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); @@ -1252,13 +1286,16 @@ 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 { @@ -1279,6 +1316,7 @@ fldWithIndex = TailRecipe( 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); diff --git a/third_party/rust/cranelift-codegen/src/context.rs b/third_party/rust/cranelift-codegen/src/context.rs index ffff2e25abbb..a0bd1e680d8d 100644 --- a/third_party/rust/cranelift-codegen/src/context.rs +++ b/third_party/rust/cranelift-codegen/src/context.rs @@ -275,14 +275,15 @@ impl Context { } /// Perform LICM on the function. - pub fn licm<'a, FOI: Into>>(&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. diff --git a/third_party/rust/cranelift-codegen/src/ir/dfg.rs b/third_party/rust/cranelift-codegen/src/ir/dfg.rs index ecb22237f921..2ac9969d978a 100644 --- a/third_party/rust/cranelift-codegen/src/ir/dfg.rs +++ b/third_party/rust/cranelift-codegen/src/ir/dfg.rs @@ -430,26 +430,38 @@ impl DataFlowGraph { /// 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. @@ -489,7 +501,10 @@ impl DataFlowGraph { // 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; @@ -504,7 +519,7 @@ impl DataFlowGraph { } 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() { @@ -662,9 +677,9 @@ impl DataFlowGraph { ctrl_typevar: Type, ) -> Option { 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)); } @@ -672,7 +687,7 @@ impl DataFlowGraph { 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) }) } @@ -934,7 +949,10 @@ impl DataFlowGraph { ) -> 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) { @@ -943,7 +961,7 @@ impl DataFlowGraph { } } 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); diff --git a/third_party/rust/cranelift-codegen/src/ir/extname.rs b/third_party/rust/cranelift-codegen/src/ir/extname.rs index 05f1adc54a24..b35c9aeb0511 100644 --- a/third_party/rust/cranelift-codegen/src/ir/extname.rs +++ b/third_party/rust/cranelift-codegen/src/ir/extname.rs @@ -13,7 +13,7 @@ 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 @@ -68,12 +68,12 @@ impl ExternalName { } } - /// 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"); /// ``` diff --git a/third_party/rust/cranelift-codegen/src/ir/instructions.rs b/third_party/rust/cranelift-codegen/src/ir/instructions.rs index 84e34b1f39c4..b01525ca805d 100644 --- a/third_party/rust/cranelift-codegen/src/ir/instructions.rs +++ b/third_party/rust/cranelift-codegen/src/ir/instructions.rs @@ -335,8 +335,8 @@ pub struct OpcodeConstraints { 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, } @@ -360,7 +360,7 @@ impl OpcodeConstraints { /// 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 } @@ -371,7 +371,7 @@ impl OpcodeConstraints { /// 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 } @@ -394,7 +394,7 @@ impl OpcodeConstraints { /// 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) { @@ -411,10 +411,10 @@ impl OpcodeConstraints { /// `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) } @@ -603,8 +603,8 @@ mod tests { 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!( @@ -619,8 +619,8 @@ mod tests { 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) { @@ -629,18 +629,18 @@ mod tests { } 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] diff --git a/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs b/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs index 1d8ed9478020..8cc259420f44 100644 --- a/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs +++ b/third_party/rust/cranelift-codegen/src/isa/enc_tables.rs @@ -40,7 +40,7 @@ pub type LegalizeCode = u8; /// 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 + Copy> { pub ty: Type, diff --git a/third_party/rust/cranelift-codegen/src/isa/mod.rs b/third_party/rust/cranelift-codegen/src/isa/mod.rs index f304cf09c31b..b4bf97d3345d 100644 --- a/third_party/rust/cranelift-codegen/src/isa/mod.rs +++ b/third_party/rust/cranelift-codegen/src/isa/mod.rs @@ -196,7 +196,7 @@ impl TargetFrontendConfig { /// 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; diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs b/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs index 67fe3a486a8c..2542eb3eb905 100644 --- a/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs +++ b/third_party/rust/cranelift-codegen/src/isa/x86/abi.rs @@ -270,7 +270,7 @@ pub fn prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> CodegenRes } } -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" @@ -291,7 +291,7 @@ pub fn baldrdash_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> /// 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"); } @@ -363,7 +363,7 @@ pub fn fastcall_prologue_epilogue(func: &mut ir::Function, isa: &TargetIsa) -> C } /// 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; diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs index 9c52563a27a4..a709d03b764e 100644 --- a/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs +++ b/third_party/rust/cranelift-codegen/src/isa/x86/enc_tables.rs @@ -23,6 +23,9 @@ pub fn needs_sib_byte(reg: RegUnit) -> bool { 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, @@ -71,6 +74,22 @@ fn size_plus_maybe_sib_for_in_reg_1( ) -> 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( diff --git a/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs b/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs index b8bdc83ca825..e337704f6666 100644 --- a/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs +++ b/third_party/rust/cranelift-codegen/src/legalizer/boundary.rs @@ -201,8 +201,14 @@ where // 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; @@ -440,11 +446,11 @@ fn legalize_inst_arguments( // 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 @@ -472,11 +478,11 @@ fn legalize_inst_arguments( // [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 { @@ -487,7 +493,7 @@ fn legalize_inst_arguments( 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 { diff --git a/third_party/rust/cranelift-codegen/src/legalizer/split.rs b/third_party/rust/cranelift-codegen/src/legalizer/split.rs index 1cce097f2658..46f530bf6151 100644 --- a/third_party/rust/cranelift-codegen/src/legalizer/split.rs +++ b/third_party/rust/cranelift-codegen/src/legalizer/split.rs @@ -133,14 +133,14 @@ fn split_any( "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. @@ -155,21 +155,23 @@ fn split_any( // 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, ); } diff --git a/third_party/rust/cranelift-codegen/src/licm.rs b/third_party/rust/cranelift-codegen/src/licm.rs index f9954087b4ac..b203fdfe9e2a 100644 --- a/third_party/rust/cranelift-codegen/src/licm.rs +++ b/third_party/rust/cranelift-codegen/src/licm.rs @@ -1,11 +1,12 @@ //! 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; @@ -14,6 +15,7 @@ use timing; /// 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, @@ -36,7 +38,7 @@ pub fn do_licm( 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 @@ -60,6 +62,7 @@ pub fn do_licm( // 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, @@ -87,7 +90,7 @@ fn create_pre_header( } } { - 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(); @@ -108,21 +111,24 @@ fn has_pre_header( 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 diff --git a/third_party/rust/cranelift-codegen/src/print_errors.rs b/third_party/rust/cranelift-codegen/src/print_errors.rs index 8e764065a7cb..73c8cf809acf 100644 --- a/third_party/rust/cranelift-codegen/src/print_errors.rs +++ b/third_party/rust/cranelift-codegen/src/print_errors.rs @@ -2,7 +2,7 @@ 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; @@ -23,6 +23,7 @@ pub fn pretty_verifier_error<'a>( ) -> 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), @@ -30,12 +31,31 @@ pub fn pretty_verifier_error<'a>( 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, &'a mut Vec); 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, @@ -59,7 +79,45 @@ impl<'a> FuncWriter for PrettyVerifierError<'a> { } } -/// 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, +) -> 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, @@ -70,37 +128,29 @@ fn pretty_instruction_error( func_w: &mut FuncWriter, errors: &mut Vec, ) -> 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(()) @@ -114,45 +164,54 @@ fn pretty_preamble_error( func_w: &mut FuncWriter, errors: &mut Vec, ) -> fmt::Result { + 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 indent = 4; - let mut i = 0; - let mut printed_entity = false; - + let mut printed_error = false; while i != errors.len() { if entity == errors[i].location { - let err = errors.remove(i); - - if !printed_entity { - func_w.write_entity_definition(w, func, entity, value)?; - printed_entity = true; + if !printed_error { + print_arrow(w, &s)?; + printed_error = true; } - - print_error(w, indent, entity.to_string(), err)?; + let err = errors.remove(i); + 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(()) } diff --git a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs index 053d7f7dee06..cfdfd984fd31 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/coalescing.rs @@ -375,7 +375,7 @@ impl<'a> Context<'a> { } /// 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) { diff --git a/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs b/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs index b297578caefd..d3a11a9d4515 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/register_set.rs @@ -72,7 +72,7 @@ impl RegisterSet { 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) diff --git a/third_party/rust/cranelift-codegen/src/regalloc/reload.rs b/third_party/rust/cranelift-codegen/src/regalloc/reload.rs index e22fefc0fcfc..6d16ec5d3f98 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/reload.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/reload.rs @@ -266,7 +266,7 @@ impl<'a> Context<'a> { let retvals = &defs[self.cur.func.dfg[inst] .opcode() .constraints() - .fixed_results()..]; + .num_fixed_results()..]; if !retvals.is_empty() { let sig = self .cur @@ -367,7 +367,7 @@ impl<'a> Context<'a> { let offset = self.cur.func.dfg[inst] .opcode() .constraints() - .fixed_value_arguments(); + .num_fixed_value_arguments(); if args.len() == offset { return; } diff --git a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs index 1ce0649fed60..168956703ca7 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/spilling.rs @@ -134,11 +134,8 @@ impl<'a> Context<'a> { 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); @@ -237,17 +234,15 @@ impl<'a> Context<'a> { 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); @@ -282,23 +277,25 @@ impl<'a> Context<'a> { // 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. @@ -315,35 +312,42 @@ impl<'a> Context<'a> { // 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 => {} - } - 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); + // 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. @@ -356,7 +360,7 @@ impl<'a> Context<'a> { 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") @@ -376,10 +380,10 @@ impl<'a> Context<'a> { // 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 @@ -396,7 +400,7 @@ impl<'a> Context<'a> { ), 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); diff --git a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs index 55fece93c152..13ef4a5381fe 100644 --- a/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs +++ b/third_party/rust/cranelift-codegen/src/regalloc/virtregs.rs @@ -291,20 +291,22 @@ impl UFEntry { 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`. diff --git a/third_party/rust/cranelift-codegen/src/simple_gvn.rs b/third_party/rust/cranelift-codegen/src/simple_gvn.rs index 54d1040e9df9..d60bdb6899c5 100644 --- a/third_party/rust/cranelift-codegen/src/simple_gvn.rs +++ b/third_party/rust/cranelift-codegen/src/simple_gvn.rs @@ -110,10 +110,8 @@ pub fn do_simple_gvn(func: &mut Function, domtree: &mut DominatorTree) { 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; } @@ -123,9 +121,8 @@ pub fn do_simple_gvn(func: &mut Function, domtree: &mut DominatorTree) { 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 diff --git a/third_party/rust/cranelift-codegen/src/verifier/mod.rs b/third_party/rust/cranelift-codegen/src/verifier/mod.rs index 31a7dfc029a2..84244cc59098 100644 --- a/third_party/rust/cranelift-codegen/src/verifier/mod.rs +++ b/third_party/rust/cranelift-codegen/src/verifier/mod.rs @@ -524,12 +524,12 @@ impl<'a> Verifier<'a> { ); } - 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(); @@ -861,18 +861,13 @@ impl<'a> Verifier<'a> { 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); } } } diff --git a/third_party/rust/cranelift-codegen/src/write.rs b/third_party/rust/cranelift-codegen/src/write.rs index d790efa920f2..b4f9b1c76dee 100644 --- a/third_party/rust/cranelift-codegen/src/write.rs +++ b/third_party/rust/cranelift-codegen/src/write.rs @@ -14,6 +14,16 @@ 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, @@ -22,7 +32,7 @@ pub trait FuncWriter { aliases: &SecondaryMap>, isa: Option<&TargetIsa>, inst: Inst, - ident: usize, + indent: usize, ) -> fmt::Result; /// Write the preamble to `w`. By default, this uses `write_entity_definition`. @@ -108,6 +118,17 @@ impl FuncWriter for PlainWriter { ) -> 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. @@ -227,7 +248,7 @@ fn decorate_ebb( 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)?; } diff --git a/third_party/rust/cranelift-entity/.cargo-checksum.json b/third_party/rust/cranelift-entity/.cargo-checksum.json index 216e09340f32..44fb1c4a658a 100644 --- a/third_party/rust/cranelift-entity/.cargo-checksum.json +++ b/third_party/rust/cranelift-entity/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/cranelift-entity/Cargo.toml b/third_party/rust/cranelift-entity/Cargo.toml index 5fd59bb3a829..fb48ec0b2f4d 100644 --- a/third_party/rust/cranelift-entity/Cargo.toml +++ b/third_party/rust/cranelift-entity/Cargo.toml @@ -12,7 +12,7 @@ [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/" diff --git a/third_party/rust/cranelift-entity/src/primary.rs b/third_party/rust/cranelift-entity/src/primary.rs index e23e8e2a6b06..9b87098239fa 100644 --- a/third_party/rust/cranelift-entity/src/primary.rs +++ b/third_party/rust/cranelift-entity/src/primary.rs @@ -111,6 +111,16 @@ where 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`. diff --git a/third_party/rust/cranelift-frontend/.cargo-checksum.json b/third_party/rust/cranelift-frontend/.cargo-checksum.json index 2434911c68f7..e69fee51fbfa 100644 --- a/third_party/rust/cranelift-frontend/.cargo-checksum.json +++ b/third_party/rust/cranelift-frontend/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/cranelift-frontend/Cargo.toml b/third_party/rust/cranelift-frontend/Cargo.toml index 514c55f63289..eac3aeaef0a3 100644 --- a/third_party/rust/cranelift-frontend/Cargo.toml +++ b/third_party/rust/cranelift-frontend/Cargo.toml @@ -12,7 +12,7 @@ [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/" @@ -21,7 +21,7 @@ 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] diff --git a/third_party/rust/cranelift-frontend/src/frontend.rs b/third_party/rust/cranelift-frontend/src/frontend.rs index 0c595a585fca..692bc48de61d 100644 --- a/third_party/rust/cranelift-frontend/src/frontend.rs +++ b/third_party/rust/cranelift-frontend/src/frontend.rs @@ -605,12 +605,12 @@ impl<'a> FunctionBuilder<'a> { 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); } @@ -679,7 +679,7 @@ impl<'a> FunctionBuilder<'a> { 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 { @@ -765,7 +765,10 @@ impl<'a> FunctionBuilder<'a> { 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 { @@ -987,6 +990,63 @@ ebb0: ); } + #[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)); diff --git a/third_party/rust/cranelift-wasm/.cargo-checksum.json b/third_party/rust/cranelift-wasm/.cargo-checksum.json index 20c60a70f125..23de9b817fff 100644 --- a/third_party/rust/cranelift-wasm/.cargo-checksum.json +++ b/third_party/rust/cranelift-wasm/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/cranelift-wasm/Cargo.toml b/third_party/rust/cranelift-wasm/Cargo.toml index 471a9107dbca..cd2e54433f34 100644 --- a/third_party/rust/cranelift-wasm/Cargo.toml +++ b/third_party/rust/cranelift-wasm/Cargo.toml @@ -12,7 +12,7 @@ [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" @@ -21,15 +21,15 @@ 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] @@ -50,7 +50,7 @@ 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" diff --git a/third_party/rust/cranelift-wasm/src/code_translator.rs b/third_party/rust/cranelift-wasm/src/code_translator.rs index 8d5fee979aca..8a270e687efe 100644 --- a/third_party/rust/cranelift-wasm/src/code_translator.rs +++ b/third_party/rust/cranelift-wasm/src/code_translator.rs @@ -253,7 +253,7 @@ pub fn translate_operator( } 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 { diff --git a/third_party/rust/cranelift-wasm/src/environ/dummy.rs b/third_party/rust/cranelift-wasm/src/environ/dummy.rs index ae2183efb916..926c87cf9e33 100644 --- a/third_party/rust/cranelift-wasm/src/environ/dummy.rs +++ b/third_party/rust/cranelift-wasm/src/environ/dummy.rs @@ -52,6 +52,15 @@ pub struct DummyModuleInfo { /// 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>, @@ -78,6 +87,9 @@ impl DummyModuleInfo { 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(), @@ -326,8 +338,8 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ } 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 { @@ -375,6 +387,13 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { 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 } @@ -382,6 +401,14 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { 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, @@ -391,9 +418,18 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { ) { // 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, diff --git a/third_party/rust/cranelift-wasm/src/environ/spec.rs b/third_party/rust/cranelift-wasm/src/environ/spec.rs index d5518e037ac9..d963038f1968 100644 --- a/third_party/rust/cranelift-wasm/src/environ/spec.rs +++ b/third_party/rust/cranelift-wasm/src/environ/spec.rs @@ -237,7 +237,7 @@ pub trait FuncEnvironment { /// 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; @@ -268,11 +268,18 @@ pub trait ModuleEnvironment<'data> { /// 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, @@ -283,6 +290,10 @@ pub trait ModuleEnvironment<'data> { ); /// 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, diff --git a/third_party/rust/cranelift-wasm/src/lib.rs b/third_party/rust/cranelift-wasm/src/lib.rs index b119d2df8f20..86f7c2a76997 100644 --- a/third_party/rust/cranelift-wasm/src/lib.rs +++ b/third_party/rust/cranelift-wasm/src/lib.rs @@ -66,8 +66,8 @@ pub use environ::{ 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"))] diff --git a/third_party/rust/cranelift-wasm/src/sections_translator.rs b/third_party/rust/cranelift-wasm/src/sections_translator.rs index e8468d9d4c5e..bab2ac1f90d9 100644 --- a/third_party/rust/cranelift-wasm/src/sections_translator.rs +++ b/third_party/rust/cranelift-wasm/src/sections_translator.rs @@ -19,8 +19,8 @@ use translation_utils::{ 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. @@ -60,58 +60,61 @@ pub fn parse_import_section<'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, + ); + } + 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, + ); } - 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), - }), } } Ok(()) diff --git a/third_party/rust/cranelift-wasm/src/translation_utils.rs b/third_party/rust/cranelift-wasm/src/translation_utils.rs index cc2926dad1f6..95b24b9f0f76 100644 --- a/third_party/rust/cranelift-wasm/src/translation_utils.rs +++ b/third_party/rust/cranelift-wasm/src/translation_utils.rs @@ -13,6 +13,21 @@ entity_impl!(FuncIndex); 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); diff --git a/third_party/rust/wasmparser/.cargo-checksum.json b/third_party/rust/wasmparser/.cargo-checksum.json index d274396b701f..74ced29d471a 100644 --- a/third_party/rust/wasmparser/.cargo-checksum.json +++ b/third_party/rust/wasmparser/.cargo-checksum.json @@ -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 diff --git a/third_party/rust/wasmparser/Cargo.toml b/third_party/rust/wasmparser/Cargo.toml index 43de5e3d31ad..993c90bf743e 100644 --- a/third_party/rust/wasmparser/Cargo.toml +++ b/third_party/rust/wasmparser/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "wasmparser" -version = "0.21.8" +version = "0.22.0" authors = ["Yury Delendik "] exclude = ["fuzz/**/*", "tests/**/*"] description = "A simple event-driven library for parsing WebAssembly binary files.\n" diff --git a/third_party/rust/wasmparser/README.md b/third_party/rust/wasmparser/README.md index 34a0fb21922a..87986366a4b4 100644 --- a/third_party/rust/wasmparser/README.md +++ b/third_party/rust/wasmparser/README.md @@ -1,10 +1,20 @@ -# 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 @@ -38,6 +48,7 @@ fn main() { } ``` + ## Fuzzing To fuzz test wasmparser.rs, switch to a nightly Rust compiler and install [cargo-fuzz]: diff --git a/third_party/rust/wasmparser/src/binary_reader.rs b/third_party/rust/wasmparser/src/binary_reader.rs index 75d3a27efe9f..482585734b98 100644 --- a/third_party/rust/wasmparser/src/binary_reader.rs +++ b/third_party/rust/wasmparser/src/binary_reader.rs @@ -23,7 +23,7 @@ use limits::{ 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, }; @@ -65,6 +65,24 @@ pub struct SectionHeader<'a> { 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> { @@ -361,23 +379,6 @@ impl<'a> BinaryReader<'a> { }) } - pub(crate) fn read_name_map(&mut self, limit: usize) -> Result]>> { - 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() } @@ -1188,21 +1189,24 @@ impl<'a> BrTable<'a> { /// let mut reader = wasmparser::BinaryReader::new(&buf); /// let op = reader.read_operator().unwrap(); /// if let wasmparser::Operator::BrTable { ref table } = op { - /// let br_table_depths = table.read_table(); + /// let br_table_depths = table.read_table().unwrap(); /// assert!(br_table_depths.0 == vec![1,2].into_boxed_slice() && /// br_table_depths.1 == 0); /// } else { /// unreachable!(); /// } /// ``` - pub fn read_table(&self) -> (Box<[u32]>, u32) { + pub fn read_table(&self) -> Result<(Box<[u32]>, u32)> { let mut reader = BinaryReader::new(self.buffer); let mut table = Vec::new(); while !reader.eof() { - table.push(reader.read_var_u32().unwrap()); + table.push(reader.read_var_u32()?); } - let default_target = table.pop().unwrap(); - (table.into_boxed_slice(), default_target) + let default_target = table.pop().ok_or_else(|| BinaryReaderError { + message: "br_table missing default target", + offset: reader.original_position(), + })?; + Ok((table.into_boxed_slice(), default_target)) } } @@ -1241,6 +1245,6 @@ impl<'a> Iterator for BrTableIterator<'a> { if self.reader.eof() { return None; } - Some(self.reader.read_var_u32().unwrap()) + self.reader.read_var_u32().ok() } } diff --git a/third_party/rust/wasmparser/src/lib.rs b/third_party/rust/wasmparser/src/lib.rs index 35c7ae142b15..907510c5f609 100644 --- a/third_party/rust/wasmparser/src/lib.rs +++ b/third_party/rust/wasmparser/src/lib.rs @@ -34,6 +34,7 @@ extern crate hashmap_core; extern crate alloc; pub use binary_reader::BinaryReader; +pub use binary_reader::Range; use binary_reader::SectionHeader; pub use parser::LocalName; @@ -41,7 +42,6 @@ pub use parser::NameEntry; pub use parser::Parser; pub use parser::ParserInput; pub use parser::ParserState; -pub use parser::Range; pub use parser::RelocEntry; pub use parser::WasmDecoder; diff --git a/third_party/rust/wasmparser/src/parser.rs b/third_party/rust/wasmparser/src/parser.rs index 583a8a2ec959..2f23a1bdbf35 100644 --- a/third_party/rust/wasmparser/src/parser.rs +++ b/third_party/rust/wasmparser/src/parser.rs @@ -23,11 +23,19 @@ use limits::{ use primitives::{ BinaryReaderError, CustomSectionKind, ExternalKind, FuncType, GlobalType, - ImportSectionEntryType, LinkingType, MemoryType, NameType, Naming, Operator, RelocType, Result, + ImportSectionEntryType, LinkingType, MemoryType, Naming, Operator, RelocType, Result, SectionCode, TableType, Type, }; -use binary_reader::{BinaryReader, SectionHeader}; +use readers::{ + CodeSectionReader, Data, DataSectionReader, Element, ElementItems, ElementSectionReader, + Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global, GlobalSectionReader, + Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader, ModuleReader, Name, + NameSectionReader, NamingReader, OperatorsReader, Reloc, RelocSectionReader, Section, + SectionReader, TableSectionReader, TypeSectionReader, +}; + +use binary_reader::{BinaryReader, Range}; const MAX_DATA_CHUNK_SIZE: usize = MAX_WASM_STRING_SIZE; @@ -58,24 +66,6 @@ enum InitExpressionContinuation { DataSection, } -/// 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] - } -} - #[derive(Debug)] pub enum ParserState<'a> { Error(BinaryReaderError), @@ -164,15 +154,59 @@ pub trait WasmDecoder<'a> { fn last_state(&self) -> &ParserState<'a>; } +enum ParserSectionReader<'a> { + None, + CodeSectionReader(CodeSectionReader<'a>), + DataSectionReader(DataSectionReader<'a>), + ElementSectionReader(ElementSectionReader<'a>), + ExportSectionReader(ExportSectionReader<'a>), + FunctionSectionReader(FunctionSectionReader<'a>), + GlobalSectionReader(GlobalSectionReader<'a>), + ImportSectionReader(ImportSectionReader<'a>), + MemorySectionReader(MemorySectionReader<'a>), + TableSectionReader(TableSectionReader<'a>), + TypeSectionReader(TypeSectionReader<'a>), + NameSectionReader(NameSectionReader<'a>), + LinkingSectionReader(LinkingSectionReader<'a>), + RelocSectionReader(RelocSectionReader<'a>), +} + +macro_rules! section_reader { + ($self:ident, $ty_and_name:ident) => { + if let ParserSectionReader::$ty_and_name(ref mut reader) = $self.section_reader { + reader + } else { + panic!("expected {} reader", stringify!($ty_and_name)); + } + }; +} + +macro_rules! start_section_reader { + ($self:ident, $ty_and_name:ident, $factory:ident) => {{ + let reader = $self + .current_section + .as_ref() + .expect("section") + .$factory()?; + $self.section_entries_left = reader.get_count(); + $self.section_reader = ParserSectionReader::$ty_and_name(reader); + }}; +} + /// The `Parser` type. A simple event-driven parser of WebAssembly binary /// format. The `read(&mut self)` is used to iterate through WebAssembly records. pub struct Parser<'a> { - reader: BinaryReader<'a>, + data: &'a [u8], state: ParserState<'a>, - section_range: Option, - function_range: Option, + module_reader: Option>, + current_section: Option>, + section_reader: ParserSectionReader<'a>, + element_items: Option>, + current_function_body: Option>, init_expr_continuation: Option, - read_data_bytes: Option, + current_data_segment: Option<&'a [u8]>, + binary_reader: Option>, + operators_reader: Option>, section_entries_left: u32, } @@ -188,90 +222,122 @@ impl<'a> Parser<'a> { /// ``` pub fn new(data: &[u8]) -> Parser { Parser { - reader: BinaryReader::new(data), + data, state: ParserState::Initial, - section_range: None, - function_range: None, + module_reader: None, + current_section: None, + section_reader: ParserSectionReader::None, + element_items: None, + current_function_body: None, init_expr_continuation: None, - read_data_bytes: None, + current_data_segment: None, + binary_reader: None, + operators_reader: None, section_entries_left: 0, } } pub fn eof(&self) -> bool { - self.reader.eof() + match self.state { + ParserState::EndWasm => true, + ParserState::BeginWasm { .. } | ParserState::EndSection => { + self.module_reader.as_ref().expect("module reader").eof() + } + _ => false, // in-process of reading + } } pub fn current_position(&self) -> usize { - self.reader.current_position() + if let ParserState::Initial = self.state { + return 0; + } + if self.binary_reader.is_some() { + return self + .binary_reader + .as_ref() + .expect("binary reader") + .original_position(); + } + if self.operators_reader.is_some() { + return self + .operators_reader + .as_ref() + .expect("operators reader") + .original_position(); + } + match self.section_reader { + ParserSectionReader::CodeSectionReader(ref reader) => return reader.original_position(), + ParserSectionReader::DataSectionReader(ref reader) => return reader.original_position(), + ParserSectionReader::ElementSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::ExportSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::FunctionSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::GlobalSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::ImportSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::MemorySectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::TableSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::TypeSectionReader(ref reader) => return reader.original_position(), + ParserSectionReader::NameSectionReader(ref reader) => return reader.original_position(), + ParserSectionReader::LinkingSectionReader(ref reader) => { + return reader.original_position() + } + ParserSectionReader::RelocSectionReader(ref reader) => { + return reader.original_position() + } + _ => (), + }; + // TODO might not cover all cases + self.module_reader + .as_ref() + .expect("module reader") + .current_position() } - fn read_header(&mut self) -> Result<()> { - let version = self.reader.read_file_header()?; + fn read_module(&mut self) -> Result<()> { + let module_reader = ModuleReader::new(self.data)?; + let version = module_reader.get_version(); + self.module_reader = Some(module_reader); self.state = ParserState::BeginWasm { version }; Ok(()) } fn read_section_header(&mut self) -> Result<()> { - let SectionHeader { - code, - payload_start, - payload_len, - } = self.reader.read_section_header()?; - let payload_end = payload_start + payload_len; - if self.reader.buffer.len() < payload_end { - return Err(BinaryReaderError { - message: "Section body extends past end of file", - offset: self.reader.buffer.len(), - }); - } - if self.reader.position > payload_end { - return Err(BinaryReaderError { - message: "Section header is too big to fit into section body", - offset: payload_end, - }); - } - let range = Range { - start: self.reader.position, - end: payload_end, - }; + let section = self.module_reader.as_mut().expect("module reader").read()?; + let code = section.code; + let range = section.get_range(); + self.current_section = Some(section); self.state = ParserState::BeginSection { code, range }; - self.section_range = Some(range); Ok(()) } fn read_type_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - self.state = ParserState::TypeSectionEntry(self.reader.read_func_type()?); + let type_entry = section_reader!(self, TypeSectionReader).read()?; + self.state = ParserState::TypeSectionEntry(type_entry); self.section_entries_left -= 1; Ok(()) } fn read_import_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - let module = self.reader.read_string()?; - let field = self.reader.read_string()?; - let kind = self.reader.read_external_kind()?; - let ty: ImportSectionEntryType; - match kind { - ExternalKind::Function => { - ty = ImportSectionEntryType::Function(self.reader.read_var_u32()?) - } - ExternalKind::Table => { - ty = ImportSectionEntryType::Table(self.reader.read_table_type()?) - } - ExternalKind::Memory => { - ty = ImportSectionEntryType::Memory(self.reader.read_memory_type()?) - } - ExternalKind::Global => { - ty = ImportSectionEntryType::Global(self.reader.read_global_type()?) - } - } - + let Import { module, field, ty } = section_reader!(self, ImportSectionReader).read()?; self.state = ParserState::ImportSectionEntry { module, field, ty }; self.section_entries_left -= 1; Ok(()) @@ -279,27 +345,31 @@ impl<'a> Parser<'a> { fn read_function_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - self.state = ParserState::FunctionSectionEntry(self.reader.read_var_u32()?); + let func_type = section_reader!(self, FunctionSectionReader).read()?; + self.state = ParserState::FunctionSectionEntry(func_type); self.section_entries_left -= 1; Ok(()) } fn read_memory_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - self.state = ParserState::MemorySectionEntry(self.reader.read_memory_type()?); + let memory_type = section_reader!(self, MemorySectionReader).read()?; + self.state = ParserState::MemorySectionEntry(memory_type); self.section_entries_left -= 1; Ok(()) } fn read_global_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - self.state = ParserState::BeginGlobalSectionEntry(self.reader.read_global_type()?); + let Global { ty, init_expr } = section_reader!(self, GlobalSectionReader).read()?; + self.state = ParserState::BeginGlobalSectionEntry(ty); + self.operators_reader = Some(init_expr.get_operators_reader()); self.section_entries_left -= 1; Ok(()) } @@ -310,8 +380,13 @@ impl<'a> Parser<'a> { } fn read_init_expression_operator(&mut self) -> Result<()> { - let op = self.reader.read_operator()?; + let op = self + .operators_reader + .as_mut() + .expect("operator reader") + .read()?; if let Operator::End = op { + self.operators_reader = None; self.state = ParserState::EndInitExpressionBody; return Ok(()); } @@ -321,11 +396,9 @@ impl<'a> Parser<'a> { fn read_export_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - let field = self.reader.read_string()?; - let kind = self.reader.read_external_kind()?; - let index = self.reader.read_var_u32()?; + let Export { field, kind, index } = section_reader!(self, ExportSectionReader).read()?; self.state = ParserState::ExportSectionEntry { field, kind, index }; self.section_entries_left -= 1; Ok(()) @@ -333,24 +406,36 @@ impl<'a> Parser<'a> { fn read_element_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - self.state = ParserState::BeginElementSectionEntry(self.reader.read_var_u32()?); + let Element { + table_index, + init_expr, + items, + } = section_reader!(self, ElementSectionReader).read()?; + self.state = ParserState::BeginElementSectionEntry(table_index); + self.operators_reader = Some(init_expr.get_operators_reader()); + self.element_items = Some(items); self.section_entries_left -= 1; Ok(()) } fn read_element_entry_body(&mut self) -> Result<()> { - let num_elements = self.reader.read_var_u32()? as usize; + let mut reader = self + .element_items + .take() + .expect("element items") + .get_items_reader()?; + let num_elements = reader.get_count() as usize; if num_elements > MAX_WASM_TABLE_ENTRIES { return Err(BinaryReaderError { message: "num_elements is out of bounds", - offset: self.reader.position - 1, + offset: 0, // reader.position - 1, // TODO offset }); } let mut elements: Vec = Vec::with_capacity(num_elements); for _ in 0..num_elements { - elements.push(self.reader.read_var_u32()?); + elements.push(reader.read()?); } self.state = ParserState::ElementSectionEntryBody(elements.into_boxed_slice()); Ok(()) @@ -358,28 +443,47 @@ impl<'a> Parser<'a> { fn read_function_body(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + self.current_function_body = None; + return self.check_section_end(); } - let size = self.reader.read_var_u32()? as usize; - let body_end = self.reader.position + size; - let range = Range { - start: self.reader.position, - end: body_end, - }; + let function_body = section_reader!(self, CodeSectionReader).read()?; + let range = function_body.get_range(); self.state = ParserState::BeginFunctionBody { range }; - self.function_range = Some(range); + self.current_function_body = Some(function_body); self.section_entries_left -= 1; Ok(()) } fn read_function_body_locals(&mut self) -> Result<()> { - let local_count = self.reader.read_local_count()?; + let function_body = self.current_function_body.as_mut().expect("function body"); + let mut reader = function_body.get_locals_reader()?; + let local_count = reader.get_count() as usize; + if local_count > MAX_WASM_FUNCTION_LOCALS { + return Err(BinaryReaderError { + message: "local_count is out of bounds", + offset: reader.original_position() - 1, + }); + } let mut locals: Vec<(u32, Type)> = Vec::with_capacity(local_count); - let mut locals_total = 0; + let mut locals_total: usize = 0; for _ in 0..local_count { - let (count, ty) = self.reader.read_local_decl(&mut locals_total)?; + let (count, ty) = reader.read()?; + locals_total = + locals_total + .checked_add(count as usize) + .ok_or_else(|| BinaryReaderError { + message: "locals_total is out of bounds", + offset: reader.original_position() - 1, + })?; + if locals_total > MAX_WASM_FUNCTION_LOCALS { + return Err(BinaryReaderError { + message: "locals_total is out of bounds", + offset: reader.original_position() - 1, + }); + } locals.push((count, ty)); } + self.operators_reader = Some(function_body.get_operators_reader()?); self.state = ParserState::FunctionBodyLocals { locals: locals.into_boxed_slice(), }; @@ -387,72 +491,107 @@ impl<'a> Parser<'a> { } fn read_code_operator(&mut self) -> Result<()> { - if self.reader.position >= self.function_range.unwrap().end { + if self + .operators_reader + .as_ref() + .expect("operator reader") + .eof() + { if let ParserState::CodeOperator(Operator::End) = self.state { self.state = ParserState::EndFunctionBody; - self.function_range = None; + self.operators_reader = None; + self.current_function_body = None; return Ok(()); } + let reader = self.operators_reader.as_ref().expect("operator reader"); return Err(BinaryReaderError { message: "Expected end of function marker", - offset: self.function_range.unwrap().end, + offset: reader.original_position(), }); } - let op = self.reader.read_operator()?; + let reader = self.operators_reader.as_mut().expect("operator reader"); + let op = reader.read()?; self.state = ParserState::CodeOperator(op); Ok(()) } fn read_table_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - self.state = ParserState::TableSectionEntry(self.reader.read_table_type()?); + let table_entry = section_reader!(self, TableSectionReader).read()?; + self.state = ParserState::TableSectionEntry(table_entry); self.section_entries_left -= 1; Ok(()) } fn read_data_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - let index = self.reader.read_var_u32()?; - self.state = ParserState::BeginDataSectionEntry(index); + let Data { + memory_index, + init_expr, + data, + } = section_reader!(self, DataSectionReader).read()?; + self.state = ParserState::BeginDataSectionEntry(memory_index); + self.operators_reader = Some(init_expr.get_operators_reader()); + self.current_data_segment = Some(data); self.section_entries_left -= 1; Ok(()) } fn read_data_entry_body(&mut self) -> Result<()> { - let size = self.reader.read_var_u32()?; - self.state = ParserState::BeginDataSectionEntryBody(size); - self.read_data_bytes = Some(size); + let size = self.current_data_segment.expect("data entry").len(); + self.state = ParserState::BeginDataSectionEntryBody(size as u32); Ok(()) } + fn read_naming<'b>( + mut naming_reader: NamingReader<'a>, + limit: usize, + ) -> Result]>> + where + 'a: 'b, + { + let count = naming_reader.get_count() as usize; + if count > limit { + return Err(BinaryReaderError { + message: "name map size is out of bound", + offset: naming_reader.original_position() - 1, + }); + } + let mut result = Vec::with_capacity(count); + for _ in 0..count { + result.push(naming_reader.read()?); + } + Ok(result.into_boxed_slice()) + } + fn read_name_entry(&mut self) -> Result<()> { - if self.reader.position >= self.section_range.unwrap().end { + if section_reader!(self, NameSectionReader).eof() { return self.position_to_section_end(); } - let ty = self.reader.read_name_type()?; - self.reader.read_var_u32()?; // payload_len - let entry = match ty { - NameType::Module => NameEntry::Module(self.reader.read_string()?), - NameType::Function => { - NameEntry::Function(self.reader.read_name_map(MAX_WASM_FUNCTIONS)?) + let entry = match section_reader!(self, NameSectionReader).read()? { + Name::Module(name) => NameEntry::Module(name.get_name()?), + Name::Function(func) => { + NameEntry::Function(Self::read_naming(func.get_map()?, MAX_WASM_FUNCTIONS)?) } - NameType::Local => { - let funcs_len = self.reader.read_var_u32()? as usize; + Name::Local(locals) => { + let mut reader = locals.get_function_local_reader()?; + let funcs_len = reader.get_count() as usize; if funcs_len > MAX_WASM_FUNCTIONS { return Err(BinaryReaderError { message: "function count is out of bounds", - offset: self.reader.position - 1, + offset: reader.original_position() - 1, }); } let mut funcs: Vec> = Vec::with_capacity(funcs_len); for _ in 0..funcs_len { + let func = reader.read()?; funcs.push(LocalName { - index: self.reader.read_var_u32()?, - locals: self.reader.read_name_map(MAX_WASM_FUNCTION_LOCALS)?, + index: func.func_index, + locals: Self::read_naming(func.get_map()?, MAX_WASM_FUNCTION_LOCALS)?, }); } NameEntry::Local(funcs.into_boxed_slice()) @@ -463,38 +602,32 @@ impl<'a> Parser<'a> { } fn read_source_mapping(&mut self) -> Result<()> { - self.state = ParserState::SourceMappingURL(self.reader.read_string()?); + let url = self + .current_section + .as_ref() + .expect("section") + .get_sourcemappingurl_section_content()?; + self.state = ParserState::SourceMappingURL(url); Ok(()) } // See https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md fn read_reloc_header(&mut self) -> Result<()> { - let section_id_position = self.reader.position; - let section_id = self.reader.read_var_u7()?; - let section_code = self - .reader - .read_section_code(section_id, section_id_position)?; + let section_code = section_reader!(self, RelocSectionReader).get_section_code(); self.state = ParserState::RelocSectionHeader(section_code); Ok(()) } fn read_reloc_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - let ty = self.reader.read_reloc_type()?; - let offset = self.reader.read_var_u32()?; - let index = self.reader.read_var_u32()?; - let addend = match ty { - RelocType::FunctionIndexLEB - | RelocType::TableIndexSLEB - | RelocType::TableIndexI32 - | RelocType::TypeIndexLEB - | RelocType::GlobalIndexLEB => None, - RelocType::GlobalAddrLEB | RelocType::GlobalAddrSLEB | RelocType::GlobalAddrI32 => { - Some(self.reader.read_var_u32()?) - } - }; + let Reloc { + ty, + offset, + index, + addend, + } = section_reader!(self, RelocSectionReader).read()?; self.state = ParserState::RelocSectionEntry(RelocEntry { ty, offset, @@ -507,9 +640,9 @@ impl<'a> Parser<'a> { fn read_linking_entry(&mut self) -> Result<()> { if self.section_entries_left == 0 { - return self.position_to_section_end(); + return self.check_section_end(); } - let entry = self.reader.read_linking_type()?; + let entry = section_reader!(self, LinkingSectionReader).read()?; self.state = ParserState::LinkingSectionEntry(entry); self.section_entries_left -= 1; Ok(()) @@ -521,82 +654,88 @@ impl<'a> Parser<'a> { code: SectionCode::Type, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, TypeSectionReader, get_type_section_reader); self.read_type_entry()?; } ParserState::BeginSection { code: SectionCode::Import, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, ImportSectionReader, get_import_section_reader); self.read_import_entry()?; } ParserState::BeginSection { code: SectionCode::Function, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, FunctionSectionReader, get_function_section_reader); self.read_function_entry()?; } ParserState::BeginSection { code: SectionCode::Memory, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, MemorySectionReader, get_memory_section_reader); self.read_memory_entry()?; } ParserState::BeginSection { code: SectionCode::Global, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, GlobalSectionReader, get_global_section_reader); self.read_global_entry()?; } ParserState::BeginSection { code: SectionCode::Export, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, ExportSectionReader, get_export_section_reader); self.read_export_entry()?; } ParserState::BeginSection { code: SectionCode::Element, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, ElementSectionReader, get_element_section_reader); self.read_element_entry()?; } ParserState::BeginSection { code: SectionCode::Code, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, CodeSectionReader, get_code_section_reader); self.read_function_body()?; } ParserState::BeginSection { code: SectionCode::Table, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, TableSectionReader, get_table_section_reader); self.read_table_entry()?; } ParserState::BeginSection { code: SectionCode::Data, .. } => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, DataSectionReader, get_data_section_reader); self.read_data_entry()?; } ParserState::BeginSection { code: SectionCode::Start, .. } => { - self.state = ParserState::StartSectionEntry(self.reader.read_var_u32()?); + let func_index = self + .current_section + .as_ref() + .expect("section") + .get_start_section_content()?; + self.state = ParserState::StartSectionEntry(func_index); } ParserState::BeginSection { code: SectionCode::Custom { .. }, .. } => { + self.create_custom_section_binary_reader(); self.read_section_body_bytes()?; } _ => unreachable!(), @@ -604,22 +743,39 @@ impl<'a> Parser<'a> { Ok(()) } + fn create_custom_section_binary_reader(&mut self) { + let reader = self + .current_section + .as_ref() + .expect("section") + .get_binary_reader(); + self.binary_reader = Some(reader); + } + fn read_custom_section_body(&mut self) -> Result<()> { match self.state { ParserState::ReadingCustomSection(CustomSectionKind::Name) => { + let reader = self + .current_section + .as_ref() + .expect("section") + .get_name_section_reader()?; + self.section_reader = ParserSectionReader::NameSectionReader(reader); self.read_name_entry()?; } ParserState::ReadingCustomSection(CustomSectionKind::SourceMappingURL) => { self.read_source_mapping()?; } ParserState::ReadingCustomSection(CustomSectionKind::Reloc) => { + start_section_reader!(self, RelocSectionReader, get_reloc_section_reader); self.read_reloc_header()?; } ParserState::ReadingCustomSection(CustomSectionKind::Linking) => { - self.section_entries_left = self.reader.read_var_u32()?; + start_section_reader!(self, LinkingSectionReader, get_linking_section_reader); self.read_linking_entry()?; } ParserState::ReadingCustomSection(CustomSectionKind::Unknown) => { + self.create_custom_section_binary_reader(); self.read_section_body_bytes()?; } _ => unreachable!(), @@ -627,61 +783,70 @@ impl<'a> Parser<'a> { Ok(()) } - fn ensure_reader_position_in_section_range(&self) -> Result<()> { - if self.section_range.unwrap().end < self.reader.position { - return Err(BinaryReaderError { - message: "Position past the section end", - offset: self.section_range.unwrap().end, - }); - } - Ok(()) - } - fn position_to_section_end(&mut self) -> Result<()> { - self.ensure_reader_position_in_section_range()?; - self.reader.skip_to(self.section_range.unwrap().end); - self.section_range = None; + self.current_section = None; + self.binary_reader = None; self.state = ParserState::EndSection; Ok(()) } + fn check_section_end(&mut self) -> Result<()> { + match self.section_reader { + ParserSectionReader::CodeSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::DataSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::ElementSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::ExportSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::FunctionSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::GlobalSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::ImportSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::MemorySectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::TableSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::TypeSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::LinkingSectionReader(ref reader) => reader.ensure_end()?, + ParserSectionReader::RelocSectionReader(ref reader) => reader.ensure_end()?, + _ => unreachable!(), + } + self.position_to_section_end() + } + fn read_section_body_bytes(&mut self) -> Result<()> { - self.ensure_reader_position_in_section_range()?; - if self.section_range.unwrap().end == self.reader.position { + if self.binary_reader.as_ref().expect("binary reader").eof() { self.state = ParserState::EndSection; - self.section_range = None; + self.binary_reader = None; return Ok(()); } - let to_read = - if self.section_range.unwrap().end - self.reader.position < MAX_DATA_CHUNK_SIZE { - self.section_range.unwrap().end - self.reader.position - } else { - MAX_DATA_CHUNK_SIZE - }; - let bytes = self.reader.read_bytes(to_read)?; + let binary_reader = self.binary_reader.as_mut().expect("binary reader"); + let to_read = if binary_reader.buffer.len() - binary_reader.position < MAX_DATA_CHUNK_SIZE { + binary_reader.buffer.len() - binary_reader.position + } else { + MAX_DATA_CHUNK_SIZE + }; + let bytes = binary_reader.read_bytes(to_read)?; self.state = ParserState::SectionRawData(bytes); Ok(()) } fn read_data_chunk(&mut self) -> Result<()> { - if self.read_data_bytes.unwrap() == 0 { + let data = self.current_data_segment.expect("data"); + if data.len() == 0 { self.state = ParserState::EndDataSectionEntryBody; - self.read_data_bytes = None; + self.current_data_segment = None; return Ok(()); } - let to_read = if self.read_data_bytes.unwrap() as usize > MAX_DATA_CHUNK_SIZE { + let to_read = if data.len() > MAX_DATA_CHUNK_SIZE { MAX_DATA_CHUNK_SIZE } else { - self.read_data_bytes.unwrap() as usize + data.len() }; - let chunk = self.reader.read_bytes(to_read)?; - *self.read_data_bytes.as_mut().unwrap() -= to_read as u32; - self.state = ParserState::DataSectionEntryBodyChunk(chunk); + let (head, tail) = data.split_at(to_read); + self.current_data_segment = Some(tail); + self.state = ParserState::DataSectionEntryBodyChunk(head); Ok(()) } fn read_next_section(&mut self) -> Result<()> { - if self.reader.eof() { + if self.module_reader.as_ref().expect("module_reader").eof() { + self.current_section = None; self.state = ParserState::EndWasm; } else { self.read_section_header()?; @@ -693,7 +858,7 @@ impl<'a> Parser<'a> { match self.state { ParserState::EndWasm => panic!("Parser in end state"), ParserState::Error(_) => panic!("Parser in error state"), - ParserState::Initial => self.read_header()?, + ParserState::Initial => self.read_module()?, ParserState::BeginWasm { .. } | ParserState::EndSection => self.read_next_section()?, ParserState::BeginSection { .. } => self.read_section_body()?, ParserState::SkippingSection => { @@ -738,9 +903,7 @@ impl<'a> Parser<'a> { } ParserState::EndFunctionBody => self.read_function_body()?, ParserState::SkippingFunctionBody => { - assert!(self.reader.position <= self.function_range.unwrap().end); - self.reader.skip_to(self.function_range.unwrap().end); - self.function_range = None; + self.current_function_body = None; self.read_function_body()?; } ParserState::EndDataSectionEntry => self.read_data_entry()?, @@ -757,7 +920,13 @@ impl<'a> Parser<'a> { ParserState::NameSectionEntry(_) => self.read_name_entry()?, ParserState::SourceMappingURL(_) => self.position_to_section_end()?, ParserState::RelocSectionHeader(_) => { - self.section_entries_left = self.reader.read_var_u32()?; + let mut reader = self + .current_section + .as_ref() + .expect("section") + .get_binary_reader(); + self.section_entries_left = reader.read_var_u32()?; + self.binary_reader = Some(reader); self.read_reloc_entry()?; } ParserState::RelocSectionEntry(_) => self.read_reloc_entry()?, @@ -804,7 +973,15 @@ impl<'a> Parser<'a> { fn read_raw_section_data(&mut self) { match self.state { - ParserState::BeginSection { .. } => self.state = ParserState::ReadingSectionRawData, + ParserState::BeginSection { .. } => { + self.binary_reader = Some( + self.current_section + .as_ref() + .expect("section") + .get_binary_reader(), + ); + self.state = ParserState::ReadingSectionRawData; + } _ => panic!("Invalid reader state during reading raw section data"), } } @@ -884,19 +1061,19 @@ impl<'a> WasmDecoder<'a> for Parser<'a> { where 'a: 'b, { - let range; match self.state { - ParserState::BeginSection { .. } => { - range = self.section_range.unwrap(); - self.skip_section(); - } - ParserState::BeginFunctionBody { .. } | ParserState::FunctionBodyLocals { .. } => { - range = self.function_range.unwrap(); - self.skip_function_body(); - } + ParserState::BeginSection { .. } => self + .current_section + .as_ref() + .expect("section") + .get_binary_reader(), + ParserState::BeginFunctionBody { .. } | ParserState::FunctionBodyLocals { .. } => self + .current_function_body + .as_ref() + .expect("function body") + .get_binary_reader(), _ => panic!("Invalid reader state during get binary reader operation"), - }; - BinaryReader::new(range.slice(self.reader.buffer)) + } } /// Reads next record from the WebAssembly binary data. It also allows to diff --git a/third_party/rust/wasmparser/src/readers/code_section.rs b/third_party/rust/wasmparser/src/readers/code_section.rs index 05bc5ac47c2e..17f173b8e75a 100644 --- a/third_party/rust/wasmparser/src/readers/code_section.rs +++ b/third_party/rust/wasmparser/src/readers/code_section.rs @@ -14,7 +14,7 @@ */ use super::{ - BinaryReader, BinaryReaderError, OperatorsReader, Result, SectionIteratorLimited, + BinaryReader, BinaryReaderError, OperatorsReader, Range, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, Type, }; @@ -63,6 +63,13 @@ impl<'a> FunctionBody<'a> { let pos = reader.position; Ok(OperatorsReader::new(&self.data[pos..], self.offset + pos)) } + + pub(crate) fn get_range(&self) -> Range { + Range { + start: self.offset, + end: self.offset + self.data.len(), + } + } } pub struct LocalsReader<'a> { @@ -75,6 +82,10 @@ impl<'a> LocalsReader<'a> { self.count } + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + pub fn read(&mut self) -> Result<(u32, Type)> { let count = self.reader.read_var_u32()?; let value_type = self.reader.read_type()?; diff --git a/third_party/rust/wasmparser/src/readers/mod.rs b/third_party/rust/wasmparser/src/readers/mod.rs index 8fd5bce896e2..8d7ce2c01f8a 100644 --- a/third_party/rust/wasmparser/src/readers/mod.rs +++ b/third_party/rust/wasmparser/src/readers/mod.rs @@ -15,8 +15,8 @@ use super::{ BinaryReader, BinaryReaderError, CustomSectionKind, ExternalKind, FuncType, GlobalType, - ImportSectionEntryType, LinkingType, MemoryType, NameType, Naming, Operator, RelocType, Result, - SectionCode, TableType, Type, + ImportSectionEntryType, LinkingType, MemoryType, NameType, Naming, Operator, Range, RelocType, + Result, SectionCode, TableType, Type, }; use super::SectionHeader; diff --git a/third_party/rust/wasmparser/src/readers/module.rs b/third_party/rust/wasmparser/src/readers/module.rs index 0ee52c69844c..d0871fe22940 100644 --- a/third_party/rust/wasmparser/src/readers/module.rs +++ b/third_party/rust/wasmparser/src/readers/module.rs @@ -16,7 +16,7 @@ use std::iter::{IntoIterator, Iterator}; use super::{ - BinaryReader, BinaryReaderError, CustomSectionKind, Result, SectionCode, SectionHeader, + BinaryReader, BinaryReaderError, CustomSectionKind, Range, Result, SectionCode, SectionHeader, }; use super::{ @@ -219,6 +219,13 @@ impl<'a> Section<'a> { { BinaryReader::new_with_offset(self.data, self.offset) } + + pub(crate) fn get_range(&self) -> Range { + Range { + start: self.offset, + end: self.offset + self.data.len(), + } + } } /// Reads top-level WebAssembly file structure: header and sections. diff --git a/third_party/rust/wasmparser/src/readers/operators.rs b/third_party/rust/wasmparser/src/readers/operators.rs index 20080820c17d..0de5ce86bfd8 100644 --- a/third_party/rust/wasmparser/src/readers/operators.rs +++ b/third_party/rust/wasmparser/src/readers/operators.rs @@ -33,6 +33,10 @@ impl<'a> OperatorsReader<'a> { self.reader.eof() } + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + pub fn ensure_end(&self) -> Result<()> { if self.eof() { return Ok(()); @@ -49,6 +53,24 @@ impl<'a> OperatorsReader<'a> { { self.reader.read_operator() } + + pub fn into_iter_with_offsets<'b>(self) -> OperatorsIteratorWithOffsets<'b> + where + 'a: 'b, + { + OperatorsIteratorWithOffsets { + reader: self, + err: false, + } + } + + pub fn read_with_offset<'b>(&mut self) -> Result<(Operator<'b>, usize)> + where + 'a: 'b, + { + let pos = self.reader.original_position(); + Ok((self.read()?, pos)) + } } impl<'a> IntoIterator for OperatorsReader<'a> { @@ -104,3 +126,45 @@ impl<'a> Iterator for OperatorsIterator<'a> { Some(result) } } + +pub struct OperatorsIteratorWithOffsets<'a> { + reader: OperatorsReader<'a>, + err: bool, +} + +impl<'a> Iterator for OperatorsIteratorWithOffsets<'a> { + type Item = Result<(Operator<'a>, usize)>; + + /// Reads content of the code section with offsets. + /// + /// # Examples + /// ``` + /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, + /// # 0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, + /// # 0x0a, 0x05, 0x01, 0x03, 0x00, /* offset = 23 */ 0x01, 0x0b]; + /// use wasmparser::{ModuleReader, Result, Operator}; + /// let mut reader = ModuleReader::new(data).expect("module reader"); + /// let section = reader.read().expect("type section"); + /// let section = reader.read().expect("function section"); + /// let section = reader.read().expect("code section"); + /// let mut code_reader = section.get_code_section_reader().expect("code section reader"); + /// for _ in 0..code_reader.get_count() { + /// let body = code_reader.read().expect("function body"); + /// let mut op_reader = body.get_operators_reader().expect("op reader"); + /// let ops = op_reader.into_iter_with_offsets().collect::>>().expect("ops"); + /// assert!( + /// if let [(Operator::Nop, 23), (Operator::End, 24)] = ops.as_slice() { true } else { false }, + /// "found {:?}", + /// ops + /// ); + /// } + /// ``` + fn next(&mut self) -> Option { + if self.err || self.reader.eof() { + return None; + } + let result = self.reader.read_with_offset(); + self.err = result.is_err(); + Some(result) + } +} diff --git a/third_party/rust/wasmparser/src/validator.rs b/third_party/rust/wasmparser/src/validator.rs index 0592edd5c054..532de8ac88fe 100644 --- a/third_party/rust/wasmparser/src/validator.rs +++ b/third_party/rust/wasmparser/src/validator.rs @@ -173,15 +173,20 @@ enum OperatorAction { } impl OperatorAction { - fn remove_frame_stack_types(func_state: &mut FuncState, remove_count: usize) { + fn remove_frame_stack_types( + func_state: &mut FuncState, + remove_count: usize, + ) -> OperatorValidatorResult<()> { if remove_count == 0 { - return; + return Ok(()); } let last_block = func_state.blocks.last_mut().unwrap(); if last_block.is_stack_polymorphic() { let len = func_state.stack_types.len(); - let non_polymorphic_len = len - last_block.stack_starts_at; - let remove_non_polymorphic = min(non_polymorphic_len, remove_count); + let remove_non_polymorphic = len + .checked_sub(last_block.stack_starts_at) + .ok_or("invalid block signature")? + .min(remove_count); func_state .stack_types .truncate(len - remove_non_polymorphic); @@ -193,8 +198,9 @@ impl OperatorAction { let keep = func_state.stack_types.len() - remove_count; func_state.stack_types.truncate(keep); } + Ok(()) } - fn update(&self, func_state: &mut FuncState) { + fn update(&self, func_state: &mut FuncState) -> OperatorValidatorResult<()> { match *self { OperatorAction::None => (), OperatorAction::PushBlock(ty, block_type) => { @@ -244,16 +250,16 @@ impl OperatorAction { last_block.polymorphic_values = None; } OperatorAction::ChangeFrame(remove_count) => { - OperatorAction::remove_frame_stack_types(func_state, remove_count); + OperatorAction::remove_frame_stack_types(func_state, remove_count)? } OperatorAction::ChangeFrameWithType(remove_count, ty) => { - OperatorAction::remove_frame_stack_types(func_state, remove_count); + OperatorAction::remove_frame_stack_types(func_state, remove_count)?; func_state.stack_types.push(ty); } OperatorAction::ChangeFrameWithTypes(remove_count, ref new_items) => { - OperatorAction::remove_frame_stack_types(func_state, remove_count); + OperatorAction::remove_frame_stack_types(func_state, remove_count)?; if new_items.is_empty() { - return; + return Ok(()); } func_state.stack_types.extend_from_slice(new_items); } @@ -265,15 +271,15 @@ impl OperatorAction { last_block.polymorphic_values = None; } OperatorAction::ChangeFrameAfterSelect(ty) => { - OperatorAction::remove_frame_stack_types(func_state, 3); + OperatorAction::remove_frame_stack_types(func_state, 3)?; if ty.is_none() { let last_block = func_state.blocks.last_mut().unwrap(); assert!(last_block.is_stack_polymorphic()); last_block.polymorphic_values = Some(last_block.polymorphic_values.unwrap() + 1); - return; + return Ok(()); } - func_state.stack_types.push(ty.unwrap()) + func_state.stack_types.push(ty.unwrap()); } OperatorAction::DeadCode => { let last_block = func_state.blocks.last_mut().unwrap(); @@ -286,6 +292,7 @@ impl OperatorAction { func_state.end_function = true; } } + Ok(()) } } @@ -562,7 +569,12 @@ impl OperatorValidator { self.check_frame_size(func_state, 3)?; let last_block = func_state.last_block(); Ok(if last_block.is_stack_polymorphic() { - match func_state.stack_types.len() - last_block.stack_starts_at { + match func_state + .stack_types + .len() + .checked_sub(last_block.stack_starts_at) + .ok_or("invalid block signature")? + { 0 => None, 1 => { self.check_operands_1(func_state, Type::I32)?; @@ -1697,11 +1709,17 @@ impl<'a> ValidatingParser<'a> { .as_ref() .unwrap() .process_operator(operator, self); - if check.is_err() { - self.validation_error = self.create_validation_error(check.err().unwrap()); - } else { - let action = check.ok().unwrap(); - action.update(&mut self.current_operator_validator.as_mut().unwrap().func_state) + match check { + Ok(action) => { + if let Err(err) = action.update( + &mut self.current_operator_validator.as_mut().unwrap().func_state, + ) { + self.create_validation_error(err); + } + } + Err(err) => { + self.validation_error = self.create_validation_error(err); + } } } ParserState::EndFunctionBody => { diff --git a/toolkit/components/ctypes/ctypes.cpp b/toolkit/components/ctypes/ctypes.cpp index 5beb18eb6711..1d612841441a 100644 --- a/toolkit/components/ctypes/ctypes.cpp +++ b/toolkit/components/ctypes/ctypes.cpp @@ -5,6 +5,7 @@ #include "ctypes.h" #include "jsapi.h" +#include "js/MemoryFunctions.h" #include "mozilla/ModuleUtils.h" #include "nsMemory.h" #include "nsString.h" diff --git a/toolkit/components/osfile/NativeOSFileInternals.cpp b/toolkit/components/osfile/NativeOSFileInternals.cpp index 2054d760f998..671f32b025bd 100644 --- a/toolkit/components/osfile/NativeOSFileInternals.cpp +++ b/toolkit/components/osfile/NativeOSFileInternals.cpp @@ -37,6 +37,7 @@ #include "jsapi.h" #include "jsfriendapi.h" #include "js/Conversions.h" +#include "js/MemoryFunctions.h" #include "js/Utility.h" #include "xpcpublic.h" diff --git a/tools/tryselect/docs/selectors/fuzzy.rst b/tools/tryselect/docs/selectors/fuzzy.rst index 44142daa4a8d..caedb9114214 100644 --- a/tools/tryselect/docs/selectors/fuzzy.rst +++ b/tools/tryselect/docs/selectors/fuzzy.rst @@ -100,7 +100,7 @@ Would produce the following ``try_task_config.json``: { "templates":{ "env":{ - "MOZHARNESS_TEST_PATHS":"layout/reftests/reftest-sanity" + "MOZHARNESS_TEST_PATHS":"{\"reftest\":\"layout/reftests/reftest-sanity\"}" } }, "tasks":[ diff --git a/tools/tryselect/selectors/coverage.py b/tools/tryselect/selectors/coverage.py index 92642bd9bec9..ae17a38707d3 100644 --- a/tools/tryselect/selectors/coverage.py +++ b/tools/tryselect/selectors/coverage.py @@ -22,7 +22,7 @@ from moztest.resolve import TestResolver from mozversioncontrol import get_repository_object from ..cli import BaseTryParser -from ..tasks import generate_tasks, filter_tasks_by_paths +from ..tasks import generate_tasks, filter_tasks_by_paths, resolve_tests_by_suite from ..push import push_to_try here = os.path.abspath(os.path.dirname(__file__)) @@ -375,7 +375,7 @@ def run_coverage_try(templates={}, full=False, parameters=None, print('Found ' + test_count_message) # Set the test paths to be run by setting MOZHARNESS_TEST_PATHS. - path_env = {'MOZHARNESS_TEST_PATHS': ':'.join(test_files)} + path_env = {'MOZHARNESS_TEST_PATHS': json.dumps(resolve_tests_by_suite(test_files))} templates.setdefault('env', {}).update(path_env) # Build commit message. diff --git a/tools/tryselect/tasks.py b/tools/tryselect/tasks.py index c17fce5dfc39..f4dc1dd9a4d8 100644 --- a/tools/tryselect/tasks.py +++ b/tools/tryselect/tasks.py @@ -11,6 +11,7 @@ import os import re import shutil import sys +from collections import defaultdict from mozboot.util import get_state_dir from mozbuild.base import MozbuildObject @@ -120,3 +121,18 @@ def filter_tasks_by_paths(tasks, paths): return any(re.search(pattern, task) for pattern in task_regexes) return filter(match_task, tasks) + + +def resolve_tests_by_suite(paths): + resolver = TestResolver.from_environment(cwd=here) + _, run_tests = resolver.resolve_metadata(paths) + + suite_to_tests = defaultdict(list) + for test in run_tests: + key = test['flavor'] + subsuite = test.get('subsuite') + if subsuite: + key += '-' + subsuite + suite_to_tests[key].append(test['srcdir_relpath']) + + return suite_to_tests diff --git a/tools/tryselect/templates.py b/tools/tryselect/templates.py index c737ea9a562a..09a5e81eed2e 100644 --- a/tools/tryselect/templates.py +++ b/tools/tryselect/templates.py @@ -9,6 +9,7 @@ tasks. They live under taskcluster/taskgraph/templates. from __future__ import absolute_import, print_function, unicode_literals +import json import os import sys from abc import ABCMeta, abstractmethod @@ -16,6 +17,7 @@ from argparse import Action, SUPPRESS import mozpack.path as mozpath from mozbuild.base import BuildEnvironmentNotFoundException, MozbuildObject +from .tasks import resolve_tests_by_suite here = os.path.abspath(os.path.dirname(__file__)) build = MozbuildObject.from_environment(cwd=here) @@ -79,8 +81,7 @@ class Path(Template): paths = [mozpath.relpath(mozpath.join(os.getcwd(), p), build.topsrcdir) for p in paths] return { 'env': { - # can't use os.pathsep as machine splitting could be a different platform - 'MOZHARNESS_TEST_PATHS': ':'.join(paths), + 'MOZHARNESS_TEST_PATHS': json.dumps(resolve_tests_by_suite(paths)), } } diff --git a/tools/tryselect/test/conftest.py b/tools/tryselect/test/conftest.py index 4428f2c739a9..20d576c8b32c 100644 --- a/tools/tryselect/test/conftest.py +++ b/tools/tryselect/test/conftest.py @@ -4,10 +4,20 @@ from __future__ import absolute_import, print_function, unicode_literals +from moztest.resolve import TestResolver from mozversioncontrol import HgRepository, GitRepository import pytest +@pytest.fixture +def patch_resolver(monkeypatch): + def inner(suites, tests): + def fake_test_metadata(*args, **kwargs): + return suites, tests + monkeypatch.setattr(TestResolver, 'resolve_metadata', fake_test_metadata) + return inner + + @pytest.fixture(autouse=True) def patch_vcs(monkeypatch, tmpdir): # Make sure we don't accidentally push to try diff --git a/tools/tryselect/test/test_tasks.py b/tools/tryselect/test/test_tasks.py index c73f567e67cc..9e01f5cceda8 100644 --- a/tools/tryselect/test/test_tasks.py +++ b/tools/tryselect/test/test_tasks.py @@ -5,19 +5,8 @@ from __future__ import absolute_import, print_function, unicode_literals import mozunit -import pytest -from moztest.resolve import TestResolver -from tryselect.tasks import filter_tasks_by_paths - - -@pytest.fixture -def patch_resolver(monkeypatch): - def inner(suites, tests): - def fake_test_metadata(*args, **kwargs): - return suites, tests - monkeypatch.setattr(TestResolver, 'resolve_metadata', fake_test_metadata) - return inner +from tryselect.tasks import filter_tasks_by_paths, resolve_tests_by_suite def test_filter_tasks_by_paths(patch_resolver): @@ -30,5 +19,21 @@ def test_filter_tasks_by_paths(patch_resolver): assert filter_tasks_by_paths(tasks, 'dummy') == ['foobar/xpcshell-1', 'foobar/xpcshell'] +def test_resolve_tests_by_suite(patch_resolver): + patch_resolver([], [{'flavor': 'xpcshell', 'srcdir_relpath': 'xpcshell.js'}]) + assert resolve_tests_by_suite(['xpcshell.js']) == { + 'xpcshell': ['xpcshell.js'], + } + + patch_resolver([], [ + {'flavor': 'xpcshell', 'srcdir_relpath': 'xpcshell.js'}, + {'flavor': 'mochitest', 'srcdir_relpath': 'mochitest.js'}, + ]) + assert resolve_tests_by_suite(['xpcshell.js', 'mochitest.js']) == { + 'xpcshell': ['xpcshell.js'], + 'mochitest': ['mochitest.js'], + } + + if __name__ == '__main__': mozunit.main() diff --git a/tools/tryselect/test/test_templates.py b/tools/tryselect/test/test_templates.py index bf0895090960..87a7f4eec7a9 100644 --- a/tools/tryselect/test/test_templates.py +++ b/tools/tryselect/test/test_templates.py @@ -29,9 +29,9 @@ TEMPLATE_TESTS = { ], 'path': [ ([], None), - (['dom/indexedDB'], {'env': {'MOZHARNESS_TEST_PATHS': 'dom/indexedDB'}}), + (['dom/indexedDB'], {'env': {'MOZHARNESS_TEST_PATHS': '{"xpcshell": ["dom/indexedDB"]}'}}), (['dom/indexedDB', 'testing'], - {'env': {'MOZHARNESS_TEST_PATHS': 'dom/indexedDB:testing'}}), + {'env': {'MOZHARNESS_TEST_PATHS': '{"xpcshell": ["dom/indexedDB", "testing"]}'}}), (['invalid/path'], SystemExit), ], 'rebuild': [ @@ -49,7 +49,14 @@ TEMPLATE_TESTS = { } -def test_templates(template, args, expected): +@pytest.fixture +def template_patch_resolver(patch_resolver): + def inner(paths): + patch_resolver([], [{'flavor': 'xpcshell', 'srcdir_relpath': path} for path in paths]) + return inner + + +def test_templates(template_patch_resolver, template, args, expected): parser = ArgumentParser() t = all_templates[template]() @@ -58,9 +65,13 @@ def test_templates(template, args, expected): if inspect.isclass(expected) and issubclass(expected, BaseException): with pytest.raises(expected): args = parser.parse_args(args) + if template == 'path': + template_patch_resolver(**vars(args)) t.context(**vars(args)) else: args = parser.parse_args(args) + if template == 'path': + template_patch_resolver(**vars(args)) assert t.context(**vars(args)) == expected diff --git a/xpcom/reflect/xptinfo/xptinfo.cpp b/xpcom/reflect/xptinfo/xptinfo.cpp index f399dae7afa5..56ee4090834d 100644 --- a/xpcom/reflect/xptinfo/xptinfo.cpp +++ b/xpcom/reflect/xptinfo/xptinfo.cpp @@ -10,6 +10,7 @@ #include "mozilla/ArrayUtils.h" #include "jsfriendapi.h" +#include "js/Symbol.h" using namespace mozilla; using namespace mozilla::dom; diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h index a8a9ba9ce4cf..24581bb95278 100644 --- a/xpcom/reflect/xptinfo/xptinfo.h +++ b/xpcom/reflect/xptinfo/xptinfo.h @@ -17,6 +17,7 @@ #include "nsID.h" #include "mozilla/Assertions.h" #include "jsapi.h" +#include "js/Symbol.h" #include "js/Value.h" #include "nsString.h" #include "nsTArray.h"