Merge mozilla-central to autoland. a=merge on a CLOSED TREE

This commit is contained in:
Andreea Pavel 2018-04-14 00:58:36 +03:00
Родитель 0594f50321 01f50bc3d8
Коммит 69ae5fe098
165 изменённых файлов: 3365 добавлений и 986 удалений

Просмотреть файл

@ -121,4 +121,5 @@ jobs:
by-project:
# No default branch
mozilla-central:
- {hour: 10, minute: 0}
- {weekday: 'Monday', hour: 10, minute: 0}
- {weekday: 'Thursday', hour: 10, minute: 0}

Просмотреть файл

@ -592,7 +592,7 @@ TextAttrsMgr::FontStyleTextAttr::
TextAttrsMgr::FontWeightTextAttr::
FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
TTextAttr<int32_t>(!aFrame)
TTextAttr<FontWeight>(!aFrame)
{
mRootNativeValue = GetFontWeight(aRootFrame);
mIsRootDefined = true;
@ -605,7 +605,7 @@ TextAttrsMgr::FontWeightTextAttr::
bool
TextAttrsMgr::FontWeightTextAttr::
GetValueFor(Accessible* aAccessible, int32_t* aValue)
GetValueFor(Accessible* aAccessible, FontWeight* aValue)
{
nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
if (elm) {
@ -620,15 +620,16 @@ TextAttrsMgr::FontWeightTextAttr::
void
TextAttrsMgr::FontWeightTextAttr::
ExposeValue(nsIPersistentProperties* aAttributes, const int32_t& aValue)
ExposeValue(nsIPersistentProperties* aAttributes,
const FontWeight& aValue)
{
nsAutoString formattedValue;
formattedValue.AppendInt(aValue);
formattedValue.AppendFloat(aValue.ToFloat());
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::fontWeight, formattedValue);
}
int32_t
FontWeight
TextAttrsMgr::FontWeightTextAttr::
GetFontWeight(nsIFrame* aFrame)
{
@ -645,8 +646,9 @@ TextAttrsMgr::FontWeightTextAttr::
// bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
// needed on Mac, but it is "safe" to use on all platforms. (For non-Mac
// platforms it always return false.)
if (font->IsSyntheticBold())
return 700;
if (font->IsSyntheticBold()) {
return FontWeight::Bold();
}
// On Windows, font->GetStyle()->weight will give the same weight as
// fontEntry->Weight(), the weight of the first font in the font group,

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef nsTextAttrs_h_
#define nsTextAttrs_h_
#include "mozilla/FontPropertyTypes.h"
#include "nsCOMPtr.h"
#include "nsColor.h"
#include "nsString.h"
@ -354,7 +355,7 @@ protected:
/**
* Class is used for the work with "font-weight" text attribute.
*/
class FontWeightTextAttr : public TTextAttr<int32_t>
class FontWeightTextAttr : public TTextAttr<mozilla::FontWeight>
{
public:
FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
@ -363,13 +364,14 @@ protected:
protected:
// TTextAttr
virtual bool GetValueFor(Accessible* aAccessible, int32_t* aValue)
virtual bool GetValueFor(Accessible* aAccessible,
mozilla::FontWeight* aValue)
override;
virtual void ExposeValue(nsIPersistentProperties* aAttributes,
const int32_t& aValue) override;
const mozilla::FontWeight& aValue) override;
private:
int32_t GetFontWeight(nsIFrame* aFrame);
mozilla::FontWeight GetFontWeight(nsIFrame* aFrame);
};
/**

Просмотреть файл

@ -144,6 +144,7 @@ support-files =
[browser_dbg-async-stepping.js]
[browser_dbg-babel-breakpoint-console.js]
[browser_dbg-babel-scopes.js]
skip-if = ccov # Bug 1441545
[browser_dbg-babel-stepping.js]
[browser_dbg-babel-preview.js]
skip-if = (os == "win" && ccov) # Bug 1448523

Просмотреть файл

@ -82,6 +82,7 @@ skip-if = os == 'win' || debug # Bug 1282269, 1448084
[browser_toolbox_keyboard_navigation.js]
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
[browser_toolbox_options.js]
[browser_toolbox_options_multiple_tabs.js]
[browser_toolbox_options_disable_buttons.js]
[browser_toolbox_options_disable_cache-01.js]
[browser_toolbox_options_disable_cache-02.js]

Просмотреть файл

@ -332,11 +332,16 @@ async function testToggleWebExtensions() {
"There should not be any checkbox for the unregistered WebExtensions");
}
function getToolNode(id) {
return panelWin.document.getElementById(id);
}
async function testToggleTools() {
let toolNodes = panelWin.document.querySelectorAll(
"#default-tools-box input[type=checkbox]:not([data-unsupported])," +
"#additional-tools-box input[type=checkbox]:not([data-unsupported])");
let enabledTools = [...toolNodes].filter(node => node.checked);
let toolNodeIds = [...toolNodes].map(node => node.id);
let enabledToolIds = [...toolNodes].filter(node => node.checked).map(node => node.id);
let toggleableTools = gDevTools.getDefaultTools()
.filter(tool => {
@ -358,39 +363,43 @@ async function testToggleTools() {
}
// Toggle each tool
for (let node of toolNodes) {
await toggleTool(node);
for (let id of toolNodeIds) {
await toggleTool(getToolNode(id));
}
// Toggle again to reset tool enablement state
for (let node of toolNodes) {
await toggleTool(node);
for (let id of toolNodeIds) {
await toggleTool(getToolNode(id));
}
// Test that a tool can still be added when no tabs are present:
// Disable all tools
for (let node of enabledTools) {
await toggleTool(node);
for (let id of enabledToolIds) {
await toggleTool(getToolNode(id));
}
// Re-enable the tools which are enabled by default
for (let node of enabledTools) {
await toggleTool(node);
for (let id of enabledToolIds) {
await toggleTool(getToolNode(id));
}
// Toggle first, middle, and last tools to ensure that toolbox tabs are
// inserted in order
let firstTool = toolNodes[0];
let middleTool = toolNodes[(toolNodes.length / 2) | 0];
let lastTool = toolNodes[toolNodes.length - 1];
let firstToolId = toolNodeIds[0];
let middleToolId = toolNodeIds[(toolNodeIds.length / 2) | 0];
let lastToolId = toolNodeIds[toolNodeIds.length - 1];
await toggleTool(firstTool);
await toggleTool(firstTool);
await toggleTool(middleTool);
await toggleTool(middleTool);
await toggleTool(lastTool);
await toggleTool(lastTool);
await toggleTool(getToolNode(firstToolId));
await toggleTool(getToolNode(firstToolId));
await toggleTool(getToolNode(middleToolId));
await toggleTool(getToolNode(middleToolId));
await toggleTool(getToolNode(lastToolId));
await toggleTool(getToolNode(lastToolId));
}
/**
* Toggle tool node checkbox. Note: because toggling the checkbox will result in
* re-rendering of the tool list, we must re-query the checkboxes every time.
*/
async function toggleTool(node) {
let deferred = defer();

Просмотреть файл

@ -0,0 +1,112 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = "data:text/html;charset=utf8,test for dynamically registering " +
"and unregistering tools across multiple tabs";
let tab1, tab2, modifiedPref;
add_task(async function() {
tab1 = await openToolboxOptionsInNewTab();
tab2 = await openToolboxOptionsInNewTab();
await testToggleTools();
await cleanup();
});
async function openToolboxOptionsInNewTab() {
const tab = await addTab(URL);
const target = TargetFactory.forTab(tab);
const toolbox = await gDevTools.showToolbox(target);
const doc = toolbox.doc;
const panel = await toolbox.selectTool("options");
const { id } = panel.panelDoc.querySelector(
"#default-tools-box input[type=checkbox]:not([data-unsupported]):not([checked])");
return {
tab,
toolbox,
doc,
panelWin: panel.panelWin,
// This is a getter becuse toolbox tools list gets re-setup every time there
// is a tool-registered or tool-undregistered event.
get checkbox() {
return panel.panelDoc.getElementById(id);
}
};
}
async function testToggleTools() {
is(tab1.checkbox.id, tab2.checkbox.id, "Default tool box should be in sync.");
const toolId = tab1.checkbox.id;
const testTool = gDevTools.getDefaultTools().find(tool => tool.id === toolId);
// Store modified pref names so that they can be cleared on error.
modifiedPref = testTool.visibilityswitch;
info(`Registering tool ${toolId} in the first tab.`);
await toggleTool(tab1, toolId);
info(`Unregistering tool ${toolId} in the first tab.`);
await toggleTool(tab1, toolId);
info(`Registering tool ${toolId} in the second tab.`);
await toggleTool(tab2, toolId);
info(`Unregistering tool ${toolId} in the second tab.`);
await toggleTool(tab2, toolId);
info(`Registering tool ${toolId} in the first tab.`);
await toggleTool(tab1, toolId);
info(`Unregistering tool ${toolId} in the second tab.`);
await toggleTool(tab2, toolId);
}
async function toggleTool({ doc, panelWin, checkbox, tab }, toolId) {
const prevChecked = checkbox.checked;
(prevChecked ? checkRegistered : checkUnregistered)(toolId);
const onToggleTool = gDevTools.once(
`tool-${prevChecked ? "unregistered" : "registered"}`);
EventUtils.sendMouseEvent({ type: "click" }, checkbox, panelWin);
const id = await onToggleTool;
is(id, toolId, `Correct event for ${toolId} was fired`);
// await new Promise(resolve => setTimeout(resolve, 60000));
(prevChecked ? checkUnregistered : checkRegistered)(toolId);
}
async function checkUnregistered(toolId) {
ok(!tab1.doc.getElementById("toolbox-tab-" + toolId),
`Tab for unregistered tool ${toolId} is not present in first toolbox`);
ok(!tab1.checkbox.checked,
`Checkbox for unregistered tool ${toolId} is not checked in first toolbox`);
ok(!tab2.doc.getElementById("toolbox-tab-" + toolId),
`Tab for unregistered tool ${toolId} is not present in second toolbox`);
ok(!tab2.checkbox.checked,
`Checkbox for unregistered tool ${toolId} is not checked in second toolbox`);
}
function checkRegistered(toolId) {
ok(tab1.doc.getElementById("toolbox-tab-" + toolId),
`Tab for registered tool ${toolId} is present in first toolbox`);
ok(tab1.checkbox.checked,
`Checkbox for registered tool ${toolId} is checked in first toolbox`);
ok(tab2.doc.getElementById("toolbox-tab-" + toolId),
`Tab for registered tool ${toolId} is present in second toolbox`);
ok(tab2.checkbox.checked,
`Checkbox for registered tool ${toolId} is checked in second toolbox`);
}
async function cleanup() {
await tab1.toolbox.destroy();
await tab2.toolbox.destroy();
gBrowser.removeCurrentTab();
gBrowser.removeCurrentTab();
Services.prefs.clearUserPref(modifiedPref);
tab1 = tab2 = modifiedPref = null;
}

Просмотреть файл

@ -61,11 +61,10 @@ function OptionsPanel(iframeWindow, toolbox) {
this.toolbox = toolbox;
this.isReady = false;
this.setupToolsList = this.setupToolsList.bind(this);
this._prefChanged = this._prefChanged.bind(this);
this._themeRegistered = this._themeRegistered.bind(this);
this._themeUnregistered = this._themeUnregistered.bind(this);
this._webExtensionRegistered = this._webExtensionRegistered.bind(this);
this._webExtensionUnregistered = this._webExtensionUnregistered.bind(this);
this._disableJSClicked = this._disableJSClicked.bind(this);
this.disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
@ -106,8 +105,14 @@ OptionsPanel.prototype = {
gDevTools.on("theme-registered", this._themeRegistered);
gDevTools.on("theme-unregistered", this._themeUnregistered);
this.toolbox.on("webextension-registered", this._webExtensionRegistered);
this.toolbox.on("webextension-unregistered", this._webExtensionUnregistered);
// Refresh the tools list when a new tool or webextension has been
// registered to the toolbox.
this.toolbox.on("tool-registered", this.setupToolsList);
this.toolbox.on("webextension-registered", this.setupToolsList);
// Refresh the tools list when a new tool or webextension has been
// unregistered from the toolbox.
this.toolbox.on("tool-unregistered", this.setupToolsList);
this.toolbox.on("webextension-unregistered", this.setupToolsList);
},
_removeListeners: function() {
@ -116,8 +121,10 @@ OptionsPanel.prototype = {
Services.prefs.removeObserver("devtools.source-map.client-service.enabled",
this._prefChanged);
this.toolbox.off("webextension-registered", this._webExtensionRegistered);
this.toolbox.off("webextension-unregistered", this._webExtensionUnregistered);
this.toolbox.off("tool-registered", this.setupToolsList);
this.toolbox.off("tool-unregistered", this.setupToolsList);
this.toolbox.off("webextension-registered", this.setupToolsList);
this.toolbox.off("webextension-unregistered", this.setupToolsList);
gDevTools.off("theme-registered", this._themeRegistered);
gDevTools.off("theme-unregistered", this._themeUnregistered);
@ -148,18 +155,6 @@ OptionsPanel.prototype = {
}
},
_webExtensionRegistered: function(extensionUUID) {
// Refresh the tools list when a new webextension has been registered
// to the toolbox.
this.setupToolsList();
},
_webExtensionUnregistered: function(extensionUUID) {
// Refresh the tools list when a new webextension has been unregistered
// from the toolbox.
this.setupToolsList();
},
async setupToolbarButtonsList() {
// Ensure the toolbox is open, and the buttons are all set up.
await this.toolbox.isOpen;

Просмотреть файл

@ -380,8 +380,20 @@ IPCBlobInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
// We have the remote inputStream, let's check if we can execute the callback.
case eRunning: {
MutexAutoLock lock(mMutex);
return MaybeExecuteInputStreamCallback(aCallback, aEventTarget, lock);
{
MutexAutoLock lock(mMutex);
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
}
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->AsyncWait(aCallback ? this : nullptr,
0, 0, aEventTarget);
}
// Stream is closed.
@ -435,64 +447,28 @@ IPCBlobInputStream::StreamReady(already_AddRefed<nsIInputStream> aInputStream)
this);
}
nsCOMPtr<nsIInputStreamCallback> inputStreamCallback = this;
nsCOMPtr<nsIEventTarget> inputStreamCallbackEventTarget;
{
MutexAutoLock lock(mMutex);
nsCOMPtr<nsIInputStreamCallback> inputStreamCallback;
inputStreamCallback.swap(mInputStreamCallback);
nsCOMPtr<nsIEventTarget> inputStreamCallbackEventTarget;
inputStreamCallbackEventTarget.swap(mInputStreamCallbackEventTarget);
if (inputStreamCallback) {
MaybeExecuteInputStreamCallback(inputStreamCallback,
inputStreamCallbackEventTarget,
lock);
inputStreamCallbackEventTarget = mInputStreamCallbackEventTarget;
if (!mInputStreamCallback) {
inputStreamCallback = nullptr;
}
}
}
nsresult
IPCBlobInputStream::MaybeExecuteInputStreamCallback(nsIInputStreamCallback* aCallback,
nsIEventTarget* aCallbackEventTarget,
const MutexAutoLock& aProofOfLock)
{
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mRemoteStream || mAsyncRemoteStream);
// If the callback has been already set, we return an error.
if (mInputStreamCallback && aCallback) {
return NS_ERROR_FAILURE;
}
bool hadCallback = !!mInputStreamCallback;
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aCallbackEventTarget;
nsCOMPtr<nsIInputStreamCallback> callback = this;
if (!mInputStreamCallback) {
if (!hadCallback) {
// Nothing was pending.
return NS_OK;
if (inputStreamCallback) {
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Let's set a null callback in order to abort the current operation.
callback = nullptr;
MOZ_ASSERT(mAsyncRemoteStream);
rv = mAsyncRemoteStream->AsyncWait(inputStreamCallback, 0, 0,
inputStreamCallbackEventTarget);
Unused << NS_WARN_IF(NS_FAILED(rv));
}
// We don't need to be locked anymore.
MutexAutoUnlock unlock(mMutex);
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->AsyncWait(callback, 0, 0, aCallbackEventTarget);
}
void

Просмотреть файл

@ -44,11 +44,6 @@ public:
private:
~IPCBlobInputStream();
nsresult
MaybeExecuteInputStreamCallback(nsIInputStreamCallback* aCallback,
nsIEventTarget* aEventTarget,
const MutexAutoLock& aProofOfLock);
nsresult
EnsureAsyncRemoteStream();

Просмотреть файл

@ -117,7 +117,7 @@ struct FontListEntry {
nsString familyName;
nsString faceName;
nsCString filepath;
uint16_t weight;
float weight;
int16_t stretch;
uint8_t italic;
uint8_t index;

Просмотреть файл

@ -8,6 +8,7 @@
#include "nsMathMLElement.h"
#include "base/compiler_specific.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/FontPropertyTypes.h"
#include "nsGkAtoms.h"
#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
#include "nsCRT.h"
@ -726,10 +727,10 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
str.CompressWhitespace();
if (str.EqualsASCII("normal")) {
aData->SetKeywordValue(eCSSProperty_font_weight,
NS_FONT_WEIGHT_NORMAL);
FontWeight::Normal().ToFloat());
} else if (str.EqualsASCII("bold")) {
aData->SetKeywordValue(eCSSProperty_font_weight,
NS_FONT_WEIGHT_BOLD);
FontWeight::Bold().ToFloat());
}
}
}

Просмотреть файл

@ -645,11 +645,11 @@ public:
// Set size of buffer, allocating memory as required.
// If size is increased, new buffer area is filled with 0.
bool SetSize(size_t aSize);
MOZ_MUST_USE bool SetSize(size_t aSize);
// Add aData at the beginning of buffer.
bool Prepend(const uint8_t* aData, size_t aSize);
MOZ_MUST_USE bool Prepend(const uint8_t* aData, size_t aSize);
// Replace current content with aData.
bool Replace(const uint8_t* aData, size_t aSize);
MOZ_MUST_USE bool Replace(const uint8_t* aData, size_t aSize);
// Clear the memory buffer. Will set target mData and mSize to 0.
void Clear();
// Remove aSize bytes from the front of the sample.
@ -658,7 +658,7 @@ public:
private:
friend class MediaRawData;
explicit MediaRawDataWriter(MediaRawData* aMediaRawData);
bool EnsureSize(size_t aSize);
MOZ_MUST_USE bool EnsureSize(size_t aSize);
MediaRawData* mTarget;
};

Просмотреть файл

@ -3054,6 +3054,22 @@ ScriptLoader::NumberOfProcessors()
return mNumberOfProcessors;
}
static bool
IsInternalURIScheme(nsIURI* uri)
{
bool isWebExt;
if (NS_SUCCEEDED(uri->SchemeIs("moz-extension", &isWebExt)) && isWebExt) {
return true;
}
bool isResource;
if (NS_SUCCEEDED(uri->SchemeIs("resource", &isResource)) && isResource) {
return true;
}
return false;
}
nsresult
ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
nsIIncrementalStreamLoader* aLoader,
@ -3142,10 +3158,9 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
rv = channel->GetOriginalURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// Fixup moz-extension URIs, because the channel URI points to file:,
// which won't be allowed to load.
bool isWebExt = false;
if (uri && NS_SUCCEEDED(uri->SchemeIs("moz-extension", &isWebExt)) && isWebExt) {
// Fixup moz-extension: and resource: URIs, because the channel URI will
// point to file:, which won't be allowed to load.
if (uri && IsInternalURIScheme(uri)) {
request->mBaseURL = uri;
} else {
channel->GetURI(getter_AddRefs(request->mBaseURL));

Просмотреть файл

@ -0,0 +1,61 @@
// Custom *.sjs file specifically for the needs of Bug 1453814
// small red image
const IMG_BYTES = atob(
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
"P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
const FRAME = `
<!DOCTYPE html>
<html>
<head>
<title>Bug 1453814 - Do not allow same-site cookies for cross origin redirect</title>
</head>
<body>
<script type="application/javascript">
let cookie = document.cookie;
// now reset the cookie for the next test
document.cookie = "myKey=;" + "expires=Thu, 01 Jan 1970 00:00:00 GMT";
window.parent.postMessage({result: cookie}, 'http://mochi.test:8888');
</script>
</body>
</html>`;
const SAME_ORIGIN = "http://mochi.test:8888/"
const CROSS_ORIGIN = "http://example.com/";
const PATH = "tests/dom/security/test/general/file_same_site_cookies_redirect.sjs";
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
if (request.queryString === "setSameSiteCookie") {
response.setHeader("Set-Cookie", "myKey=strictSameSiteCookie; samesite=strict", true);
response.setHeader("Content-Type", "image/png");
response.write(IMG_BYTES);
return;
}
if (request.queryString === "sameToCrossRedirect") {
let URL = CROSS_ORIGIN + PATH + "?loadFrame";
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Location", URL, false);
return;
}
if (request.queryString === "crossToSameRedirect") {
let URL = SAME_ORIGIN + PATH + "?loadFrame";
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Location", URL, false);
return;
}
if (request.queryString === "loadFrame") {
response.write(FRAME);
return;
}
// we should never get here, but just in case return something unexpected
response.write("D'oh");
}

Просмотреть файл

@ -12,6 +12,7 @@ support-files =
file_same_site_cookies_toplevel_nav.sjs
file_same_site_cookies_cross_origin_context.sjs
file_same_site_cookies_from_script.sjs
file_same_site_cookies_redirect.sjs
[test_contentpolicytype_targeted_link_iframe.html]
[test_nosniff.html]
@ -29,3 +30,4 @@ skip-if = toolkit == 'android'
[test_same_site_cookies_toplevel_nav.html]
[test_same_site_cookies_cross_origin_context.html]
[test_same_site_cookies_from_script.html]
[test_same_site_cookies_redirect.html]

Просмотреть файл

@ -0,0 +1,83 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1453814 - Do not allow same-site cookies for cross origin redirect</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<img id="cookieImage">
<iframe id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/*
* Description of the test:
* 1) We load an image from http://mochi.test which set a same site cookie
* 2) We then load an iframe that redirects
* (a) from same-origin to cross-origin
* (b) from cross-origin to same-origin
* 3) We observe that in both cases same-site cookies should not be send
*/
SimpleTest.waitForExplicitFinish();
const SAME_ORIGIN = "http://mochi.test:8888/"
const CROSS_ORIGIN = "http://example.com/";
const PATH = "tests/dom/security/test/general/file_same_site_cookies_redirect.sjs";
let curTest = 0;
var tests = [
{
description: "same-site cookie, redirect same-site to cross-site",
imgSRC: SAME_ORIGIN + PATH + "?setSameSiteCookie",
frameSRC: SAME_ORIGIN + PATH + "?sameToCrossRedirect",
result: "", // no cookie should be set
},
{
description: "same-site cookie, redirect cross-site to same-site",
imgSRC: SAME_ORIGIN + PATH + "?setSameSiteCookie",
frameSRC: CROSS_ORIGIN + PATH + "?crossToSameRedirect",
result: "", // no cookie should be set
},
];
window.addEventListener("message", receiveMessage);
function receiveMessage(event) {
is(event.data.result, tests[curTest].result, tests[curTest].description);
curTest += 1;
// // lets see if we ran all the tests
if (curTest == tests.length) {
window.removeEventListener("message", receiveMessage);
SimpleTest.finish();
return;
}
// otherwise it's time to run the next test
setCookieAndInitTest();
}
function setupQueryResultAndRunTest() {
let testframe = document.getElementById("testframe");
testframe.src = tests[curTest].frameSRC;
}
function setCookieAndInitTest() {
var cookieImage = document.getElementById("cookieImage");
cookieImage.onload = function() {
ok(true, "trying to set cookie for test (" + tests[curTest].description + ")");
setupQueryResultAndRunTest();
}
cookieImage.onerror = function() {
ok(false, "could not load image for test (" + tests[curTest].description + ")");
}
cookieImage.src = tests[curTest].imgSRC;
}
// fire up the test
setCookieAndInitTest();
</script>
</body>
</html>

Просмотреть файл

@ -294,6 +294,9 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */)
.setWasm(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm")))
.setWasmBaseline(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_baselinejit")))
.setWasmIon(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_ionjit")))
#ifdef ENABLE_WASM_GC
.setWasmGc(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_gc")))
#endif
.setThrowOnAsmJSValidationFailure(GetWorkerPref<bool>(
NS_LITERAL_CSTRING("throw_on_asmjs_validation_failure")))
.setBaseline(GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit")))

Просмотреть файл

@ -98,3 +98,6 @@ BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']
if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_GC'] = True

Просмотреть файл

@ -12,6 +12,7 @@
#include "Logging.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticMutex.h"
#include "nsTArray.h"
namespace mozilla {
namespace gfx {
@ -84,6 +85,8 @@ private:
class DWriteFontFileStream final : public IDWriteFontFileStream
{
public:
explicit DWriteFontFileStream(uint64_t aFontFileKey);
/**
* Used by the FontFileLoader to create a new font stream,
* this font stream is created from data in memory. The memory
@ -92,7 +95,7 @@ public:
*
* @param aData Font data
*/
DWriteFontFileStream(uint8_t *aData, uint32_t aSize, uint64_t aFontFileKey);
bool Initialize(uint8_t *aData, uint32_t aSize);
// IUnknown interface
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
@ -135,7 +138,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
private:
std::vector<uint8_t> mData;
nsTArray<uint8_t> mData;
Atomic<uint32_t> mRefCnt;
uint64_t mFontFileKey;
@ -166,13 +169,10 @@ DWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
return S_OK;
}
DWriteFontFileStream::DWriteFontFileStream(uint8_t *aData, uint32_t aSize,
uint64_t aFontFileKey)
DWriteFontFileStream::DWriteFontFileStream(uint64_t aFontFileKey)
: mRefCnt(0)
, mFontFileKey(aFontFileKey)
{
mData.resize(aSize);
memcpy(&mData.front(), aData, aSize);
}
DWriteFontFileStream::~DWriteFontFileStream()
@ -181,10 +181,20 @@ DWriteFontFileStream::~DWriteFontFileStream()
sFontFileStreams.erase(mFontFileKey);
}
bool
DWriteFontFileStream::Initialize(uint8_t *aData, uint32_t aSize)
{
if (!mData.SetLength(aSize, fallible)) {
return false;
}
memcpy(mData.Elements(), aData, aSize);
return true;
}
HRESULT STDMETHODCALLTYPE
DWriteFontFileStream::GetFileSize(UINT64 *fileSize)
{
*fileSize = mData.size();
*fileSize = mData.Length();
return S_OK;
}
@ -201,7 +211,7 @@ DWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
void **fragmentContext)
{
// We are required to do bounds checking.
if (fileOffset + fragmentSize > mData.size()) {
if (fileOffset + fragmentSize > mData.Length()) {
return E_FAIL;
}
@ -232,8 +242,12 @@ NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
sFontFileStreamsMutex.Lock();
uint64_t fontFileKey = sNextFontFileKey++;
RefPtr<IDWriteFontFileStream> ffsRef =
new DWriteFontFileStream(aFontData, aDataLength, fontFileKey);
RefPtr<DWriteFontFileStream> ffsRef = new DWriteFontFileStream(fontFileKey);
if (!ffsRef->Initialize(aFontData, aDataLength)) {
sFontFileStreamsMutex.Unlock();
gfxWarning() << "Failed to create DWriteFontFileStream.";
return nullptr;
}
sFontFileStreams[fontFileKey] = ffsRef;
sFontFileStreamsMutex.Unlock();

Просмотреть файл

@ -32,7 +32,10 @@ NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength, F
if (!aFontData || !aDataLength) {
return nullptr;
}
UniquePtr<uint8_t[]> fontData(new uint8_t[aDataLength]);
UniquePtr<uint8_t[]> fontData(new (fallible) uint8_t[aDataLength]);
if (!fontData) {
return nullptr;
}
memcpy(fontData.get(), aFontData, aDataLength);
FT_Face face = Factory::NewFTFaceFromData(aFTLibrary, fontData.get(), aDataLength, 0);

Просмотреть файл

@ -137,7 +137,7 @@ ScaledFontDWrite::ScaledFontDWrite(IDWriteFontFace *aFontFace,
, mContrast(aContrast)
{
if (aStyle) {
mStyle = SkFontStyle(aStyle->weight,
mStyle = SkFontStyle(aStyle->weight.ToIntRounded(),
DWriteFontStretchFromStretch(aStyle->stretch),
aStyle->style == NS_FONT_STYLE_NORMAL ?
SkFontStyle::kUpright_Slant : SkFontStyle::kItalic_Slant);

Просмотреть файл

@ -82,17 +82,6 @@ public:
void Unmap() override
{ }
bool AddConsumer()
{
return ++mConsumers == 1;
}
bool RemoveConsumer()
{
MOZ_ASSERT(mConsumers > 0);
return --mConsumers == 0;
}
private:
size_t GetDataLength() const
{
@ -105,7 +94,6 @@ private:
}
int32_t mStride;
uint32_t mConsumers;
IntSize mSize;
RefPtr<SharedMemoryBasic> mBuf;
SurfaceFormat mFormat;

Просмотреть файл

@ -54,44 +54,22 @@ SharedSurfacesParent::Get(const wr::ExternalImageId& aId)
return surface.forget();
}
/* static */ already_AddRefed<DataSourceSurface>
SharedSurfacesParent::Acquire(const wr::ExternalImageId& aId)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (!sInstance) {
return nullptr;
}
RefPtr<SourceSurfaceSharedDataWrapper> surface;
sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface));
if (surface) {
DebugOnly<bool> rv = surface->AddConsumer();
MOZ_ASSERT(!rv);
}
return surface.forget();
}
/* static */ bool
SharedSurfacesParent::Release(const wr::ExternalImageId& aId)
/* static */ void
SharedSurfacesParent::Remove(const wr::ExternalImageId& aId)
{
//MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (!sInstance) {
return false;
return;
}
uint64_t id = wr::AsUint64(aId);
RefPtr<SourceSurfaceSharedDataWrapper> surface;
sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface));
if (!surface) {
return false;
return;
}
if (surface->RemoveConsumer()) {
sInstance->mSurfaces.Remove(id);
}
return true;
sInstance->mSurfaces.Remove(id);
}
/* static */ void
@ -193,13 +171,5 @@ SharedSurfacesParent::Add(const wr::ExternalImageId& aId,
sInstance->mSurfaces.Put(id, surface.forget());
}
/* static */ void
SharedSurfacesParent::Remove(const wr::ExternalImageId& aId)
{
//MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
DebugOnly<bool> rv = Release(aId);
MOZ_ASSERT(rv);
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -35,16 +35,9 @@ public:
static void Initialize();
static void Shutdown();
// Get without increasing the consumer count.
static already_AddRefed<gfx::DataSourceSurface>
Get(const wr::ExternalImageId& aId);
// Get but also increase the consumer count. Must call Release after finished.
static already_AddRefed<gfx::DataSourceSurface>
Acquire(const wr::ExternalImageId& aId);
static bool Release(const wr::ExternalImageId& aId);
static void Add(const wr::ExternalImageId& aId,
const SurfaceDescriptorShared& aDesc,
base::ProcessId aPid);

133
gfx/src/FontPropertyTypes.h Normal file
Просмотреть файл

@ -0,0 +1,133 @@
/* -*- Mode: C++; tab-width: 20; 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/. */
/* font specific types shared by both thebes and layout */
#ifndef GFX_FONT_PROPERTY_TYPES_H
#define GFX_FONT_PROPERTY_TYPES_H
#include <cstdint>
/*
* This file is separate from gfxFont.h so that layout can include it
* without bringing in gfxFont.h and everything it includes.
*/
namespace mozilla {
/**
* A type that will in future encode a value as fixed point.
*/
class FontFixedPointValue
{
public:
// Ugh. We need a default constructor to allow this type to be used in the
// union in nsCSSValue. Furthermore we need the default and copy
// constructors to be "trivial" (i.e. the compiler implemented defaults that
// do no initialization).
// Annoyingly it seems we can't make the default implementations constexpr
// (at least in clang). We'd like to do that to allow Thin() et. al. below
// to also be constexpr. :/
FontFixedPointValue() = default;
FontFixedPointValue(const FontFixedPointValue& aOther) = default;
// Not currently encoded, but it will be in future
explicit FontFixedPointValue(int16_t aValue)
: mEncoded(aValue)
{}
explicit FontFixedPointValue(int32_t aValue)
: mEncoded(aValue)
{}
explicit FontFixedPointValue(float aValue)
: mEncoded(int16_t(aValue))
{}
float ToFloat() const {
return float(mEncoded);
}
int16_t ToIntRounded() const {
return mEncoded;
}
bool operator==(const FontFixedPointValue& aOther) const {
return mEncoded == aOther.mEncoded;
}
bool operator!=(const FontFixedPointValue& aOther) const {
return mEncoded != aOther.mEncoded;
}
bool operator<(const FontFixedPointValue& aOther) const {
return mEncoded < aOther.mEncoded;
}
bool operator<=(const FontFixedPointValue& aOther) const {
return mEncoded <= aOther.mEncoded;
}
bool operator>=(const FontFixedPointValue& aOther) const {
return mEncoded >= aOther.mEncoded;
}
bool operator>(const FontFixedPointValue& aOther) const {
return mEncoded > aOther.mEncoded;
}
int16_t ForHash() const {
return mEncoded;
}
protected:
int16_t mEncoded;
};
class FontWeight : public FontFixedPointValue
{
public:
// Ugh, to get union in nsCSSValue compiling
FontWeight() = default;
FontWeight(const FontWeight& aOther) = default;
// Not currently encoded, but it will be in future
explicit FontWeight(int16_t aValue)
: FontFixedPointValue(aValue)
{}
explicit FontWeight(int32_t aValue)
: FontFixedPointValue(aValue)
{}
explicit FontWeight(float aValue)
: FontFixedPointValue(int16_t(aValue))
{}
bool operator==(const FontWeight& aOther) const
{
return mEncoded == aOther.mEncoded;
}
/// The "distance" between two font weights
float operator-(const FontWeight& aOther) const {
return this->ToFloat() - aOther.ToFloat();
}
static FontWeight Thin() {
return FontWeight{100};
}
static FontWeight Normal() {
return FontWeight{400};
}
static FontWeight Bold() {
return FontWeight{700};
}
};
} // namespace mozilla
#endif // GFX_FONT_PROPERTY_TYPES_H

Просмотреть файл

@ -45,6 +45,7 @@ EXPORTS += [
EXPORTS.mozilla += [
'AppUnits.h',
'ArrayView.h',
'FontPropertyTypes.h',
]
EXPORTS.mozilla.gfx += [

Просмотреть файл

@ -13,6 +13,7 @@
#include "gfxFontConstants.h" // for NS_FONT_KERNING_AUTO, etc
#include "gfxFontFeatures.h"
#include "gfxFontVariations.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/RefPtr.h" // for RefPtr
#include "nsColor.h" // for nsColor and NS_RGBA
#include "nsCoord.h" // for nscoord
@ -44,6 +45,7 @@ const uint8_t kGenericFont_fantasy = 0x20;
// Font structure.
struct nsFont {
typedef mozilla::FontWeight FontWeight;
// list of font families, either named or generic
mozilla::FontFamilyList fontlist;
@ -79,7 +81,7 @@ struct nsFont {
nscolor fontSmoothingBackgroundColor = NS_RGBA(0,0,0,0);
// The weight of the font; see gfxFontConstants.h.
uint16_t weight = NS_FONT_WEIGHT_NORMAL;
FontWeight weight = FontWeight::Normal();
// The stretch of the font (the sum of various NS_FONT_STRETCH_*
// constants; see gfxFontConstants.h).

Просмотреть файл

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ArrayUtils.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/intl/OSPreferences.h"
@ -219,12 +220,12 @@ gfxDWriteFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
if (LOG_FONTLIST_ENABLED()) {
LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
" with style: %s weight: %d stretch: %d psname: %s fullname: %s",
" with style: %s weight: %g stretch: %d psname: %s fullname: %s",
NS_ConvertUTF16toUTF8(fe->Name()).get(),
NS_ConvertUTF16toUTF8(Name()).get(),
(fe->IsItalic()) ?
"italic" : (fe->IsOblique() ? "oblique" : "normal"),
fe->Weight(), fe->Stretch(),
fe->Weight().ToFloat(), fe->Stretch(),
NS_ConvertUTF16toUTF8(psname).get(),
NS_ConvertUTF16toUTF8(fullname).get()));
}
@ -956,7 +957,7 @@ gfxDWriteFontList::GetDefaultFontForPlatform(const gfxFontStyle *aStyle)
gfxFontEntry *
gfxDWriteFontList::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -980,7 +981,7 @@ gfxDWriteFontList::LookupLocalFont(const nsAString& aFontName,
gfxFontEntry *
gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
@ -1151,12 +1152,12 @@ gfxDWriteFontList::InitFontListForPlatform()
if (LOG_FONTLIST_ENABLED()) {
gfxFontEntry *fe = faces[i];
LOG_FONTLIST(("(fontlist) moved (%s) to family (%s)"
" with style: %s weight: %d stretch: %d",
" with style: %s weight: %g stretch: %d",
NS_ConvertUTF16toUTF8(fe->Name()).get(),
NS_ConvertUTF16toUTF8(gillSansMTFamily->Name()).get(),
(fe->IsItalic()) ?
"italic" : (fe->IsOblique() ? "oblique" : "normal"),
fe->Weight(), fe->Stretch()));
fe->Weight().ToFloat(), fe->Stretch()));
}
}

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef GFX_DWRITEFONTLIST_H
#define GFX_DWRITEFONTLIST_H
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "gfxDWriteCommon.h"
#include "dwrite_3.h"
@ -46,6 +47,8 @@ class gfxDWriteFontEntry;
class gfxDWriteFontFamily : public gfxFontFamily
{
public:
typedef mozilla::FontWeight FontWeight;
/**
* Constructs a new DWriteFont Family.
*
@ -119,7 +122,7 @@ public:
weight = std::max<uint16_t>(100, weight);
weight = std::min<uint16_t>(900, weight);
mWeight = weight;
mWeight = FontWeight(weight);
mIsCJK = UNINITIALIZED_VALUE;
}
@ -137,7 +140,7 @@ public:
*/
gfxDWriteFontEntry(const nsAString& aFaceName,
IDWriteFont *aFont,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr),
@ -164,7 +167,7 @@ public:
gfxDWriteFontEntry(const nsAString& aFaceName,
IDWriteFontFile *aFontFile,
IDWriteFontFileStream *aFontFileStream,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
: gfxFontEntry(aFaceName), mFont(nullptr),
@ -401,12 +404,12 @@ public:
gfxFontFamily* CreateFontFamily(const nsAString& aName) const override;
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle);
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -11,6 +11,7 @@
#include "gfxTextRun.h"
#include "harfbuzz/hb.h"
#include "mozilla/FontPropertyTypes.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -135,7 +136,7 @@ bool
gfxDWriteFont::GetFakeMetricsForArialBlack(DWRITE_FONT_METRICS *aFontMetrics)
{
gfxFontStyle style(mStyle);
style.weight = 700;
style.weight = FontWeight(700);
bool needsBold;
gfxFontEntry* fe =
@ -156,7 +157,7 @@ void
gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
{
DWRITE_FONT_METRICS fontMetrics;
if (!(mFontEntry->Weight() == 900 &&
if (!(mFontEntry->Weight() == FontWeight(900) &&
!mFontEntry->IsUserFont() &&
mFontEntry->Name().EqualsLiteral("Arial Black") &&
GetFakeMetricsForArialBlack(&fontMetrics)))

Просмотреть файл

@ -5,6 +5,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/Base64.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/ContentChild.h"
@ -256,7 +257,7 @@ FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold
/* static */
FT2FontEntry*
FT2FontEntry::CreateFontEntry(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
@ -327,7 +328,9 @@ FT2FontEntry::CreateFontEntry(const FontListEntry& aFLE)
FT2FontEntry *fe = new FT2FontEntry(aFLE.faceName());
fe->mFilename = aFLE.filepath();
fe->mFTFontIndex = aFLE.index();
fe->mWeight = aFLE.weight();
// The weight transported across IPC is a float, so we need to explicitly
// convert it back to a FontWeight.
fe->mWeight = FontWeight(aFLE.weight());
fe->mStretch = aFLE.stretch();
fe->mStyle = (aFLE.italic() ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL);
return fe;
@ -340,7 +343,7 @@ FTFaceIsItalic(FT_Face aFace)
return !!(aFace->style_flags & FT_STYLE_FLAG_ITALIC);
}
static uint16_t
static FontWeight
FTFaceGetWeight(FT_Face aFace)
{
TT_OS2 *os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(aFace, ft_sfnt_os2));
@ -368,7 +371,7 @@ FTFaceGetWeight(FT_Face aFace)
NS_ASSERTION(result >= 100 && result <= 900, "Invalid weight in font!");
return result;
return FontWeight(result);
}
// Used to create the font entry for installed faces on the device,
@ -661,9 +664,12 @@ FT2FontFamily::AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList)
continue;
}
// We convert the weight to a float purely for transport across IPC.
// Ideally we'd avoid doing that.
aFontList->AppendElement(FontListEntry(Name(), fe->Name(),
fe->mFilename,
fe->Weight(), fe->Stretch(),
fe->Weight().ToFloat(),
fe->Stretch(),
fe->mStyle,
fe->mFTFontIndex));
}
@ -985,7 +991,7 @@ AppendToFaceList(nsCString& aFaceList,
aFaceList.Append(',');
aFaceList.Append(aFontEntry->IsItalic() ? '1' : '0');
aFaceList.Append(',');
aFaceList.AppendInt(aFontEntry->Weight());
aFaceList.AppendFloat(aFontEntry->Weight().ToFloat());
aFaceList.Append(',');
aFaceList.AppendInt(aFontEntry->Stretch());
aFaceList.Append(',');
@ -1144,11 +1150,11 @@ gfxFT2FontList::AddFaceToList(const nsCString& aEntryName, uint32_t aIndex,
AppendToFaceList(aFaceList, name, fe);
if (LOG_ENABLED()) {
LOG(("(fontinit) added (%s) to family (%s)"
" with style: %s weight: %d stretch: %d",
" with style: %s weight: %g stretch: %d",
NS_ConvertUTF16toUTF8(fe->Name()).get(),
NS_ConvertUTF16toUTF8(family->Name()).get(),
fe->IsItalic() ? "italic" : "normal",
fe->Weight(), fe->Stretch()));
fe->Weight().ToFloat(), fe->Stretch()));
}
}
}
@ -1458,7 +1464,7 @@ gfxFT2FontList::InitFontListForPlatform()
gfxFontEntry*
gfxFT2FontList::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -1540,7 +1546,7 @@ gfxFT2FontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
gfxFontEntry*
gfxFT2FontList::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -43,7 +43,7 @@ public:
// create a font entry for a downloaded font
static FT2FontEntry*
CreateFontEntry(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
@ -122,12 +122,12 @@ public:
virtual ~gfxFT2FontList();
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle) override;
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -160,40 +160,40 @@ GetFaceNames(FcPattern* aFont, const nsAString& aFamilyName,
}
}
static uint16_t
static FontWeight
MapFcWeight(int aFcWeight)
{
if (aFcWeight <= (FC_WEIGHT_THIN + FC_WEIGHT_EXTRALIGHT) / 2) {
return 100;
return FontWeight(100);
}
if (aFcWeight <= (FC_WEIGHT_EXTRALIGHT + FC_WEIGHT_LIGHT) / 2) {
return 200;
return FontWeight(200);
}
if (aFcWeight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_BOOK) / 2) {
return 300;
return FontWeight(300);
}
if (aFcWeight <= (FC_WEIGHT_REGULAR + FC_WEIGHT_MEDIUM) / 2) {
// This includes FC_WEIGHT_BOOK
return 400;
return FontWeight(400);
}
if (aFcWeight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2) {
return 500;
return FontWeight(500);
}
if (aFcWeight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2) {
return 600;
return FontWeight(600);
}
if (aFcWeight <= (FC_WEIGHT_BOLD + FC_WEIGHT_EXTRABOLD) / 2) {
return 700;
return FontWeight(700);
}
if (aFcWeight <= (FC_WEIGHT_EXTRABOLD + FC_WEIGHT_BLACK) / 2) {
return 800;
return FontWeight(800);
}
if (aFcWeight <= FC_WEIGHT_BLACK) {
return 900;
return FontWeight(900);
}
// including FC_WEIGHT_EXTRABLACK
return 901;
return FontWeight(901);
}
static int16_t
@ -311,7 +311,7 @@ CreateFaceForPattern(FcPattern* aPattern)
}
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t *aData,
@ -334,7 +334,7 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
FcPattern* aFontPattern,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
: gfxFontEntry(aFaceName), mFontPattern(aFontPattern),
@ -1202,13 +1202,13 @@ gfxFontconfigFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
if (LOG_FONTLIST_ENABLED()) {
LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
" with style: %s weight: %d stretch: %d"
" with style: %s weight: %g stretch: %d"
" psname: %s fullname: %s",
NS_ConvertUTF16toUTF8(fontEntry->Name()).get(),
NS_ConvertUTF16toUTF8(Name()).get(),
(fontEntry->IsItalic()) ?
"italic" : (fontEntry->IsOblique() ? "oblique" : "normal"),
fontEntry->Weight(), fontEntry->Stretch(),
fontEntry->Weight().ToFloat(), fontEntry->Stretch(),
NS_ConvertUTF16toUTF8(psname).get(),
NS_ConvertUTF16toUTF8(fullname).get()));
}
@ -1857,7 +1857,7 @@ gfxFcPlatformFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
gfxFontEntry*
gfxFcPlatformFontList::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -1876,7 +1876,7 @@ gfxFcPlatformFontList::LookupLocalFont(const nsAString& aFontName,
gfxFontEntry*
gfxFcPlatformFontList::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -10,6 +10,7 @@
#include "gfxFontEntry.h"
#include "gfxFT2FontBase.h"
#include "gfxPlatformFontList.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/mozalloc.h"
#include "nsAutoRef.h"
#include "nsClassHashtable.h"
@ -93,7 +94,7 @@ public:
// used for data fonts where the fontentry takes ownership
// of the font data and the FT_Face
explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t *aData,
@ -103,7 +104,7 @@ public:
// used for @font-face local system fonts with explicit patterns
explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
FcPattern* aFontPattern,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle);
@ -287,11 +288,13 @@ public:
InfallibleTArray<mozilla::dom::SystemFontListEntry>* retValue);
gfxFontEntry*
LookupLocalFont(const nsAString& aFontName, uint16_t aWeight,
LookupLocalFont(const nsAString& aFontName,
FontWeight aWeight,
int16_t aStretch, uint8_t aStyle) override;
gfxFontEntry*
MakePlatformFont(const nsAString& aFontName, uint16_t aWeight,
MakePlatformFont(const nsAString& aFontName,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -7,6 +7,7 @@
#include "mozilla/BinarySearch.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/SVGContextPaint.h"
@ -3521,7 +3522,7 @@ gfxFont::GetSmallCapsFont()
style.size *= SMALL_CAPS_SCALE_FACTOR;
style.variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
gfxFontEntry* fe = GetFontEntry();
bool needsBold = style.weight >= 600 && !fe->IsBold();
bool needsBold = style.weight >= FontWeight(600) && !fe->IsBold();
return fe->FindOrMakeFont(&style, needsBold, mUnicodeRangeMap);
}
@ -3531,7 +3532,7 @@ gfxFont::GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel)
gfxFontStyle style(*GetStyle());
style.AdjustForSubSuperscript(aAppUnitsPerDevPixel);
gfxFontEntry* fe = GetFontEntry();
bool needsBold = style.weight >= 600 && !fe->IsBold();
bool needsBold = style.weight >= FontWeight(600) && !fe->IsBold();
return fe->FindOrMakeFont(&style, needsBold, mUnicodeRangeMap);
}
@ -4110,7 +4111,8 @@ gfxFontStyle::gfxFontStyle() :
size(DEFAULT_PIXEL_FONT_SIZE), sizeAdjust(-1.0f), baselineOffset(0.0f),
languageOverride(NO_FONT_LANGUAGE_OVERRIDE),
fontSmoothingBackgroundColor(NS_RGBA(0, 0, 0, 0)),
weight(NS_FONT_WEIGHT_NORMAL), stretch(NS_FONT_STRETCH_NORMAL),
weight(FontWeight::Normal()),
stretch(NS_FONT_STRETCH_NORMAL),
style(NS_FONT_STYLE_NORMAL),
variantCaps(NS_FONT_VARIANT_CAPS_NORMAL),
variantSubSuper(NS_FONT_VARIANT_POSITION_NORMAL),
@ -4121,7 +4123,9 @@ gfxFontStyle::gfxFontStyle() :
{
}
gfxFontStyle::gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
gfxFontStyle::gfxFontStyle(uint8_t aStyle,
FontWeight aWeight,
int16_t aStretch,
gfxFloat aSize,
nsAtom *aLanguage, bool aExplicitLanguage,
float aSizeAdjust, bool aSystemFont,
@ -4133,7 +4137,8 @@ gfxFontStyle::gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
size(aSize), sizeAdjust(aSizeAdjust), baselineOffset(0.0f),
languageOverride(aLanguageOverride),
fontSmoothingBackgroundColor(NS_RGBA(0, 0, 0, 0)),
weight(aWeight), stretch(aStretch),
weight(aWeight),
stretch(aStretch),
style(aStyle),
variantCaps(NS_FONT_VARIANT_CAPS_NORMAL),
variantSubSuper(NS_FONT_VARIANT_POSITION_NORMAL),
@ -4147,10 +4152,12 @@ gfxFontStyle::gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
MOZ_ASSERT(!mozilla::IsNaN(size));
MOZ_ASSERT(!mozilla::IsNaN(sizeAdjust));
if (weight > 900)
weight = 900;
if (weight < 100)
weight = 100;
if (weight > FontWeight(900)) {
weight = FontWeight(900);
}
if (weight < FontWeight(100)) {
weight = FontWeight(100);
}
if (size >= FONT_MAX_SIZE) {
size = FONT_MAX_SIZE;

Просмотреть файл

@ -25,6 +25,7 @@
#include "nsIObserver.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Attributes.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/TypedEnumBits.h"
#include "MainThreadUtils.h"
#include <algorithm>
@ -75,8 +76,10 @@ class SVGContextPaint;
} // namespace mozilla
struct gfxFontStyle {
typedef mozilla::FontWeight FontWeight;
gfxFontStyle();
gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
gfxFontStyle(uint8_t aStyle, FontWeight aWeight, int16_t aStretch,
gfxFloat aSize, nsAtom *aLanguage, bool aExplicitLanguage,
float aSizeAdjust, bool aSystemFont,
bool aPrinterFont,
@ -137,7 +140,7 @@ struct gfxFontStyle {
nscolor fontSmoothingBackgroundColor;
// The weight of the font: 100, 200, ... 900.
uint16_t weight;
FontWeight weight;
// The stretch of the font (the sum of various NS_FONT_STRETCH_*
// constants; see gfxFontConstants.h).
@ -184,8 +187,8 @@ struct gfxFontStyle {
}
PLDHashNumber Hash() const {
return ((style + (systemFont << 7) +
(weight << 8)) + uint32_t(size*1000) + int32_t(sizeAdjust*1000)) ^
return (style + (systemFont << 7) + (weight.ForHash() << 8) +
uint32_t(size*1000) + int32_t(sizeAdjust*1000)) ^
nsRefPtrHashKey<nsAtom>::HashKey(language);
}

Просмотреть файл

@ -3,12 +3,14 @@
* 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 "gfxFontEntry.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Logging.h"
#include "gfxFontEntry.h"
#include "gfxTextRun.h"
#include "gfxPlatform.h"
#include "nsGkAtoms.h"
@ -1234,24 +1236,25 @@ StretchDistance(int16_t aFontStretch, int16_t aTargetStretch)
// weight distance ==> [0,1598]
static inline uint32_t
WeightDistance(uint32_t aFontWeight, uint32_t aTargetWeight)
WeightDistance(FontWeight aFontWeight, FontWeight aTargetWeight)
{
// Compute a measure of the "distance" between the requested
// weight and the given fontEntry
int32_t distance = 0, addedDistance = 0;
float distance = 0.0f, addedDistance = 0.0f;
if (aTargetWeight != aFontWeight) {
if (aTargetWeight > 500) {
if (aTargetWeight > FontWeight(500)) {
distance = aFontWeight - aTargetWeight;
} else if (aTargetWeight < 400) {
} else if (aTargetWeight < FontWeight(400)) {
distance = aTargetWeight - aFontWeight;
} else {
// special case - target is between 400 and 500
// font weights between 400 and 500 are close
if (aFontWeight >= 400 && aFontWeight <= 500) {
if (aFontWeight >= FontWeight(400) &&
aFontWeight <= FontWeight(500)) {
if (aFontWeight < aTargetWeight) {
distance = 500 - aFontWeight;
distance = FontWeight(500) - aFontWeight;
} else {
distance = aFontWeight - aTargetWeight;
}
@ -1263,7 +1266,7 @@ WeightDistance(uint32_t aFontWeight, uint32_t aTargetWeight)
addedDistance = 100;
}
}
if (distance < 0) {
if (distance < 0.0f) {
distance = -distance + REVERSE_WEIGHT_DISTANCE;
}
distance += addedDistance;
@ -1307,7 +1310,7 @@ gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
aNeedsSyntheticBold = false;
bool wantBold = aFontStyle.weight >= 600;
bool wantBold = aFontStyle.weight >= FontWeight(600);
gfxFontEntry *fe = nullptr;
// If the family has only one face, we simply return it; no further
@ -1406,7 +1409,7 @@ gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
if (matched) {
aFontEntryList.AppendElement(matched);
if (!matched->IsBold() && aFontStyle.weight >= 600 &&
if (!matched->IsBold() && aFontStyle.weight >= FontWeight(600) &&
aFontStyle.allowSyntheticWeight) {
aNeedsSyntheticBold = true;
}
@ -1442,7 +1445,7 @@ gfxFontFamily::CheckForSimpleFamily()
return;
}
uint8_t faceIndex = (fe->IsItalic() ? kItalicMask : 0) |
(fe->Weight() >= 600 ? kBoldMask : 0);
(fe->Weight() >= FontWeight(600) ? kBoldMask : 0);
if (faces[faceIndex]) {
return; // two faces resolve to the same slot; family isn't "simple"
}
@ -1501,7 +1504,7 @@ CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle)
}
// measure of closeness of weight to the desired value
rank += 9 - Abs((aFontEntry->Weight() - aStyle->weight) / 100);
rank += 9 - Abs((aFontEntry->Weight() - aStyle->weight) / 100.0f);
} else {
// if no font to match, prefer non-bold, non-italic fonts
if (aFontEntry->IsUpright()) {

Просмотреть файл

@ -20,6 +20,7 @@
#include "nsUnicodeScriptCodes.h"
#include "nsDataHashtable.h"
#include "harfbuzz/hb.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
@ -109,6 +110,7 @@ struct gfxFontFeatureInfo {
class gfxFontEntry {
public:
typedef mozilla::FontWeight FontWeight;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::unicode::Script Script;
@ -139,7 +141,7 @@ public:
// returns Name() if nothing better is available.
virtual nsString RealFaceName();
uint16_t Weight() const { return mWeight; }
FontWeight Weight() const { return mWeight; }
int16_t Stretch() const { return mStretch; }
bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
@ -148,7 +150,7 @@ public:
bool IsItalic() const { return mStyle == NS_FONT_STYLE_ITALIC; }
bool IsOblique() const { return mStyle == NS_FONT_STYLE_OBLIQUE; }
bool IsUpright() const { return mStyle == NS_FONT_STYLE_NORMAL; }
bool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
bool IsBold() const { return mWeight >= FontWeight(600); } // bold == weights 600 and above
bool IgnoreGDEF() const { return mIgnoreGDEF; }
bool IgnoreGSUB() const { return mIgnoreGSUB; }
@ -161,7 +163,7 @@ public:
bool IsNormalStyle() const
{
return IsUpright() &&
Weight() == NS_FONT_WEIGHT_NORMAL &&
Weight() == FontWeight::Normal() &&
Stretch() == NS_FONT_STRETCH_NORMAL;
}
@ -402,7 +404,7 @@ public:
uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
uint16_t mWeight;
FontWeight mWeight;
int16_t mStretch;
RefPtr<gfxCharacterMap> mCharacterMap;

Просмотреть файл

@ -445,20 +445,20 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize)
{
GDIFontEntry *fe = static_cast<GDIFontEntry*>(GetFontEntry());
uint16_t weight;
FontWeight weight;
if (fe->IsUserFont()) {
if (fe->IsLocalUserFont()) {
// for local user fonts, don't change the original weight
// in the entry's logfont, because that could alter the
// choice of actual face used (bug 724231)
weight = 0;
weight = FontWeight(0);
} else {
// avoid GDI synthetic bold which occurs when weight
// specified is >= font data weight + 200
weight = mNeedsBold ? 700 : 200;
weight = mNeedsBold ? FontWeight(700) : FontWeight(200);
}
} else {
weight = mNeedsBold ? 700 : fe->Weight();
weight = mNeedsBold ? FontWeight(700) : fe->Weight();
}
fe->FillLogFont(&aLogFont, weight, aSize);

Просмотреть файл

@ -115,7 +115,8 @@ FontTypeToOutPrecision(uint8_t fontType)
GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
gfxWindowsFontType aFontType,
uint8_t aStyle, uint16_t aWeight,
uint8_t aStyle,
FontWeight aWeight,
int16_t aStretch,
gfxUserFontData *aUserFontData)
: gfxFontEntry(aFaceName),
@ -255,7 +256,8 @@ GDIFontEntry::LookupUnscaledFont(HFONT aFont)
void
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
uint16_t aWeight, gfxFloat aSize)
FontWeight aWeight,
gfxFloat aSize)
{
memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
@ -270,8 +272,8 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
// for installed families with no bold face, and for downloaded fonts
// (but NOT for local user fonts, because it could cause a different,
// glyph-incompatible face to be used)
if (aWeight) {
aLogFont->lfWeight = aWeight;
if (aWeight.ToFloat() != 0.0f) {
aLogFont->lfWeight = LONG(aWeight.ToFloat());
}
// for non-local() user fonts, we never want to apply italics here;
@ -303,7 +305,7 @@ GDIFontEntry::TestCharacterMap(uint32_t aCh)
if (!IsUpright()) {
fakeStyle.style = NS_FONT_STYLE_ITALIC;
}
fakeStyle.weight = mWeight * 100;
fakeStyle.weight = mWeight;
RefPtr<gfxFont> tempFont = FindOrMakeFont(&fakeStyle, false);
if (!tempFont || !tempFont->Valid())
@ -382,7 +384,7 @@ GDIFontEntry::InitLogFont(const nsAString& aName,
// it may give us a regular one based on weight. Windows should
// do fake italic for us in that case.
mLogFont.lfItalic = !IsUpright();
mLogFont.lfWeight = mWeight;
mLogFont.lfWeight = int(mWeight.ToFloat());
int len = std::min<int>(aName.Length(), LF_FACESIZE - 1);
memcpy(&mLogFont.lfFaceName, aName.BeginReading(), len * sizeof(char16_t));
@ -393,7 +395,8 @@ GDIFontEntry*
GDIFontEntry::CreateFontEntry(const nsAString& aName,
gfxWindowsFontType aFontType,
uint8_t aStyle,
uint16_t aWeight, int16_t aStretch,
FontWeight aWeight,
int16_t aStretch,
gfxUserFontData* aUserFontData)
{
// jtdfix - need to set charset, unicode ranges, pitch/family
@ -464,7 +467,7 @@ GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) {
fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get());
// check if we already know about this face
if (fe->mWeight == logFont.lfWeight &&
if (fe->mWeight == FontWeight(int32_t(logFont.lfWeight)) &&
fe->IsItalic() == (logFont.lfItalic == 0xFF)) {
// update the charset bit here since this could be different
// XXX Can we still do this now that we store mCharset
@ -481,7 +484,7 @@ GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL);
fe = GDIFontEntry::CreateFontEntry(nsDependentString(lpelfe->elfFullName),
feType, italicStyle,
(uint16_t) (logFont.lfWeight), 0,
FontWeight(int32_t(logFont.lfWeight)), 0,
nullptr);
if (!fe)
return 1;
@ -707,7 +710,7 @@ gfxGDIFontList::EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,
gfxFontEntry*
gfxGDIFontList::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -734,7 +737,7 @@ gfxGDIFontList::LookupLocalFont(const nsAString& aFontName,
fe->mIsLocalUserFont = true;
// make the new font entry match the userfont entry style characteristics
fe->mWeight = (aWeight == 0 ? 400 : aWeight);
fe->mWeight = (aWeight == FontWeight(0) ? FontWeight(400) : aWeight);
fe->mStyle = aStyle;
return fe;
@ -799,7 +802,7 @@ FixupSymbolEncodedFont(uint8_t* aFontData, uint32_t aLength)
gfxFontEntry*
gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
@ -864,7 +867,7 @@ gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
// make a new font entry using the unique name
WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
uint16_t w = (aWeight == 0 ? 400 : aWeight);
FontWeight w = (aWeight == FontWeight(0) ? FontWeight(400) : aWeight);
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName,
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef GFX_GDIFONTLIST_H
#define GFX_GDIFONTLIST_H
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "gfxWindowsPlatform.h"
#include "gfxPlatformFontList.h"
@ -107,11 +108,15 @@ enum gfxWindowsFontType {
class GDIFontEntry : public gfxFontEntry
{
public:
typedef mozilla::FontWeight FontWeight;
LPLOGFONTW GetLogFont() { return &mLogFont; }
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize);
void FillLogFont(LOGFONTW *aLogFont,
FontWeight aWeight,
gfxFloat aSize);
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
DWORD fontType)
@ -164,12 +169,13 @@ public:
static GDIFontEntry* CreateFontEntry(const nsAString& aName,
gfxWindowsFontType aFontType,
uint8_t aStyle,
uint16_t aWeight, int16_t aStretch,
FontWeight aWeight,
int16_t aStretch,
gfxUserFontData* aUserFontData);
// create a font entry for a font referenced by its fullname
static GDIFontEntry* LoadLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle);
@ -182,7 +188,7 @@ protected:
friend class gfxGDIFont;
GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType,
uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
uint8_t aStyle, FontWeight aWeight, int16_t aStretch,
gfxUserFontData *aUserFontData);
void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType);
@ -314,6 +320,8 @@ private:
class gfxGDIFontList : public gfxPlatformFontList {
public:
typedef mozilla::FontWeight FontWeight;
static gfxGDIFontList* PlatformFontList() {
return static_cast<gfxGDIFontList*>(sPlatformFontList);
}
@ -330,12 +338,12 @@ public:
gfxFloat aDevToCssSize = 1.0) override;
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle);
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -8,6 +8,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "nsDataHashtable.h"
#include "nsRefPtrHashtable.h"
@ -30,13 +31,13 @@ class MacOSFontEntry : public gfxFontEntry
public:
friend class gfxMacPlatformFontList;
MacOSFontEntry(const nsAString& aPostscriptName, int32_t aWeight,
MacOSFontEntry(const nsAString& aPostscriptName, FontWeight aWeight,
bool aIsStandardFace = false,
double aSizeHint = 0.0);
// for use with data fonts
MacOSFontEntry(const nsAString& aPostscriptName, CGFontRef aFontRef,
uint16_t aWeight, uint16_t aStretch, uint8_t aStyle,
FontWeight aWeight, uint16_t aStretch, uint8_t aStyle,
bool aIsDataUserFont, bool aIsLocal);
virtual ~MacOSFontEntry() {
@ -130,12 +131,12 @@ public:
bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) override;
gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle) override;
gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -65,6 +65,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Preferences.h"
#include "mozilla/Sprintf.h"
@ -363,7 +364,7 @@ MacOSFontEntry::IsCFF()
}
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
int32_t aWeight,
FontWeight aWeight,
bool aIsStandardFace,
double aSizeHint)
: gfxFontEntry(aPostscriptName, aIsStandardFace),
@ -387,7 +388,8 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
CGFontRef aFontRef,
uint16_t aWeight, uint16_t aStretch,
FontWeight aWeight,
uint16_t aStretch,
uint8_t aStyle,
bool aIsDataUserFont,
bool aIsLocalUserFont)
@ -902,7 +904,8 @@ gfxMacFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
// create a font entry
MacOSFontEntry *fontEntry =
new MacOSFontEntry(postscriptFontName, cssWeight, isStandardFace, mSizeHint);
new MacOSFontEntry(postscriptFontName, FontWeight(cssWeight),
isStandardFace, mSizeHint);
if (!fontEntry) {
break;
}
@ -1530,7 +1533,7 @@ gfxMacPlatformFontList::AppleWeightToCSSWeight(int32_t aAppleWeight)
gfxFontEntry*
gfxMacPlatformFontList::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -1545,8 +1548,8 @@ gfxMacPlatformFontList::LookupLocalFont(const nsAString& aFontName,
return nullptr;
}
NS_ASSERTION(aWeight >= 100 && aWeight <= 900,
"bogus font weight value!");
MOZ_ASSERT(aWeight >= FontWeight(100) && aWeight <= FontWeight(900),
"bogus font weight value!");
newFontEntry =
new MacOSFontEntry(aFontName, fontRef, aWeight, aStretch, aStyle,
@ -1563,7 +1566,7 @@ static void ReleaseData(void *info, const void *data, size_t size)
gfxFontEntry*
gfxMacPlatformFontList::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
@ -1571,7 +1574,8 @@ gfxMacPlatformFontList::MakePlatformFont(const nsAString& aFontName,
{
NS_ASSERTION(aFontData, "MakePlatformFont called with null data");
NS_ASSERTION(aWeight >= 100 && aWeight <= 900, "bogus font weight value!");
MOZ_ASSERT(aWeight >= FontWeight(100) && aWeight <= FontWeight(900),
"bogus font weight value!");
// create the font entry
nsAutoString uniqueName;
@ -1701,7 +1705,7 @@ gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID,
aFontStyle.style =
(traits & NSFontItalicTrait) ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL;
aFontStyle.weight =
(traits & NSFontBoldTrait) ? NS_FONT_WEIGHT_BOLD : NS_FONT_WEIGHT_NORMAL;
(traits & NSFontBoldTrait) ? FontWeight::Bold() : FontWeight::Normal();
aFontStyle.stretch =
(traits & NSFontExpandedTrait) ?
NS_FONT_STRETCH_EXPANDED : (traits & NSFontCondensedTrait) ?

Просмотреть файл

@ -3,6 +3,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 "mozilla/FontPropertyTypes.h"
#include "mozilla/layers/CompositorManagerChild.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeChild.h"
@ -1757,7 +1758,7 @@ gfxPlatform::IsFontFormatSupported(uint32_t aFormatFlags)
gfxFontEntry*
gfxPlatform::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -1769,7 +1770,7 @@ gfxPlatform::LookupLocalFont(const nsAString& aFontName,
gfxFontEntry*
gfxPlatform::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef GFX_PLATFORM_H
#define GFX_PLATFORM_H
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/Logging.h"
#include "mozilla/gfx/Types.h"
#include "nsTArray.h"
@ -158,6 +159,7 @@ class gfxPlatform {
friend class SRGBOverrideObserver;
public:
typedef mozilla::FontWeight FontWeight;
typedef mozilla::gfx::Color Color;
typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
typedef mozilla::gfx::DrawTarget DrawTarget;
@ -391,7 +393,7 @@ public:
* who must either AddRef() or delete.
*/
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle);
@ -404,7 +406,7 @@ public:
* who must either AddRef() or delete.
*/
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -19,6 +19,7 @@
#include "nsIMemoryReporter.h"
#include "mozilla/Attributes.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
#include "mozilla/RangedArray.h"
@ -97,6 +98,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader
friend class InitOtherFamilyNamesRunnable;
public:
typedef mozilla::FontWeight FontWeight;
typedef mozilla::unicode::Script Script;
static gfxPlatformFontList* PlatformFontList() {
@ -186,14 +188,14 @@ public:
// look up a font by name on the host platform
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle) = 0;
// create a new platform font from downloaded data (@font-face)
// this method is responsible to ensure aFontData is free()'d
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -26,6 +26,7 @@
#include "base/task.h"
#include "base/thread.h"
#include "base/message_loop.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/2D.h"
@ -274,7 +275,7 @@ gfxPlatformGtk::CreateFontGroup(const FontFamilyList& aFontFamilyList,
gfxFontEntry*
gfxPlatformGtk::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle)
{
@ -285,7 +286,7 @@ gfxPlatformGtk::LookupLocalFont(const nsAString& aFontName,
gfxFontEntry*
gfxPlatformGtk::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -66,7 +66,7 @@ public:
* support @font-face src local() )
*/
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle) override;
@ -75,7 +75,7 @@ public:
*
*/
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
FontWeight aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,

Просмотреть файл

@ -1768,9 +1768,9 @@ gfxTextRun::Dump(FILE* aOutput) {
NS_ConvertUTF16toUTF8 fontName(font->GetName());
nsAutoCString lang;
style->language->ToUTF8String(lang);
fprintf(aOutput, "%d: %s %f/%d/%d/%s", glyphRuns[i].mCharacterOffset,
fprintf(aOutput, "%d: %s %f/%g/%d/%s", glyphRuns[i].mCharacterOffset,
fontName.get(), style->size,
style->weight, style->style, lang.get());
style->weight.ToFloat(), style->style, lang.get());
}
fputc(']', aOutput);
}
@ -2416,7 +2416,7 @@ gfxFontGroup::InitTextRun(DrawTarget* aDrawTarget,
nsAutoCString str((const char*)aString, aLength);
MOZ_LOG(log, LogLevel::Warning,\
("(%s) fontgroup: [%s] default: %s lang: %s script: %d "
"len %d weight: %d width: %d style: %s size: %6.2f %zu-byte "
"len %d weight: %g width: %d style: %s size: %6.2f %zu-byte "
"TEXTRUN [%s] ENDTEXTRUN\n",
(mStyle.systemFont ? "textrunui" : "textrun"),
NS_ConvertUTF16toUTF8(families).get(),
@ -2425,7 +2425,7 @@ gfxFontGroup::InitTextRun(DrawTarget* aDrawTarget,
(mFamilyList.GetDefaultFontType() == eFamily_sans_serif ?
"sans-serif" : "none")),
lang.get(), static_cast<int>(Script::LATIN), aLength,
uint32_t(mStyle.weight), uint32_t(mStyle.stretch),
mStyle.weight.ToFloat(), uint32_t(mStyle.stretch),
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
"normal")),
@ -2464,7 +2464,7 @@ gfxFontGroup::InitTextRun(DrawTarget* aDrawTarget,
uint32_t runLen = runLimit - runStart;
MOZ_LOG(log, LogLevel::Warning,\
("(%s) fontgroup: [%s] default: %s lang: %s script: %d "
"len %d weight: %d width: %d style: %s size: %6.2f "
"len %d weight: %g width: %d style: %s size: %6.2f "
"%zu-byte TEXTRUN [%s] ENDTEXTRUN\n",
(mStyle.systemFont ? "textrunui" : "textrun"),
NS_ConvertUTF16toUTF8(families).get(),
@ -2473,7 +2473,7 @@ gfxFontGroup::InitTextRun(DrawTarget* aDrawTarget,
(mFamilyList.GetDefaultFontType() == eFamily_sans_serif ?
"sans-serif" : "none")),
lang.get(), static_cast<int>(runScript), runLen,
uint32_t(mStyle.weight), uint32_t(mStyle.stretch),
mStyle.weight.ToFloat(), uint32_t(mStyle.stretch),
(mStyle.style & NS_FONT_STYLE_ITALIC ? "italic" :
(mStyle.style & NS_FONT_STYLE_OBLIQUE ? "oblique" :
"normal")),
@ -2818,7 +2818,7 @@ gfxFontGroup::FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh)
return nullptr;
}
bool needsBold = mStyle.weight >= 600 && !fe->IsBold() &&
bool needsBold = mStyle.weight >= FontWeight(600) && !fe->IsBold() &&
mStyle.allowSyntheticWeight;
return fe->FindOrMakeFont(&mStyle, needsBold);
}
@ -3444,7 +3444,7 @@ gfxFontGroup::WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
gfxPlatformFontList::PlatformFontList()->
SystemFindFontForChar(aCh, aNextCh, aRunScript, &mStyle);
if (fe) {
bool wantBold = mStyle.weight >= 600;
bool wantBold = mStyle.weight >= FontWeight(600);
return fe->FindOrMakeFont(&mStyle, wantBold && !fe->IsBold());
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "gfxPrefs.h"
#include "nsIProtocolHandler.h"
#include "gfxFontConstants.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
@ -104,7 +105,7 @@ private:
gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet* aFontSet,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -120,8 +121,8 @@ gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet* aFontSet,
mLoader(nullptr),
mFontSet(aFontSet)
{
MOZ_ASSERT(aWeight != 0,
"aWeight must not be 0; use NS_FONT_WEIGHT_NORMAL instead");
MOZ_ASSERT(aWeight != FontWeight(0),
"aWeight must not be 0; use FontWeight::Normal() instead");
mIsUserFontContainer = true;
mSrcList = aFontFaceSrcList;
mSrcIndex = 0;
@ -144,7 +145,7 @@ gfxUserFontEntry::~gfxUserFontEntry()
bool
gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -935,7 +936,7 @@ already_AddRefed<gfxUserFontEntry>
gfxUserFontSet::FindOrCreateUserFontEntry(
const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -975,7 +976,7 @@ gfxUserFontSet::FindOrCreateUserFontEntry(
already_AddRefed<gfxUserFontEntry>
gfxUserFontSet::CreateUserFontEntry(
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -996,7 +997,7 @@ gfxUserFontEntry*
gfxUserFontSet::FindExistingUserFontEntry(
gfxUserFontFamily* aFamily,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -1005,8 +1006,8 @@ gfxUserFontSet::FindExistingUserFontEntry(
gfxCharacterMap* aUnicodeRanges,
uint8_t aFontDisplay)
{
MOZ_ASSERT(aWeight != 0,
"aWeight must not be 0; use NS_FONT_WEIGHT_NORMAL instead");
MOZ_ASSERT(aWeight != FontWeight(0),
"aWeight must not be 0; use FontWeight::Normal() instead");
nsTArray<RefPtr<gfxFontEntry>>& fontList = aFamily->GetFontList();
@ -1039,12 +1040,12 @@ gfxUserFontSet::AddUserFontEntry(const nsAString& aFamilyName,
family->AddFontEntry(aUserFontEntry);
if (LOG_ENABLED()) {
LOG(("userfonts (%p) added to \"%s\" (%p) style: %s weight: %d "
LOG(("userfonts (%p) added to \"%s\" (%p) style: %s weight: %g "
"stretch: %d display: %d",
this, NS_ConvertUTF16toUTF8(aFamilyName).get(), aUserFontEntry,
(aUserFontEntry->IsItalic() ? "italic" :
(aUserFontEntry->IsOblique() ? "oblique" : "normal")),
aUserFontEntry->Weight(), aUserFontEntry->Stretch(),
aUserFontEntry->Weight().ToFloat(), aUserFontEntry->Stretch(),
aUserFontEntry->GetFontDisplay()));
}
}

Просмотреть файл

@ -16,6 +16,7 @@
#include "nsIPrincipal.h"
#include "nsIScriptError.h"
#include "nsURIHashKey.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/net/ReferrerPolicy.h"
#include "gfxFontConstants.h"
@ -184,6 +185,7 @@ class gfxUserFontSet {
friend class gfxOTSContext;
public:
typedef mozilla::FontWeight FontWeight;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxUserFontSet)
@ -229,7 +231,7 @@ public:
// TODO: support for unicode ranges not yet implemented
virtual already_AddRefed<gfxUserFontEntry> CreateUserFontEntry(
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -243,7 +245,7 @@ public:
already_AddRefed<gfxUserFontEntry> FindOrCreateUserFontEntry(
const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -404,8 +406,8 @@ public:
HashFeatures(aKey->mFontEntry->mFeatureSettings),
HashVariations(aKey->mFontEntry->mVariationSettings),
mozilla::HashString(aKey->mFontEntry->mFamilyName),
aKey->mFontEntry->mWeight.ForHash(),
(aKey->mFontEntry->mStyle |
(aKey->mFontEntry->mWeight << 2) |
(aKey->mFontEntry->mStretch << 11) ) ^
aKey->mFontEntry->mLanguageOverride);
}
@ -497,7 +499,7 @@ protected:
gfxUserFontEntry* FindExistingUserFontEntry(
gfxUserFontFamily* aFamily,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -537,6 +539,8 @@ class gfxUserFontEntry : public gfxFontEntry {
friend class gfxOTSContext;
public:
typedef mozilla::FontWeight FontWeight;
enum UserFontLoadState {
STATUS_NOT_LOADED = 0,
STATUS_LOAD_PENDING,
@ -547,7 +551,7 @@ public:
gfxUserFontEntry(gfxUserFontSet* aFontSet,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
@ -560,7 +564,7 @@ public:
// Return whether the entry matches the given list of attributes
bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
FontWeight aWeight,
int32_t aStretch,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,

Просмотреть файл

@ -100,6 +100,9 @@ RenderThread::ShutDownTask(layers::SynchronousTask* aTask)
{
layers::AutoCompleteTask complete(aTask);
MOZ_ASSERT(IsInRenderThread());
MutexAutoLock lock(mRenderTextureMapLock);
mRenderTextures.Clear();
}
// static

Просмотреть файл

@ -456,10 +456,9 @@ fn get_proc_address(glcontext_ptr: *mut c_void,
let symbol_name = CString::new(name).unwrap();
let symbol = unsafe { get_proc_address_from_glcontext(glcontext_ptr, symbol_name.as_ptr()) };
// For now panic, not sure we should be though or if we can recover
if symbol.is_null() {
// XXX Bug 1322949 Make whitelist for extensions
println!("Could not find symbol {:?} by glcontext", symbol_name);
warn!("Could not find symbol {:?} by glcontext", symbol_name);
}
symbol as *const _
@ -564,7 +563,7 @@ pub extern "C" fn wr_renderer_render(renderer: &mut Renderer,
Ok(_) => true,
Err(errors) => {
for e in errors {
println!(" Failed to render: {:?}", e);
warn!(" Failed to render: {:?}", e);
let msg = CString::new(format!("wr_renderer_render: {:?}", e)).unwrap();
unsafe {
gfx_critical_note(msg.as_ptr());
@ -836,7 +835,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
let version = gl.get_string(gl::VERSION);
println!("WebRender - OpenGL version new {}", version);
info!("WebRender - OpenGL version new {}", version);
let workers = unsafe {
Arc::clone(&(*thread_pool).0)
@ -879,7 +878,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
let (renderer, sender) = match Renderer::new(gl, notifier, opts) {
Ok((renderer, sender)) => (renderer, sender),
Err(e) => {
println!(" Failed to create a Renderer: {:?}", e);
warn!(" Failed to create a Renderer: {:?}", e);
let msg = CString::new(format!("wr_window_new: {:?}", e)).unwrap();
unsafe {
gfx_critical_note(msg.as_ptr());
@ -1323,7 +1322,7 @@ pub extern "C" fn wr_api_capture(
file.write(revision).unwrap();
}
Err(e) => {
println!("Unable to create path '{:?}' for capture: {:?}", path, e);
warn!("Unable to create path '{:?}' for capture: {:?}", path, e);
return
}
}

Просмотреть файл

@ -10,6 +10,8 @@ extern crate app_units;
extern crate gleam;
extern crate rayon;
extern crate thread_profiler;
#[macro_use]
extern crate log;
#[cfg(target_os = "windows")]

Просмотреть файл

@ -17,6 +17,7 @@ AnimationFrameBuffer::AnimationFrameBuffer()
, mInsertIndex(0)
, mGetIndex(0)
, mSizeKnown(false)
, mRedecodeError(false)
{ }
void
@ -71,7 +72,16 @@ AnimationFrameBuffer::Insert(RawAccessFrameRef&& aFrame)
// and we did not keep all of the frames. Replace whatever is there
// (probably an empty frame) with the new frame.
MOZ_ASSERT(MayDiscard());
MOZ_ASSERT(mInsertIndex < mFrames.Length());
// The first decode produced fewer frames than the redecodes, presumably
// because it hit an out-of-memory error which later attempts avoided. Just
// stop the animation because we can't tell the image that we have more
// frames now.
if (mInsertIndex >= mFrames.Length()) {
mRedecodeError = true;
mPending = 0;
return false;
}
if (mInsertIndex > 0) {
MOZ_ASSERT(!mFrames[mInsertIndex]);
@ -127,9 +137,23 @@ AnimationFrameBuffer::Insert(RawAccessFrameRef&& aFrame)
bool
AnimationFrameBuffer::MarkComplete()
{
// We may have stopped decoding at a different point in the animation than we
// did previously. That means the decoder likely hit a new error, e.g. OOM.
// This will prevent us from advancing as well, because we are missing the
// required frames to blend.
//
// XXX(aosmond): In an ideal world, we would be generating full frames, and
// the consumer of our data doesn't care about our internal state. It simply
// knows about the first frame, the current frame, and how long to display the
// current frame.
if (NS_WARN_IF(mInsertIndex != mFrames.Length())) {
MOZ_ASSERT(mSizeKnown);
mRedecodeError = true;
mPending = 0;
}
// We reached the end of the animation, the next frame we get, if we get
// another, will be the first frame again.
MOZ_ASSERT(mInsertIndex == mFrames.Length());
mInsertIndex = 0;
// Since we only request advancing when we want to resume at a certain point
@ -231,7 +255,7 @@ AnimationFrameBuffer::AdvanceInternal()
}
}
if (!mSizeKnown || MayDiscard()) {
if (!mRedecodeError && (!mSizeKnown || MayDiscard())) {
// Calculate how many frames we have requested ahead of the current frame.
size_t buffered = mPending;
if (mGetIndex > mInsertIndex) {
@ -276,13 +300,6 @@ AnimationFrameBuffer::Reset()
return false;
}
// If we are over the threshold, then we know we will have missing frames in
// our buffer. The easiest thing to do is to drop everything but the first
// frame and go back to the initial state.
bool restartDecoder = mPending == 0;
mInsertIndex = 0;
mPending = 2 * mBatch;
// Discard all frames besides the first, because the decoder always expects
// that when it re-inserts a frame, it is not present. (It doesn't re-insert
// the first frame.)
@ -290,6 +307,16 @@ AnimationFrameBuffer::Reset()
RawAccessFrameRef discard = Move(mFrames[i]);
}
mInsertIndex = 0;
// If we hit an error after redecoding, we never want to restart decoding.
if (mRedecodeError) {
MOZ_ASSERT(mPending == 0);
return false;
}
bool restartDecoder = mPending == 0;
mPending = 2 * mBatch;
return restartDecoder;
}

Просмотреть файл

@ -129,6 +129,12 @@ public:
*/
bool SizeKnown() const { return mSizeKnown; }
/**
* @returns True if encountered an error during redecode which should cause
* the caller to stop inserting frames.
*/
bool HasRedecodeError() const { return mRedecodeError; }
/**
* @returns The current frame index we have advanced to.
*/
@ -187,6 +193,9 @@ private:
// True if the total number of frames is known.
bool mSizeKnown;
// True if we encountered an error while redecoding.
bool mRedecodeError;
};
} // namespace image

Просмотреть файл

@ -224,13 +224,14 @@ AnimationSurfaceProvider::Run()
FinishDecoding();
// Even if it is the last frame, we may not have enough frames buffered
// ahead of the current.
if (continueDecoding) {
MOZ_ASSERT(mDecoder);
continue;
// ahead of the current. If we are shutting down, we want to ensure we
// release the thread as soon as possible. The animation may advance even
// during shutdown, which keeps us decoding, and thus blocking the decode
// pool during teardown.
if (!mDecoder || !continueDecoding ||
DecodePool::Singleton()->IsShuttingDown()) {
return;
}
return;
}
// Notify for the progress we've made so far.
@ -245,9 +246,13 @@ AnimationSurfaceProvider::Run()
}
// There's new output available - a new frame! Grab it. If we don't need any
// more for the moment we can break out of the loop.
// more for the moment we can break out of the loop. If we are shutting
// down, we want to ensure we release the thread as soon as possible. The
// animation may advance even during shutdown, which keeps us decoding, and
// thus blocking the decode pool during teardown.
MOZ_ASSERT(result == LexerResult(Yield::OUTPUT_AVAILABLE));
if (!CheckForNewFrameAtYield()) {
if (!CheckForNewFrameAtYield() ||
DecodePool::Singleton()->IsShuttingDown()) {
return;
}
}
@ -294,10 +299,7 @@ AnimationSurfaceProvider::CheckForNewFrameAtYield()
AnnounceSurfaceAvailable();
}
// If we are shutting down, we want to ensure we release the thread as soon
// as possible. The animation may advance even during shutdown, which keeps
// us decoding, and thus blocking the decode pool during teardown.
return continueDecoding && !DecodePool::Singleton()->IsShuttingDown();
return continueDecoding;
}
bool
@ -347,10 +349,7 @@ AnimationSurfaceProvider::CheckForNewFrameAtTerminalState()
AnnounceSurfaceAvailable();
}
// If we are shutting down, we want to ensure we release the thread as soon
// as possible. The animation may advance even during shutdown, which keeps
// us decoding, and thus blocking the decode pool during teardown.
return continueDecoding && !DecodePool::Singleton()->IsShuttingDown();
return continueDecoding;
}
void
@ -378,15 +377,15 @@ AnimationSurfaceProvider::FinishDecoding()
NotifyDecodeComplete(WrapNotNull(mImage), WrapNotNull(mDecoder));
}
// Destroy our decoder; we don't need it anymore.
bool mayDiscard;
// Determine if we need to recreate the decoder, in case we are discarding
// frames and need to loop back to the beginning.
bool recreateDecoder;
{
MutexAutoLock lock(mFramesMutex);
mayDiscard = mFrames.MayDiscard();
recreateDecoder = !mFrames.HasRedecodeError() && mFrames.MayDiscard();
}
if (mayDiscard) {
// Recreate the decoder so we can regenerate the frames again.
if (recreateDecoder) {
mDecoder = DecoderFactory::CloneAnimationDecoder(mDecoder);
MOZ_ASSERT(mDecoder);
} else {

Просмотреть файл

@ -143,6 +143,7 @@ TEST_F(ImageAnimationFrameBuffer, FinishUnderBatchAndThreshold)
EXPECT_FALSE(keepDecoding);
EXPECT_TRUE(buffer.SizeKnown());
EXPECT_EQ(size_t(0), buffer.PendingDecode());
EXPECT_FALSE(buffer.HasRedecodeError());
}
EXPECT_FALSE(buffer.MayDiscard());
@ -220,6 +221,7 @@ TEST_F(ImageAnimationFrameBuffer, FinishMultipleBatchesUnderThreshold)
EXPECT_TRUE(buffer.SizeKnown());
EXPECT_EQ(size_t(0), buffer.PendingDecode());
EXPECT_EQ(size_t(5), frames.Length());
EXPECT_FALSE(buffer.HasRedecodeError());
// Finish progressing through the animation.
for ( ; i < frames.Length(); ++i) {
@ -330,6 +332,7 @@ TEST_F(ImageAnimationFrameBuffer, MayDiscard)
EXPECT_TRUE(buffer.SizeKnown());
EXPECT_EQ(size_t(2), buffer.PendingDecode());
EXPECT_EQ(size_t(10), frames.Length());
EXPECT_FALSE(buffer.HasRedecodeError());
// Use remaining pending room. It shouldn't add new frames, only replace.
do {
@ -513,3 +516,159 @@ TEST_F(ImageAnimationFrameBuffer, StartAfterBeginningAndReset)
EXPECT_EQ(size_t(0), buffer.PendingAdvance());
}
TEST_F(ImageAnimationFrameBuffer, RedecodeMoreFrames)
{
const size_t kThreshold = 5;
const size_t kBatch = 2;
AnimationFrameBuffer buffer;
buffer.Initialize(kThreshold, kBatch, 0);
const auto& frames = buffer.Frames();
// Add frames until we exceed the threshold.
bool keepDecoding;
bool restartDecoder;
size_t i = 0;
do {
keepDecoding = buffer.Insert(CreateEmptyFrame());
EXPECT_TRUE(keepDecoding);
if (i > 0) {
restartDecoder = buffer.AdvanceTo(i);
EXPECT_FALSE(restartDecoder);
}
++i;
} while (!buffer.MayDiscard());
// Should have threshold + 1 frames, and still not complete.
EXPECT_EQ(size_t(6), frames.Length());
EXPECT_FALSE(buffer.SizeKnown());
// Now we lock in at 6 frames.
keepDecoding = buffer.MarkComplete();
EXPECT_TRUE(keepDecoding);
EXPECT_TRUE(buffer.SizeKnown());
EXPECT_FALSE(buffer.HasRedecodeError());
// Reinsert 6 frames first.
i = 0;
do {
keepDecoding = buffer.Insert(CreateEmptyFrame());
EXPECT_TRUE(keepDecoding);
restartDecoder = buffer.AdvanceTo(i);
EXPECT_FALSE(restartDecoder);
++i;
} while (i < 6);
// We should now encounter an error and shutdown further decodes.
keepDecoding = buffer.Insert(CreateEmptyFrame());
EXPECT_FALSE(keepDecoding);
EXPECT_EQ(size_t(0), buffer.PendingDecode());
EXPECT_TRUE(buffer.HasRedecodeError());
}
TEST_F(ImageAnimationFrameBuffer, RedecodeFewerFrames)
{
const size_t kThreshold = 5;
const size_t kBatch = 2;
AnimationFrameBuffer buffer;
buffer.Initialize(kThreshold, kBatch, 0);
const auto& frames = buffer.Frames();
// Add frames until we exceed the threshold.
bool keepDecoding;
bool restartDecoder;
size_t i = 0;
do {
keepDecoding = buffer.Insert(CreateEmptyFrame());
EXPECT_TRUE(keepDecoding);
if (i > 0) {
restartDecoder = buffer.AdvanceTo(i);
EXPECT_FALSE(restartDecoder);
}
++i;
} while (!buffer.MayDiscard());
// Should have threshold + 1 frames, and still not complete.
EXPECT_EQ(size_t(6), frames.Length());
EXPECT_FALSE(buffer.SizeKnown());
// Now we lock in at 6 frames.
keepDecoding = buffer.MarkComplete();
EXPECT_TRUE(keepDecoding);
EXPECT_TRUE(buffer.SizeKnown());
EXPECT_FALSE(buffer.HasRedecodeError());
// Reinsert 5 frames before marking complete.
i = 0;
do {
keepDecoding = buffer.Insert(CreateEmptyFrame());
EXPECT_TRUE(keepDecoding);
restartDecoder = buffer.AdvanceTo(i);
EXPECT_FALSE(restartDecoder);
++i;
} while (i < 5);
// We should now encounter an error and shutdown further decodes.
keepDecoding = buffer.MarkComplete();
EXPECT_FALSE(keepDecoding);
EXPECT_EQ(size_t(0), buffer.PendingDecode());
EXPECT_TRUE(buffer.HasRedecodeError());
}
TEST_F(ImageAnimationFrameBuffer, RedecodeFewerFramesAndBehindAdvancing)
{
const size_t kThreshold = 5;
const size_t kBatch = 2;
AnimationFrameBuffer buffer;
buffer.Initialize(kThreshold, kBatch, 0);
const auto& frames = buffer.Frames();
// Add frames until we exceed the threshold.
bool keepDecoding;
bool restartDecoder;
size_t i = 0;
do {
keepDecoding = buffer.Insert(CreateEmptyFrame());
EXPECT_TRUE(keepDecoding);
if (i > 0) {
restartDecoder = buffer.AdvanceTo(i);
EXPECT_FALSE(restartDecoder);
}
++i;
} while (!buffer.MayDiscard());
// Should have threshold + 1 frames, and still not complete.
EXPECT_EQ(size_t(6), frames.Length());
EXPECT_FALSE(buffer.SizeKnown());
// Now we lock in at 6 frames.
keepDecoding = buffer.MarkComplete();
EXPECT_TRUE(keepDecoding);
EXPECT_TRUE(buffer.SizeKnown());
EXPECT_FALSE(buffer.HasRedecodeError());
// Reinsert frames without advancing until we exhaust our pending space. This
// should be less than the current buffer length by definition.
i = 0;
do {
keepDecoding = buffer.Insert(CreateEmptyFrame());
++i;
} while (keepDecoding);
EXPECT_EQ(size_t(2), i);
// We should now encounter an error and shutdown further decodes.
keepDecoding = buffer.MarkComplete();
EXPECT_FALSE(keepDecoding);
EXPECT_EQ(size_t(0), buffer.PendingDecode());
EXPECT_TRUE(buffer.HasRedecodeError());
// We should however be able to continue advancing to the last decoded frame
// without it requesting the decoder to restart.
i = 0;
do {
restartDecoder = buffer.AdvanceTo(i);
EXPECT_FALSE(restartDecoder);
++i;
} while (i < 2);
}

Просмотреть файл

@ -587,6 +587,19 @@ WasmSaturatingTruncationSupported(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
WasmGcEnabled(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
#ifdef ENABLE_WASM_GC
bool isSupported = cx->options().wasmBaseline() && cx->options().wasmGc();
#else
bool isSupported = false;
#endif
args.rval().setBoolean(isSupported);
return true;
}
static bool
WasmCompileMode(JSContext* cx, unsigned argc, Value* vp)
{
@ -5503,6 +5516,10 @@ gc::ZealModeHelpText),
" Returns a boolean indicating whether a given module has finished compiled code for tier2. \n"
"This will return true early if compilation isn't two-tiered. "),
JS_FN_HELP("wasmGcEnabled", WasmGcEnabled, 1, 0,
"wasmGcEnabled(bool)",
" Returns a boolean indicating whether the WebAssembly GC support is enabled."),
JS_FN_HELP("isLazyFunction", IsLazyFunction, 1, 0,
"isLazyFunction(fun)",
" True if fun is a lazy JSFunction."),

Просмотреть файл

@ -0,0 +1,383 @@
// Ensure that if gc types aren't enabled, test cases properly fail.
if (!wasmGcEnabled()) {
quit(0);
}
// Dummy constructor.
function Baguette(calories) {
this.calories = calories;
}
// Type checking.
const { validate, CompileError } = WebAssembly;
assertErrorMessage(() => wasmEvalText(`(module
(func (result anyref)
i32.const 42
)
)`), CompileError, mismatchError('i32', 'anyref'));
assertErrorMessage(() => wasmEvalText(`(module
(func (result anyref)
i32.const 0
ref.null anyref
i32.const 42
select
)
)`), CompileError, /select operand types/);
assertErrorMessage(() => wasmEvalText(`(module
(func (result i32)
ref.null anyref
if
i32.const 42
end
)
)`), CompileError, mismatchError('anyref', 'i32'));
// Basic compilation tests.
let simpleTests = [
"(module (func (drop (ref.null anyref))))",
"(module (func $test (local anyref)))",
"(module (func $test (param anyref)))",
"(module (func $test (result anyref) (ref.null anyref)))",
"(module (func $test (block anyref (unreachable)) unreachable))",
"(module (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
`(module (import "a" "b" (param anyref)))`,
`(module (import "a" "b" (result anyref)))`,
];
for (let src of simpleTests) {
wasmEvalText(src, {a:{b(){}}});
assertEq(validate(wasmTextToBinary(src)), true);
}
// Basic behavioral tests.
let { exports } = wasmEvalText(`(module
(func (export "is_null") (result i32)
ref.null anyref
ref.is_null
)
(func $sum (result i32) (param i32)
get_local 0
i32.const 42
i32.add
)
(func (export "is_null_spill") (result i32)
ref.null anyref
i32.const 58
call $sum
drop
ref.is_null
)
(func (export "is_null_local") (result i32) (local anyref)
ref.null anyref
set_local 0
i32.const 58
call $sum
drop
get_local 0
ref.is_null
)
)`);
assertEq(exports.is_null(), 1);
assertEq(exports.is_null_spill(), 1);
assertEq(exports.is_null_local(), 1);
// Anyref param and result in wasm functions.
exports = wasmEvalText(`(module
(func (export "is_null") (result i32) (param $ref anyref)
get_local $ref
ref.is_null
)
(func (export "ref_or_null") (result anyref) (param $ref anyref) (param $selector i32)
get_local $ref
ref.null anyref
get_local $selector
select
)
(func $recursive (export "nested") (result anyref) (param $ref anyref) (param $i i32)
;; i == 10 => ret $ref
get_local $i
i32.const 10
i32.eq
if
get_local $ref
return
end
get_local $ref
get_local $i
i32.const 1
i32.add
call $recursive
)
)`).exports;
assertErrorMessage(() => exports.is_null(undefined), TypeError, "can't convert undefined to object");
assertEq(exports.is_null(null), 1);
assertEq(exports.is_null({}), 0);
assertEq(exports.is_null("hi"), 0);
assertEq(exports.is_null(3), 0);
assertEq(exports.is_null(3.5), 0);
assertEq(exports.is_null(true), 0);
assertEq(exports.is_null(Symbol("croissant")), 0);
assertEq(exports.is_null(new Baguette(100)), 0);
let baguette = new Baguette(42);
assertEq(exports.ref_or_null(null, 0), null);
assertEq(exports.ref_or_null(baguette, 0), null);
let ref = exports.ref_or_null(baguette, 1);
assertEq(ref, baguette);
assertEq(ref.calories, baguette.calories);
ref = exports.nested(baguette, 0);
assertEq(ref, baguette);
assertEq(ref.calories, baguette.calories);
// More interesting use cases about control flow joins.
function assertJoin(body) {
let val = { i: -1 };
assertEq(wasmEvalText(`(module
(func (export "test") (param $ref anyref) (param $i i32) (result anyref)
${body}
)
)`).exports.test(val), val);
assertEq(val.i, -1);
}
assertJoin("(block anyref get_local $ref)");
assertJoin("(block $out anyref get_local $ref br $out)");
assertJoin("(loop anyref get_local $ref)");
assertJoin(`(block $out anyref (loop $top anyref
get_local $i
i32.const 1
i32.add
tee_local $i
i32.const 10
i32.eq
if
get_local $ref
return
end
br $top))
`);
assertJoin(`(block $out (loop $top
get_local $i
i32.const 1
i32.add
tee_local $i
i32.const 10
i32.le_s
if
br $top
else
get_local $ref
return
end
)) unreachable
`);
assertJoin(`(block $out anyref (loop $top
get_local $ref
get_local $i
i32.const 1
i32.add
tee_local $i
i32.const 10
i32.eq
br_if $out
br $top
) unreachable)
`);
assertJoin(`(block $out anyref (block $unreachable anyref (loop $top
get_local $ref
get_local $i
i32.const 1
i32.add
tee_local $i
br_table $unreachable $out
) unreachable))
`);
let x = { i: 42 }, y = { f: 53 };
exports = wasmEvalText(`(module
(func (export "test") (param $lhs anyref) (param $rhs anyref) (param $i i32) (result anyref)
get_local $lhs
get_local $rhs
get_local $i
select
)
)`).exports;
let result = exports.test(x, y, 0);
assertEq(result, y);
assertEq(result.i, undefined);
assertEq(result.f, 53);
assertEq(x.i, 42);
result = exports.test(x, y, 1);
assertEq(result, x);
assertEq(result.i, 42);
assertEq(result.f, undefined);
assertEq(y.f, 53);
// Anyref in params/result of imported functions.
let firstBaguette = new Baguette(13),
secondBaguette = new Baguette(37);
let imports = {
i: 0,
myBaguette: null,
funcs: {
param(x) {
if (this.i === 0) {
assertEq(x, firstBaguette);
assertEq(x.calories, 13);
assertEq(secondBaguette !== null, true);
} else if (this.i === 1 || this.i === 2) {
assertEq(x, secondBaguette);
assertEq(x.calories, 37);
assertEq(firstBaguette !== null, true);
} else if (this.i === 3) {
assertEq(x, null);
} else {
firstBaguette = null;
secondBaguette = null;
gc(); // evil mode
}
this.i++;
},
ret() {
return imports.myBaguette;
}
}
};
exports = wasmEvalText(`(module
(import $ret "funcs" "ret" (result anyref))
(import $param "funcs" "param" (param anyref))
(func (export "param") (param $x anyref) (param $y anyref)
get_local $y
get_local $x
call $param
call $param
)
(func (export "ret") (result anyref)
call $ret
)
)`, imports).exports;
exports.param(firstBaguette, secondBaguette);
exports.param(secondBaguette, null);
exports.param(firstBaguette, secondBaguette);
imports.myBaguette = null;
assertEq(exports.ret(), null);
imports.myBaguette = new Baguette(1337);
assertEq(exports.ret(), imports.myBaguette);
// Check lazy stubs generation.
exports = wasmEvalText(`(module
(import $mirror "funcs" "mirror" (param anyref) (result anyref))
(import $augment "funcs" "augment" (param anyref) (result anyref))
(global $count_f (mut i32) (i32.const 0))
(global $count_g (mut i32) (i32.const 0))
(func $f (param $param anyref) (result anyref)
i32.const 1
get_global $count_f
i32.add
set_global $count_f
get_local $param
call $augment
)
(func $g (param $param anyref) (result anyref)
i32.const 1
get_global $count_g
i32.add
set_global $count_g
get_local $param
call $mirror
)
(table (export "table") 10 anyfunc)
(elem (i32.const 0) $f $g $mirror $augment)
(type $table_type (func (param anyref) (result anyref)))
(func (export "call_indirect") (param $i i32) (param $ref anyref) (result anyref)
get_local $ref
get_local $i
call_indirect $table_type
)
(func (export "count_f") (result i32) get_global $count_f)
(func (export "count_g") (result i32) get_global $count_g)
)`, {
funcs: {
mirror(x) {
return x;
},
augment(x) {
x.i++;
x.newProp = "hello";
return x;
}
}
}).exports;
x = { i: 19 };
assertEq(exports.table.get(0)(x), x);
assertEq(x.i, 20);
assertEq(x.newProp, "hello");
assertEq(exports.count_f(), 1);
assertEq(exports.count_g(), 0);
x = { i: 21 };
assertEq(exports.table.get(1)(x), x);
assertEq(x.i, 21);
assertEq(typeof x.newProp, "undefined");
assertEq(exports.count_f(), 1);
assertEq(exports.count_g(), 1);
x = { i: 22 };
assertEq(exports.table.get(2)(x), x);
assertEq(x.i, 22);
assertEq(typeof x.newProp, "undefined");
assertEq(exports.count_f(), 1);
assertEq(exports.count_g(), 1);
x = { i: 23 };
assertEq(exports.table.get(3)(x), x);
assertEq(x.i, 24);
assertEq(x.newProp, "hello");
assertEq(exports.count_f(), 1);
assertEq(exports.count_g(), 1);

Просмотреть файл

@ -0,0 +1 @@
|jit-test| test-also=--wasm-gc; include:wasm.js

Просмотреть файл

@ -0,0 +1,28 @@
if (wasmGcEnabled()) {
quit();
}
const { CompileError, validate } = WebAssembly;
const UNRECOGNIZED_OPCODE_OR_BAD_TYPE = /(unrecognized opcode|bad type|invalid inline block type)/;
function assertValidateError(text) {
assertEq(validate(wasmTextToBinary(text)), false);
}
let simpleTests = [
"(module (func (drop (ref.null anyref))))",
"(module (func $test (local anyref)))",
"(module (func $test (param anyref)))",
"(module (func $test (result anyref) (ref.null anyref)))",
"(module (func $test (block anyref (unreachable)) unreachable))",
"(module (func $test (local anyref) (result i32) (ref.is_null (get_local 0))))",
`(module (import "a" "b" (param anyref)))`,
`(module (import "a" "b" (result anyref)))`,
];
for (let src of simpleTests) {
print(src)
assertErrorMessage(() => wasmEvalText(src), CompileError, UNRECOGNIZED_OPCODE_OR_BAD_TYPE);
assertValidateError(src);
}

Просмотреть файл

@ -568,6 +568,8 @@ MIRTypeToSize(MIRType type)
return 4;
case MIRType::Double:
return 8;
case MIRType::Pointer:
return sizeof(uintptr_t);
default:
MOZ_CRASH("MIRTypeToSize - unhandled case");
}

Просмотреть файл

@ -935,6 +935,9 @@ class JS_PUBLIC_API(ContextOptions) {
wasm_(true),
wasmBaseline_(true),
wasmIon_(true),
#ifdef ENABLE_WASM_GC
wasmGc_(false),
#endif
testWasmAwaitTier2_(false),
throwOnAsmJSValidationFailure_(false),
nativeRegExp_(true),
@ -1032,6 +1035,14 @@ class JS_PUBLIC_API(ContextOptions) {
return *this;
}
#ifdef ENABLE_WASM_GC
bool wasmGc() const { return wasmGc_; }
ContextOptions& setWasmGc(bool flag) {
wasmGc_ = flag;
return *this;
}
#endif
bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
ContextOptions& setThrowOnAsmJSValidationFailure(bool flag) {
throwOnAsmJSValidationFailure_ = flag;
@ -1117,6 +1128,9 @@ class JS_PUBLIC_API(ContextOptions) {
setWasm(false);
setWasmBaseline(false);
setWasmIon(false);
#ifdef ENABLE_WASM_GC
setWasmGc(false);
#endif
setNativeRegExp(false);
}
@ -1127,6 +1141,9 @@ class JS_PUBLIC_API(ContextOptions) {
bool wasm_ : 1;
bool wasmBaseline_ : 1;
bool wasmIon_ : 1;
#ifdef ENABLE_WASM_GC
bool wasmGc_ : 1;
#endif
bool testWasmAwaitTier2_ : 1;
bool throwOnAsmJSValidationFailure_ : 1;
bool nativeRegExp_ : 1;

Просмотреть файл

@ -695,6 +695,7 @@ if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_SATURATING_TRUNC_OPS'] = True
DEFINES['ENABLE_WASM_SIGNEXTEND_OPS'] = True
DEFINES['ENABLE_WASM_THREAD_OPS'] = True
DEFINES['ENABLE_WASM_GC'] = True
# An experiment we want to run on Nightly and early Beta: Can we change the JS
# representation of an exported global from the global's value to an instance

Просмотреть файл

@ -482,6 +482,9 @@ static bool enableNativeRegExp = false;
static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
static bool enableWasmBaseline = false;
static bool enableWasmIon = false;
#ifdef ENABLE_WASM_GC
static bool enableWasmGc = false;
#endif
static bool enableTestWasmAwaitTier2 = false;
static bool enableAsyncStacks = false;
static bool enableStreams = false;
@ -8295,6 +8298,9 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
enableNativeRegExp = !op.getBoolOption("no-native-regexp");
enableWasmBaseline = !op.getBoolOption("no-wasm-baseline");
enableWasmIon = !op.getBoolOption("no-wasm-ion");
#ifdef ENABLE_WASM_GC
enableWasmGc = op.getBoolOption("wasm-gc");
#endif
enableTestWasmAwaitTier2 = op.getBoolOption("test-wasm-await-tier2");
enableAsyncStacks = !op.getBoolOption("no-async-stacks");
enableStreams = op.getBoolOption("enable-streams");
@ -8306,6 +8312,9 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
.setWasm(enableWasm)
.setWasmBaseline(enableWasmBaseline)
.setWasmIon(enableWasmIon)
#ifdef ENABLE_WASM_GC
.setWasmGc(enableWasmGc)
#endif
.setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
.setNativeRegExp(enableNativeRegExp)
.setAsyncStack(enableAsyncStacks)
@ -8608,6 +8617,9 @@ SetWorkerContextOptions(JSContext* cx)
.setWasm(enableWasm)
.setWasmBaseline(enableWasmBaseline)
.setWasmIon(enableWasmIon)
#ifdef ENABLE_WASM_GC
.setWasmGc(enableWasmGc)
#endif
.setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
.setNativeRegExp(enableNativeRegExp)
.setStreams(enableStreams)
@ -8851,6 +8863,9 @@ main(int argc, char** argv, char** envp)
|| !op.addBoolOption('\0', "no-wasm-ion", "Disable wasm ion compiler")
|| !op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block "
"instantiation on completion of tier2")
#ifdef ENABLE_WASM_GC
|| !op.addBoolOption('\0', "wasm-gc", "Enable wasm GC features")
#endif
|| !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
|| !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
|| !op.addBoolOption('\0', "enable-streams", "Enable WHATWG Streams")

Просмотреть файл

@ -20,6 +20,9 @@ UNIFIED_SOURCES += [
DEFINES['EXPORT_JS_API'] = True
DEFINES['ENABLE_WASM_GLOBAL'] = True
if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_GC'] = True
# Also set in ../moz.build
DEFINES['ENABLE_SHARED_ARRAY_BUFFER'] = True

Просмотреть файл

@ -116,6 +116,10 @@ class ProtectedData
T& refNoCheck() { return value; }
const T& refNoCheck() const { return value; }
static size_t offsetOfValue() {
return offsetof(ThisType, value);
}
private:
T value;
#ifdef JS_HAS_PROTECTED_DATA_CHECKS

Просмотреть файл

@ -95,6 +95,7 @@ class JSFunction : public js::NativeObject
NATIVE_CLASS_CTOR = NATIVE_FUN | CONSTRUCTOR | CLASSCONSTRUCTOR_KIND,
ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR,
ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA,
ASMJS_NATIVE = ASMJS_KIND | NATIVE_FUN,
WASM_FUN = NATIVE_FUN | WASM_OPTIMIZED,
INTERPRETED_METHOD = INTERPRETED | METHOD_KIND,
INTERPRETED_METHOD_GENERATOR_OR_ASYNC = INTERPRETED | METHOD_KIND,

Просмотреть файл

@ -1759,7 +1759,7 @@ class MOZ_STACK_CLASS ModuleValidator
arrayViews_(cx),
atomicsPresent_(false),
simdPresent_(false),
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False,
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled()
? Shareable::True
: Shareable::False,
@ -7724,6 +7724,9 @@ ValidateGlobalVariable(JSContext* cx, const AsmJSGlobal& global, HandleValue imp
*val = Val(simdConstant.asInt32x4());
return true;
}
case ValType::AnyRef: {
MOZ_CRASH("not available in asm.js");
}
}
}
}

Просмотреть файл

@ -209,6 +209,7 @@ enum class AstExprKind
Load,
Nop,
Pop,
RefNull,
Return,
SetGlobal,
SetLocal,
@ -1163,6 +1164,19 @@ class AstExtraConversionOperator final : public AstExpr
};
#endif
class AstRefNull final : public AstExpr
{
ValType refType_;
public:
static const AstExprKind Kind = AstExprKind::RefNull;
explicit AstRefNull(ValType refType)
: AstExpr(Kind, ExprType::Limit), refType_(refType)
{}
ValType refType() const {
return refType_;
}
};
// This is an artificial AST node which can fill operand slots in an AST
// constructed from parsing or decoding stack-machine code that doesn't have
// an inherent AST structure.

Просмотреть файл

@ -296,6 +296,15 @@ struct RegI64 : public Register64
static RegI64 Invalid() { return RegI64(Register64::Invalid()); }
};
struct RegPtr : public Register
{
RegPtr() : Register(Register::Invalid()) {}
explicit RegPtr(Register reg) : Register(reg) {}
bool isValid() const { return *this != Invalid(); }
bool isInvalid() const { return !isValid(); }
static RegPtr Invalid() { return RegPtr(Register::Invalid()); }
};
struct RegF32 : public FloatRegister
{
RegF32() : FloatRegister() {}
@ -316,10 +325,21 @@ struct RegF64 : public FloatRegister
struct AnyReg
{
union {
RegI32 i32_;
RegI64 i64_;
RegPtr ref_;
RegF32 f32_;
RegF64 f64_;
};
enum { I32, I64, REF, F32, F64 } tag;
explicit AnyReg(RegI32 r) { tag = I32; i32_ = r; }
explicit AnyReg(RegI64 r) { tag = I64; i64_ = r; }
explicit AnyReg(RegF32 r) { tag = F32; f32_ = r; }
explicit AnyReg(RegF64 r) { tag = F64; f64_ = r; }
explicit AnyReg(RegPtr r) { tag = REF; ref_ = r; }
RegI32 i32() const {
MOZ_ASSERT(tag == I32);
@ -337,6 +357,11 @@ struct AnyReg
MOZ_ASSERT(tag == F64);
return f64_;
}
RegPtr ref() const {
MOZ_ASSERT(tag == REF);
return ref_;
}
AnyRegister any() const {
switch (tag) {
case F32: return AnyRegister(f32_);
@ -352,20 +377,14 @@ struct AnyReg
// only on 64-bit platforms.
MOZ_CRASH("AnyReg::any() on 32-bit platform");
#endif
case REF:
MOZ_CRASH("AnyReg::any() not implemented for ref types");
default:
MOZ_CRASH();
}
// Work around GCC 5 analysis/warning bug.
MOZ_CRASH("AnyReg::any(): impossible case");
}
union {
RegI32 i32_;
RegI64 i64_;
RegF32 f32_;
RegF64 f64_;
};
enum { I32, I64, F32, F64 } tag;
};
// Platform-specific registers.
@ -691,6 +710,10 @@ class BaseRegAlloc
#endif
}
bool isAvailablePtr(RegPtr r) {
return isAvailableGPR(r);
}
bool isAvailableF32(RegF32 r) {
return isAvailableFPU(r);
}
@ -726,6 +749,18 @@ class BaseRegAlloc
allocInt64(specific);
}
MOZ_MUST_USE RegPtr needPtr() {
if (!hasGPR())
bc.sync();
return RegPtr(allocGPR());
}
void needPtr(RegPtr specific) {
if (!isAvailablePtr(specific))
bc.sync();
allocGPR(specific);
}
MOZ_MUST_USE RegF32 needF32() {
if (!hasFPU<MIRType::Float32>())
bc.sync();
@ -758,6 +793,10 @@ class BaseRegAlloc
freeInt64(r);
}
void freePtr(RegPtr r) {
freeGPR(r);
}
void freeF64(RegF64 r) {
freeFPU(r);
}
@ -817,6 +856,10 @@ class BaseRegAlloc
void addKnownF64(RegF64 r) {
knownFPU_.add(r);
}
void addKnownRef(RegPtr r) {
knownGPR_.add(r);
}
};
#endif
};
@ -888,23 +931,28 @@ class ScratchF32 : public ScratchFloat32Scope
#endif
#ifdef RABALDR_SCRATCH_I32
class ScratchI32 : public BaseScratchRegister
template<class RegType>
class ScratchGPR : public BaseScratchRegister
{
public:
explicit ScratchI32(BaseRegAlloc& ra)
explicit ScratchGPR(BaseRegAlloc& ra)
: BaseScratchRegister(ra, BaseRegAlloc::ScratchKind::I32)
{}
operator RegI32() const { return RegI32(RabaldrScratchI32); }
operator RegType() const { return RegType(RabaldrScratchI32); }
};
#else
class ScratchI32 : public ScratchRegisterScope
template<class RegType>
class ScratchGPR : public ScratchRegisterScope
{
public:
explicit ScratchI32(MacroAssembler& m) : ScratchRegisterScope(m) {}
operator RegI32() const { return RegI32(Register(*this)); }
explicit ScratchGPR(MacroAssembler& m) : ScratchRegisterScope(m) {}
operator RegType() const { return RegType(Register(*this)); }
};
#endif
using ScratchI32 = ScratchGPR<RegI32>;
using ScratchPtr = ScratchGPR<RegPtr>;
#if defined(JS_CODEGEN_X86)
// ScratchEBX is a mnemonic device: For some atomic ops we really need EBX,
// no other register will do. And we would normally have to allocate that
@ -985,6 +1033,7 @@ BaseLocalIter::settle()
case MIRType::Int64:
case MIRType::Double:
case MIRType::Float32:
case MIRType::Pointer:
if (argsIter_->argInRegister())
frameOffset_ = pushLocal(MIRTypeToSize(mirType_));
else
@ -1003,6 +1052,7 @@ BaseLocalIter::settle()
case ValType::I64:
case ValType::F32:
case ValType::F64:
case ValType::AnyRef:
mirType_ = ToMIRType(locals_[index_]);
frameOffset_ = pushLocal(MIRTypeToSize(mirType_));
break;
@ -1242,7 +1292,7 @@ class BaseStackFrame
masm.load64(Address(sp_, localOffset(src)), dest);
}
void loadLocalPtr(const Local& src, Register dest) {
void loadLocalPtr(const Local& src, RegPtr dest) {
masm.loadPtr(Address(sp_, localOffset(src)), dest);
}
@ -1551,7 +1601,7 @@ class BaseStackFrame
// Disambiguation: this loads a "Ptr" value from the stack, it does not load
// the "StackPtr".
void loadStackPtr(int32_t offset, Register dest) {
void loadStackPtr(int32_t offset, RegPtr dest) {
masm.loadPtr(Address(sp_, stackOffset(offset)), dest);
}
@ -1862,6 +1912,7 @@ class BaseCompiler final : public BaseCompilerInterface
RegI32 joinRegI32_;
RegI64 joinRegI64_;
RegPtr joinRegPtr_;
RegF32 joinRegF32_;
RegF64 joinRegF64_;
@ -1924,16 +1975,19 @@ class BaseCompiler final : public BaseCompilerInterface
bool isAvailableI32(RegI32 r) { return ra.isAvailableI32(r); }
bool isAvailableI64(RegI64 r) { return ra.isAvailableI64(r); }
bool isAvailableRef(RegPtr r) { return ra.isAvailablePtr(r); }
bool isAvailableF32(RegF32 r) { return ra.isAvailableF32(r); }
bool isAvailableF64(RegF64 r) { return ra.isAvailableF64(r); }
MOZ_MUST_USE RegI32 needI32() { return ra.needI32(); }
MOZ_MUST_USE RegI64 needI64() { return ra.needI64(); }
MOZ_MUST_USE RegPtr needRef() { return ra.needPtr(); }
MOZ_MUST_USE RegF32 needF32() { return ra.needF32(); }
MOZ_MUST_USE RegF64 needF64() { return ra.needF64(); }
void needI32(RegI32 specific) { ra.needI32(specific); }
void needI64(RegI64 specific) { ra.needI64(specific); }
void needRef(RegPtr specific) { ra.needPtr(specific); }
void needF32(RegF32 specific) { ra.needF32(specific); }
void needF64(RegF64 specific) { ra.needF64(specific); }
@ -1943,6 +1997,7 @@ class BaseCompiler final : public BaseCompilerInterface
void freeI32(RegI32 r) { ra.freeI32(r); }
void freeI64(RegI64 r) { ra.freeI64(r); }
void freeRef(RegPtr r) { ra.freePtr(r); }
void freeF32(RegF32 r) { ra.freeF32(r); }
void freeF64(RegF64 r) { ra.freeF64(r); }
@ -2018,6 +2073,10 @@ class BaseCompiler final : public BaseCompilerInterface
#endif
}
RegI32 narrowPtr(RegPtr r) {
return RegI32(r);
}
RegI32 lowPart(RegI64 r) {
#ifdef JS_PUNBOX64
return RegI32(r.reg);
@ -2050,6 +2109,11 @@ class BaseCompiler final : public BaseCompilerInterface
masm.move64(src, dest);
}
void moveRef(RegPtr src, RegPtr dest) {
if (src != dest)
masm.movePtr(src, dest);
}
void moveF64(RegF64 src, RegF64 dest) {
if (src != dest)
masm.moveDouble(src, dest);
@ -2065,6 +2129,8 @@ class BaseCompiler final : public BaseCompilerInterface
needI32(joinRegI32_);
else if (type == ExprType::I64)
needI64(joinRegI64_);
else if (type == ExprType::AnyRef)
needRef(joinRegPtr_);
}
void maybeUnreserveJoinRegI(ExprType type) {
@ -2072,6 +2138,8 @@ class BaseCompiler final : public BaseCompilerInterface
freeI32(joinRegI32_);
else if (type == ExprType::I64)
freeI64(joinRegI64_);
else if (type == ExprType::AnyRef)
freeRef(joinRegPtr_);
}
void maybeReserveJoinReg(ExprType type) {
@ -2088,6 +2156,9 @@ class BaseCompiler final : public BaseCompilerInterface
case ExprType::F64:
needF64(joinRegF64_);
break;
case ExprType::AnyRef:
needRef(joinRegPtr_);
break;
default:
break;
}
@ -2107,6 +2178,9 @@ class BaseCompiler final : public BaseCompilerInterface
case ExprType::F64:
freeF64(joinRegF64_);
break;
case ExprType::AnyRef:
freeRef(joinRegPtr_);
break;
default:
break;
}
@ -2127,6 +2201,10 @@ class BaseCompiler final : public BaseCompilerInterface
struct Stk
{
private:
Stk() : kind_(Unknown), i64val_(0) {}
public:
enum Kind
{
// The Mem opcodes are all clustered at the beginning to
@ -2135,6 +2213,7 @@ class BaseCompiler final : public BaseCompilerInterface
MemI64, // 64-bit integer stack value ("offs")
MemF32, // 32-bit floating stack value ("offs")
MemF64, // 64-bit floating stack value ("offs")
MemRef, // reftype (pointer wide) stack value ("offs")
// The Local opcodes follow the Mem opcodes for a similar
// quick test within hasLocal().
@ -2142,47 +2221,61 @@ class BaseCompiler final : public BaseCompilerInterface
LocalI64, // Local int64 var ("slot")
LocalF32, // Local float32 var ("slot")
LocalF64, // Local double var ("slot")
LocalRef, // Local reftype (pointer wide) var ("slot")
RegisterI32, // 32-bit integer register ("i32reg")
RegisterI64, // 64-bit integer register ("i64reg")
RegisterF32, // 32-bit floating register ("f32reg")
RegisterF64, // 64-bit floating register ("f64reg")
RegisterRef, // reftype (pointer wide) register ("refReg")
ConstI32, // 32-bit integer constant ("i32val")
ConstI64, // 64-bit integer constant ("i64val")
ConstF32, // 32-bit floating constant ("f32val")
ConstF64, // 64-bit floating constant ("f64val")
ConstRef, // reftype (pointer wide) constant ("refval")
Unknown,
};
Kind kind_;
static const Kind MemLast = MemF64;
static const Kind LocalLast = LocalF64;
static const Kind MemLast = MemRef;
static const Kind LocalLast = LocalRef;
union {
RegI32 i32reg_;
RegI64 i64reg_;
RegPtr refReg_;
RegF32 f32reg_;
RegF64 f64reg_;
int32_t i32val_;
int64_t i64val_;
intptr_t refval_;
float f32val_;
double f64val_;
uint32_t slot_;
uint32_t offs_;
};
explicit Stk(RegI32 r) : kind_(RegisterI32), i32reg_(r) {}
explicit Stk(RegI64 r) : kind_(RegisterI64), i64reg_(r) {}
explicit Stk(RegF32 r) : kind_(RegisterF32), f32reg_(r) {}
explicit Stk(RegF64 r) : kind_(RegisterF64), f64reg_(r) {}
explicit Stk(int32_t v) : kind_(ConstI32), i32val_(v) {}
explicit Stk(int64_t v) : kind_(ConstI64), i64val_(v) {}
explicit Stk(float v) : kind_(ConstF32), f32val_(v) {}
explicit Stk(double v) : kind_(ConstF64), f64val_(v) {}
explicit Stk(RegI32 r) : kind_(RegisterI32), i32reg_(r) {}
explicit Stk(RegI64 r) : kind_(RegisterI64), i64reg_(r) {}
explicit Stk(RegPtr r) : kind_(RegisterRef), refReg_(r) {}
explicit Stk(RegF32 r) : kind_(RegisterF32), f32reg_(r) {}
explicit Stk(RegF64 r) : kind_(RegisterF64), f64reg_(r) {}
explicit Stk(int32_t v) : kind_(ConstI32), i32val_(v) {}
explicit Stk(int64_t v) : kind_(ConstI64), i64val_(v) {}
explicit Stk(float v) : kind_(ConstF32), f32val_(v) {}
explicit Stk(double v) : kind_(ConstF64), f64val_(v) {}
explicit Stk(Kind k, uint32_t v) : kind_(k), slot_(v) {
MOZ_ASSERT(k > MemLast && k <= LocalLast);
}
static Stk StkRef(intptr_t v) {
Stk s;
s.kind_ = ConstRef;
s.refval_ = v;
return s;
}
void setOffs(Kind k, uint32_t v) { MOZ_ASSERT(k <= MemLast); kind_ = k; offs_ = v; }
@ -2191,11 +2284,13 @@ class BaseCompiler final : public BaseCompilerInterface
RegI32 i32reg() const { MOZ_ASSERT(kind_ == RegisterI32); return i32reg_; }
RegI64 i64reg() const { MOZ_ASSERT(kind_ == RegisterI64); return i64reg_; }
RegPtr refReg() const { MOZ_ASSERT(kind_ == RegisterRef); return refReg_; }
RegF32 f32reg() const { MOZ_ASSERT(kind_ == RegisterF32); return f32reg_; }
RegF64 f64reg() const { MOZ_ASSERT(kind_ == RegisterF64); return f64reg_; }
int32_t i32val() const { MOZ_ASSERT(kind_ == ConstI32); return i32val_; }
int64_t i64val() const { MOZ_ASSERT(kind_ == ConstI64); return i64val_; }
intptr_t refval() const { MOZ_ASSERT(kind_ == ConstRef); return refval_; }
// For these two, use an out-param instead of simply returning, to
// use the normal stack and not the x87 FP stack (which has effect on
@ -2215,6 +2310,10 @@ class BaseCompiler final : public BaseCompilerInterface
stk_.infallibleEmplaceBack(Stk(Forward<Args>(args)...));
}
void pushConstRef(intptr_t v) {
stk_.infallibleEmplaceBack(Stk::StkRef(v));
}
void loadConstI32(const Stk& src, RegI32 dest) {
moveImm32(src.i32val(), dest);
}
@ -2247,6 +2346,22 @@ class BaseCompiler final : public BaseCompilerInterface
moveI64(src.i64reg(), dest);
}
void loadConstRef(const Stk& src, RegPtr dest) {
moveImmRef(src.refval(), dest);
}
void loadMemRef(const Stk& src, RegPtr dest) {
fr.loadStackPtr(src.offs(), dest);
}
void loadLocalRef(const Stk& src, RegPtr dest) {
fr.loadLocalPtr(localFromSlot(src.slot(), MIRType::Pointer), dest);
}
void loadRegisterRef(const Stk& src, RegPtr dest) {
moveRef(src.refReg(), dest);
}
void loadConstF64(const Stk& src, RegF64 dest) {
double d;
src.f64val(&d);
@ -2399,6 +2514,25 @@ class BaseCompiler final : public BaseCompilerInterface
}
}
void loadRef(const Stk& src, RegPtr dest) {
switch (src.kind()) {
case Stk::ConstRef:
loadConstRef(src, dest);
break;
case Stk::MemRef:
loadMemRef(src, dest);
break;
case Stk::LocalRef:
loadLocalRef(src, dest);
break;
case Stk::RegisterRef:
loadRegisterRef(src, dest);
break;
default:
MOZ_CRASH("Compiler bug: expected ref on stack");
}
}
// Flush all local and register value stack elements to memory.
//
// TODO / OPTIMIZE: As this is fairly expensive and causes worse
@ -2501,6 +2635,19 @@ class BaseCompiler final : public BaseCompilerInterface
v.setOffs(Stk::MemF32, offs);
break;
}
case Stk::LocalRef: {
ScratchPtr scratch(*this);
loadLocalRef(v, scratch);
uint32_t offs = fr.pushPtr(scratch);
v.setOffs(Stk::MemRef, offs);
break;
}
case Stk::RegisterRef: {
uint32_t offs = fr.pushPtr(v.refReg());
freeRef(v.refReg());
v.setOffs(Stk::MemRef, offs);
break;
}
default: {
break;
}
@ -2544,6 +2691,11 @@ class BaseCompiler final : public BaseCompilerInterface
push(r);
}
void pushRef(RegPtr r) {
MOZ_ASSERT(!isAvailableRef(r));
push(r);
}
void pushF64(RegF64 r) {
MOZ_ASSERT(!isAvailableF64(r));
push(r);
@ -2564,6 +2716,10 @@ class BaseCompiler final : public BaseCompilerInterface
push(v);
}
void pushRef(intptr_t v) {
pushConstRef(v);
}
void pushF64(double v) {
push(v);
}
@ -2584,6 +2740,10 @@ class BaseCompiler final : public BaseCompilerInterface
push(Stk::LocalI64, slot);
}
void pushLocalRef(uint32_t slot) {
push(Stk::LocalRef, slot);
}
void pushLocalF64(uint32_t slot) {
push(Stk::LocalF64, slot);
}
@ -2698,6 +2858,54 @@ class BaseCompiler final : public BaseCompilerInterface
return specific;
}
// Call only from other popRef() variants.
// v must be the stack top. May pop the CPU stack.
void popRef(const Stk& v, RegPtr dest) {
MOZ_ASSERT(&v == &stk_.back());
switch (v.kind()) {
case Stk::ConstRef:
loadConstRef(v, dest);
break;
case Stk::LocalRef:
loadLocalRef(v, dest);
break;
case Stk::MemRef:
fr.popPtr(dest);
break;
case Stk::RegisterRef:
loadRegisterRef(v, dest);
break;
default:
MOZ_CRASH("Compiler bug: expected ref on stack");
}
}
RegPtr popRef(RegPtr specific) {
Stk& v = stk_.back();
if (!(v.kind() == Stk::RegisterRef && v.refReg() == specific)) {
needRef(specific);
popRef(v, specific);
if (v.kind() == Stk::RegisterRef)
freeRef(v.refReg());
}
stk_.popBack();
return specific;
}
MOZ_MUST_USE RegPtr popRef() {
Stk& v = stk_.back();
RegPtr r;
if (v.kind() == Stk::RegisterRef)
r = v.refReg();
else
popRef(v, (r = needRef()));
stk_.popBack();
return r;
}
// Call only from other popF64() variants.
// v must be the stack top. May pop the CPU stack.
@ -2914,6 +3122,12 @@ class BaseCompiler final : public BaseCompilerInterface
k == Stk::LocalF32);
return Some(AnyReg(popF32(joinRegF32_)));
}
case ExprType::AnyRef: {
DebugOnly<Stk::Kind> k(stk_.back().kind());
MOZ_ASSERT(k == Stk::RegisterRef || k == Stk::ConstRef || k == Stk::MemRef ||
k == Stk::LocalRef);
return Some(AnyReg(popRef(joinRegPtr_)));
}
default: {
MOZ_CRASH("Compiler bug: unexpected expression type");
}
@ -2944,6 +3158,10 @@ class BaseCompiler final : public BaseCompilerInterface
MOZ_ASSERT(isAvailableF64(joinRegF64_));
needF64(joinRegF64_);
return Some(AnyReg(joinRegF64_));
case ExprType::AnyRef:
MOZ_ASSERT(isAvailableRef(joinRegPtr_));
needRef(joinRegPtr_);
return Some(AnyReg(joinRegPtr_));
case ExprType::Void:
return Nothing();
default:
@ -2967,6 +3185,9 @@ class BaseCompiler final : public BaseCompilerInterface
case AnyReg::F32:
pushF32(r->f32());
break;
case AnyReg::REF:
pushRef(r->ref());
break;
}
}
@ -2986,6 +3207,9 @@ class BaseCompiler final : public BaseCompilerInterface
case AnyReg::F32:
freeF32(r->f32());
break;
case AnyReg::REF:
freeRef(r->ref());
break;
}
}
@ -2998,6 +3222,7 @@ class BaseCompiler final : public BaseCompilerInterface
for (uint32_t i = stk_.length() - 1; numval > 0; numval--, i--) {
Stk& v = stk_[i];
switch (v.kind()) {
case Stk::MemRef: size += BaseStackFrame::StackSizeOfPtr; break;
case Stk::MemI32: size += BaseStackFrame::StackSizeOfPtr; break;
case Stk::MemI64: size += BaseStackFrame::StackSizeOfInt64; break;
case Stk::MemF64: size += BaseStackFrame::StackSizeOfDouble; break;
@ -3024,6 +3249,9 @@ class BaseCompiler final : public BaseCompilerInterface
case Stk::RegisterF32:
freeF32(v.f32reg());
break;
case Stk::RegisterRef:
freeRef(v.refReg());
break;
default:
break;
}
@ -3070,6 +3298,9 @@ class BaseCompiler final : public BaseCompilerInterface
case Stk::RegisterF64:
check.addKnownF64(item.f64reg());
break;
case Stk::RegisterRef:
check.addKnownRef(item.refReg());
break;
default:
break;
}
@ -3159,6 +3390,9 @@ class BaseCompiler final : public BaseCompilerInterface
case MIRType::Int64:
fr.storeLocalI64(RegI64(i->gpr64()), l);
break;
case MIRType::Pointer:
fr.storeLocalPtr(RegPtr(i->gpr()), l);
break;
case MIRType::Double:
fr.storeLocalF64(RegF64(i->fpu()), l);
break;
@ -3488,6 +3722,17 @@ class BaseCompiler final : public BaseCompilerInterface
}
break;
}
case ValType::AnyRef: {
ABIArg argLoc = call->abi.next(MIRType::Pointer);
if (argLoc.kind() == ABIArg::Stack) {
ScratchPtr scratch(*this);
loadRef(arg, scratch);
masm.storePtr(scratch, Address(masm.getStackPointer(), argLoc.offsetFromArgBase()));
} else {
loadRef(arg, RegPtr(argLoc.gpr()));
}
break;
}
default:
MOZ_CRASH("Function argument type");
}
@ -3561,6 +3806,10 @@ class BaseCompiler final : public BaseCompilerInterface
masm.move64(Imm64(v), dest);
}
void moveImmRef(intptr_t v, RegPtr dest) {
masm.movePtr(ImmWord(v), dest);
}
void moveImmF32(float f, RegF32 dest) {
masm.loadConstantFloat32(f, dest);
}
@ -3691,6 +3940,13 @@ class BaseCompiler final : public BaseCompilerInterface
return r;
}
RegPtr captureReturnedRef() {
RegPtr r = RegPtr(ReturnReg);
MOZ_ASSERT(isAvailableRef(r));
needRef(r);
return r;
}
void returnCleanup(bool popStack) {
if (popStack)
fr.popStackBeforeBranch(controlOutermost().stackHeight);
@ -5275,6 +5531,11 @@ class BaseCompiler final : public BaseCompilerInterface
*r0 = popF64();
}
void pop2xRef(RegPtr* r0, RegPtr* r1) {
*r1 = popRef();
*r0 = popRef();
}
RegI32 popI64ToI32() {
RegI64 r = popI64();
return narrowI64(r);
@ -5614,6 +5875,9 @@ class BaseCompiler final : public BaseCompilerInterface
MOZ_MUST_USE bool emitGrowMemory();
MOZ_MUST_USE bool emitCurrentMemory();
MOZ_MUST_USE bool emitRefNull();
void emitRefIsNull();
MOZ_MUST_USE bool emitAtomicCmpXchg(ValType type, Scalar::Type viewType);
MOZ_MUST_USE bool emitAtomicLoad(ValType type, Scalar::Type viewType);
MOZ_MUST_USE bool emitAtomicRMW(ValType type, Scalar::Type viewType, AtomicOp op);
@ -6851,10 +7115,9 @@ BaseCompiler::sniffConditionalControlCmp(Cond compareOp, ValType operandType)
OpBytes op;
iter_.peekOp(&op);
switch (op.b0) {
case uint16_t(Op::Select):
MOZ_FALLTHROUGH;
case uint16_t(Op::BrIf):
case uint16_t(Op::If):
case uint16_t(Op::Select):
setLatentCompare(compareOp, operandType);
return true;
default:
@ -7436,6 +7699,12 @@ BaseCompiler::doReturn(ExprType type, bool popStack)
freeF32(rv);
break;
}
case ExprType::AnyRef: {
RegPtr rv = popRef(RegPtr(ReturnReg));
returnCleanup(popStack);
freeRef(rv);
break;
}
default: {
MOZ_CRASH("Function return type");
}
@ -7500,6 +7769,11 @@ BaseCompiler::pushReturned(const FunctionCall& call, ExprType type)
pushF64(rv);
break;
}
case ExprType::AnyRef: {
RegPtr rv = captureReturnedRef();
pushRef(rv);
break;
}
default:
MOZ_CRASH("Function return type");
}
@ -7827,6 +8101,9 @@ BaseCompiler::emitGetLocal()
case ValType::F32:
pushLocalF32(slot);
break;
case ValType::AnyRef:
pushLocalRef(slot);
break;
default:
MOZ_CRASH("Local variable type");
}
@ -7883,6 +8160,16 @@ BaseCompiler::emitSetOrTeeLocal(uint32_t slot)
pushF32(rv);
break;
}
case ValType::AnyRef: {
RegPtr rv = popRef();
syncLocal(slot);
fr.storeLocalPtr(rv, localFromSlot(slot, MIRType::Pointer));
if (isSetLocal)
freeRef(rv);
else
pushRef(rv);
break;
}
default:
MOZ_CRASH("Local variable type");
}
@ -8403,6 +8690,16 @@ BaseCompiler::emitSelect()
pushF64(r);
break;
}
case ValType::AnyRef: {
RegPtr r, rs;
pop2xRef(&r, &rs);
emitBranchPerform(&b);
moveRef(rs, r);
masm.bind(&done);
freeRef(rs);
pushRef(r);
break;
}
default: {
MOZ_CRASH("select type");
}
@ -8557,6 +8854,29 @@ BaseCompiler::emitCurrentMemory()
return true;
}
bool
BaseCompiler::emitRefNull()
{
if (!iter_.readRefNull())
return false;
if (deadCode_)
return true;
pushRef(NULLREF_VALUE);
return true;
}
void
BaseCompiler::emitRefIsNull()
{
RegPtr r = popRef();
RegI32 rd = narrowPtr(r);
masm.cmpPtrSet(Assembler::Equal, r, ImmWord(NULLREF_VALUE), rd);
pushI32(rd);
}
bool
BaseCompiler::emitAtomicCmpXchg(ValType type, Scalar::Type viewType)
{
@ -9424,6 +9744,19 @@ BaseCompiler::emitBody()
case uint16_t(Op::CurrentMemory):
CHECK_NEXT(emitCurrentMemory());
#ifdef ENABLE_WASM_GC
case uint16_t(Op::RefNull):
if (env_.gcTypesEnabled == HasGcTypes::False)
return iter_.unrecognizedOpcode(&op);
CHECK_NEXT(emitRefNull());
break;
case uint16_t(Op::RefIsNull):
if (env_.gcTypesEnabled == HasGcTypes::False)
return iter_.unrecognizedOpcode(&op);
CHECK_NEXT(emitConversion(emitRefIsNull, ValType::AnyRef, ValType::I32));
break;
#endif
// Numeric operations
case uint16_t(Op::NumericPrefix): {
#ifdef ENABLE_WASM_SATURATING_TRUNC_OPS
@ -9702,6 +10035,7 @@ BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
fr(*masm),
joinRegI32_(RegI32(ReturnReg)),
joinRegI64_(RegI64(ReturnReg64)),
joinRegPtr_(RegPtr(ReturnReg)),
joinRegF32_(RegF32(ReturnFloat32Reg)),
joinRegF64_(RegF64(ReturnDoubleReg))
{
@ -9809,7 +10143,7 @@ js::wasm::BaselineCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo
ValTypeVector locals;
if (!locals.appendAll(env.funcSigs[func.index]->args()))
return false;
if (!DecodeLocalEntries(d, env.kind, &locals))
if (!DecodeLocalEntries(d, env.kind, env.gcTypesEnabled, &locals))
return false;
// One-pass baseline compilation.

Просмотреть файл

@ -62,6 +62,9 @@ enum class TypeCode
// A function pointer with any signature
AnyFunc = 0x70, // SLEB128(-0x10)
// A reference to any type.
AnyRef = 0x6f,
// Type constructor for function types
Func = 0x60, // SLEB128(-0x20)
@ -78,6 +81,8 @@ enum class ValType
F32 = uint8_t(TypeCode::F32),
F64 = uint8_t(TypeCode::F64),
AnyRef = uint8_t(TypeCode::AnyRef),
// ------------------------------------------------------------------------
// The rest of these types are currently only emitted internally when
// compiling asm.js and are rejected by wasm validation.
@ -93,6 +98,10 @@ enum class ValType
typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
// The representation of a null reference value throughout the compiler.
static const intptr_t NULLREF_VALUE = intptr_t((void*)nullptr);
enum class DefinitionKind
{
Function = 0x00,
@ -323,6 +332,10 @@ enum class Op
I64Extend32S = 0xc4,
#endif
// GC ops
RefNull = 0xd0,
RefIsNull = 0xd1,
FirstPrefix = 0xfc,
NumericPrefix = 0xfc,
ThreadPrefix = 0xfe,

Просмотреть файл

@ -177,6 +177,7 @@ wasm::Classify(OpBytes op)
case Op::F64ConvertUI64:
case Op::F64ReinterpretI64:
case Op::F64PromoteF32:
case Op::RefIsNull:
#ifdef ENABLE_WASM_SIGNEXTEND_OPS
case Op::I32Extend8S:
case Op::I32Extend16S:
@ -240,6 +241,8 @@ wasm::Classify(OpBytes op)
return OpKind::CurrentMemory;
case Op::GrowMemory:
return OpKind::GrowMemory;
case Op::RefNull:
return OpKind::RefNull;
case Op::NumericPrefix: {
#ifdef ENABLE_WASM_SATURATING_TRUNC_OPS
switch (NumericOp(op.b1)) {

Просмотреть файл

@ -41,20 +41,22 @@ enum class LabelKind : uint8_t
// represents the type of a value produced by an unconditional branch.
enum class StackType
{
I32 = uint8_t(ValType::I32),
I64 = uint8_t(ValType::I64),
F32 = uint8_t(ValType::F32),
F64 = uint8_t(ValType::F64),
I32 = uint8_t(ValType::I32),
I64 = uint8_t(ValType::I64),
F32 = uint8_t(ValType::F32),
F64 = uint8_t(ValType::F64),
I8x16 = uint8_t(ValType::I8x16),
I16x8 = uint8_t(ValType::I16x8),
I32x4 = uint8_t(ValType::I32x4),
F32x4 = uint8_t(ValType::F32x4),
B8x16 = uint8_t(ValType::B8x16),
B16x8 = uint8_t(ValType::B16x8),
B32x4 = uint8_t(ValType::B32x4),
I8x16 = uint8_t(ValType::I8x16),
I16x8 = uint8_t(ValType::I16x8),
I32x4 = uint8_t(ValType::I32x4),
F32x4 = uint8_t(ValType::F32x4),
B8x16 = uint8_t(ValType::B8x16),
B16x8 = uint8_t(ValType::B16x8),
B32x4 = uint8_t(ValType::B32x4),
Any = uint8_t(TypeCode::Limit)
AnyRef = uint8_t(ValType::AnyRef),
Any = uint8_t(TypeCode::Limit),
};
static inline StackType
@ -71,7 +73,49 @@ NonAnyToValType(StackType type)
}
static inline bool
Unify(StackType one, StackType two, StackType* result)
IsRefType(StackType st)
{
return IsRefType(NonAnyToValType(st));
}
static inline bool
IsSubtypeOf(StackType one, StackType two)
{
MOZ_ASSERT(IsRefType(one));
MOZ_ASSERT(IsRefType(two));
return one == two || two == StackType::AnyRef;
}
static inline bool
Unify(HasGcTypes gcTypesEnabled, StackType observed, StackType expected, StackType* result)
{
if (MOZ_LIKELY(observed == expected)) {
*result = observed;
return true;
}
if (observed == StackType::Any) {
*result = expected;
return true;
}
if (expected == StackType::Any) {
*result = observed;
return true;
}
if (gcTypesEnabled == HasGcTypes::True && IsRefType(observed) && IsRefType(expected) &&
IsSubtypeOf(observed, expected))
{
*result = expected;
return true;
}
return false;
}
static inline bool
Join(HasGcTypes gcTypesEnabled, StackType one, StackType two, StackType* result)
{
if (MOZ_LIKELY(one == two)) {
*result = one;
@ -88,6 +132,22 @@ Unify(StackType one, StackType two, StackType* result)
return true;
}
if (gcTypesEnabled == HasGcTypes::True && IsRefType(one) && IsRefType(two)) {
if (IsSubtypeOf(two, one)) {
*result = one;
return true;
}
if (IsSubtypeOf(one, two)) {
*result = two;
return true;
}
// No subtyping relations between the two types.
*result = StackType::AnyRef;
return true;
}
return false;
}
@ -113,7 +173,6 @@ enum class OpKind {
BrIf,
BrTable,
Nop,
Nullary,
Unary,
Binary,
Comparison,
@ -159,6 +218,7 @@ enum class OpKind {
SimdBooleanReduction,
SimdShiftByScalar,
SimdComparison,
RefNull,
};
// Return the OpKind for a given Op. This is used for sanity-checking that
@ -534,6 +594,7 @@ class MOZ_STACK_CLASS OpIter : private Policy
MOZ_MUST_USE bool readB8x16Const(I8x16* i8x16);
MOZ_MUST_USE bool readB16x8Const(I16x8* i16x8);
MOZ_MUST_USE bool readB32x4Const(I32x4* i32x4);
MOZ_MUST_USE bool readRefNull();
MOZ_MUST_USE bool readCall(uint32_t* calleeIndex, ValueVector* argValues);
MOZ_MUST_USE bool readCallIndirect(uint32_t* sigIndex, Value* callee, ValueVector* argValues);
MOZ_MUST_USE bool readOldCallDirect(uint32_t numFuncImports, uint32_t* funcIndex,
@ -731,7 +792,7 @@ OpIter<Policy>::popWithType(StackType expectedType, Value* value)
TypeAndValue<Value> tv = valueStack_.popCopy();
StackType _;
if (MOZ_UNLIKELY(!Unify(tv.type(), expectedType, &_)))
if (MOZ_UNLIKELY(!Unify(env_.gcTypesEnabled, tv.type(), expectedType, &_)))
return typeMismatch(tv.type(), expectedType);
*value = tv.value();
@ -783,8 +844,11 @@ OpIter<Policy>::topWithType(ValType expectedType, Value* value)
TypeAndValue<Value>& tv = valueStack_.back();
if (MOZ_UNLIKELY(!Unify(tv.type(), ToStackType(expectedType), &tv.typeRef())))
if (MOZ_UNLIKELY(!Unify(env_.gcTypesEnabled, tv.type(), ToStackType(expectedType),
&tv.typeRef())))
{
return typeMismatch(tv.type(), ToStackType(expectedType));
}
*value = tv.value();
return true;
@ -846,6 +910,7 @@ OpIter<Policy>::readBlockType(ExprType* type)
if (!d_.readBlockType(&unchecked))
return fail("unable to read block signature");
bool known = false;
switch (unchecked) {
case uint8_t(ExprType::Void):
case uint8_t(ExprType::I32):
@ -859,11 +924,18 @@ OpIter<Policy>::readBlockType(ExprType* type)
case uint8_t(ExprType::B8x16):
case uint8_t(ExprType::B16x8):
case uint8_t(ExprType::B32x4):
known = true;
break;
case uint8_t(ExprType::AnyRef):
known = env_.gcTypesEnabled == HasGcTypes::True;
break;
case uint8_t(ExprType::Limit):
break;
default:
return fail("invalid inline block type");
}
if (!known)
return fail("invalid inline block type");
*type = ExprType(unchecked);
return true;
}
@ -1382,7 +1454,7 @@ OpIter<Policy>::readSelect(StackType* type, Value* trueValue, Value* falseValue,
if (!popAnyType(&trueType, trueValue))
return false;
if (!Unify(falseType, trueType, type))
if (!Join(env_.gcTypesEnabled, falseType, trueType, type))
return fail("select operand types must match");
infalliblePush(*type);
@ -1595,6 +1667,17 @@ OpIter<Policy>::readB32x4Const(I32x4* i32x4)
push(ValType::B32x4);
}
template <typename Policy>
inline bool
OpIter<Policy>::readRefNull()
{
MOZ_ASSERT(Classify(op_) == OpKind::RefNull);
uint8_t valType;
if (!d_.readValType(&valType) || ValType(valType) != ValType::AnyRef)
return fail("unknown nullref type");
return push(StackType::AnyRef);
}
template <typename Policy>
inline bool
OpIter<Policy>::popCallArgs(const ValTypeVector& expectedTypes, ValueVector* values)

Просмотреть файл

@ -102,7 +102,7 @@ class AstDecodeContext
lifo(lifo),
d(d),
generateNames(generateNames),
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False,
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled()
? Shareable::True
: Shareable::False),
@ -1824,7 +1824,7 @@ AstDecodeFunctionBody(AstDecodeContext &c, uint32_t funcIndex, AstFunc** func)
if (!locals.appendAll(sig->args()))
return false;
if (!DecodeLocalEntries(c.d, ModuleKind::Wasm, &locals))
if (!DecodeLocalEntries(c.d, ModuleKind::Wasm, c.env().gcTypesEnabled, &locals))
return false;
AstDecodeOpIter iter(c.env(), c.d);

Просмотреть файл

@ -536,6 +536,9 @@ AddressOf(SymbolicAddress imm, ABIFunctionType* abiType)
case SymbolicAddress::CallImport_F64:
*abiType = Args_General4;
return FuncCast(Instance::callImport_f64, *abiType);
case SymbolicAddress::CallImport_Ref:
*abiType = Args_General4;
return FuncCast(Instance::callImport_ref, *abiType);
case SymbolicAddress::CoerceInPlace_ToInt32:
*abiType = Args_General1;
return FuncCast(CoerceInPlace_ToInt32, *abiType);
@ -690,6 +693,7 @@ wasm::NeedsBuiltinThunk(SymbolicAddress sym)
case SymbolicAddress::CallImport_I32:
case SymbolicAddress::CallImport_I64:
case SymbolicAddress::CallImport_F64:
case SymbolicAddress::CallImport_Ref:
case SymbolicAddress::CoerceInPlace_ToInt32: // GenerateImportJitExit
case SymbolicAddress::CoerceInPlace_ToNumber:
#if defined(JS_CODEGEN_MIPS32)

Просмотреть файл

@ -609,22 +609,25 @@ LazyStubSegment::addStubs(size_t codeLength, const Uint32Vector& funcExportIndic
return false;
size_t i = 0;
for (DebugOnly<uint32_t> funcExportIndex : funcExportIndices) {
for (uint32_t funcExportIndex : funcExportIndices) {
const CodeRange& interpRange = codeRanges[i];
MOZ_ASSERT(interpRange.isInterpEntry());
MOZ_ASSERT(interpRange.funcIndex() == funcExports[funcExportIndex].funcIndex());
codeRanges_.infallibleAppend(interpRange);
codeRanges_.back().offsetBy(offsetInSegment);
i++;
const CodeRange& jitRange = codeRanges[i + 1];
if (funcExports[funcExportIndex].sig().temporarilyUnsupportedAnyRef())
continue;
const CodeRange& jitRange = codeRanges[i];
MOZ_ASSERT(jitRange.isJitEntry());
MOZ_ASSERT(jitRange.funcIndex() == interpRange.funcIndex());
codeRanges_.infallibleAppend(jitRange);
codeRanges_.back().offsetBy(offsetInSegment);
i += 2;
i++;
}
return true;
@ -658,8 +661,8 @@ struct ProjectLazyFuncIndex
static constexpr unsigned LAZY_STUB_LIFO_DEFAULT_CHUNK_SIZE = 8 * 1024;
bool
LazyStubTier::createMany(const Uint32Vector& funcExportIndices, const CodeTier& codeTier,
size_t* stubSegmentIndex)
LazyStubTier::createMany(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
const CodeTier& codeTier, size_t* stubSegmentIndex)
{
MOZ_ASSERT(funcExportIndices.length());
@ -673,16 +676,21 @@ LazyStubTier::createMany(const Uint32Vector& funcExportIndices, const CodeTier&
uint8_t* moduleSegmentBase = codeTier.segment().base();
CodeRangeVector codeRanges;
DebugOnly<uint32_t> numExpectedRanges = 0;
for (uint32_t funcExportIndex : funcExportIndices) {
const FuncExport& fe = funcExports[funcExportIndex];
numExpectedRanges += fe.sig().temporarilyUnsupportedAnyRef() ? 1 : 2;
void* calleePtr = moduleSegmentBase +
moduleRanges[fe.interpCodeRangeIndex()].funcNormalEntry();
Maybe<ImmPtr> callee;
callee.emplace(calleePtr, ImmPtr::NoCheckToken());
if (!GenerateEntryStubs(masm, funcExportIndex, fe, callee, /* asmjs*/ false, &codeRanges))
if (!GenerateEntryStubs(masm, funcExportIndex, fe, callee, /* asmjs */ false,
gcTypesEnabled, &codeRanges))
{
return false;
}
}
MOZ_ASSERT(codeRanges.length() == 2 * funcExportIndices.length(), "two entries per function");
MOZ_ASSERT(codeRanges.length() == numExpectedRanges, "incorrect number of entries per function");
masm.finish();
@ -743,7 +751,9 @@ LazyStubTier::createMany(const Uint32Vector& funcExportIndices, const CodeTier&
fe.funcIndex(), &exportIndex));
MOZ_ALWAYS_TRUE(exports_.insert(exports_.begin() + exportIndex, Move(lazyExport)));
interpRangeIndex += 2;
// Functions with anyref in their sig have only one entry (interp).
// All other functions get an extra jit entry.
interpRangeIndex += fe.sig().temporarilyUnsupportedAnyRef() ? 1 : 2;
}
return true;
@ -757,12 +767,22 @@ LazyStubTier::createOne(uint32_t funcExportIndex, const CodeTier& codeTier)
return false;
size_t stubSegmentIndex;
if (!createMany(funcExportIndexes, codeTier, &stubSegmentIndex))
if (!createMany(codeTier.code().metadata().temporaryHasGcTypes, funcExportIndexes, codeTier,
&stubSegmentIndex))
{
return false;
}
const UniqueLazyStubSegment& segment = stubSegments_[stubSegmentIndex];
const CodeRangeVector& codeRanges = segment->codeRanges();
// Functions that have anyref in their sig don't get a jit entry.
if (codeTier.metadata().funcExports[funcExportIndex].sig().temporarilyUnsupportedAnyRef()) {
MOZ_ASSERT(codeRanges.length() >= 1);
MOZ_ASSERT(codeRanges.back().isInterpEntry());
return true;
}
MOZ_ASSERT(codeRanges.length() >= 2);
MOZ_ASSERT(codeRanges[codeRanges.length() - 2].isInterpEntry());
@ -774,14 +794,14 @@ LazyStubTier::createOne(uint32_t funcExportIndex, const CodeTier& codeTier)
}
bool
LazyStubTier::createTier2(const Uint32Vector& funcExportIndices, const CodeTier& codeTier,
Maybe<size_t>* outStubSegmentIndex)
LazyStubTier::createTier2(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
const CodeTier& codeTier, Maybe<size_t>* outStubSegmentIndex)
{
if (!funcExportIndices.length())
return true;
size_t stubSegmentIndex;
if (!createMany(funcExportIndices, codeTier, &stubSegmentIndex))
if (!createMany(gcTypesEnabled, funcExportIndices, codeTier, &stubSegmentIndex))
return false;
outStubSegmentIndex->emplace(stubSegmentIndex);

Просмотреть файл

@ -400,6 +400,7 @@ struct MetadataCacheablePod
{
ModuleKind kind;
MemoryUsage memoryUsage;
HasGcTypes temporaryHasGcTypes;
uint32_t minMemoryLength;
uint32_t globalDataLength;
Maybe<uint32_t> maxMemoryLength;
@ -408,6 +409,7 @@ struct MetadataCacheablePod
explicit MetadataCacheablePod(ModuleKind kind)
: kind(kind),
memoryUsage(MemoryUsage::None),
temporaryHasGcTypes(HasGcTypes::False),
minMemoryLength(0),
globalDataLength(0)
{}
@ -572,8 +574,8 @@ class LazyStubTier
LazyFuncExportVector exports_;
size_t lastStubSegmentIndex_;
bool createMany(const Uint32Vector& funcExportIndices, const CodeTier& codeTier,
size_t* stubSegmentIndex);
bool createMany(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
const CodeTier& codeTier, size_t* stubSegmentIndex);
public:
LazyStubTier() : lastStubSegmentIndex_(0) {}
@ -593,8 +595,8 @@ class LazyStubTier
// them in a single stub. Jit entries won't be used until
// setJitEntries() is actually called, after the Code owner has committed
// tier2.
bool createTier2(const Uint32Vector& funcExportIndices, const CodeTier& codeTier,
Maybe<size_t>* stubSegmentIndex);
bool createTier2(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExportIndices,
const CodeTier& codeTier, Maybe<size_t>* stubSegmentIndex);
void setJitEntries(const Maybe<size_t>& stubSegmentIndex, const Code& code);
void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data) const;

Просмотреть файл

@ -87,10 +87,17 @@ DecodeCodeSection(const ModuleEnvironment& env, DecoderT& d, ModuleGenerator& mg
bool
CompileArgs::initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller)
{
baselineEnabled = cx->options().wasmBaseline();
ionEnabled = cx->options().wasmIon();
#ifdef ENABLE_WASM_GC
bool gcEnabled = cx->options().wasmGc();
#else
bool gcEnabled = false;
#endif
baselineEnabled = cx->options().wasmBaseline() || gcEnabled;
ionEnabled = cx->options().wasmIon() && !gcEnabled;
sharedMemoryEnabled = cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled();
testTiering = cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2;
gcTypesEnabled = gcEnabled ? HasGcTypes::True : HasGcTypes::False;
testTiering = (cx->options().testWasmAwaitTier2() || JitOptions.wasmDelayTier2) && !gcEnabled;
// Debug information such as source view or debug traps will require
// additional memory and permanently stay in baseline code, so we try to
@ -424,7 +431,7 @@ wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, Uni
DebugEnabled debug;
InitialCompileFlags(args, d, &mode, &tier, &debug);
ModuleEnvironment env(mode, tier, debug,
ModuleEnvironment env(mode, tier, debug, args.gcTypesEnabled,
args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
if (!DecodeModuleEnvironment(d, &env))
return nullptr;
@ -450,7 +457,9 @@ wasm::CompileTier2(const CompileArgs& args, Module& module, Atomic<bool>* cancel
UniqueChars error;
Decoder d(module.bytecode().bytes, 0, &error);
ModuleEnvironment env(CompileMode::Tier2, Tier::Ion, DebugEnabled::False,
MOZ_ASSERT(args.gcTypesEnabled == HasGcTypes::False, "can't ion-compile with gc types yet");
ModuleEnvironment env(CompileMode::Tier2, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
if (!DecodeModuleEnvironment(d, &env))
return false;
@ -572,7 +581,7 @@ wasm::CompileStreaming(const CompileArgs& args,
DebugEnabled debug;
InitialCompileFlags(args, d, &mode, &tier, &debug);
env.emplace(mode, tier, debug,
env.emplace(mode, tier, debug, args.gcTypesEnabled,
args.sharedMemoryEnabled ? Shareable::True : Shareable::False);
if (!DecodeModuleEnvironment(d, env.ptr()))
return nullptr;

Просмотреть файл

@ -50,6 +50,7 @@ struct CompileArgs : ShareableBase<CompileArgs>
bool debugEnabled;
bool ionEnabled;
bool sharedMemoryEnabled;
HasGcTypes gcTypesEnabled;
bool testTiering;
CompileArgs(Assumptions&& assumptions, ScriptedCaller&& scriptedCaller)
@ -59,6 +60,7 @@ struct CompileArgs : ShareableBase<CompileArgs>
debugEnabled(false),
ionEnabled(false),
sharedMemoryEnabled(false),
gcTypesEnabled(HasGcTypes::False),
testTiering(false)
{}

Просмотреть файл

@ -542,7 +542,7 @@ DebugState::debugGetLocalTypes(uint32_t funcIndex, ValTypeVector* locals, size_t
size_t offsetInModule = range.funcLineOrBytecode();
Decoder d(maybeBytecode_->begin() + offsetInModule, maybeBytecode_->end(),
offsetInModule, /* error = */ nullptr);
return DecodeLocalEntries(d, metadata().kind, locals);
return DecodeLocalEntries(d, metadata().kind, metadata().temporaryHasGcTypes, locals);
}
ExprType

Просмотреть файл

@ -1139,6 +1139,7 @@ ThunkedNativeToDescription(SymbolicAddress func)
case SymbolicAddress::CallImport_I32:
case SymbolicAddress::CallImport_I64:
case SymbolicAddress::CallImport_F64:
case SymbolicAddress::CallImport_Ref:
case SymbolicAddress::CoerceInPlace_ToInt32:
case SymbolicAddress::CoerceInPlace_ToNumber:
MOZ_ASSERT(!NeedsBuiltinThunk(func), "not in sync with NeedsBuiltinThunk");

Просмотреть файл

@ -840,6 +840,7 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode)
// Copy over data from the ModuleEnvironment.
metadata_->memoryUsage = env_->memoryUsage;
metadata_->temporaryHasGcTypes = env_->gcTypesEnabled;
metadata_->minMemoryLength = env_->minMemoryLength;
metadata_->maxMemoryLength = env_->maxMemoryLength;
metadata_->startFuncIndex = env_->startFuncIndex;

Просмотреть файл

@ -133,6 +133,10 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
case ValType::F64:
args[i].set(JS::CanonicalizedDoubleValue(*(double*)&argv[i]));
break;
case ValType::AnyRef: {
args[i].set(ObjectOrNullValue(*(JSObject**)&argv[i]));
break;
}
case ValType::I64:
case ValType::I8x16:
case ValType::I16x8:
@ -188,23 +192,28 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
if (!TypeScript::ThisTypes(script)->hasType(TypeSet::UndefinedType()))
return true;
// Functions with anyref in signature don't have a jit exit at the moment.
if (fi.sig().temporarilyUnsupportedAnyRef())
return true;
const ValTypeVector& importArgs = fi.sig().args();
size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
for (uint32_t i = 0; i < numKnownArgs; i++) {
TypeSet::Type type = TypeSet::UnknownType();
switch (importArgs[i]) {
case ValType::I32: type = TypeSet::Int32Type(); break;
case ValType::F32: type = TypeSet::DoubleType(); break;
case ValType::F64: type = TypeSet::DoubleType(); break;
case ValType::I64: MOZ_CRASH("NYI");
case ValType::I8x16: MOZ_CRASH("NYI");
case ValType::I16x8: MOZ_CRASH("NYI");
case ValType::I32x4: MOZ_CRASH("NYI");
case ValType::F32x4: MOZ_CRASH("NYI");
case ValType::B8x16: MOZ_CRASH("NYI");
case ValType::B16x8: MOZ_CRASH("NYI");
case ValType::B32x4: MOZ_CRASH("NYI");
case ValType::I32: type = TypeSet::Int32Type(); break;
case ValType::F32: type = TypeSet::DoubleType(); break;
case ValType::F64: type = TypeSet::DoubleType(); break;
case ValType::AnyRef: MOZ_CRASH("case guarded above");
case ValType::I64: MOZ_CRASH("NYI");
case ValType::I8x16: MOZ_CRASH("NYI");
case ValType::I16x8: MOZ_CRASH("NYI");
case ValType::I32x4: MOZ_CRASH("NYI");
case ValType::F32x4: MOZ_CRASH("NYI");
case ValType::B8x16: MOZ_CRASH("NYI");
case ValType::B16x8: MOZ_CRASH("NYI");
case ValType::B32x4: MOZ_CRASH("NYI");
}
if (!TypeScript::ArgTypes(script, i)->hasType(type))
return true;
@ -265,6 +274,31 @@ Instance::callImport_f64(Instance* instance, int32_t funcImportIndex, int32_t ar
return ToNumber(cx, rval, (double*)argv);
}
static bool
ToRef(JSContext* cx, HandleValue val, void* addr)
{
if (val.isNull()) {
*(JSObject**)addr = nullptr;
return true;
}
JSObject* obj = ToObject(cx, val);
if (!obj)
return false;
*(JSObject**)addr = obj;
return true;
}
/* static */ int32_t
Instance::callImport_ref(Instance* instance, int32_t funcImportIndex, int32_t argc, uint64_t* argv)
{
JSContext* cx = TlsContext.get();
RootedValue rval(cx);
if (!instance->callImport(cx, funcImportIndex, argc, argv, &rval))
return false;
return ToRef(cx, rval, argv);
}
/* static */ uint32_t
Instance::growMemory_i32(Instance* instance, uint32_t delta)
{
@ -672,6 +706,11 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
if (!ToNumber(cx, v, (double*)&exportArgs[i]))
return false;
break;
case ValType::AnyRef: {
if (!ToRef(cx, v, &exportArgs[i]))
return false;
break;
}
case ValType::I8x16: {
SimdConstant simd;
if (!ToSimdConstant<Int8x16>(cx, v, &simd))
@ -755,6 +794,8 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
}
void* retAddr = &exportArgs[0];
bool expectsObject = false;
JSObject* retObj = nullptr;
switch (func.sig().ret()) {
case ExprType::Void:
@ -771,6 +812,10 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
case ExprType::F64:
args.rval().set(NumberValue(*(double*)retAddr));
break;
case ExprType::AnyRef:
retObj = *(JSObject**)retAddr;
expectsObject = true;
break;
case ExprType::I8x16:
retObj = CreateSimd<Int8x16>(cx, (int8_t*)retAddr);
if (!retObj)
@ -810,7 +855,9 @@ Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args)
MOZ_CRASH("Limit");
}
if (retObj)
if (expectsObject)
args.rval().set(ObjectOrNullValue(retObj));
else if (retObj)
args.rval().set(ObjectValue(*retObj));
return true;

Просмотреть файл

@ -164,6 +164,7 @@ class Instance
static int32_t callImport_i32(Instance*, int32_t, int32_t, uint64_t*);
static int32_t callImport_i64(Instance*, int32_t, int32_t, uint64_t*);
static int32_t callImport_f64(Instance*, int32_t, int32_t, uint64_t*);
static int32_t callImport_ref(Instance*, int32_t, int32_t, uint64_t*);
static uint32_t growMemory_i32(Instance* instance, uint32_t delta);
static uint32_t currentMemory_i32(Instance* instance);
static int32_t wait_i32(Instance* instance, uint32_t byteOffset, int32_t value, int64_t timeout);

Просмотреть файл

@ -219,6 +219,9 @@ class FunctionCompiler
case ValType::F64:
ins = MConstant::New(alloc(), DoubleValue(0.0), MIRType::Double);
break;
case ValType::AnyRef:
MOZ_CRASH("ion support for anyref locale default value NYI");
break;
case ValType::I8x16:
ins = MSimdConstant::New(alloc(), SimdConstant::SplatX16(0), MIRType::Int8x16);
break;
@ -2980,6 +2983,7 @@ SimdToLaneType(ValType type)
case ValType::I64:
case ValType::F32:
case ValType::F64:
case ValType::AnyRef:
break;
}
MOZ_CRASH("bad simd type");
@ -3260,6 +3264,7 @@ EmitSimdCtor(FunctionCompiler& f, ValType type)
case ValType::I64:
case ValType::F32:
case ValType::F64:
case ValType::AnyRef:
break;
}
MOZ_CRASH("unexpected SIMD type");
@ -3973,6 +3978,11 @@ EmitBodyExprs(FunctionCompiler& f)
case uint16_t(Op::F64ReinterpretI64):
CHECK(EmitReinterpret(f, ValType::F64, ValType::I64, MIRType::Double));
// GC types are NYI in Ion.
case uint16_t(Op::RefNull):
case uint16_t(Op::RefIsNull):
return f.iter().unrecognizedOpcode(&op);
// Sign extensions
#ifdef ENABLE_WASM_SIGNEXTEND_OPS
case uint16_t(Op::I32Extend8S):
@ -4386,7 +4396,7 @@ wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,
ValTypeVector locals;
if (!locals.appendAll(env.funcSigs[func.index]->args()))
return false;
if (!DecodeLocalEntries(d, env.kind, &locals))
if (!DecodeLocalEntries(d, env.kind, env.gcTypesEnabled, &locals))
return false;
// Set up for Ion compilation.

Просмотреть файл

@ -1291,11 +1291,23 @@ WasmInstanceObject::getExportedFunction(JSContext* cx, HandleWasmInstanceObject
RootedAtom name(cx, NumberToAtom(cx, funcIndex));
if (!name)
return false;
// Functions with anyref don't have jit entries yet, so they should
// mostly behave like asm.js functions. Pretend it's the case, until
// jit entries are implemented.
JSFunction::Flags flags = sig.temporarilyUnsupportedAnyRef()
? JSFunction::ASMJS_NATIVE
: JSFunction::WASM_FUN;
fun.set(NewNativeFunction(cx, WasmCall, numArgs, name, gc::AllocKind::FUNCTION_EXTENDED,
SingletonObject, JSFunction::WASM_FUN));
SingletonObject, flags));
if (!fun)
return false;
fun->setWasmJitEntry(instance.code().getAddressOfJitEntry(funcIndex));
if (sig.temporarilyUnsupportedAnyRef())
fun->setAsmJSIndex(funcIndex);
else
fun->setWasmJitEntry(instance.code().getAddressOfJitEntry(funcIndex));
}
fun->setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT, ObjectValue(*instanceObj));

Просмотреть файл

@ -271,8 +271,10 @@ Module::finishTier2(UniqueLinkDataTier linkData2, UniqueCodeTier tier2, ModuleEn
return false;
}
HasGcTypes gcTypesEnabled = code().metadata().temporaryHasGcTypes;
Maybe<size_t> stub2Index;
if (!stubs2->createTier2(funcExportIndices, *tier2, &stub2Index))
if (!stubs2->createTier2(gcTypesEnabled, funcExportIndices, *tier2, &stub2Index))
return false;
// Install the data in the data structures. They will not be visible

Просмотреть файл

@ -92,6 +92,10 @@ SetupABIArguments(MacroAssembler& masm, const FuncExport& fe, Register argv, Reg
masm.load32(src, iter->gpr());
else if (type == MIRType::Int64)
masm.load64(src, iter->gpr64());
else if (type == MIRType::Pointer)
masm.loadPtr(src, iter->gpr());
else
MOZ_CRASH("unknown GPR type");
break;
#ifdef JS_CODEGEN_REGISTER_PAIR
case ABIArg::GPR_PAIR:
@ -148,6 +152,10 @@ SetupABIArguments(MacroAssembler& masm, const FuncExport& fe, Register argv, Reg
#endif
break;
}
case MIRType::Pointer:
masm.loadPtr(src, scratch);
masm.storePtr(scratch, Address(masm.getStackPointer(), iter->offsetFromArgBase()));
break;
case MIRType::Double:
masm.loadDouble(src, ScratchDoubleReg);
masm.storeDouble(ScratchDoubleReg,
@ -204,6 +212,9 @@ StoreABIReturn(MacroAssembler& masm, const FuncExport& fe, Register argv)
masm.canonicalizeDouble(ReturnDoubleReg);
masm.storeDouble(ReturnDoubleReg, Address(argv, 0));
break;
case ExprType::AnyRef:
masm.storePtr(ReturnReg, Address(argv, 0));
break;
case ExprType::I8x16:
case ExprType::I16x8:
case ExprType::I32x4:
@ -255,13 +266,20 @@ static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() *
NonVolatileRegs.fpus().getPushSizeInBytes();
#endif
#if defined(JS_CODEGEN_ARM64)
// Stacks are 16-byte aligned, hence the extra word.
static const unsigned FramePushedBeforeAlign = NonVolatileRegsPushSize + 2 * sizeof(void*);
#ifdef ENABLE_WASM_GC
static const unsigned NumExtraPushed = 2; // tls and argv
#else
static const unsigned FramePushedBeforeAlign = NonVolatileRegsPushSize + sizeof(void*);
static const unsigned NumExtraPushed = 1; // argv
#endif
#ifdef JS_CODEGEN_ARM64
static const unsigned WasmPushSize = 16;
#else
static const unsigned WasmPushSize = sizeof(void*);
#endif
static const unsigned FramePushedBeforeAlign = NonVolatileRegsPushSize + NumExtraPushed * WasmPushSize;
static void
AssertExpectedSP(const MacroAssembler& masm)
{
@ -276,7 +294,7 @@ WasmPush(MacroAssembler& masm, const Operand& op)
{
#ifdef JS_CODEGEN_ARM64
// Allocate a pad word so that SP can remain properly aligned.
masm.reserveStack(16);
masm.reserveStack(WasmPushSize);
masm.storePtr(op, Address(masm.getStackPointer(), 0));
#else
masm.Push(op);
@ -289,7 +307,7 @@ WasmPop(MacroAssembler& masm, Register r)
#ifdef JS_CODEGEN_ARM64
// Also pop the pad word allocated by WasmPush.
masm.loadPtr(Address(masm.getStackPointer(), 0), r);
masm.freeStack(16);
masm.freeStack(WasmPushSize);
#else
masm.Pop(r);
#endif
@ -303,6 +321,17 @@ MoveSPForJitABI(MacroAssembler& masm)
#endif
}
#ifdef ENABLE_WASM_GC
static void
SuppressGC(MacroAssembler& masm, int32_t increment, Register scratch)
{
masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, cx)), scratch);
masm.add32(Imm32(increment),
Address(scratch, offsetof(JSContext, suppressGC) +
js::ThreadLocalData<int32_t>::offsetOfValue()));
}
#endif
static void
CallFuncExport(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmPtr>& funcPtr)
{
@ -319,7 +348,7 @@ CallFuncExport(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmPtr>&
// must map from the ABI of ExportFuncPtr to the export's signature's ABI.
static bool
GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmPtr>& funcPtr,
Offsets* offsets)
HasGcTypes gcTypesEnabled, Offsets* offsets)
{
AssertExpectedSP(masm);
masm.haltingAlign(CodeAlignment);
@ -372,6 +401,12 @@ GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmP
else
masm.loadPtr(Address(masm.getStackPointer(), argBase + arg.offsetFromArgBase()), WasmTlsReg);
#ifdef ENABLE_WASM_GC
WasmPush(masm, WasmTlsReg);
if (gcTypesEnabled == HasGcTypes::True)
SuppressGC(masm, 1, scratch);
#endif
// Save 'argv' on the stack so that we can recover it after the call.
WasmPush(masm, argv);
@ -425,6 +460,12 @@ GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmP
// Recover the 'argv' pointer which was saved before aligning the stack.
WasmPop(masm, argv);
#ifdef ENABLE_WASM_GC
WasmPop(masm, WasmTlsReg);
if (gcTypesEnabled == HasGcTypes::True)
SuppressGC(masm, -1, WasmTlsReg);
#endif
// Store the return value in argv[0].
StoreABIReturn(masm, fe, argv);
@ -451,7 +492,7 @@ GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe, const Maybe<ImmP
MOZ_ASSERT(masm.framePushed() == 0);
#if defined(JS_CODEGEN_ARM64)
masm.setFramePushed(16);
masm.setFramePushed(WasmPushSize);
WasmPop(masm, lr);
masm.abiret();
#else
@ -528,7 +569,7 @@ GenerateJitEntryThrow(MacroAssembler& masm, unsigned frameSize)
static bool
GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& fe,
const Maybe<ImmPtr>& funcPtr, Offsets* offsets)
const Maybe<ImmPtr>& funcPtr, HasGcTypes gcTypesEnabled, Offsets* offsets)
{
AssertExpectedSP(masm);
@ -540,7 +581,15 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport&
// left):
// <-- retAddr | descriptor | callee | argc | this | arg1..N
unsigned normalBytesNeeded = StackArgBytes(fe.sig().args());
#ifdef ENABLE_WASM_GC
// Save WasmTlsReg in the uppermost part of the reserved area, because we
// need it directly after the call.
unsigned savedTlsSize = AlignBytes(sizeof(void*), WasmStackAlignment);
#else
unsigned savedTlsSize = 0;
#endif
unsigned normalBytesNeeded = StackArgBytes(fe.sig().args()) + savedTlsSize;
MIRTypeVector coerceArgTypes;
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Int32));
@ -554,6 +603,10 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport&
// instruction.
unsigned frameSize = StackDecrementForCall(WasmStackAlignment, 0, bytesNeeded);
#ifdef ENABLE_WASM_GC
unsigned savedTlsOffset = frameSize - sizeof(void*);
#endif
// Reserve stack space for wasm ABI arguments, set up like this:
// <-- ABI args | padding
masm.reserveStack(frameSize);
@ -726,12 +779,26 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport&
// Setup wasm register state.
masm.loadWasmPinnedRegsFromTls();
#ifdef ENABLE_WASM_GC
if (gcTypesEnabled == HasGcTypes::True) {
masm.storePtr(WasmTlsReg, Address(sp, savedTlsOffset));
SuppressGC(masm, 1, ScratchIonEntry);
}
#endif
// Call into the real function. Note that, due to the throw stub, fp, tls
// and pinned registers may be clobbered.
masm.assertStackAlignment(WasmStackAlignment);
CallFuncExport(masm, fe, funcPtr);
masm.assertStackAlignment(WasmStackAlignment);
#ifdef ENABLE_WASM_GC
if (gcTypesEnabled == HasGcTypes::True) {
masm.loadPtr(Address(sp, savedTlsOffset), WasmTlsReg);
SuppressGC(masm, -1, WasmTlsReg);
}
#endif
// If fp is equal to the FailFP magic value (set by the throw stub), then
// report the exception to the JIT caller by jumping into the exception
// stub; otherwise the FP value is still set to the parent ion frame value.
@ -758,6 +825,9 @@ GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex, const FuncExport&
masm.canonicalizeDouble(ReturnDoubleReg);
masm.boxDouble(ReturnDoubleReg, JSReturnOperand, ScratchDoubleReg);
break;
case ExprType::AnyRef:
MOZ_CRASH("return anyref in jitentry NYI");
break;
case ExprType::I64:
case ExprType::I8x16:
case ExprType::I16x8:
@ -845,6 +915,9 @@ StackCopy(MacroAssembler& masm, MIRType type, Register scratch, Address src, Add
masm.load64(src, scratch64);
masm.store64(scratch64, dst);
#endif
} else if (type == MIRType::Pointer) {
masm.loadPtr(src, scratch);
masm.storePtr(scratch, dst);
} else if (type == MIRType::Float32) {
masm.loadFloat32(src, ScratchFloat32Reg);
masm.storeFloat32(ScratchFloat32Reg, dst);
@ -878,8 +951,10 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO
masm.breakpoint();
else
masm.store64(i->gpr64(), dst);
} else {
MOZ_CRASH("unexpected input type?");
} else if (type == MIRType::Pointer) {
if (toValue)
MOZ_CRASH("generating a jit exit for anyref NYI");
masm.storePtr(i->gpr(), dst);
}
break;
#ifdef JS_CODEGEN_REGISTER_PAIR
@ -926,6 +1001,8 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO
} else if (type == MIRType::Int64) {
// We can't box int64 into Values (yet).
masm.breakpoint();
} else if (type == MIRType::Pointer) {
MOZ_CRASH("generating a jit exit for anyref NYI");
} else {
MOZ_ASSERT(IsFloatingPointType(type));
if (type == MIRType::Float32) {
@ -1122,6 +1199,11 @@ GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, uint32_t fu
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
masm.loadDouble(argv, ReturnDoubleReg);
break;
case ExprType::AnyRef:
masm.call(SymbolicAddress::CallImport_Ref);
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
masm.loadPtr(argv, ReturnReg);
break;
case ExprType::I8x16:
case ExprType::I16x8:
case ExprType::I32x4:
@ -1297,6 +1379,9 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
case ExprType::F64:
masm.convertValueToDouble(JSReturnOperand, ReturnDoubleReg, &oolConvert);
break;
case ExprType::AnyRef:
MOZ_CRASH("anyref returned by import (jit exit) NYI");
break;
case ExprType::I8x16:
case ExprType::I16x8:
case ExprType::I32x4:
@ -1701,21 +1786,22 @@ GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel, CallableOffsets*
bool
wasm::GenerateEntryStubs(MacroAssembler& masm, size_t funcExportIndex, const FuncExport& fe,
const Maybe<ImmPtr>& callee, bool isAsmJS, CodeRangeVector* codeRanges)
const Maybe<ImmPtr>& callee, bool isAsmJS, HasGcTypes gcTypesEnabled,
CodeRangeVector* codeRanges)
{
MOZ_ASSERT(!callee == fe.hasEagerStubs());
MOZ_ASSERT_IF(isAsmJS, fe.hasEagerStubs());
Offsets offsets;
if (!GenerateInterpEntry(masm, fe, callee, &offsets))
if (!GenerateInterpEntry(masm, fe, callee, gcTypesEnabled, &offsets))
return false;
if (!codeRanges->emplaceBack(CodeRange::InterpEntry, fe.funcIndex(), offsets))
return false;
if (isAsmJS)
if (isAsmJS || fe.sig().temporarilyUnsupportedAnyRef())
return true;
if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, &offsets))
if (!GenerateJitEntry(masm, funcExportIndex, fe, callee, gcTypesEnabled, &offsets))
return false;
if (!codeRanges->emplaceBack(CodeRange::JitEntry, fe.funcIndex(), offsets))
return false;
@ -1748,6 +1834,9 @@ wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& import
if (!code->codeRanges.emplaceBack(CodeRange::ImportInterpExit, funcIndex, interpOffsets))
return false;
if (fi.sig().temporarilyUnsupportedAnyRef())
continue;
JitExitOffsets jitOffsets;
if (!GenerateImportJitExit(masm, fi, &throwLabel, &jitOffsets))
return false;
@ -1762,8 +1851,11 @@ wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& import
const FuncExport& fe = exports[i];
if (!fe.hasEagerStubs())
continue;
if (!GenerateEntryStubs(masm, i, fe, noAbsolute, env.isAsmJS(), &code->codeRanges))
if (!GenerateEntryStubs(masm, i, fe, noAbsolute, env.isAsmJS(),
env.gcTypesEnabled, &code->codeRanges))
{
return false;
}
}
JitSpew(JitSpew_Codegen, "# Emitting wasm exit stubs");

Просмотреть файл

@ -39,7 +39,7 @@ GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& imports,
extern bool
GenerateEntryStubs(jit::MacroAssembler& masm, size_t funcExportIndex,
const FuncExport& funcExport, const Maybe<jit::ImmPtr>& callee,
bool isAsmJS, CodeRangeVector* codeRanges);
bool isAsmJS, HasGcTypes gcTypesEnabled, CodeRangeVector* codeRanges);
} // namespace wasm
} // namespace js

Просмотреть файл

@ -115,6 +115,7 @@ class WasmToken
Offset,
OpenParen,
Param,
RefNull,
Result,
Return,
SetGlobal,
@ -331,6 +332,7 @@ class WasmToken
case Load:
case Loop:
case Nop:
case RefNull:
case Return:
case SetGlobal:
case SetLocal:
@ -888,6 +890,8 @@ WasmTokenStream::next()
return WasmToken(WasmToken::Align, begin, cur_);
if (consume(u"anyfunc"))
return WasmToken(WasmToken::AnyFunc, begin, cur_);
if (consume(u"anyref"))
return WasmToken(WasmToken::ValueType, ValType::AnyRef, begin, cur_);
#ifdef ENABLE_WASM_THREAD_OPS
if (consume(u"atomic.wake"))
return WasmToken(WasmToken::Wake, ThreadOp::Wake, begin, cur_);
@ -1665,6 +1669,13 @@ WasmTokenStream::next()
return WasmToken(WasmToken::Result, begin, cur_);
if (consume(u"return"))
return WasmToken(WasmToken::Return, begin, cur_);
if (consume(u"ref.")) {
if (consume(u"null"))
return WasmToken(WasmToken::RefNull, begin, cur_);
if (consume(u"is_null"))
return WasmToken(WasmToken::UnaryOpcode, Op::RefIsNull, begin, cur_);
break;
}
break;
case 's':
@ -2932,6 +2943,19 @@ ParseGrowMemory(WasmParseContext& c, bool inParens)
return new(c.lifo) AstGrowMemory(operand);
}
static AstExpr*
ParseRefNull(WasmParseContext& c)
{
WasmToken token;
if (!c.ts.match(WasmToken::ValueType, &token, c.error))
return nullptr;
if (token.valueType() != ValType::AnyRef) {
c.ts.generateError(token, "only anyref is supported for nullref", c.error);
return nullptr;
}
return new(c.lifo) AstRefNull(ValType::AnyRef);
}
static AstExpr*
ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
{
@ -3008,6 +3032,8 @@ ParseExprBody(WasmParseContext& c, WasmToken token, bool inParens)
return new(c.lifo) AstCurrentMemory();
case WasmToken::GrowMemory:
return ParseGrowMemory(c, inParens);
case WasmToken::RefNull:
return ParseRefNull(c);
default:
c.ts.generateError(token, c.error);
return nullptr;
@ -4325,6 +4351,7 @@ ResolveExpr(Resolver& r, AstExpr& expr)
case AstExprKind::Pop:
case AstExprKind::Unreachable:
case AstExprKind::CurrentMemory:
case AstExprKind::RefNull:
return true;
case AstExprKind::Drop:
return ResolveDropOperator(r, expr.as<AstDrop>());
@ -4929,6 +4956,13 @@ EncodeWake(Encoder& e, AstWake& s)
EncodeLoadStoreFlags(e, s.address());
}
static bool
EncodeRefNull(Encoder& e, AstRefNull& s)
{
return e.writeOp(Op::RefNull) &&
e.writeValType(s.refType());
}
static bool
EncodeExpr(Encoder& e, AstExpr& expr)
{
@ -4939,6 +4973,8 @@ EncodeExpr(Encoder& e, AstExpr& expr)
return e.writeOp(Op::Nop);
case AstExprKind::Unreachable:
return e.writeOp(Op::Unreachable);
case AstExprKind::RefNull:
return EncodeRefNull(e, expr.as<AstRefNull>());
case AstExprKind::BinaryOperator:
return EncodeBinaryOperator(e, expr.as<AstBinaryOperator>());
case AstExprKind::Block:

Просмотреть файл

@ -72,6 +72,9 @@ Val::writePayload(uint8_t* dst) const
case ValType::B32x4:
memcpy(dst, &u, jit::Simd128DataSize);
return;
case ValType::AnyRef:
// TODO
MOZ_CRASH("writing imported value of AnyRef in global NYI");
}
}
@ -172,7 +175,7 @@ static const unsigned sTotalBits = sizeof(ImmediateType) * 8;
static const unsigned sTagBits = 1;
static const unsigned sReturnBit = 1;
static const unsigned sLengthBits = 4;
static const unsigned sTypeBits = 2;
static const unsigned sTypeBits = 3;
static const unsigned sMaxTypes = (sTotalBits - sTagBits - sReturnBit - sLengthBits) / sTypeBits;
static bool
@ -183,6 +186,7 @@ IsImmediateType(ValType vt)
case ValType::I64:
case ValType::F32:
case ValType::F64:
case ValType::AnyRef:
return true;
case ValType::I8x16:
case ValType::I16x8:
@ -199,7 +203,7 @@ IsImmediateType(ValType vt)
static unsigned
EncodeImmediateType(ValType vt)
{
static_assert(3 < (1 << sTypeBits), "fits");
static_assert(4 < (1 << sTypeBits), "fits");
switch (vt) {
case ValType::I32:
return 0;
@ -209,6 +213,8 @@ EncodeImmediateType(ValType vt)
return 2;
case ValType::F64:
return 3;
case ValType::AnyRef:
return 4;
case ValType::I8x16:
case ValType::I16x8:
case ValType::I32x4:

Просмотреть файл

@ -183,9 +183,10 @@ SizeOf(ValType vt)
case ValType::B16x8:
case ValType::B32x4:
return 16;
default:
MOZ_CRASH("Invalid ValType");
case ValType::AnyRef:
MOZ_CRASH("unexpected anyref");
}
MOZ_CRASH("Invalid ValType");
}
static inline bool
@ -275,21 +276,34 @@ static inline jit::MIRType
ToMIRType(ValType vt)
{
switch (vt) {
case ValType::I32: return jit::MIRType::Int32;
case ValType::I64: return jit::MIRType::Int64;
case ValType::F32: return jit::MIRType::Float32;
case ValType::F64: return jit::MIRType::Double;
case ValType::I8x16: return jit::MIRType::Int8x16;
case ValType::I16x8: return jit::MIRType::Int16x8;
case ValType::I32x4: return jit::MIRType::Int32x4;
case ValType::F32x4: return jit::MIRType::Float32x4;
case ValType::B8x16: return jit::MIRType::Bool8x16;
case ValType::B16x8: return jit::MIRType::Bool16x8;
case ValType::B32x4: return jit::MIRType::Bool32x4;
case ValType::I32: return jit::MIRType::Int32;
case ValType::I64: return jit::MIRType::Int64;
case ValType::F32: return jit::MIRType::Float32;
case ValType::F64: return jit::MIRType::Double;
case ValType::AnyRef: return jit::MIRType::Pointer;
case ValType::I8x16: return jit::MIRType::Int8x16;
case ValType::I16x8: return jit::MIRType::Int16x8;
case ValType::I32x4: return jit::MIRType::Int32x4;
case ValType::F32x4: return jit::MIRType::Float32x4;
case ValType::B8x16: return jit::MIRType::Bool8x16;
case ValType::B16x8: return jit::MIRType::Bool16x8;
case ValType::B32x4: return jit::MIRType::Bool32x4;
}
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad type");
}
static inline bool
IsRefType(ValType vt)
{
return vt == ValType::AnyRef;
}
static inline bool
IsNumberType(ValType vt)
{
return !IsRefType(vt);
}
// The ExprType enum represents the type of a WebAssembly expression or return
// value and may either be a value type or void. Soon, expression types will be
// generalized to a list of ValType and this enum will go away, replaced,
@ -297,22 +311,23 @@ ToMIRType(ValType vt)
enum class ExprType
{
Void = uint8_t(TypeCode::BlockVoid),
Void = uint8_t(TypeCode::BlockVoid),
I32 = uint8_t(TypeCode::I32),
I64 = uint8_t(TypeCode::I64),
F32 = uint8_t(TypeCode::F32),
F64 = uint8_t(TypeCode::F64),
I32 = uint8_t(TypeCode::I32),
I64 = uint8_t(TypeCode::I64),
F32 = uint8_t(TypeCode::F32),
F64 = uint8_t(TypeCode::F64),
AnyRef = uint8_t(TypeCode::AnyRef),
I8x16 = uint8_t(TypeCode::I8x16),
I16x8 = uint8_t(TypeCode::I16x8),
I32x4 = uint8_t(TypeCode::I32x4),
F32x4 = uint8_t(TypeCode::F32x4),
B8x16 = uint8_t(TypeCode::B8x16),
B16x8 = uint8_t(TypeCode::B16x8),
B32x4 = uint8_t(TypeCode::B32x4),
I8x16 = uint8_t(TypeCode::I8x16),
I16x8 = uint8_t(TypeCode::I16x8),
I32x4 = uint8_t(TypeCode::I32x4),
F32x4 = uint8_t(TypeCode::F32x4),
B8x16 = uint8_t(TypeCode::B8x16),
B16x8 = uint8_t(TypeCode::B16x8),
B32x4 = uint8_t(TypeCode::B32x4),
Limit = uint8_t(TypeCode::Limit)
Limit = uint8_t(TypeCode::Limit)
};
static inline bool
@ -350,18 +365,19 @@ static inline const char*
ToCString(ExprType type)
{
switch (type) {
case ExprType::Void: return "void";
case ExprType::I32: return "i32";
case ExprType::I64: return "i64";
case ExprType::F32: return "f32";
case ExprType::F64: return "f64";
case ExprType::I8x16: return "i8x16";
case ExprType::I16x8: return "i16x8";
case ExprType::I32x4: return "i32x4";
case ExprType::F32x4: return "f32x4";
case ExprType::B8x16: return "b8x16";
case ExprType::B16x8: return "b16x8";
case ExprType::B32x4: return "b32x4";
case ExprType::Void: return "void";
case ExprType::I32: return "i32";
case ExprType::I64: return "i64";
case ExprType::F32: return "f32";
case ExprType::F64: return "f64";
case ExprType::AnyRef: return "anyref";
case ExprType::I8x16: return "i8x16";
case ExprType::I16x8: return "i16x8";
case ExprType::I32x4: return "i32x4";
case ExprType::F32x4: return "f32x4";
case ExprType::B8x16: return "b8x16";
case ExprType::B16x8: return "b16x8";
case ExprType::B32x4: return "b32x4";
case ExprType::Limit:;
}
MOZ_CRASH("bad expression type");
@ -450,6 +466,12 @@ enum class Shareable
True
};
enum class HasGcTypes
{
False,
True
};
// The Val class represents a single WebAssembly value of a given value type,
// mostly for the purpose of numeric literals and initializers. A Val does not
// directly map to a JS value since there is not (currently) a precise
@ -569,8 +591,17 @@ class Sig
bool hasI64ArgOrRet() const {
if (ret() == ExprType::I64)
return true;
for (ValType a : args()) {
if (a == ValType::I64)
for (ValType arg : args()) {
if (arg == ValType::I64)
return true;
}
return false;
}
bool temporarilyUnsupportedAnyRef() const {
if (ret() == ExprType::AnyRef)
return true;
for (ValType arg : args()) {
if (arg == ValType::AnyRef)
return true;
}
return false;
@ -1437,6 +1468,7 @@ enum class SymbolicAddress
CallImport_I32,
CallImport_I64,
CallImport_F64,
CallImport_Ref,
CoerceInPlace_ToInt32,
CoerceInPlace_ToNumber,
CoerceInPlace_JitEntry,

Просмотреть файл

@ -302,7 +302,7 @@ wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals)
}
static bool
DecodeValType(Decoder& d, ModuleKind kind, ValType* type)
DecodeValType(Decoder& d, ModuleKind kind, HasGcTypes gcTypesEnabled, ValType* type)
{
uint8_t unchecked;
if (!d.readValType(&unchecked))
@ -315,6 +315,11 @@ DecodeValType(Decoder& d, ModuleKind kind, ValType* type)
case uint8_t(ValType::I64):
*type = ValType(unchecked);
return true;
case uint8_t(ValType::AnyRef):
if (gcTypesEnabled == HasGcTypes::False)
break;
*type = ValType(unchecked);
return true;
case uint8_t(ValType::I8x16):
case uint8_t(ValType::I16x8):
case uint8_t(ValType::I32x4):
@ -333,7 +338,8 @@ DecodeValType(Decoder& d, ModuleKind kind, ValType* type)
}
bool
wasm::DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals)
wasm::DecodeLocalEntries(Decoder& d, ModuleKind kind, HasGcTypes gcTypesEnabled,
ValTypeVector* locals)
{
uint32_t numLocalEntries;
if (!d.readVarU32(&numLocalEntries))
@ -348,7 +354,7 @@ wasm::DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals)
return d.fail("too many locals");
ValType type;
if (!DecodeValType(d, kind, &type))
if (!DecodeValType(d, kind, gcTypesEnabled, &type))
return false;
if (!locals->appendN(type, count))
@ -742,6 +748,20 @@ DecodeFunctionBodyExprs(const ModuleEnvironment& env, const Sig& sig, const ValT
return iter.unrecognizedOpcode(&op);
#endif
}
#ifdef ENABLE_WASM_GC
case uint16_t(Op::RefNull): {
if (env.gcTypesEnabled == HasGcTypes::False)
return iter.unrecognizedOpcode(&op);
CHECK(iter.readRefNull());
break;
}
case uint16_t(Op::RefIsNull): {
if (env.gcTypesEnabled == HasGcTypes::False)
return iter.unrecognizedOpcode(&op);
CHECK(iter.readConversion(ValType::AnyRef, ValType::I32, &nothing));
break;
}
#endif
case uint16_t(Op::ThreadPrefix): {
#ifdef ENABLE_WASM_THREAD_OPS
switch (op.b1) {
@ -936,7 +956,7 @@ wasm::ValidateFunctionBody(const ModuleEnvironment& env, uint32_t funcIndex, uin
const uint8_t* bodyBegin = d.currentPosition();
if (!DecodeLocalEntries(d, ModuleKind::Wasm, &locals))
if (!DecodeLocalEntries(d, ModuleKind::Wasm, env.gcTypesEnabled, &locals))
return false;
if (!DecodeFunctionBodyExprs(env, sig, locals, bodyBegin + bodySize, &d))
@ -1001,7 +1021,7 @@ DecodeTypeSection(Decoder& d, ModuleEnvironment* env)
return false;
for (uint32_t i = 0; i < numArgs; i++) {
if (!DecodeValType(d, ModuleKind::Wasm, &args[i]))
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &args[i]))
return false;
}
@ -1016,7 +1036,7 @@ DecodeTypeSection(Decoder& d, ModuleEnvironment* env)
if (numRets == 1) {
ValType type;
if (!DecodeValType(d, ModuleKind::Wasm, &type))
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &type))
return false;
result = ToExprType(type);
@ -1161,7 +1181,8 @@ GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable)
static bool
DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable)
{
if (!DecodeValType(d, ModuleKind::Wasm, type))
// No gc types in globals at the moment.
if (!DecodeValType(d, ModuleKind::Wasm, HasGcTypes::False, type))
return false;
uint8_t flags;
@ -1980,7 +2001,13 @@ wasm::Validate(JSContext* cx, const ShareableBytes& bytecode, UniqueChars* error
{
Decoder d(bytecode.bytes, 0, error);
ModuleEnvironment env(CompileMode::Once, Tier::Ion, DebugEnabled::False,
#ifdef ENABLE_WASM_GC
HasGcTypes gcSupport = cx->options().wasmGc() ? HasGcTypes::True : HasGcTypes::False;
#else
HasGcTypes gcSupport = HasGcTypes::False;
#endif
ModuleEnvironment env(CompileMode::Once, Tier::Ion, DebugEnabled::False, gcSupport,
cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled()
? Shareable::True
: Shareable::False);

Просмотреть файл

@ -60,6 +60,7 @@ struct ModuleEnvironment
const ModuleKind kind;
const CompileMode mode;
const Shareable sharedMemoryEnabled;
const HasGcTypes gcTypesEnabled;
const Tier tier;
// Module fields decoded from the module environment (or initialized while
@ -87,12 +88,14 @@ struct ModuleEnvironment
explicit ModuleEnvironment(CompileMode mode,
Tier tier,
DebugEnabled debug,
HasGcTypes hasGcTypes,
Shareable sharedMemoryEnabled,
ModuleKind kind = ModuleKind::Wasm)
: debug(debug),
kind(kind),
mode(mode),
sharedMemoryEnabled(sharedMemoryEnabled),
gcTypesEnabled(hasGcTypes),
tier(tier),
memoryUsage(MemoryUsage::None),
minMemoryLength(0)
@ -696,7 +699,7 @@ MOZ_MUST_USE bool
EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
MOZ_MUST_USE bool
DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals);
DecodeLocalEntries(Decoder& d, ModuleKind kind, HasGcTypes gcTypesEnabled, ValTypeVector* locals);
// Returns whether the given [begin, end) prefix of a module's bytecode starts a
// code section and, if so, returns the SectionRange of that code section.

Просмотреть файл

@ -773,6 +773,9 @@ ReloadPrefsCallback(const char* pref, void* data)
bool useWasm = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm");
bool useWasmIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_ionjit");
bool useWasmBaseline = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_baselinejit");
#ifdef ENABLE_WASM_GC
bool useWasmGc = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_gc");
#endif
bool throwOnAsmJSValidationFailure = Preferences::GetBool(JS_OPTIONS_DOT_STR
"throw_on_asmjs_validation_failure");
bool useNativeRegExp = Preferences::GetBool(JS_OPTIONS_DOT_STR "native_regexp");
@ -844,6 +847,9 @@ ReloadPrefsCallback(const char* pref, void* data)
.setWasm(useWasm)
.setWasmIon(useWasmIon)
.setWasmBaseline(useWasmBaseline)
#ifdef ENABLE_WASM_GC
.setWasmGc(useWasmGc)
#endif
.setThrowOnAsmJSValidationFailure(throwOnAsmJSValidationFailure)
.setNativeRegExp(useNativeRegExp)
.setAsyncStack(useAsyncStack)

Просмотреть файл

@ -63,3 +63,6 @@ LOCAL_INCLUDES += [
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-shadow', '-Werror=format']
if CONFIG['NIGHTLY_BUILD']:
DEFINES['ENABLE_WASM_GC'] = True

Просмотреть файл

@ -636,7 +636,7 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
// This overrides the initial values specified in fontStyle, to avoid
// inconsistencies in which attributes allow CSS changes and which do not.
if (mFlags & MATH_FONT_WEIGHT_BOLD) {
font.weight = NS_FONT_WEIGHT_BOLD;
font.weight = FontWeight::Bold();
if (mFlags & MATH_FONT_STYLING_NORMAL) {
font.style = NS_FONT_STYLE_NORMAL;
} else {
@ -644,7 +644,7 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
}
} else if (mFlags & MATH_FONT_STYLING_NORMAL) {
font.style = NS_FONT_STYLE_NORMAL;
font.weight = NS_FONT_WEIGHT_NORMAL;
font.weight = FontWeight::Normal();
} else {
mathVar = NS_MATHML_MATHVARIANT_ITALIC;
}
@ -723,20 +723,20 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
if (mathVar == NS_MATHML_MATHVARIANT_BOLD && doMathvariantStyling) {
font.style = NS_FONT_STYLE_NORMAL;
font.weight = NS_FONT_WEIGHT_BOLD;
font.weight = FontWeight::Bold();
} else if (mathVar == NS_MATHML_MATHVARIANT_ITALIC && doMathvariantStyling) {
font.style = NS_FONT_STYLE_ITALIC;
font.weight = NS_FONT_WEIGHT_NORMAL;
font.weight = FontWeight::Normal();
} else if (mathVar == NS_MATHML_MATHVARIANT_BOLD_ITALIC &&
doMathvariantStyling) {
font.style = NS_FONT_STYLE_ITALIC;
font.weight = NS_FONT_WEIGHT_BOLD;
font.weight = FontWeight::Bold();
} else if (mathVar != NS_MATHML_MATHVARIANT_NONE) {
// Mathvariant overrides fontstyle and fontweight
// Need to check to see if mathvariant is actually applied as this function
// is used for other purposes.
font.style = NS_FONT_STYLE_NORMAL;
font.weight = NS_FONT_WEIGHT_NORMAL;
font.weight = FontWeight::Normal();
}
gfxFontGroup* newFontGroup = nullptr;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше