зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central. a=merge
--HG-- rename : servo/components/style/properties/longhand/box.mako.rs => servo/components/style/properties/longhands/box.mako.rs
This commit is contained in:
Коммит
4c18cd4036
|
@ -8,6 +8,9 @@
|
|||
(^|/)\.DS_Store$
|
||||
\.pdb
|
||||
\.egg-info
|
||||
\.gcda
|
||||
\.gcno
|
||||
\.gcov
|
||||
|
||||
# Vim swap files.
|
||||
^\.sw.$
|
||||
|
|
|
@ -453,7 +453,8 @@ async function setupHistory() {
|
|||
let today = new Date();
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(1);
|
||||
today.setSeconds(0);
|
||||
today.setMilliseconds(1);
|
||||
addPlace("http://today.com/", "Today", today.getTime() * 1000);
|
||||
|
||||
let lastYear = new Date();
|
||||
|
@ -564,7 +565,8 @@ async function setupFormHistory() {
|
|||
let today = new Date();
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(1);
|
||||
today.setSeconds(0);
|
||||
today.setMilliseconds(1);
|
||||
timestamp = today.getTime() * 1000;
|
||||
results = await searchEntries(["guid"], { fieldname: "today" });
|
||||
await update({ op: "update", firstUsed: timestamp, guid: results[0].guid });
|
||||
|
@ -655,7 +657,8 @@ async function setupDownloads() {
|
|||
let today = new Date();
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(1);
|
||||
today.setSeconds(0);
|
||||
today.setMilliseconds(1);
|
||||
|
||||
download = await Downloads.createDownload({
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
|
|
|
@ -127,10 +127,10 @@ var Policies = {
|
|||
addAllowDenyPermissions("cookie", param.Allow, param.Block);
|
||||
|
||||
if (param.Block) {
|
||||
const hosts = param.Block.map(uri => uri.host).sort().join("\n");
|
||||
const hosts = param.Block.map(url => url.hostname).sort().join("\n");
|
||||
runOncePerModification("clearCookiesForBlockedHosts", hosts, () => {
|
||||
for (let blocked of param.Block) {
|
||||
Services.cookies.removeCookiesWithOriginAttributes("{}", blocked.host);
|
||||
Services.cookies.removeCookiesWithOriginAttributes("{}", blocked.hostname);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -508,9 +508,9 @@ var Policies = {
|
|||
// |homepages| will be a string containing a pipe-separated ('|') list of
|
||||
// URLs because that is what the "Home page" section of about:preferences
|
||||
// (and therefore what the pref |browser.startup.homepage|) accepts.
|
||||
let homepages = param.URL.spec;
|
||||
let homepages = param.URL.href;
|
||||
if (param.Additional && param.Additional.length > 0) {
|
||||
homepages += "|" + param.Additional.map(url => url.spec).join("|");
|
||||
homepages += "|" + param.Additional.map(url => url.href).join("|");
|
||||
}
|
||||
if (param.Locked) {
|
||||
setAndLockPref("browser.startup.homepage", homepages);
|
||||
|
@ -563,14 +563,14 @@ var Policies = {
|
|||
|
||||
"OverrideFirstRunPage": {
|
||||
onProfileAfterChange(manager, param) {
|
||||
let url = param ? param.spec : "";
|
||||
let url = param ? param.href : "";
|
||||
setAndLockPref("startup.homepage_welcome_url", url);
|
||||
}
|
||||
},
|
||||
|
||||
"OverridePostUpdatePage": {
|
||||
onProfileAfterChange(manager, param) {
|
||||
let url = param ? param.spec : "";
|
||||
let url = param ? param.href : "";
|
||||
setAndLockPref("startup.homepage_override_url", url);
|
||||
// The pref startup.homepage_override_url is only used
|
||||
// as a fallback when the update.xml file hasn't provided
|
||||
|
@ -857,18 +857,18 @@ function addAllowDenyPermissions(permissionName, allowList, blockList) {
|
|||
|
||||
for (let origin of allowList) {
|
||||
try {
|
||||
Services.perms.add(origin,
|
||||
Services.perms.add(Services.io.newURI(origin.href),
|
||||
permissionName,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_POLICY);
|
||||
} catch (ex) {
|
||||
log.error(`Added by default for ${permissionName} permission in the permission
|
||||
manager - ${origin.spec}`);
|
||||
manager - ${origin.href}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let origin of blockList) {
|
||||
Services.perms.add(origin,
|
||||
Services.perms.add(Services.io.newURI(origin.href),
|
||||
permissionName,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_POLICY);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* A Bookmark object received through the policy engine will be an
|
||||
* object with the following properties:
|
||||
*
|
||||
* - URL (nsIURI)
|
||||
* - URL (URL)
|
||||
* (required) The URL for this bookmark
|
||||
*
|
||||
* - Title (string)
|
||||
|
@ -25,7 +25,7 @@
|
|||
* If missing, the bookmark will be created directly into the
|
||||
* chosen placement.
|
||||
*
|
||||
* - Favicon (nsIURI)
|
||||
* - Favicon (URL)
|
||||
* (optional) An http:, https: or data: URL with the favicon.
|
||||
* If possible, we recommend against using this property, in order
|
||||
* to keep the json file small.
|
||||
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
*
|
||||
* Note: The Policy Engine automatically converts the strings given to
|
||||
* the URL and favicon properties into a nsIURI object.
|
||||
* the URL and favicon properties into a URL object.
|
||||
*
|
||||
* The schema for this object is defined in policies-schema.json.
|
||||
*/
|
||||
|
@ -109,7 +109,7 @@ async function calculateLists(specifiedBookmarks) {
|
|||
// MAP of url (string) -> bookmarks objects from the Policy Engine
|
||||
let specifiedBookmarksMap = new Map();
|
||||
for (let bookmark of specifiedBookmarks) {
|
||||
specifiedBookmarksMap.set(bookmark.URL.spec, bookmark);
|
||||
specifiedBookmarksMap.set(bookmark.URL.href, bookmark);
|
||||
}
|
||||
|
||||
// LIST B
|
||||
|
@ -193,7 +193,7 @@ async function insertBookmark(bookmark) {
|
|||
bookmark.Folder);
|
||||
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
url: bookmark.URL,
|
||||
url: Services.io.newURI(bookmark.URL.href),
|
||||
title: bookmark.Title,
|
||||
guid: generateGuidWithPrefix(BookmarksPolicies.BOOKMARK_GUID_PREFIX),
|
||||
parentGuid,
|
||||
|
@ -209,24 +209,24 @@ async function setFaviconForBookmark(bookmark) {
|
|||
let faviconURI;
|
||||
let nullPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
|
||||
|
||||
switch (bookmark.Favicon.scheme) {
|
||||
case "data":
|
||||
switch (bookmark.Favicon.protocol) {
|
||||
case "data:":
|
||||
// data urls must first call replaceFaviconDataFromDataURL, using a
|
||||
// fake URL. Later, it's needed to call setAndFetchFaviconForPage
|
||||
// with the same URL.
|
||||
faviconURI = Services.io.newURI("fake-favicon-uri:" + bookmark.URL.spec);
|
||||
faviconURI = Services.io.newURI("fake-favicon-uri:" + bookmark.URL.href);
|
||||
|
||||
PlacesUtils.favicons.replaceFaviconDataFromDataURL(
|
||||
faviconURI,
|
||||
bookmark.Favicon.spec,
|
||||
bookmark.Favicon.href,
|
||||
0, /* max expiration length */
|
||||
nullPrincipal
|
||||
);
|
||||
break;
|
||||
|
||||
case "http":
|
||||
case "https":
|
||||
faviconURI = bookmark.Favicon;
|
||||
case "http:":
|
||||
case "https:":
|
||||
faviconURI = Services.io.newURI(bookmark.Favicon.href);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -236,7 +236,7 @@ async function setFaviconForBookmark(bookmark) {
|
|||
|
||||
return new Promise(resolve => {
|
||||
PlacesUtils.favicons.setAndFetchFaviconForPage(
|
||||
bookmark.URL,
|
||||
Services.io.newURI(bookmark.URL.href),
|
||||
faviconURI,
|
||||
false, /* forceReload */
|
||||
PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
|
||||
|
|
|
@ -40,7 +40,7 @@ var ProxyPolicies = {
|
|||
}
|
||||
|
||||
if (param.AutoConfigURL) {
|
||||
setPref("network.proxy.autoconfig_url", param.AutoConfigURL.spec);
|
||||
setPref("network.proxy.autoconfig_url", param.AutoConfigURL.href);
|
||||
}
|
||||
|
||||
if (param.UseProxyForDNS !== undefined) {
|
||||
|
|
|
@ -15,7 +15,7 @@ let CURRENT_POLICY;
|
|||
|
||||
const BASE_POLICY = {
|
||||
"policies": {
|
||||
"display_bookmarks_toolbar": true,
|
||||
"DisplayBookmarksToolbar": true,
|
||||
"Bookmarks": [
|
||||
{
|
||||
"Title": "Bookmark 1",
|
||||
|
|
|
@ -16,9 +16,9 @@ add_task(async function test_proxy_modes_and_autoconfig() {
|
|||
});
|
||||
}
|
||||
|
||||
let autoconfigURL = Services.io.newURI("data:text/plain,test");
|
||||
let autoconfigURL = new URL("data:text/plain,test");
|
||||
ProxyPolicies.configureProxySettings({AutoConfigURL: autoconfigURL}, (_, value) => {
|
||||
is(value, autoconfigURL.spec, "AutoconfigURL correctly set");
|
||||
is(value, autoconfigURL.href, "AutoconfigURL correctly set");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -206,6 +206,7 @@ var Sanitizer = {
|
|||
d.setHours(0); // zero us back to midnight...
|
||||
d.setMinutes(0);
|
||||
d.setSeconds(0);
|
||||
d.setMilliseconds(0);
|
||||
startDate = d.valueOf() * 1000; // convert to epoch usec
|
||||
break;
|
||||
case Sanitizer.TIMESPAN_24HOURS :
|
||||
|
|
|
@ -2912,6 +2912,27 @@ exports.CSS_PROPERTIES = {
|
|||
"caret-color",
|
||||
"scrollbar-face-color",
|
||||
"scrollbar-track-color",
|
||||
"text-anchor",
|
||||
"color-interpolation",
|
||||
"color-interpolation-filters",
|
||||
"fill",
|
||||
"fill-opacity",
|
||||
"fill-rule",
|
||||
"shape-rendering",
|
||||
"stroke",
|
||||
"stroke-width",
|
||||
"stroke-linecap",
|
||||
"stroke-linejoin",
|
||||
"stroke-miterlimit",
|
||||
"stroke-opacity",
|
||||
"stroke-dasharray",
|
||||
"stroke-dashoffset",
|
||||
"clip-rule",
|
||||
"marker-start",
|
||||
"marker-mid",
|
||||
"marker-end",
|
||||
"paint-order",
|
||||
"-moz-context-properties",
|
||||
"list-style-position",
|
||||
"list-style-type",
|
||||
"list-style-image",
|
||||
|
@ -2981,27 +3002,6 @@ exports.CSS_PROPERTIES = {
|
|||
"-moz-user-select",
|
||||
"-moz-window-dragging",
|
||||
"-moz-force-broken-image-icon",
|
||||
"text-anchor",
|
||||
"color-interpolation",
|
||||
"color-interpolation-filters",
|
||||
"fill",
|
||||
"fill-opacity",
|
||||
"fill-rule",
|
||||
"shape-rendering",
|
||||
"stroke",
|
||||
"stroke-width",
|
||||
"stroke-linecap",
|
||||
"stroke-linejoin",
|
||||
"stroke-miterlimit",
|
||||
"stroke-opacity",
|
||||
"stroke-dasharray",
|
||||
"stroke-dashoffset",
|
||||
"clip-rule",
|
||||
"marker-start",
|
||||
"marker-mid",
|
||||
"marker-end",
|
||||
"paint-order",
|
||||
"-moz-context-properties",
|
||||
"dominant-baseline",
|
||||
"vector-effect",
|
||||
"stop-color",
|
||||
|
|
|
@ -45,7 +45,8 @@ class MOZ_RAII AutoMemMap
|
|||
|
||||
public:
|
||||
explicit AutoMemMap(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||
: fd(nullptr)
|
||||
: fileInfo()
|
||||
, fd(nullptr)
|
||||
, fileMap(nullptr)
|
||||
, addr(nullptr)
|
||||
{
|
||||
|
|
|
@ -1359,7 +1359,9 @@ public:
|
|||
HeapSnapshotHandler(CoreDumpWriter& writer,
|
||||
JS::CompartmentSet* compartments)
|
||||
: writer(writer),
|
||||
compartments(compartments)
|
||||
compartments(compartments),
|
||||
nodeCount(0),
|
||||
edgeCount(0)
|
||||
{ }
|
||||
|
||||
// JS::ubi::BreadthFirst handler interface.
|
||||
|
|
|
@ -133,6 +133,15 @@ HasUserPassword(const nsACString& aStringURI)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Assume that 1 tab is accidental, but more than 1 implies this is
|
||||
// supposed to be tab-separated content.
|
||||
static bool
|
||||
MaybeTabSeparatedContent(const nsCString& aStringURI)
|
||||
{
|
||||
auto firstTab = aStringURI.FindChar('\t');
|
||||
return firstTab != kNotFound && aStringURI.RFindChar('\t') != firstTab;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
|
||||
uint32_t aFixupFlags,
|
||||
|
@ -147,8 +156,8 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
|
|||
|
||||
// Eliminate embedded newlines, which single-line text fields now allow:
|
||||
uriString.StripCRLF();
|
||||
// Cleanup the empty spaces that might be on each end:
|
||||
uriString.Trim(" ");
|
||||
// Cleanup the empty spaces and tabs that might be on each end:
|
||||
uriString.Trim(" \t");
|
||||
|
||||
NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -360,12 +369,16 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
|
|||
inputHadDuffProtocol = true;
|
||||
}
|
||||
|
||||
// NB: this rv gets returned at the end of this method if we never
|
||||
// do a keyword fixup after this (because the pref or the flags passed
|
||||
// might not let us).
|
||||
rv = FixupURIProtocol(uriString, info, getter_AddRefs(uriWithProtocol));
|
||||
if (uriWithProtocol) {
|
||||
info->mFixedURI = uriWithProtocol;
|
||||
// Note: this rv gets returned at the end of this method if we don't fix up
|
||||
// the protocol and don't do a keyword fixup after this (because the pref
|
||||
// or the flags passed might not let us).
|
||||
rv = NS_OK;
|
||||
// Avoid fixing up content that looks like tab-separated values
|
||||
if (!MaybeTabSeparatedContent(uriString)) {
|
||||
rv = FixupURIProtocol(uriString, info, getter_AddRefs(uriWithProtocol));
|
||||
if (uriWithProtocol) {
|
||||
info->mFixedURI = uriWithProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
// See if it is a keyword
|
||||
|
|
|
@ -493,6 +493,16 @@ var testcases = [ {
|
|||
alternateURI: "http://www.xn--lodaehvb5cdik4g.xn--node/",
|
||||
protocolChange: true,
|
||||
},
|
||||
{
|
||||
input: " \t mozilla.org/\t \t ",
|
||||
fixedURI: "http://mozilla.org/",
|
||||
alternateURI: "http://www.mozilla.org/",
|
||||
protocolChange: true,
|
||||
},
|
||||
{
|
||||
input: " moz\ti\tlla.org ",
|
||||
keywordLookup: true,
|
||||
},
|
||||
];
|
||||
|
||||
if (Services.appinfo.OS.toLowerCase().startsWith("win")) {
|
||||
|
@ -589,24 +599,25 @@ function do_single_test_run() {
|
|||
|
||||
// Both APIs should then also be using the same spec.
|
||||
Assert.equal(!!fixupURIOnly, !!URIInfo.preferredURI);
|
||||
if (fixupURIOnly)
|
||||
Assert.equal(fixupURIOnly.spec, URIInfo.preferredURI.spec);
|
||||
if (fixupURIOnly) {
|
||||
Assert.equal(fixupURIOnly.spec, URIInfo.preferredURI.spec, "Fixed and preferred URI should match");
|
||||
}
|
||||
|
||||
let isFileURL = expectedFixedURI && expectedFixedURI.startsWith("file");
|
||||
|
||||
// Check the fixedURI:
|
||||
let makeAlternativeURI = flags & urifixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI;
|
||||
if (makeAlternativeURI && alternativeURI != null) {
|
||||
Assert.equal(URIInfo.fixedURI.spec, alternativeURI);
|
||||
Assert.equal(URIInfo.fixedURI.spec, alternativeURI, "should have gotten alternate URI");
|
||||
} else {
|
||||
Assert.equal(URIInfo.fixedURI && URIInfo.fixedURI.spec, expectedFixedURI);
|
||||
Assert.equal(URIInfo.fixedURI && URIInfo.fixedURI.spec, expectedFixedURI, "should get correct fixed URI");
|
||||
}
|
||||
|
||||
// Check booleans on input:
|
||||
let couldDoKeywordLookup = flags & urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
|
||||
Assert.equal(!!URIInfo.keywordProviderName, couldDoKeywordLookup && expectKeywordLookup);
|
||||
Assert.equal(URIInfo.fixupChangedProtocol, expectProtocolChange);
|
||||
Assert.equal(URIInfo.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null);
|
||||
Assert.equal(!!URIInfo.keywordProviderName, couldDoKeywordLookup && expectKeywordLookup, "keyword lookup as expected");
|
||||
Assert.equal(URIInfo.fixupChangedProtocol, expectProtocolChange, "protocol change as expected");
|
||||
Assert.equal(URIInfo.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null, "alternative URI as expected");
|
||||
|
||||
// Check the preferred URI
|
||||
if (couldDoKeywordLookup) {
|
||||
|
@ -620,19 +631,21 @@ function do_single_test_run() {
|
|||
}
|
||||
let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
|
||||
let spec = URIInfo.preferredURI.spec.replace(/%27/g, "'");
|
||||
Assert.equal(spec, searchURL);
|
||||
Assert.equal(spec, searchURL, "should get correct search URI");
|
||||
} else {
|
||||
Assert.equal(URIInfo.preferredURI, null);
|
||||
Assert.equal(URIInfo.preferredURI, null, "not expecting a preferred URI");
|
||||
}
|
||||
} else {
|
||||
Assert.equal(URIInfo.preferredURI.spec, URIInfo.fixedURI.spec);
|
||||
Assert.equal(URIInfo.preferredURI.spec, URIInfo.fixedURI.spec, "fixed URI should match");
|
||||
}
|
||||
} else {
|
||||
// In these cases, we should never be doing a keyword lookup and
|
||||
// the fixed URI should be preferred:
|
||||
Assert.equal(URIInfo.preferredURI.spec, URIInfo.fixedURI.spec);
|
||||
let prefURI = URIInfo.preferredURI && URIInfo.preferredURI.spec;
|
||||
let fixedURI = URIInfo.fixedURI && URIInfo.fixedURI.spec;
|
||||
Assert.equal(prefURI, fixedURI, "fixed URI should be same as expected");
|
||||
}
|
||||
Assert.equal(sanitize(testInput), URIInfo.originalInput);
|
||||
Assert.equal(sanitize(testInput), URIInfo.originalInput, "should mirror original input");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,8 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsAString.h"
|
||||
|
@ -512,6 +514,41 @@ EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|||
lm->~EventListenerManagerMapEntry();
|
||||
}
|
||||
|
||||
static bool
|
||||
IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
MOZ_ASSERT(!aWindow || !aChannel,
|
||||
"A window and channel should not both be provided.");
|
||||
|
||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = services::GetThirdPartyUtil();
|
||||
if (!thirdPartyUtil) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// In the absence of a window or channel, we assume that we are first-party.
|
||||
bool thirdParty = false;
|
||||
|
||||
if (aWindow) {
|
||||
Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
|
||||
aURI,
|
||||
&thirdParty);
|
||||
}
|
||||
|
||||
if (aChannel) {
|
||||
// Note, we must call IsThirdPartyChannel() here and not just try to
|
||||
// use nsILoadInfo.isThirdPartyContext. That nsILoadInfo property only
|
||||
// indicates if the parent loading window is third party or not. We
|
||||
// want to check the channel URI against the loading principal as well.
|
||||
Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
|
||||
nullptr,
|
||||
&thirdParty);
|
||||
}
|
||||
|
||||
return thirdParty;
|
||||
}
|
||||
|
||||
class SameOriginCheckerImpl final : public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
|
@ -8815,6 +8852,36 @@ nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
}
|
||||
|
||||
// static public
|
||||
bool
|
||||
nsContentUtils::StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
if (!StaticPrefs::privacy_trackingprotection_storagerestriction_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let's check if this is a 3rd party context.
|
||||
if (!IsThirdPartyWindowOrChannel(aWindow, aChannel, aURI)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
|
||||
// aChannel and aWindow are mutually exclusive.
|
||||
channel = aChannel;
|
||||
if (aWindow) {
|
||||
nsIDocument* document = aWindow->GetExtantDoc();
|
||||
if (document) {
|
||||
channel = document->GetChannel();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
||||
return httpChannel && httpChannel->GetIsTrackingResource();
|
||||
}
|
||||
|
||||
// static, private
|
||||
nsContentUtils::StorageAccess
|
||||
nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
|
||||
|
@ -8832,6 +8899,10 @@ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
|
|||
return StorageAccess::eDeny;
|
||||
}
|
||||
|
||||
if (StorageDisabledByAntiTracking(aWindow, aChannel, aURI)) {
|
||||
return StorageAccess::eDeny;
|
||||
}
|
||||
|
||||
if (aWindow) {
|
||||
// If the document is sandboxed, then it is not permitted to use storage
|
||||
nsIDocument* document = aWindow->GetExtantDoc();
|
||||
|
@ -8907,47 +8978,15 @@ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
|
|||
return StorageAccess::eDeny;
|
||||
}
|
||||
|
||||
if (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
|
||||
behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) {
|
||||
if ((behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
|
||||
behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) &&
|
||||
IsThirdPartyWindowOrChannel(aWindow, aChannel, aURI)) {
|
||||
// XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
|
||||
// simply rejecting the request to use the storage. In the future, if we
|
||||
// change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
|
||||
// for non-cookie storage types, this may change.
|
||||
|
||||
// In the absence of a window or channel, we assume that we are first-party.
|
||||
bool thirdParty = false;
|
||||
|
||||
MOZ_ASSERT(!aWindow || !aChannel,
|
||||
"A window and channel should not both be provided.");
|
||||
|
||||
if (aWindow) {
|
||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
|
||||
do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
||||
MOZ_ASSERT(thirdPartyUtil);
|
||||
|
||||
Unused << thirdPartyUtil->IsThirdPartyWindow(aWindow->GetOuterWindow(),
|
||||
aURI,
|
||||
&thirdParty);
|
||||
}
|
||||
|
||||
if (aChannel) {
|
||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
|
||||
do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
||||
MOZ_ASSERT(thirdPartyUtil);
|
||||
|
||||
// Note, we must call IsThirdPartyChannel() here and not just try to
|
||||
// use nsILoadInfo.isThirdPartyContext. That nsILoadInfo property only
|
||||
// indicates if the parent loading window is third party or not. We
|
||||
// want to check the channel URI against the loading principal as well.
|
||||
Unused << thirdPartyUtil->IsThirdPartyChannel(aChannel,
|
||||
nullptr,
|
||||
&thirdParty);
|
||||
}
|
||||
|
||||
if (thirdParty) {
|
||||
// XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
|
||||
// simply rejecting the request to use the storage. In the future, if we
|
||||
// change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
|
||||
// for non-cookie storage types, this may change.
|
||||
|
||||
return StorageAccess::eDeny;
|
||||
}
|
||||
return StorageAccess::eDeny;
|
||||
}
|
||||
|
||||
return access;
|
||||
|
|
|
@ -2954,6 +2954,14 @@ public:
|
|||
*/
|
||||
static StorageAccess StorageAllowedForPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
/*
|
||||
* Returns true if this window/channel should disable storages because of the
|
||||
* anti-tracking feature.
|
||||
*/
|
||||
static bool StorageDisabledByAntiTracking(nsPIDOMWindowInner* aWindow,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI);
|
||||
|
||||
/*
|
||||
* Serializes a HTML nsINode into its markup representation.
|
||||
*/
|
||||
|
|
|
@ -941,6 +941,10 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
|
|||
false);
|
||||
|
||||
os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC, false);
|
||||
|
||||
if (aOuterWindow->IsTopLevelWindow()) {
|
||||
os->AddObserver(mObserver, "clear-site-data-reload-needed", false);
|
||||
}
|
||||
}
|
||||
|
||||
Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
|
||||
|
@ -1268,6 +1272,11 @@ nsGlobalWindowInner::FreeInnerObjects()
|
|||
if (os) {
|
||||
os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
|
||||
os->RemoveObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC);
|
||||
|
||||
if (GetOuterWindowInternal() &&
|
||||
GetOuterWindowInternal()->IsTopLevelWindow()) {
|
||||
os->RemoveObserver(mObserver, "clear-site-data-reload-needed");
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
|
||||
|
@ -5818,6 +5827,13 @@ nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, "clear-site-data-reload-needed")) {
|
||||
// The reload is propagated from the top-level window only.
|
||||
NS_ConvertUTF16toUTF8 otherOrigin(aData);
|
||||
PropagateClearSiteDataReload(otherOrigin);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
|
||||
mCurrentlyIdle = true;
|
||||
if (IsFrozen()) {
|
||||
|
@ -8053,6 +8069,39 @@ nsPIDOMWindowInner::MaybeCreateDoc()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::PropagateClearSiteDataReload(const nsACString& aOrigin)
|
||||
{
|
||||
nsIPrincipal* principal = GetPrincipal();
|
||||
if (!principal) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString origin;
|
||||
nsresult rv = principal->GetOrigin(origin);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
// If the URL of this window matches, let's refresh this window only.
|
||||
// We don't need to traverse the DOM tree.
|
||||
if (origin.Equals(aOrigin)) {
|
||||
nsCOMPtr<nsIDocShell> docShell = GetDocShell();
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
|
||||
if (NS_WARN_IF(!webNav)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't need any special reload flags, because this notification is
|
||||
// dispatched by Clear-Site-Data header, which should have already cleaned
|
||||
// up all the needed data.
|
||||
rv = webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CallOnChildren(&nsGlobalWindowInner::PropagateClearSiteDataReload, aOrigin);
|
||||
}
|
||||
|
||||
mozilla::dom::DocGroup*
|
||||
nsPIDOMWindowInner::GetDocGroup() const
|
||||
{
|
||||
|
|
|
@ -979,6 +979,8 @@ public:
|
|||
|
||||
bool ShouldReportForServiceWorkerScope(const nsAString& aScope);
|
||||
|
||||
void PropagateClearSiteDataReload(const nsACString& aOrigin);
|
||||
|
||||
already_AddRefed<mozilla::dom::InstallTriggerImpl> GetInstallTrigger();
|
||||
|
||||
void UpdateTopInnerWindow();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsIBFCacheEntry.h"
|
||||
|
@ -299,12 +300,25 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
|
|||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (StaticPrefs::privacy_trackingprotection_storagerestriction_enabled() &&
|
||||
nsContentUtils::StorageAllowedForWindow(window) !=
|
||||
nsContentUtils::StorageAccess::eAllow) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
JSContext* cx = aGlobal.Context();
|
||||
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
if (StaticPrefs::privacy_trackingprotection_storagerestriction_enabled() &&
|
||||
!workerPrivate->IsStorageAllowed()) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<StrongWorkerRef> workerRef =
|
||||
StrongWorkerRef::Create(workerPrivate, "BroadcastChannel",
|
||||
[bc] () { bc->Shutdown(); });
|
||||
|
|
|
@ -1106,6 +1106,11 @@ nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv)
|
|||
return;
|
||||
}
|
||||
|
||||
if (nsContentUtils::StorageDisabledByAntiTracking(GetInnerWindow(), nullptr,
|
||||
nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the document is a cookie-averse Document... return the empty string.
|
||||
if (IsCookieAverse()) {
|
||||
return;
|
||||
|
|
|
@ -2589,6 +2589,18 @@ ContentChild::RecvUpdateRequestedLocales(nsTArray<nsCString>&& aRequestedLocales
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvClearSiteDataReloadNeeded(const nsString& aOrigin)
|
||||
{
|
||||
// Rebroadcast "clear-site-data-reload-needed".
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(nullptr, "clear-site-data-reload-needed",
|
||||
aOrigin.get());
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvAddPermission(const IPC::Permission& permission)
|
||||
{
|
||||
|
|
|
@ -405,6 +405,8 @@ public:
|
|||
virtual mozilla::ipc::IPCResult RecvUpdateAppLocales(nsTArray<nsCString>&& aAppLocales) override;
|
||||
virtual mozilla::ipc::IPCResult RecvUpdateRequestedLocales(nsTArray<nsCString>&& aRequestedLocales) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvClearSiteDataReloadNeeded(const nsString& aOrigin) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvAddPermission(const IPC::Permission& permission) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvFlushMemory(const nsString& reason) override;
|
||||
|
|
|
@ -594,6 +594,7 @@ static const char* sObserverTopics[] = {
|
|||
"intl:requested-locales-changed",
|
||||
"cookie-changed",
|
||||
"private-cookie-changed",
|
||||
"clear-site-data-reload-needed",
|
||||
};
|
||||
|
||||
// PreallocateProcess is called by the PreallocatedProcessManager.
|
||||
|
@ -3012,6 +3013,9 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
(!nsCRT::strcmp(aData, u"changed"))) {
|
||||
cs->AddCookie(xpcCookie);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "clear-site-data-reload-needed")) {
|
||||
// Rebroadcast "clear-site-data-reload-needed".
|
||||
Unused << SendClearSiteDataReloadNeeded(nsString(aData));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -455,6 +455,8 @@ child:
|
|||
async UpdateAppLocales(nsCString[] appLocales);
|
||||
async UpdateRequestedLocales(nsCString[] requestedLocales);
|
||||
|
||||
async ClearSiteDataReloadNeeded(nsString origin);
|
||||
|
||||
// nsIPermissionManager messages
|
||||
async AddPermission(Permission permission);
|
||||
|
||||
|
|
|
@ -94,3 +94,5 @@ BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blo
|
|||
# LOCALIZATION NOTE (BrowserUpgradeInsecureDisplayRequest):
|
||||
# %1$S is the browser name "brandShortName"; %2$S is the URL of the upgraded request; %1$S is the upgraded scheme.
|
||||
BrowserUpgradeInsecureDisplayRequest = %1$S is upgrading an insecure display request ‘%2$S’ to use ‘%3$S’
|
||||
RunningClearSiteDataValue=Clear-Site-Data header forces the clean up of “%S” data.
|
||||
UnknownClearSiteDataValue=Clear-Site-Data header found. Unknown value “%S”.
|
||||
|
|
|
@ -113,8 +113,8 @@ static NPNetscapeFuncs sBrowserFuncs = {
|
|||
_memfree,
|
||||
_memflush,
|
||||
_reloadplugins,
|
||||
nullptr, // _getJavaEnv, unimplemented
|
||||
nullptr, // _getJavaPeer, unimplemented
|
||||
_getJavaEnv,
|
||||
_getJavaPeer,
|
||||
_geturlnotify,
|
||||
_posturlnotify,
|
||||
_getvalue,
|
||||
|
@ -1703,6 +1703,14 @@ _requestread(NPStream *pstream, NPByteRange *rangeList)
|
|||
return NPERR_STREAM_NOT_SEEKABLE;
|
||||
}
|
||||
|
||||
// Deprecated, only stubbed out
|
||||
void* /* OJI type: JRIEnv* */
|
||||
_getJavaEnv()
|
||||
{
|
||||
NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
_useragent(NPP npp)
|
||||
{
|
||||
|
@ -1736,6 +1744,14 @@ _memalloc (uint32_t size)
|
|||
return moz_xmalloc(size);
|
||||
}
|
||||
|
||||
// Deprecated, only stubbed out
|
||||
void* /* OJI type: jref */
|
||||
_getJavaPeer(NPP npp)
|
||||
{
|
||||
NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
_pushpopupsenabledstate(NPP npp, NPBool enabled)
|
||||
{
|
||||
|
|
|
@ -279,6 +279,13 @@ _useragent(NPP npp);
|
|||
void*
|
||||
_memalloc (uint32_t size);
|
||||
|
||||
// Deprecated entry points for the old Java plugin.
|
||||
void* /* OJI type: JRIEnv* */
|
||||
_getJavaEnv();
|
||||
|
||||
void* /* OJI type: jref */
|
||||
_getJavaPeer(NPP npp);
|
||||
|
||||
void
|
||||
_urlredirectresponse(NPP instance, void* notifyData, NPBool allow);
|
||||
|
||||
|
|
|
@ -875,6 +875,14 @@ _useragent(NPP aNPP);
|
|||
static void*
|
||||
_memalloc (uint32_t size);
|
||||
|
||||
// Deprecated entry points for the old Java plugin.
|
||||
static void* /* OJI type: JRIEnv* */
|
||||
_getjavaenv(void);
|
||||
|
||||
// Deprecated entry points for the old Java plugin.
|
||||
static void* /* OJI type: jref */
|
||||
_getjavapeer(NPP aNPP);
|
||||
|
||||
static bool
|
||||
_invoke(NPP aNPP, NPObject* npobj, NPIdentifier method, const NPVariant *args,
|
||||
uint32_t argCount, NPVariant *result);
|
||||
|
@ -979,8 +987,8 @@ const NPNetscapeFuncs PluginModuleChild::sBrowserFuncs = {
|
|||
mozilla::plugins::child::_memfree,
|
||||
mozilla::plugins::child::_memflush,
|
||||
mozilla::plugins::child::_reloadplugins,
|
||||
nullptr, // _getjavaenv, unimplemented
|
||||
nullptr, // _getjavapeer, unimplemented
|
||||
mozilla::plugins::child::_getjavaenv,
|
||||
mozilla::plugins::child::_getjavapeer,
|
||||
mozilla::plugins::child::_geturlnotify,
|
||||
mozilla::plugins::child::_posturlnotify,
|
||||
mozilla::plugins::child::_getvalue,
|
||||
|
@ -1296,6 +1304,21 @@ _memalloc(uint32_t aSize)
|
|||
return moz_xmalloc(aSize);
|
||||
}
|
||||
|
||||
// Deprecated entry points for the old Java plugin.
|
||||
void* /* OJI type: JRIEnv* */
|
||||
_getjavaenv(void)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* /* OJI type: jref */
|
||||
_getjavapeer(NPP aNPP)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
_invoke(NPP aNPP,
|
||||
NPObject* aNPObj,
|
||||
|
|
|
@ -180,6 +180,13 @@ nsContentSecurityManager::CheckFTPSubresourceLoad(nsIChannel* aChannel)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Allow the system principal to load everything. This is meant to
|
||||
// temporarily fix downloads and pdf.js.
|
||||
nsIPrincipal* triggeringPrincipal = loadInfo->TriggeringPrincipal();
|
||||
if (nsContentUtils::IsSystemPrincipal(triggeringPrincipal)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -193,7 +200,6 @@ nsContentSecurityManager::CheckFTPSubresourceLoad(nsIChannel* aChannel)
|
|||
}
|
||||
|
||||
// Allow loading FTP subresources in FTP documents, like XML.
|
||||
nsIPrincipal* triggeringPrincipal = loadInfo->TriggeringPrincipal();
|
||||
nsCOMPtr<nsIURI> triggeringURI;
|
||||
triggeringPrincipal->GetURI(getter_AddRefs(triggeringURI));
|
||||
if (triggeringURI && nsContentUtils::SchemeIs(triggeringURI, "ftp")) {
|
||||
|
|
|
@ -308,9 +308,7 @@ LoadContextOptions(const char* aPrefName, void* /* aClosure */)
|
|||
.setFuzzing(GetWorkerPref<bool>(NS_LITERAL_CSTRING("fuzzing.enabled")))
|
||||
#endif
|
||||
.setStreams(GetWorkerPref<bool>(NS_LITERAL_CSTRING("streams")))
|
||||
.setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")))
|
||||
.setArrayProtoValues(GetWorkerPref<bool>(
|
||||
NS_LITERAL_CSTRING("array_prototype_values")));
|
||||
.setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")));
|
||||
|
||||
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
|
||||
if (xr) {
|
||||
|
|
|
@ -91,7 +91,7 @@ ClipManager::PushOverrideForASR(const ActiveScrolledRoot* aASR,
|
|||
Maybe<wr::WrClipId> scrollId = mBuilder->GetScrollIdForDefinedScrollLayer(viewId);
|
||||
MOZ_ASSERT(scrollId.isSome());
|
||||
|
||||
CLIP_LOG("Pushing override %" PRIu64 " -> %s\n", scrollId->id,
|
||||
CLIP_LOG("Pushing override %zu -> %s\n", scrollId->id,
|
||||
aClipId ? Stringify(aClipId->id).c_str() : "(none)");
|
||||
auto it = mASROverride.insert({ *scrollId, std::stack<Maybe<wr::WrClipId>>() });
|
||||
it.first->second.push(aClipId);
|
||||
|
@ -114,7 +114,7 @@ ClipManager::PopOverrideForASR(const ActiveScrolledRoot* aASR)
|
|||
auto it = mASROverride.find(*scrollId);
|
||||
MOZ_ASSERT(it != mASROverride.end());
|
||||
MOZ_ASSERT(!(it->second.empty()));
|
||||
CLIP_LOG("Popping override %" PRIu64 " -> %s\n", scrollId->id,
|
||||
CLIP_LOG("Popping override %zu -> %s\n", scrollId->id,
|
||||
it->second.top() ? Stringify(it->second.top()->id).c_str() : "(none)");
|
||||
it->second.pop();
|
||||
if (it->second.empty()) {
|
||||
|
@ -133,7 +133,7 @@ ClipManager::ClipIdAfterOverride(const Maybe<wr::WrClipId>& aClipId)
|
|||
return aClipId;
|
||||
}
|
||||
MOZ_ASSERT(!it->second.empty());
|
||||
CLIP_LOG("Overriding %" PRIu64 " with %s\n", aClipId->id,
|
||||
CLIP_LOG("Overriding %zu with %s\n", aClipId->id,
|
||||
it->second.top() ? Stringify(it->second.top()->id).c_str() : "(none)");
|
||||
return it->second.top();
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ ClipManager::DefineClipChain(const DisplayItemClipChain* aChain,
|
|||
if (it != cache.end()) {
|
||||
// Found it in the currently-active cache, so just use the id we have for
|
||||
// it.
|
||||
CLIP_LOG("cache[%p] => %" PRIu64 "\n", chain, it->second.id);
|
||||
CLIP_LOG("cache[%p] => %zu\n", chain, it->second.id);
|
||||
clipIds.AppendElement(it->second);
|
||||
continue;
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ ClipManager::DefineClipChain(const DisplayItemClipChain* aChain,
|
|||
wr::ToRoundedLayoutRect(clip), &wrRoundedRects);
|
||||
clipIds.AppendElement(clipId);
|
||||
cache[chain] = clipId;
|
||||
CLIP_LOG("cache[%p] <= %" PRIu64 "\n", chain, clipId.id);
|
||||
CLIP_LOG("cache[%p] <= %zu\n", chain, clipId.id);
|
||||
}
|
||||
|
||||
// Now find the parent display item's clipchain id
|
||||
|
|
|
@ -514,6 +514,7 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu
|
|||
(*curveArray)[i] = read_curveType(src, curve_offset + channel_offset, &tag_len);
|
||||
if (!(*curveArray)[i]) {
|
||||
invalid_source(src, "invalid nested curveType curve");
|
||||
break;
|
||||
}
|
||||
|
||||
channel_offset += tag_len;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "nsExpirationTracker.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "gfxUtils.h"
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
@ -953,6 +955,16 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx,
|
|||
const gfxRect& aDirtyRect,
|
||||
const gfxRect& aSkipRect)
|
||||
{
|
||||
const double maxSize = (double)gfxPlatform::MaxTextureSize();
|
||||
const double maxPos = (double)std::numeric_limits<std::int16_t>::max();
|
||||
if (aRect.width > maxSize || aRect.height > maxSize ||
|
||||
std::abs(aRect.x) > maxPos || std::abs(aRect.y) > maxPos) {
|
||||
// The rectangle is huge, perhaps due to a very strong perspective or some other
|
||||
// transform. We won't be able to blur something this big so give up now before
|
||||
// overflowing or running into texture size limits later.
|
||||
return;
|
||||
}
|
||||
|
||||
IntSize blurRadius = CalculateBlurRadius(aBlurStdDev);
|
||||
bool mirrorCorners = !aCornerRadii || aCornerRadii->AreRadiiSame();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
|
@ -42,7 +43,7 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI,
|
|||
nsresult& aRv)
|
||||
: mURI(aURI)
|
||||
, mOriginAttributes(aAttrs)
|
||||
, mControlledDocument(GetControlledDocumentToken(aDocument))
|
||||
, mControlledDocument(GetSpecialCaseDocumentToken(aDocument, aURI))
|
||||
, mHash(0)
|
||||
, mIsChrome(false)
|
||||
{
|
||||
|
@ -125,11 +126,10 @@ ImageCacheKey::SchemeIs(const char* aScheme)
|
|||
}
|
||||
|
||||
/* static */ void*
|
||||
ImageCacheKey::GetControlledDocumentToken(nsIDocument* aDocument)
|
||||
ImageCacheKey::GetSpecialCaseDocumentToken(nsIDocument* aDocument, nsIURI* aURI)
|
||||
{
|
||||
// For non-controlled documents, we just return null. For controlled
|
||||
// documents, we cast the pointer into a void* to avoid dereferencing
|
||||
// it (since we only use it for comparisons), and return it.
|
||||
// For controlled documents, we cast the pointer into a void* to avoid
|
||||
// dereferencing it (since we only use it for comparisons).
|
||||
void* pointer = nullptr;
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (aDocument && swm) {
|
||||
|
@ -138,6 +138,16 @@ ImageCacheKey::GetControlledDocumentToken(nsIDocument* aDocument)
|
|||
pointer = aDocument;
|
||||
}
|
||||
}
|
||||
|
||||
// If this document has been marked as tracker, let's use its address to make
|
||||
// a unique cache key.
|
||||
if (!pointer && aDocument &&
|
||||
nsContentUtils::StorageDisabledByAntiTracking(nullptr,
|
||||
aDocument->GetChannel(),
|
||||
aURI)) {
|
||||
pointer = aDocument;
|
||||
}
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,11 @@ public:
|
|||
bool operator==(const ImageCacheKey& aOther) const;
|
||||
PLDHashNumber Hash() const { return mHash; }
|
||||
|
||||
/// A weak pointer to the URI. For logging only.
|
||||
/// A weak pointer to the URI.
|
||||
nsIURI* URI() const { return mURI; }
|
||||
|
||||
const OriginAttributes& OriginAttributesRef() const { return mOriginAttributes; }
|
||||
|
||||
/// Is this cache entry for a chrome image?
|
||||
bool IsChrome() const { return mIsChrome; }
|
||||
|
||||
|
@ -53,7 +55,11 @@ public:
|
|||
|
||||
private:
|
||||
bool SchemeIs(const char* aScheme);
|
||||
static void* GetControlledDocumentToken(nsIDocument* aDocument);
|
||||
|
||||
// For ServiceWorker and for anti-tracking we need to use the document as
|
||||
// token for the key. All those exceptions are handled by this method.
|
||||
static void* GetSpecialCaseDocumentToken(nsIDocument* aDocument,
|
||||
nsIURI* aURI);
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
Maybe<uint64_t> mBlobSerial;
|
||||
|
|
|
@ -8,11 +8,20 @@
|
|||
|
||||
interface imgIRequest;
|
||||
interface nsIDocument;
|
||||
interface nsIPrincipal;
|
||||
interface nsIProperties;
|
||||
interface nsIURI;
|
||||
|
||||
webidl Document;
|
||||
|
||||
%{ C++
|
||||
namespace mozilla {
|
||||
class OriginAttributes;
|
||||
} // mozilla namespace
|
||||
%}
|
||||
|
||||
[ptr] native OriginAttributesPtr(mozilla::OriginAttributes);
|
||||
|
||||
/**
|
||||
* imgICache interface
|
||||
*
|
||||
|
@ -41,6 +50,14 @@ interface imgICache : nsISupports
|
|||
*/
|
||||
[noscript] void removeEntry(in nsIURI uri, [optional] in Document doc);
|
||||
|
||||
/**
|
||||
* Evict images from the cache with the same origin and the same
|
||||
* originAttributes of the passed principal.
|
||||
*
|
||||
* @param aPrincipal The principal
|
||||
*/
|
||||
void removeEntriesFromPrincipal(in nsIPrincipal aPrincipal);
|
||||
|
||||
/**
|
||||
* Find Properties
|
||||
* Used to get properties such as 'type' and 'content-disposition'
|
||||
|
|
|
@ -1469,6 +1469,45 @@ imgLoader::ClearCache(bool chrome)
|
|||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgLoader::RemoveEntriesFromPrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
nsAutoString origin;
|
||||
nsresult rv = nsContentUtils::GetUTFOrigin(aPrincipal, origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
AutoTArray<RefPtr<imgCacheEntry>, 128> entriesToBeRemoved;
|
||||
|
||||
imgCacheTable& cache = GetCache(nsContentUtils::IsSystemPrincipal(aPrincipal));
|
||||
for (auto iter = cache.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto& key = iter.Key();
|
||||
|
||||
if (key.OriginAttributesRef() != BasePrincipal::Cast(aPrincipal)->OriginAttributesRef()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString imageOrigin;
|
||||
nsresult rv = nsContentUtils::GetUTFOrigin(key.URI(), imageOrigin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (imageOrigin == origin) {
|
||||
entriesToBeRemoved.AppendElement(iter.Data());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& entry : entriesToBeRemoved) {
|
||||
if (!RemoveFromCache(entry)) {
|
||||
NS_WARNING("Couldn't remove an entry from the cache in RemoveEntriesFromPrincipal()\n");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgLoader::RemoveEntry(nsIURI* aURI,
|
||||
nsIDocument* aDoc)
|
||||
|
|
|
@ -262,11 +262,14 @@ EvalKernel(JSContext* cx, HandleValue v, EvalType evalType, AbstractFramePtr cal
|
|||
const char* filename;
|
||||
bool mutedErrors;
|
||||
uint32_t pcOffset;
|
||||
DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
|
||||
&mutedErrors,
|
||||
evalType == DIRECT_EVAL
|
||||
? CALLED_FROM_JSOP_EVAL
|
||||
: NOT_CALLED_FROM_JSOP_EVAL);
|
||||
if (evalType == DIRECT_EVAL) {
|
||||
DescribeScriptedCallerForDirectEval(cx, callerScript, pc, &filename, &lineno,
|
||||
&pcOffset, &mutedErrors);
|
||||
maybeScript = callerScript;
|
||||
} else {
|
||||
DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
|
||||
&mutedErrors);
|
||||
}
|
||||
|
||||
const char* introducerFilename = filename;
|
||||
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
|
||||
|
@ -344,17 +347,16 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
|||
esg.lookupInEvalCache(linearStr, callerScript, pc);
|
||||
|
||||
if (!esg.foundScript()) {
|
||||
RootedScript maybeScript(cx);
|
||||
const char* filename;
|
||||
unsigned lineno;
|
||||
bool mutedErrors;
|
||||
uint32_t pcOffset;
|
||||
DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
|
||||
&mutedErrors, CALLED_FROM_JSOP_EVAL);
|
||||
DescribeScriptedCallerForDirectEval(cx, callerScript, pc, &filename, &lineno, &pcOffset,
|
||||
&mutedErrors);
|
||||
|
||||
const char* introducerFilename = filename;
|
||||
if (maybeScript && maybeScript->scriptSource()->introducerFilename())
|
||||
introducerFilename = maybeScript->scriptSource()->introducerFilename();
|
||||
if (callerScript->scriptSource()->introducerFilename())
|
||||
introducerFilename = callerScript->scriptSource()->introducerFilename();
|
||||
|
||||
RootedScope enclosing(cx, callerScript->innermostScope(pc));
|
||||
|
||||
|
@ -366,7 +368,8 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
|||
|
||||
if (introducerFilename) {
|
||||
options.setFileAndLine(filename, 1);
|
||||
options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
|
||||
options.setIntroductionInfo(introducerFilename, "eval", lineno, callerScript,
|
||||
pcOffset);
|
||||
} else {
|
||||
options.setFileAndLine("eval", 1);
|
||||
options.setIntroductionType("eval");
|
||||
|
|
|
@ -1360,7 +1360,7 @@ CaptureFirstSubsumedFrame(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->realm()->principals()));
|
||||
JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->nonCCWRealm()->principals()));
|
||||
if (args.length() > 1)
|
||||
capture.as<JS::FirstSubsumedFrame>().ignoreSelfHosted = JS::ToBoolean(args[1]);
|
||||
|
||||
|
|
|
@ -339,13 +339,13 @@ static const uint32_t ReferenceSizes[] = {
|
|||
uint32_t
|
||||
ReferenceTypeDescr::size(Type t)
|
||||
{
|
||||
return ReferenceSizes[t];
|
||||
return ReferenceSizes[uint32_t(t)];
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ReferenceTypeDescr::alignment(Type t)
|
||||
{
|
||||
return ReferenceSizes[t];
|
||||
return ReferenceSizes[uint32_t(t)];
|
||||
}
|
||||
|
||||
/*static*/ const char*
|
||||
|
@ -375,11 +375,11 @@ js::ReferenceTypeDescr::call(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
switch (descr->type()) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
args.rval().set(args[0]);
|
||||
return true;
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
case ReferenceType::TYPE_OBJECT:
|
||||
{
|
||||
RootedObject obj(cx, ToObject(cx, args[0]));
|
||||
if (!obj)
|
||||
|
@ -388,7 +388,7 @@ js::ReferenceTypeDescr::call(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
{
|
||||
RootedString obj(cx, ToString<CanGC>(cx, args[0]));
|
||||
if (!obj)
|
||||
|
@ -766,7 +766,45 @@ const JSFunctionSpec StructMetaTypeDescr::typedObjectMethods[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
JSObject*
|
||||
CheckedInt32
|
||||
StructMetaTypeDescr::Layout::addField(int32_t fieldAlignment, int32_t fieldSize)
|
||||
{
|
||||
// Alignment of the struct is the max of the alignment of its fields.
|
||||
structAlignment = js::Max(structAlignment, fieldAlignment);
|
||||
|
||||
// Align the pointer.
|
||||
CheckedInt32 offset = RoundUpToAlignment(sizeSoFar, fieldAlignment);
|
||||
if (!offset.isValid())
|
||||
return offset;
|
||||
|
||||
// Allocate space.
|
||||
sizeSoFar = offset + fieldSize;
|
||||
if (!sizeSoFar.isValid())
|
||||
return sizeSoFar;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
CheckedInt32
|
||||
StructMetaTypeDescr::Layout::addScalar(Scalar::Type type) {
|
||||
return addField(ScalarTypeDescr::alignment(type),
|
||||
ScalarTypeDescr::size(type));
|
||||
}
|
||||
|
||||
CheckedInt32
|
||||
StructMetaTypeDescr::Layout::addReference(ReferenceType type) {
|
||||
return addField(ReferenceTypeDescr::alignment(type),
|
||||
ReferenceTypeDescr::size(type));
|
||||
}
|
||||
|
||||
CheckedInt32
|
||||
StructMetaTypeDescr::Layout::close(int32_t *alignment) {
|
||||
if (alignment)
|
||||
*alignment = structAlignment;
|
||||
return RoundUpToAlignment(sizeSoFar, structAlignment);
|
||||
}
|
||||
|
||||
/* static */ JSObject*
|
||||
StructMetaTypeDescr::create(JSContext* cx,
|
||||
HandleObject metaTypeDescr,
|
||||
HandleObject fields)
|
||||
|
@ -779,30 +817,13 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||
// Iterate through each field. Collect values for the various
|
||||
// vectors below and also track total size and alignment. Be wary
|
||||
// of overflow!
|
||||
StringBuffer stringBuffer(cx); // Canonical string repr
|
||||
AutoValueVector fieldNames(cx); // Name of each field.
|
||||
AutoValueVector fieldTypeObjs(cx); // Type descriptor of each field.
|
||||
AutoValueVector fieldOffsets(cx); // Offset of each field field.
|
||||
RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
|
||||
RootedObject userFieldTypes(cx); // User-exposed {f:descr} object.
|
||||
CheckedInt32 sizeSoFar(0); // Size of struct thus far.
|
||||
uint32_t alignment = 1; // Alignment of struct.
|
||||
bool opaque = false; // Opacity of struct.
|
||||
|
||||
userFieldOffsets = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
|
||||
if (!userFieldOffsets)
|
||||
return nullptr;
|
||||
|
||||
userFieldTypes = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
|
||||
if (!userFieldTypes)
|
||||
return nullptr;
|
||||
|
||||
if (!stringBuffer.append("new StructType({"))
|
||||
return nullptr;
|
||||
|
||||
RootedValue fieldTypeVal(cx);
|
||||
RootedId id(cx);
|
||||
Rooted<TypeDescr*> fieldType(cx);
|
||||
|
||||
for (unsigned int i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
|
||||
|
@ -824,12 +845,59 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Collect field name and type object
|
||||
// Collect field type object
|
||||
if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
|
||||
return nullptr;
|
||||
|
||||
// Struct is opaque if any field is opaque
|
||||
if (fieldType->opaque())
|
||||
opaque = true;
|
||||
}
|
||||
|
||||
RootedObject structTypePrototype(cx, GetPrototype(cx, metaTypeDescr));
|
||||
if (!structTypePrototype)
|
||||
return nullptr;
|
||||
|
||||
return createFromArrays(cx, structTypePrototype, opaque, ids, fieldTypeObjs);
|
||||
}
|
||||
|
||||
/* static */ StructTypeDescr*
|
||||
StructMetaTypeDescr::createFromArrays(JSContext* cx,
|
||||
HandleObject structTypePrototype,
|
||||
bool opaque,
|
||||
AutoIdVector& ids,
|
||||
AutoValueVector& fieldTypeObjs)
|
||||
{
|
||||
StringBuffer stringBuffer(cx); // Canonical string repr
|
||||
AutoValueVector fieldNames(cx); // Name of each field.
|
||||
AutoValueVector fieldOffsets(cx); // Offset of each field field.
|
||||
RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
|
||||
RootedObject userFieldTypes(cx); // User-exposed {f:descr} object.
|
||||
Layout layout; // Field offsetter
|
||||
|
||||
userFieldOffsets = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
|
||||
if (!userFieldOffsets)
|
||||
return nullptr;
|
||||
|
||||
userFieldTypes = NewBuiltinClassInstance<PlainObject>(cx, TenuredObject);
|
||||
if (!userFieldTypes)
|
||||
return nullptr;
|
||||
|
||||
if (!stringBuffer.append("new StructType({"))
|
||||
return nullptr;
|
||||
|
||||
RootedId id(cx);
|
||||
Rooted<TypeDescr*> fieldType(cx);
|
||||
|
||||
for (unsigned int i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
|
||||
// Collect field name
|
||||
RootedValue fieldName(cx, IdToValue(id));
|
||||
if (!fieldNames.append(fieldName))
|
||||
return nullptr;
|
||||
if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
|
||||
return nullptr;
|
||||
|
||||
fieldType = ToObjectIf<TypeDescr>(fieldTypeObjs[i]);
|
||||
|
||||
// userFieldTypes[id] = typeObj
|
||||
if (!DefineDataProperty(cx, userFieldTypes, id, fieldTypeObjs[i],
|
||||
|
@ -848,9 +916,7 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||
if (!stringBuffer.append(&fieldType->stringRepr()))
|
||||
return nullptr;
|
||||
|
||||
// Offset of this field is the current total size adjusted for
|
||||
// the field's alignment.
|
||||
CheckedInt32 offset = RoundUpToAlignment(sizeSoFar, fieldType->alignment());
|
||||
CheckedInt32 offset = layout.addField(fieldType->alignment(), fieldType->size());
|
||||
if (!offset.isValid()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return nullptr;
|
||||
|
@ -866,20 +932,6 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add space for this field to the total struct size.
|
||||
sizeSoFar = offset + fieldType->size();
|
||||
if (!sizeSoFar.isValid()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Struct is opaque if any field is opaque
|
||||
if (fieldType->opaque())
|
||||
opaque = true;
|
||||
|
||||
// Alignment of the struct is the max of the alignment of its fields.
|
||||
alignment = js::Max(alignment, fieldType->alignment());
|
||||
}
|
||||
|
||||
// Complete string representation.
|
||||
|
@ -890,17 +942,14 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||
if (!stringRepr)
|
||||
return nullptr;
|
||||
|
||||
// Adjust the total size to be a multiple of the final alignment.
|
||||
CheckedInt32 totalSize = RoundUpToAlignment(sizeSoFar, alignment);
|
||||
int32_t alignment;
|
||||
CheckedInt32 totalSize = layout.close(&alignment);
|
||||
if (!totalSize.isValid()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Now create the resulting type descriptor.
|
||||
RootedObject structTypePrototype(cx, GetPrototype(cx, metaTypeDescr));
|
||||
if (!structTypePrototype)
|
||||
return nullptr;
|
||||
|
||||
Rooted<StructTypeDescr*> descr(cx);
|
||||
descr = NewObjectWithGivenProto<StructTypeDescr>(cx, structTypePrototype, SingletonObject);
|
||||
|
@ -1127,7 +1176,7 @@ DefineSimpleTypeDescr(JSContext* cx,
|
|||
descr->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(T::alignment(type)));
|
||||
descr->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(AssertedCast<int32_t>(T::size(type))));
|
||||
descr->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(T::Opaque));
|
||||
descr->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(type));
|
||||
descr->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(int32_t(type)));
|
||||
|
||||
if (!CreateUserSizeAndAlignmentProperties(cx, descr))
|
||||
return false;
|
||||
|
@ -2740,14 +2789,14 @@ void
|
|||
MemoryInitVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
|
||||
{
|
||||
switch (descr.type()) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
{
|
||||
js::GCPtrValue* heapValue = reinterpret_cast<js::GCPtrValue*>(mem);
|
||||
heapValue->init(UndefinedValue());
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
case ReferenceType::TYPE_OBJECT:
|
||||
{
|
||||
js::GCPtrObject* objectPtr =
|
||||
reinterpret_cast<js::GCPtrObject*>(mem);
|
||||
|
@ -2755,7 +2804,7 @@ MemoryInitVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
|
|||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
{
|
||||
js::GCPtrString* stringPtr =
|
||||
reinterpret_cast<js::GCPtrString*>(mem);
|
||||
|
@ -2810,21 +2859,21 @@ void
|
|||
MemoryTracingVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
|
||||
{
|
||||
switch (descr.type()) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
{
|
||||
GCPtrValue* heapValue = reinterpret_cast<js::GCPtrValue*>(mem);
|
||||
TraceEdge(trace_, heapValue, "reference-val");
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
case ReferenceType::TYPE_OBJECT:
|
||||
{
|
||||
GCPtrObject* objectPtr = reinterpret_cast<js::GCPtrObject*>(mem);
|
||||
TraceNullableEdge(trace_, objectPtr, "reference-obj");
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
{
|
||||
GCPtrString* stringPtr = reinterpret_cast<js::GCPtrString*>(mem);
|
||||
TraceNullableEdge(trace_, stringPtr, "reference-str");
|
||||
|
@ -2864,9 +2913,9 @@ TraceListVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
|
|||
{
|
||||
VectorType* offsets;
|
||||
switch (descr.type()) {
|
||||
case ReferenceTypeDescr::TYPE_ANY: offsets = &valueOffsets; break;
|
||||
case ReferenceTypeDescr::TYPE_OBJECT: offsets = &objectOffsets; break;
|
||||
case ReferenceTypeDescr::TYPE_STRING: offsets = &stringOffsets; break;
|
||||
case ReferenceType::TYPE_ANY: offsets = &valueOffsets; break;
|
||||
case ReferenceType::TYPE_OBJECT: offsets = &objectOffsets; break;
|
||||
case ReferenceType::TYPE_STRING: offsets = &stringOffsets; break;
|
||||
default: MOZ_CRASH("Invalid kind");
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef builtin_TypedObject_h
|
||||
#define builtin_TypedObject_h
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
#include "builtin/TypedObjectConstants.h"
|
||||
#include "gc/WeakMap.h"
|
||||
#include "js/Conversions.h"
|
||||
|
@ -286,6 +288,12 @@ class ScalarTypeDescr : public SimpleTypeDescr
|
|||
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
|
||||
macro_(Scalar::Uint8Clamped, uint8_t, uint8Clamped)
|
||||
|
||||
enum class ReferenceType {
|
||||
TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
|
||||
TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
|
||||
TYPE_STRING = JS_REFERENCETYPEREPR_STRING
|
||||
};
|
||||
|
||||
// Type for reference type constructors like `Any`, `String`, and
|
||||
// `Object`. All such type constructors share a common js::Class and
|
||||
// JSFunctionSpec. All these types are opaque.
|
||||
|
@ -293,14 +301,10 @@ class ReferenceTypeDescr : public SimpleTypeDescr
|
|||
{
|
||||
public:
|
||||
// Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
|
||||
enum Type {
|
||||
TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
|
||||
TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
|
||||
TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
|
||||
};
|
||||
static const int32_t TYPE_MAX = TYPE_STRING + 1;
|
||||
typedef ReferenceType Type;
|
||||
static const char* typeName(Type type);
|
||||
|
||||
static const int32_t TYPE_MAX = int32_t(ReferenceType::TYPE_STRING) + 1;
|
||||
static const type::Kind Kind = type::Reference;
|
||||
static const bool Opaque = true;
|
||||
static const Class class_;
|
||||
|
@ -308,8 +312,8 @@ class ReferenceTypeDescr : public SimpleTypeDescr
|
|||
static uint32_t alignment(Type t);
|
||||
static const JSFunctionSpec typeObjectMethods[];
|
||||
|
||||
ReferenceTypeDescr::Type type() const {
|
||||
return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
|
||||
ReferenceType type() const {
|
||||
return (ReferenceType) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
|
||||
}
|
||||
|
||||
const char* typeName() const {
|
||||
|
@ -320,9 +324,9 @@ class ReferenceTypeDescr : public SimpleTypeDescr
|
|||
};
|
||||
|
||||
#define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
|
||||
macro_(ReferenceTypeDescr::TYPE_ANY, GCPtrValue, Any) \
|
||||
macro_(ReferenceTypeDescr::TYPE_OBJECT, GCPtrObject, Object) \
|
||||
macro_(ReferenceTypeDescr::TYPE_STRING, GCPtrString, string)
|
||||
macro_(ReferenceType::TYPE_ANY, GCPtrValue, Any) \
|
||||
macro_(ReferenceType::TYPE_OBJECT, GCPtrObject, Object) \
|
||||
macro_(ReferenceType::TYPE_STRING, GCPtrString, string)
|
||||
|
||||
// Type descriptors whose instances are objects and hence which have
|
||||
// an associated `prototype` property.
|
||||
|
@ -435,6 +439,15 @@ class StructMetaTypeDescr : public NativeObject
|
|||
HandleObject fields);
|
||||
|
||||
public:
|
||||
// The prototype cannot be null.
|
||||
// The names in `ids` must all be non-numeric.
|
||||
// The type objects in `fieldTypeObjs` must all be TypeDescr objects.
|
||||
static StructTypeDescr* createFromArrays(JSContext* cx,
|
||||
HandleObject structTypePrototype,
|
||||
bool opaque,
|
||||
AutoIdVector& ids,
|
||||
AutoValueVector& fieldTypeObjs);
|
||||
|
||||
// Properties and methods to be installed on StructType.prototype,
|
||||
// and hence inherited by all struct type objects:
|
||||
static const JSPropertySpec typeObjectProperties[];
|
||||
|
@ -448,6 +461,27 @@ class StructMetaTypeDescr : public NativeObject
|
|||
// This is the function that gets called when the user
|
||||
// does `new StructType(...)`. It produces a struct type object.
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
class Layout
|
||||
{
|
||||
// Can call addField() directly.
|
||||
friend class StructMetaTypeDescr;
|
||||
|
||||
mozilla::CheckedInt32 sizeSoFar = 0;
|
||||
int32_t structAlignment = 1;
|
||||
|
||||
mozilla::CheckedInt32 addField(int32_t fieldAlignment, int32_t fieldSize);
|
||||
|
||||
public:
|
||||
// The field adders return the offset of the the field.
|
||||
mozilla::CheckedInt32 addScalar(Scalar::Type type);
|
||||
mozilla::CheckedInt32 addReference(ReferenceType type);
|
||||
|
||||
// The close method rounds up the structure size to the appropriate
|
||||
// alignment and returns that size. If `alignment` is not NULL then
|
||||
// return the structure alignment through that pointer.
|
||||
mozilla::CheckedInt32 close(int32_t* alignment = nullptr);
|
||||
};
|
||||
};
|
||||
|
||||
class StructTypeDescr : public ComplexTypeDescr
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "ds/MemoryProtectionExceptionHandler.h"
|
||||
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
# include "gc/Memory.h"
|
||||
#endif
|
||||
|
||||
using namespace js;
|
||||
|
||||
using mozilla::RoundUpPow2;
|
||||
|
@ -18,7 +24,7 @@ namespace detail {
|
|||
|
||||
/* static */
|
||||
UniquePtr<BumpChunk>
|
||||
BumpChunk::newWithCapacity(size_t size)
|
||||
BumpChunk::newWithCapacity(size_t size, bool protect)
|
||||
{
|
||||
MOZ_ASSERT(RoundUpPow2(size) == size);
|
||||
MOZ_ASSERT(size >= sizeof(BumpChunk));
|
||||
|
@ -26,7 +32,7 @@ BumpChunk::newWithCapacity(size_t size)
|
|||
if (!mem)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<BumpChunk> result(new (mem) BumpChunk(size));
|
||||
UniquePtr<BumpChunk> result(new (mem) BumpChunk(size, protect));
|
||||
|
||||
// We assume that the alignment of LIFO_ALLOC_ALIGN is less than that of the
|
||||
// underlying memory allocator -- creating a new BumpChunk should always
|
||||
|
@ -44,6 +50,96 @@ BumpChunk::canAlloc(size_t n)
|
|||
return bump_ <= newBump && newBump <= capacity_;
|
||||
}
|
||||
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
|
||||
static const uint8_t*
|
||||
AlignPtrUp(const uint8_t* ptr, uintptr_t align) {
|
||||
MOZ_ASSERT(mozilla::IsPowerOfTwo(align));
|
||||
uintptr_t uptr = uintptr_t(ptr);
|
||||
uintptr_t diff = uptr & (align - 1);
|
||||
diff = (align - diff) & (align - 1);
|
||||
uptr = uptr + diff;
|
||||
return (uint8_t*) uptr;
|
||||
}
|
||||
|
||||
static const uint8_t*
|
||||
AlignPtrDown(const uint8_t* ptr, uintptr_t align) {
|
||||
MOZ_ASSERT(mozilla::IsPowerOfTwo(align));
|
||||
uintptr_t uptr = uintptr_t(ptr);
|
||||
uptr = uptr & ~(align - 1);
|
||||
return (uint8_t*) uptr;
|
||||
}
|
||||
|
||||
void
|
||||
BumpChunk::setRWUntil(Loc loc) const
|
||||
{
|
||||
if (!protect_)
|
||||
return;
|
||||
|
||||
uintptr_t pageSize = gc::SystemPageSize();
|
||||
// The allocated chunks might not be aligned on page boundaries. This code
|
||||
// is used to ensure that we are changing the memory protection of pointers
|
||||
// which are within the range of the BumpChunk, or that the range formed by
|
||||
// [b .. e] is empty.
|
||||
const uint8_t* b = base();
|
||||
const uint8_t* e = capacity_;
|
||||
b = AlignPtrUp(b, pageSize);
|
||||
e = AlignPtrDown(e, pageSize);
|
||||
if (e < b)
|
||||
e = b;
|
||||
// The mid-point is aligned to the next page, and clamp to the end-point to
|
||||
// ensure that it remains in the [b .. e] range.
|
||||
const uint8_t* m = nullptr;
|
||||
switch (loc) {
|
||||
case Loc::Header:
|
||||
m = b;
|
||||
break;
|
||||
case Loc::Allocated:
|
||||
m = begin();
|
||||
break;
|
||||
case Loc::Reserved:
|
||||
m = end();
|
||||
break;
|
||||
case Loc::End:
|
||||
m = e;
|
||||
break;
|
||||
}
|
||||
m = AlignPtrUp(m, pageSize);
|
||||
if (e < m)
|
||||
m = e;
|
||||
|
||||
if (b < m)
|
||||
gc::UnprotectPages(const_cast<uint8_t*>(b), m - b);
|
||||
// Note: We could use no-access protection for everything after begin(), but
|
||||
// we need to read capabilities for reading the bump_ / capacity_ fields
|
||||
// from this function to unprotect the memory later.
|
||||
if (m < e)
|
||||
gc::MakePagesReadOnly(const_cast<uint8_t*>(m), e - m);
|
||||
}
|
||||
|
||||
// The memory protection handler is catching memory accesses error on the
|
||||
// regions registered into it. These method, instead of registering sub-ranges
|
||||
// of the BumpChunk within setRWUntil, we just register the full BumpChunk
|
||||
// ranges, and let the MemoryProtectionExceptionHandler catch bad memory
|
||||
// accesses when it is being protected by setRWUntil.
|
||||
void
|
||||
BumpChunk::addMProtectHandler() const
|
||||
{
|
||||
if (!protect_)
|
||||
return;
|
||||
js::MemoryProtectionExceptionHandler::addRegion(const_cast<uint8_t*>(base()), capacity_ - base());
|
||||
}
|
||||
|
||||
void
|
||||
BumpChunk::removeMProtectHandler() const
|
||||
{
|
||||
if (!protect_)
|
||||
return;
|
||||
js::MemoryProtectionExceptionHandler::removeRegion(const_cast<uint8_t*>(base()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace js
|
||||
|
||||
|
@ -51,10 +147,12 @@ void
|
|||
LifoAlloc::freeAll()
|
||||
{
|
||||
while (!chunks_.empty()) {
|
||||
chunks_.begin()->setRWUntil(Loc::End);
|
||||
BumpChunk bc = chunks_.popFirst();
|
||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||
}
|
||||
while (!unused_.empty()) {
|
||||
unused_.begin()->setRWUntil(Loc::End);
|
||||
BumpChunk bc = unused_.popFirst();
|
||||
decrementCurSize(bc->computedSizeOfIncludingThis());
|
||||
}
|
||||
|
@ -90,7 +188,7 @@ LifoAlloc::newChunkWithCapacity(size_t n)
|
|||
}
|
||||
|
||||
// Create a new BumpChunk, and allocate space for it.
|
||||
BumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
|
||||
BumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize, protect_);
|
||||
if (!result)
|
||||
return nullptr;
|
||||
MOZ_ASSERT(result->computedSizeOfIncludingThis() == chunkSize);
|
||||
|
@ -100,12 +198,19 @@ LifoAlloc::newChunkWithCapacity(size_t n)
|
|||
bool
|
||||
LifoAlloc::getOrCreateChunk(size_t n)
|
||||
{
|
||||
// This function is adding a new BumpChunk in which all upcoming allocation
|
||||
// would be made. Thus, we protect against out-of-bounds the last chunk in
|
||||
// which we did our previous allocations.
|
||||
if (!chunks_.empty())
|
||||
chunks_.last()->setRWUntil(Loc::Reserved);
|
||||
|
||||
// Look for existing unused BumpChunks to satisfy the request, and pick the
|
||||
// first one which is large enough, and move it into the list of used
|
||||
// chunks.
|
||||
if (!unused_.empty()) {
|
||||
if (unused_.begin()->canAlloc(n)) {
|
||||
chunks_.append(unused_.popFirst());
|
||||
chunks_.last()->setRWUntil(Loc::End);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -117,6 +222,7 @@ LifoAlloc::getOrCreateChunk(size_t n)
|
|||
BumpChunkList temp = unused_.splitAfter(i.get());
|
||||
chunks_.append(temp.popFirst());
|
||||
unused_.appendAll(std::move(temp));
|
||||
chunks_.last()->setRWUntil(Loc::End);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +233,9 @@ LifoAlloc::getOrCreateChunk(size_t n)
|
|||
if (!newChunk)
|
||||
return false;
|
||||
size_t size = newChunk->computedSizeOfIncludingThis();
|
||||
// The last chunk in which allocations are performed should be protected
|
||||
// with setRWUntil(Loc::End), but this is not necessary here because any new
|
||||
// allocation should be protected as RW already.
|
||||
chunks_.append(std::move(newChunk));
|
||||
incrementCurSize(size);
|
||||
return true;
|
||||
|
|
|
@ -216,14 +216,21 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
private:
|
||||
// Pointer to the last byte allocated in this chunk.
|
||||
uint8_t* bump_;
|
||||
// Pointer to the last byte available in this chunk.
|
||||
const uint8_t* capacity_;
|
||||
// Pointer to the first byte after this chunk.
|
||||
uint8_t* const capacity_;
|
||||
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
// Magic number used to check against poisoned values.
|
||||
const uintptr_t magic_;
|
||||
static constexpr uintptr_t magicNumber =
|
||||
sizeof(uintptr_t) == 4 ? uintptr_t(0x4c69666f) : uintptr_t(0x4c69666f42756d70);
|
||||
const uintptr_t magic_ : 24;
|
||||
static constexpr uintptr_t magicNumber = uintptr_t(0x4c6966);
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) || defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
|
||||
# define LIFO_CHUNK_PROTECT 1
|
||||
// Constant used to know if the current chunk should be protected. This is
|
||||
// mainly use to prevent dead-lock in the MemoryProtectionExceptionHandler
|
||||
// methods.
|
||||
const uintptr_t protect_ : 1;
|
||||
#endif
|
||||
|
||||
// Poison the memory with memset, in order to catch errors due to
|
||||
|
@ -269,11 +276,14 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
BumpChunk& operator=(const BumpChunk&) = delete;
|
||||
BumpChunk(const BumpChunk&) = delete;
|
||||
|
||||
explicit BumpChunk(uintptr_t capacity)
|
||||
explicit BumpChunk(uintptr_t capacity, bool protect)
|
||||
: bump_(begin()),
|
||||
capacity_(base() + capacity)
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
, magic_(magicNumber)
|
||||
#endif
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
, protect_(protect ? 1 : 0)
|
||||
#endif
|
||||
{
|
||||
// We cannot bake this value inside the BumpChunk class, because
|
||||
|
@ -292,6 +302,7 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
// no-access, as it has not been allocated within the BumpChunk.
|
||||
LIFO_MAKE_MEM_NOACCESS(bump_, capacity_ - bump_);
|
||||
#endif
|
||||
addMProtectHandler();
|
||||
}
|
||||
|
||||
// Cast |this| into a uint8_t* pointer.
|
||||
|
@ -326,6 +337,7 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
public:
|
||||
~BumpChunk() {
|
||||
release();
|
||||
removeMProtectHandler();
|
||||
}
|
||||
|
||||
// Space reserved for the BumpChunk internal data, and the alignment of the
|
||||
|
@ -350,7 +362,10 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
// This function is the only way to allocate and construct a chunk. It
|
||||
// returns a UniquePtr to the newly allocated chunk. The size given as
|
||||
// argument includes the space needed for the header of the chunk.
|
||||
static UniquePtr<BumpChunk> newWithCapacity(size_t size);
|
||||
//
|
||||
// The protect boolean is used to indicate whether the Bumpchunk memory
|
||||
// should be reported within the MemoryProtectionExceptionHandler.
|
||||
static UniquePtr<BumpChunk> newWithCapacity(size_t size, bool protect);
|
||||
|
||||
// Report allocation.
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
|
@ -443,6 +458,44 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
setBump(newBump);
|
||||
return aligned;
|
||||
}
|
||||
|
||||
// These locations are approximated locations, with the base rounded up to
|
||||
// the nearest page boundary.
|
||||
enum class Loc {
|
||||
// Refers to the inherited linked list, this includes any allocated any
|
||||
// reserved bytes, from base() to capacity_.
|
||||
//
|
||||
// This is used when freezing a LifoAlloc, such as moving a LifoAlloc to
|
||||
// another thread.
|
||||
Header = 0,
|
||||
// Refers to the set of allocated and reserved bytes, from
|
||||
// PageRoundup(begin()), to capacity_.
|
||||
//
|
||||
// This is used when a BumpChunk is moved to the list of unused chunks,
|
||||
// as we want the header to remain mutable.
|
||||
Allocated = 1,
|
||||
// Refers to the set of reserved bytes, from PageRoundup(end()) to
|
||||
// capacity_.
|
||||
//
|
||||
// This is used when a BumpChunk is no longer used for allocation, while
|
||||
// containing live data. This should catch out-of-bound accesses within
|
||||
// the LifoAlloc content.
|
||||
Reserved = 2,
|
||||
// Refers to the end of the BumpChunk.
|
||||
//
|
||||
// This is used when a BumpChunk is used for doing allocation, as
|
||||
// re-protecting at each setBump would be too costly.
|
||||
End = 3
|
||||
};
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
void setRWUntil(Loc loc) const;
|
||||
void addMProtectHandler() const;
|
||||
void removeMProtectHandler() const;
|
||||
#else
|
||||
void setRWUntil(Loc loc) const {}
|
||||
void addMProtectHandler() const {}
|
||||
void removeMProtectHandler() const {}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -453,6 +506,7 @@ class BumpChunk : public SingleLinkedListElement<BumpChunk>
|
|||
// been released to avoid thrashing before a GC.
|
||||
class LifoAlloc
|
||||
{
|
||||
using Loc = detail::BumpChunk::Loc;
|
||||
using BumpChunk = js::UniquePtr<detail::BumpChunk>;
|
||||
using BumpChunkList = detail::SingleLinkedList<detail::BumpChunk>;
|
||||
|
||||
|
@ -472,6 +526,9 @@ class LifoAlloc
|
|||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||
bool fallibleScope_;
|
||||
#endif
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
const bool protect_;
|
||||
#endif
|
||||
|
||||
void operator=(const LifoAlloc&) = delete;
|
||||
LifoAlloc(const LifoAlloc&) = delete;
|
||||
|
@ -485,10 +542,14 @@ class LifoAlloc
|
|||
|
||||
void reset(size_t defaultChunkSize) {
|
||||
MOZ_ASSERT(mozilla::RoundUpPow2(defaultChunkSize) == defaultChunkSize);
|
||||
while (!chunks_.empty())
|
||||
while (!chunks_.empty()) {
|
||||
chunks_.begin()->setRWUntil(Loc::End);
|
||||
chunks_.popFirst();
|
||||
while (!unused_.empty())
|
||||
}
|
||||
while (!unused_.empty()) {
|
||||
unused_.begin()->setRWUntil(Loc::End);
|
||||
unused_.popFirst();
|
||||
}
|
||||
defaultChunkSize_ = defaultChunkSize;
|
||||
markCount = 0;
|
||||
curSize_ = 0;
|
||||
|
@ -536,10 +597,13 @@ class LifoAlloc
|
|||
}
|
||||
|
||||
public:
|
||||
explicit LifoAlloc(size_t defaultChunkSize)
|
||||
explicit LifoAlloc(size_t defaultChunkSize, bool protect = true)
|
||||
: peakSize_(0)
|
||||
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
|
||||
, fallibleScope_(true)
|
||||
#endif
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
, protect_(protect)
|
||||
#endif
|
||||
{
|
||||
reset(defaultChunkSize);
|
||||
|
@ -641,6 +705,7 @@ class LifoAlloc
|
|||
if (!newChunk)
|
||||
return false;
|
||||
size_t size = newChunk->computedSizeOfIncludingThis();
|
||||
newChunk->setRWUntil(Loc::Allocated);
|
||||
unused_.pushFront(std::move(newChunk));
|
||||
incrementCurSize(size);
|
||||
return true;
|
||||
|
@ -714,22 +779,49 @@ class LifoAlloc
|
|||
released = chunks_.splitAfter(mark.markedChunk());
|
||||
|
||||
// Release the content of all the blocks which are after the marks.
|
||||
for (detail::BumpChunk& bc : released)
|
||||
for (detail::BumpChunk& bc : released) {
|
||||
bc.release();
|
||||
bc.setRWUntil(Loc::Allocated);
|
||||
}
|
||||
unused_.appendAll(std::move(released));
|
||||
|
||||
// Release everything which follows the mark in the last chunk.
|
||||
if (!chunks_.empty())
|
||||
if (!chunks_.empty()) {
|
||||
chunks_.last()->setRWUntil(Loc::End);
|
||||
chunks_.last()->release(mark);
|
||||
}
|
||||
}
|
||||
|
||||
void releaseAll() {
|
||||
MOZ_ASSERT(!markCount);
|
||||
for (detail::BumpChunk& bc : chunks_)
|
||||
for (detail::BumpChunk& bc : chunks_) {
|
||||
bc.release();
|
||||
bc.setRWUntil(Loc::Allocated);
|
||||
}
|
||||
unused_.appendAll(std::move(chunks_));
|
||||
}
|
||||
|
||||
// Protect the content of the LifoAlloc chunks.
|
||||
void setReadOnly() {
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
for (detail::BumpChunk& bc : chunks_)
|
||||
bc.setRWUntil(Loc::Header);
|
||||
for (detail::BumpChunk& bc : unused_)
|
||||
bc.setRWUntil(Loc::Header);
|
||||
#endif
|
||||
}
|
||||
void setReadWrite() {
|
||||
#ifdef LIFO_CHUNK_PROTECT
|
||||
BumpChunkList::Iterator e(chunks_.last());
|
||||
for (BumpChunkList::Iterator i(chunks_.begin()); i != e; ++i)
|
||||
i->setRWUntil(Loc::Reserved);
|
||||
if (!chunks_.empty())
|
||||
chunks_.last()->setRWUntil(Loc::End);
|
||||
for (detail::BumpChunk& bc : unused_)
|
||||
bc.setRWUntil(Loc::Allocated);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get the total "used" (occupied bytes) count for the arena chunks.
|
||||
size_t used() const {
|
||||
size_t accum = 0;
|
||||
|
|
|
@ -65,7 +65,9 @@ class ProtectedRegionTree
|
|||
public:
|
||||
ProtectedRegionTree()
|
||||
: lock(mutexid::ProtectedRegionTree),
|
||||
alloc(4096),
|
||||
// Here "false" is used to not use the memory protection mechanism of
|
||||
// LifoAlloc in order to prevent dead-locks.
|
||||
alloc(4096, false),
|
||||
tree(&alloc)
|
||||
{
|
||||
sProtectedRegionsInit = true;
|
||||
|
|
|
@ -431,8 +431,8 @@ void Zone::releaseAtoms()
|
|||
keepAtomsCount--;
|
||||
|
||||
if (!hasKeptAtoms() && purgeAtomsDeferred) {
|
||||
atomCache().clearAndShrink();
|
||||
purgeAtomsDeferred = false;
|
||||
purgeAtomCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,7 +444,21 @@ Zone::purgeAtomCacheOrDefer()
|
|||
return;
|
||||
}
|
||||
|
||||
purgeAtomCache();
|
||||
}
|
||||
|
||||
void
|
||||
Zone::purgeAtomCache()
|
||||
{
|
||||
MOZ_ASSERT(!hasKeptAtoms());
|
||||
MOZ_ASSERT(!purgeAtomsDeferred);
|
||||
|
||||
atomCache().clearAndShrink();
|
||||
|
||||
// Also purge the dtoa caches so that subsequent lookups populate atom
|
||||
// cache too.
|
||||
for (RealmsInZoneIter r(this); !r.done(); r.next())
|
||||
r->dtoaCache.purge();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -524,6 +524,7 @@ class Zone : public JS::shadow::Zone,
|
|||
|
||||
void traceAtomCache(JSTracer* trc);
|
||||
void purgeAtomCacheOrDefer();
|
||||
void purgeAtomCache();
|
||||
|
||||
js::ExternalStringCache& externalStringCache() { return externalStringCache_.ref(); };
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// |jit-test| error: ReferenceError
|
||||
|
||||
loadFile(`
|
||||
gczeal(2,9);
|
||||
evaluate(\`
|
||||
reportCompare(expect, actual, summary);
|
||||
\`);
|
||||
`);
|
||||
function loadFile(lfVarx) {
|
||||
try {
|
||||
evaluate(lfVarx);
|
||||
} catch (lfVare) {}
|
||||
}
|
||||
eval("(function(){({6953421313:0})})")();
|
||||
function f() {
|
||||
x[6953421313] = "a";
|
||||
}
|
||||
f();
|
|
@ -1243,7 +1243,7 @@ BaselineCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
|
|||
ObjOperandId objId = reader.objOperandId();
|
||||
Address offsetAddr = stubAddress(reader.stubOffset());
|
||||
TypedThingLayout layout = reader.typedThingLayout();
|
||||
ReferenceTypeDescr::Type type = reader.referenceTypeDescrType();
|
||||
ReferenceType type = reader.referenceTypeDescrType();
|
||||
|
||||
// Allocate the fixed registers first. These need to be fixed for
|
||||
// callTypeUpdateIC.
|
||||
|
@ -1254,7 +1254,7 @@ BaselineCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
|
|||
AutoScratchRegister scratch2(allocator, masm);
|
||||
|
||||
// We don't need a type update IC if the property is always a string.
|
||||
if (type != ReferenceTypeDescr::TYPE_STRING) {
|
||||
if (type != ReferenceType::TYPE_STRING) {
|
||||
LiveGeneralRegisterSet saveRegs;
|
||||
saveRegs.add(obj);
|
||||
saveRegs.add(val);
|
||||
|
|
|
@ -2218,7 +2218,7 @@ BaselineCompiler::emit_JSOP_MUTATEPROTO()
|
|||
// Keep values on the stack for the decompiler.
|
||||
frame.syncStack(0);
|
||||
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
|
||||
|
||||
prepareVMCall();
|
||||
|
@ -2701,7 +2701,7 @@ BaselineCompiler::getEnvironmentCoordinateObject(Register reg)
|
|||
|
||||
masm.loadPtr(frame.addressOfEnvironmentChain(), reg);
|
||||
for (unsigned i = ec.hops(); i; i--)
|
||||
masm.extractObject(Address(reg, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
|
||||
masm.unboxObject(Address(reg, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
|
||||
}
|
||||
|
||||
Address
|
||||
|
@ -3000,8 +3000,8 @@ BaselineCompiler::emitInitPropGetterSetter()
|
|||
|
||||
prepareVMCall();
|
||||
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R1.scratchReg());
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-2)), R1.scratchReg());
|
||||
|
||||
pushArg(R0.scratchReg());
|
||||
pushArg(ImmGCPtr(script->getName(pc)));
|
||||
|
@ -3057,13 +3057,13 @@ BaselineCompiler::emitInitElemGetterSetter()
|
|||
// decompiler.
|
||||
frame.syncStack(0);
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-1)), R1.scratchReg());
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R1.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(R1.scratchReg());
|
||||
pushArg(R0);
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-3)), R0.scratchReg());
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-3)), R0.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
pushArg(ImmPtr(pc));
|
||||
|
||||
|
|
|
@ -65,9 +65,9 @@ class StackValue
|
|||
};
|
||||
|
||||
private:
|
||||
Kind kind_;
|
||||
MOZ_INIT_OUTSIDE_CTOR Kind kind_;
|
||||
|
||||
union Data {
|
||||
MOZ_INIT_OUTSIDE_CTOR union Data {
|
||||
JS::Value constant;
|
||||
ValueOperand reg;
|
||||
uint32_t localSlot;
|
||||
|
@ -80,7 +80,7 @@ class StackValue
|
|||
MOZ_POP_DISABLE_NONTRIVIAL_UNION_WARNINGS
|
||||
} data;
|
||||
|
||||
JSValueType knownType_;
|
||||
MOZ_INIT_OUTSIDE_CTOR JSValueType knownType_;
|
||||
|
||||
public:
|
||||
StackValue() {
|
||||
|
|
|
@ -306,14 +306,14 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H
|
|||
MOZ_ALWAYS_TRUE(structDescr->fieldIndex(id, &fieldIndex));
|
||||
|
||||
TypeDescr* fieldDescr = &structDescr->fieldDescr(fieldIndex);
|
||||
ReferenceTypeDescr::Type type = fieldDescr->as<ReferenceTypeDescr>().type();
|
||||
if (type == ReferenceTypeDescr::TYPE_ANY) {
|
||||
ReferenceType type = fieldDescr->as<ReferenceTypeDescr>().type();
|
||||
if (type == ReferenceType::TYPE_ANY) {
|
||||
// Ignore undefined values, which are included implicitly in type
|
||||
// information for this property.
|
||||
if (value.isUndefined())
|
||||
addType = false;
|
||||
} else {
|
||||
MOZ_ASSERT(type == ReferenceTypeDescr::TYPE_OBJECT);
|
||||
MOZ_ASSERT(type == ReferenceType::TYPE_OBJECT);
|
||||
|
||||
// Ignore null values being written here. Null is included
|
||||
// implicitly in type information for this property. Note that
|
||||
|
@ -1376,7 +1376,7 @@ DoGetIntrinsicFallback(JSContext* cx, BaselineFrame* frame, ICGetIntrinsic_Fallb
|
|||
|
||||
MOZ_ASSERT(op == JSOP_GETINTRINSIC);
|
||||
|
||||
if (!GetIntrinsicOperation(cx, pc, res))
|
||||
if (!GetIntrinsicOperation(cx, script, pc, res))
|
||||
return false;
|
||||
|
||||
// An intrinsic operation will always produce the same result, so only
|
||||
|
@ -2730,7 +2730,7 @@ ICCallStubCompiler::pushArrayArguments(MacroAssembler& masm, Address arrayVal,
|
|||
// no holes.
|
||||
Register startReg = regs.takeAny();
|
||||
Register endReg = regs.takeAny();
|
||||
masm.extractObject(arrayVal, startReg);
|
||||
masm.unboxObject(arrayVal, startReg);
|
||||
masm.loadPtr(Address(startReg, NativeObject::offsetOfElements()), startReg);
|
||||
masm.load32(Address(startReg, ObjectElements::offsetOfInitializedLength()), endReg);
|
||||
masm.alignJitStackBasedOnNArgs(endReg);
|
||||
|
@ -3546,7 +3546,7 @@ ICCall_ScriptedApplyArray::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
EmitBaselineCreateStubFrameDescriptor(masm, scratch, JitFrameLayout::Size());
|
||||
|
||||
// Reload argc from length of array.
|
||||
masm.extractObject(arrayVal, argcReg);
|
||||
masm.unboxObject(arrayVal, argcReg);
|
||||
masm.loadPtr(Address(argcReg, NativeObject::offsetOfElements()), argcReg);
|
||||
masm.load32(Address(argcReg, ObjectElements::offsetOfInitializedLength()), argcReg);
|
||||
|
||||
|
|
|
@ -79,6 +79,16 @@ BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
|||
#endif
|
||||
postDebugPrologueOffset_(postDebugPrologueOffset),
|
||||
flags_(0),
|
||||
icEntriesOffset_(0),
|
||||
icEntries_(0),
|
||||
pcMappingIndexOffset_(0),
|
||||
pcMappingIndexEntries_(0),
|
||||
pcMappingOffset_(0),
|
||||
pcMappingSize_(0),
|
||||
bytecodeTypeMapOffset_(0),
|
||||
yieldEntriesOffset_(0),
|
||||
traceLoggerToggleOffsetsOffset_(0),
|
||||
numTraceLoggerToggleOffsets_(0),
|
||||
inlinedBytecodeLength_(0),
|
||||
maxInliningDepth_(UINT8_MAX),
|
||||
pendingBuilder_(nullptr),
|
||||
|
|
|
@ -18,7 +18,8 @@ using namespace js::jit;
|
|||
BytecodeAnalysis::BytecodeAnalysis(TempAllocator& alloc, JSScript* script)
|
||||
: script_(script),
|
||||
infos_(alloc),
|
||||
usesEnvironmentChain_(false)
|
||||
usesEnvironmentChain_(false),
|
||||
hasTryFinally_(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1128,7 +1128,7 @@ GetPropIRGenerator::tryAttachCrossCompartmentWrapper(HandleObject obj, ObjOperan
|
|||
// so we optimize for that case as well.
|
||||
isWindowProxy = IsWindowProxy(unwrapped);
|
||||
if (isWindowProxy) {
|
||||
MOZ_ASSERT(ToWindowIfWindowProxy(unwrapped) == unwrapped->realm()->maybeGlobal());
|
||||
MOZ_ASSERT(ToWindowIfWindowProxy(unwrapped) == &unwrapped->nonCCWGlobal());
|
||||
unwrapped = cx_->global();
|
||||
MOZ_ASSERT(unwrapped);
|
||||
}
|
||||
|
@ -1641,8 +1641,8 @@ GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId, H
|
|||
Scalar::Type type = ScalarTypeFromSimpleTypeDescrKey(typeDescr);
|
||||
monitorLoad = type == Scalar::Uint32;
|
||||
} else {
|
||||
ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
|
||||
monitorLoad = type != ReferenceTypeDescr::TYPE_STRING;
|
||||
ReferenceType type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
|
||||
monitorLoad = type != ReferenceType::TYPE_STRING;
|
||||
}
|
||||
|
||||
if (monitorLoad)
|
||||
|
@ -3337,14 +3337,14 @@ SetPropIRGenerator::tryAttachTypedObjectProperty(HandleObject obj, ObjOperandId
|
|||
|
||||
// For reference types, guard on the RHS type first, so that
|
||||
// StoreTypedObjectReferenceProperty is infallible.
|
||||
ReferenceTypeDescr::Type type = fieldDescr->as<ReferenceTypeDescr>().type();
|
||||
ReferenceType type = fieldDescr->as<ReferenceTypeDescr>().type();
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
break;
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
case ReferenceType::TYPE_OBJECT:
|
||||
writer.guardIsObjectOrNull(rhsId);
|
||||
break;
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
writer.guardType(rhsId, JSVAL_TYPE_STRING);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -873,7 +873,7 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
}
|
||||
|
||||
void storeTypedObjectReferenceProperty(ObjOperandId obj, uint32_t offset,
|
||||
TypedThingLayout layout, ReferenceTypeDescr::Type type,
|
||||
TypedThingLayout layout, ReferenceType type,
|
||||
ValOperandId rhs)
|
||||
{
|
||||
writeOpWithOperandId(CacheOp::StoreTypedObjectReferenceProperty, obj);
|
||||
|
@ -1225,8 +1225,8 @@ class MOZ_RAII CacheIRReader
|
|||
uint32_t uint32Immediate() { return buffer_.readUnsigned(); }
|
||||
void* pointer() { return buffer_.readRawPointer(); }
|
||||
|
||||
ReferenceTypeDescr::Type referenceTypeDescrType() {
|
||||
return ReferenceTypeDescr::Type(buffer_.readByte());
|
||||
ReferenceType referenceTypeDescrType() {
|
||||
return ReferenceType(buffer_.readByte());
|
||||
}
|
||||
|
||||
uint8_t readByte() {
|
||||
|
|
|
@ -1727,7 +1727,7 @@ CacheIRCompiler::emitLoadEnclosingEnvironment()
|
|||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
Register reg = allocator.defineRegister(masm, reader.objOperandId());
|
||||
masm.extractObject(Address(obj, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
|
||||
masm.unboxObject(Address(obj, EnvironmentObject::offsetOfEnclosingEnvironment()), reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2432,13 +2432,13 @@ CacheIRCompiler::emitLoadTypedObjectResultShared(const Address& fieldAddr, Regis
|
|||
masm.loadFromTypedArray(type, fieldAddr, output.valueReg(),
|
||||
/* allowDouble = */ true, scratch, nullptr);
|
||||
} else {
|
||||
ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
|
||||
ReferenceType type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
masm.loadValue(fieldAddr, output.valueReg());
|
||||
break;
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT: {
|
||||
case ReferenceType::TYPE_OBJECT: {
|
||||
Label notNull, done;
|
||||
masm.loadPtr(fieldAddr, scratch);
|
||||
masm.branchTestPtr(Assembler::NonZero, scratch, scratch, ¬Null);
|
||||
|
@ -2450,7 +2450,7 @@ CacheIRCompiler::emitLoadTypedObjectResultShared(const Address& fieldAddr, Regis
|
|||
break;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
masm.loadPtr(fieldAddr, scratch);
|
||||
masm.tagValue(JSVAL_TYPE_STRING, scratch, output.valueReg());
|
||||
break;
|
||||
|
@ -2666,18 +2666,18 @@ CacheIRCompiler::emitBreakpoint()
|
|||
}
|
||||
|
||||
void
|
||||
CacheIRCompiler::emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceTypeDescr::Type type,
|
||||
CacheIRCompiler::emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceType type,
|
||||
const Address& dest, Register scratch)
|
||||
{
|
||||
// Callers will post-barrier this store.
|
||||
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
EmitPreBarrier(masm, dest, MIRType::Value);
|
||||
masm.storeValue(val, dest);
|
||||
break;
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT: {
|
||||
case ReferenceType::TYPE_OBJECT: {
|
||||
EmitPreBarrier(masm, dest, MIRType::Object);
|
||||
Label isNull, done;
|
||||
masm.branchTestObject(Assembler::NotEqual, val, &isNull);
|
||||
|
@ -2690,7 +2690,7 @@ CacheIRCompiler::emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceTy
|
|||
break;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
EmitPreBarrier(masm, dest, MIRType::String);
|
||||
masm.unboxString(val, scratch);
|
||||
masm.storePtr(scratch, dest);
|
||||
|
|
|
@ -656,7 +656,7 @@ class MOZ_RAII CacheIRCompiler
|
|||
uint32_t typeDescr,
|
||||
const AutoOutputRegister& output);
|
||||
|
||||
void emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceTypeDescr::Type type,
|
||||
void emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceType type,
|
||||
const Address& dest, Register scratch);
|
||||
|
||||
void emitRegisterEnumerator(Register enumeratorsList, Register iter, Register scratch);
|
||||
|
|
|
@ -666,9 +666,7 @@ class OutOfLineTestObject : public OutOfLineCodeBase<CodeGenerator>
|
|||
|
||||
public:
|
||||
OutOfLineTestObject()
|
||||
#ifdef DEBUG
|
||||
: ifEmulatesUndefined_(nullptr), ifDoesntEmulateUndefined_(nullptr)
|
||||
#endif
|
||||
{ }
|
||||
|
||||
void accept(CodeGenerator* codegen) final {
|
||||
|
@ -3425,12 +3423,12 @@ CodeGenerator::visitStoreSlotT(LStoreSlotT* lir)
|
|||
if (valueType == MIRType::ObjectOrNull) {
|
||||
masm.storeObjectOrNull(ToRegister(lir->value()), dest);
|
||||
} else {
|
||||
ConstantOrRegister value;
|
||||
mozilla::Maybe<ConstantOrRegister> value;
|
||||
if (lir->value()->isConstant())
|
||||
value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
|
||||
value.emplace(ConstantOrRegister(lir->value()->toConstant()->toJSValue()));
|
||||
else
|
||||
value = TypedOrValueRegister(valueType, ToAnyRegister(lir->value()));
|
||||
masm.storeUnboxedValue(value, valueType, dest, lir->mir()->slotType());
|
||||
value.emplace(TypedOrValueRegister(valueType, ToAnyRegister(lir->value())));
|
||||
masm.storeUnboxedValue(value.ref(), valueType, dest, lir->mir()->slotType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3628,13 +3626,13 @@ CodeGenerator::visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins)
|
|||
Register temp1 = ToRegister(ins->temp1());
|
||||
Register temp2 = ToRegister(ins->temp2());
|
||||
|
||||
ConstantOrRegister value;
|
||||
mozilla::Maybe<ConstantOrRegister> value;
|
||||
if (ins->mir()->value()->isConstant())
|
||||
value = ConstantOrRegister(ins->mir()->value()->toConstant()->toJSValue());
|
||||
value.emplace(ConstantOrRegister(ins->mir()->value()->toConstant()->toJSValue()));
|
||||
else
|
||||
value = TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(ins->value()));
|
||||
value.emplace(TypedOrValueRegister(ins->mir()->value()->type(), ToAnyRegister(ins->value())));
|
||||
|
||||
emitSetPropertyPolymorphic(ins, obj, temp1, temp2, value);
|
||||
emitSetPropertyPolymorphic(ins, obj, temp1, temp2, value.ref());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -9388,7 +9386,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
|||
LInstruction* ins = ool->ins();
|
||||
const LAllocation* index;
|
||||
MIRType valueType;
|
||||
ConstantOrRegister value;
|
||||
mozilla::Maybe<ConstantOrRegister> value;
|
||||
Register spectreTemp;
|
||||
|
||||
if (ins->isStoreElementHoleV()) {
|
||||
|
@ -9397,7 +9395,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
|||
elements = ToRegister(store->elements());
|
||||
index = store->index();
|
||||
valueType = store->mir()->value()->type();
|
||||
value = TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value));
|
||||
value.emplace(TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value)));
|
||||
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
|
||||
} else if (ins->isFallibleStoreElementV()) {
|
||||
LFallibleStoreElementV* store = ins->toFallibleStoreElementV();
|
||||
|
@ -9405,7 +9403,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
|||
elements = ToRegister(store->elements());
|
||||
index = store->index();
|
||||
valueType = store->mir()->value()->type();
|
||||
value = TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value));
|
||||
value.emplace(TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value)));
|
||||
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
|
||||
} else if (ins->isStoreElementHoleT()) {
|
||||
LStoreElementHoleT* store = ins->toStoreElementHoleT();
|
||||
|
@ -9414,9 +9412,9 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
|||
index = store->index();
|
||||
valueType = store->mir()->value()->type();
|
||||
if (store->value()->isConstant())
|
||||
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
|
||||
value.emplace(ConstantOrRegister(store->value()->toConstant()->toJSValue()));
|
||||
else
|
||||
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
|
||||
value.emplace(TypedOrValueRegister(valueType, ToAnyRegister(store->value())));
|
||||
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
|
||||
} else { // ins->isFallibleStoreElementT()
|
||||
LFallibleStoreElementT* store = ins->toFallibleStoreElementT();
|
||||
|
@ -9425,9 +9423,9 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
|||
index = store->index();
|
||||
valueType = store->mir()->value()->type();
|
||||
if (store->value()->isConstant())
|
||||
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
|
||||
value.emplace(ConstantOrRegister(store->value()->toConstant()->toJSValue()));
|
||||
else
|
||||
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
|
||||
value.emplace(TypedOrValueRegister(valueType, ToAnyRegister(store->value())));
|
||||
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
|
||||
}
|
||||
|
||||
|
@ -9488,7 +9486,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
|||
saveLive(ins);
|
||||
|
||||
pushArg(Imm32(ool->strict()));
|
||||
pushArg(value);
|
||||
pushArg(value.ref());
|
||||
if (index->isConstant())
|
||||
pushArg(Imm32(ToInt32(index)));
|
||||
else
|
||||
|
@ -9737,13 +9735,13 @@ CodeGenerator::visitArrayPushT(LArrayPushT* lir)
|
|||
Register obj = ToRegister(lir->object());
|
||||
Register elementsTemp = ToRegister(lir->temp());
|
||||
Register length = ToRegister(lir->output());
|
||||
ConstantOrRegister value;
|
||||
mozilla::Maybe<ConstantOrRegister> value;
|
||||
if (lir->value()->isConstant())
|
||||
value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
|
||||
value.emplace(ConstantOrRegister(lir->value()->toConstant()->toJSValue()));
|
||||
else
|
||||
value = TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value()));
|
||||
value.emplace(TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value())));
|
||||
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
|
||||
emitArrayPush(lir, obj, value, elementsTemp, length, spectreTemp);
|
||||
emitArrayPush(lir, obj, value.ref(), elementsTemp, length, spectreTemp);
|
||||
}
|
||||
|
||||
typedef JSObject* (*ArraySliceDenseFn)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
|
||||
|
@ -11719,30 +11717,30 @@ CodeGenerator::visitLoadElementFromStateV(LLoadElementFromStateV* lir)
|
|||
// Add inlined code for loading arguments from where they are allocated.
|
||||
for (size_t i = 0, e = array->numElements(); i < e; i++) {
|
||||
MDefinition* elem = array->getElement(i);
|
||||
ConstantOrRegister input;
|
||||
mozilla::Maybe<ConstantOrRegister> input;
|
||||
|
||||
jumpTable->addCodeEntry(masm);
|
||||
Register typeReg = Register::Invalid();
|
||||
const LAllocation* a = lir->getOperand(1 + BOX_PIECES * i);
|
||||
if (a->isBogus()) {
|
||||
if (elem->type() == MIRType::Null) {
|
||||
input = NullValue();
|
||||
input.emplace(NullValue());
|
||||
} else if (elem->type() == MIRType::Undefined) {
|
||||
input = UndefinedValue();
|
||||
input.emplace(UndefinedValue());
|
||||
} else if (elem->isConstant() && elem->isEmittedAtUses()) {
|
||||
input = elem->toConstant()->toJSValue();
|
||||
input.emplace(elem->toConstant()->toJSValue());
|
||||
} else {
|
||||
MOZ_CRASH("Unsupported element constant allocation.");
|
||||
}
|
||||
} else if (a->isMemory()) {
|
||||
if (elem->type() == MIRType::Double) {
|
||||
masm.loadDouble(ToAddress(a), tempD);
|
||||
input = TypedOrValueRegister(elem->type(), AnyRegister(tempD));
|
||||
input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(tempD)));
|
||||
} else if (elem->type() == MIRType::Value) {
|
||||
typeReg = temp0;
|
||||
masm.loadPtr(ToAddress(a), temp0);
|
||||
#ifdef JS_PUNBOX64
|
||||
input = TypedOrValueRegister(ValueOperand(temp0));
|
||||
input.emplace(TypedOrValueRegister(ValueOperand(temp0)));
|
||||
#endif
|
||||
} else {
|
||||
typeReg = temp0;
|
||||
|
@ -11753,24 +11751,23 @@ CodeGenerator::visitLoadElementFromStateV(LLoadElementFromStateV* lir)
|
|||
masm.loadPtr(ToAddress(a), temp0);
|
||||
else
|
||||
MOZ_CRASH("Unsupported load size");
|
||||
input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
|
||||
input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(typeReg)));
|
||||
}
|
||||
} else if (a->isGeneralReg()) {
|
||||
typeReg = ToRegister(a);
|
||||
input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
|
||||
#ifdef JS_PUNBOX64
|
||||
if (elem->type() != MIRType::Value)
|
||||
input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
|
||||
input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(typeReg)));
|
||||
else
|
||||
input = TypedOrValueRegister(ValueOperand(typeReg));
|
||||
input.emplace(TypedOrValueRegister(ValueOperand(typeReg)));
|
||||
#else
|
||||
if (elem->type() != MIRType::Value)
|
||||
input = TypedOrValueRegister(elem->type(), AnyRegister(typeReg));
|
||||
input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(typeReg)));
|
||||
#endif
|
||||
} else if (a->isFloatReg()) {
|
||||
input = TypedOrValueRegister(elem->type(), AnyRegister(ToFloatRegister(a)));
|
||||
input.emplace(TypedOrValueRegister(elem->type(), AnyRegister(ToFloatRegister(a))));
|
||||
} else if (a->isConstantValue()) {
|
||||
input = a->toConstant()->toJSValue();
|
||||
input.emplace(a->toConstant()->toJSValue());
|
||||
} else {
|
||||
MOZ_CRASH("Unsupported element allocation.");
|
||||
}
|
||||
|
@ -11784,9 +11781,9 @@ CodeGenerator::visitLoadElementFromStateV(LLoadElementFromStateV* lir)
|
|||
MOZ_ASSERT(typeReg != Register::Invalid());
|
||||
if (a1->isMemory()) {
|
||||
masm.loadPtr(ToAddress(a1), temp1);
|
||||
input = TypedOrValueRegister(ValueOperand(typeReg, temp1));
|
||||
input.emplace(TypedOrValueRegister(ValueOperand(typeReg, temp1)));
|
||||
} else if (a1->isGeneralReg()) {
|
||||
input = TypedOrValueRegister(ValueOperand(typeReg, ToRegister(a1)));
|
||||
input.emplace(TypedOrValueRegister(ValueOperand(typeReg, ToRegister(a1))));
|
||||
} else {
|
||||
MOZ_CRASH("Unsupported Value allocation.");
|
||||
}
|
||||
|
@ -11794,7 +11791,7 @@ CodeGenerator::visitLoadElementFromStateV(LLoadElementFromStateV* lir)
|
|||
MOZ_ASSERT(lir->getOperand(1 + BOX_PIECES * i + 1)->isBogus());
|
||||
}
|
||||
#endif
|
||||
masm.moveValue(input, out);
|
||||
masm.moveValue(input.ref(), out);
|
||||
|
||||
// For the last entry, fall-through.
|
||||
if (i + 1 < e)
|
||||
|
|
|
@ -252,7 +252,7 @@ class CompileInfo
|
|||
|
||||
explicit CompileInfo(unsigned nlocals)
|
||||
: script_(nullptr), fun_(nullptr), osrPc_(nullptr),
|
||||
analysisMode_(Analysis_None), scriptNeedsArgsObj_(false),
|
||||
analysisMode_(Analysis_None), scriptNeedsArgsObj_(false), hadOverflowBailout_(false),
|
||||
mayReadFrameArgsDirectly_(false), inlineScriptTree_(nullptr),
|
||||
needsBodyEnvironmentObject_(false), funNeedsSomeEnvironmentObject_(false)
|
||||
{
|
||||
|
|
|
@ -391,7 +391,8 @@ JSContext::freeOsrTempData()
|
|||
}
|
||||
|
||||
JitRealm::JitRealm()
|
||||
: stubCodes_(nullptr)
|
||||
: stubCodes_(nullptr),
|
||||
stringsCanBeInNursery(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -844,6 +845,7 @@ IonScript::IonScript(IonCompilationId compilationId)
|
|||
safepointsStart_(0),
|
||||
safepointsSize_(0),
|
||||
frameSlots_(0),
|
||||
argumentSlots_(0),
|
||||
frameSize_(0),
|
||||
bailoutTable_(0),
|
||||
bailoutEntries_(0),
|
||||
|
@ -852,10 +854,15 @@ IonScript::IonScript(IonCompilationId compilationId)
|
|||
snapshots_(0),
|
||||
snapshotsListSize_(0),
|
||||
snapshotsRVATableSize_(0),
|
||||
recovers_(0),
|
||||
recoversSize_(0),
|
||||
constantTable_(0),
|
||||
constantEntries_(0),
|
||||
sharedStubList_(0),
|
||||
sharedStubEntries_(0),
|
||||
invalidationCount_(0),
|
||||
compilationId_(compilationId),
|
||||
optimizationLevel_(OptimizationLevel::Normal),
|
||||
osrPcMismatchCounter_(0),
|
||||
fallbackStubSpace_()
|
||||
{
|
||||
|
|
|
@ -136,6 +136,7 @@ IonBuilder::IonBuilder(JSContext* analysisContext, CompileRealm* realm,
|
|||
typeArray(nullptr),
|
||||
typeArrayHint(0),
|
||||
bytecodeTypeMap(nullptr),
|
||||
current(nullptr),
|
||||
loopDepth_(loopDepth),
|
||||
blockWorklist(*temp),
|
||||
cfgCurrent(nullptr),
|
||||
|
@ -7958,7 +7959,7 @@ IonBuilder::getElemTryReferenceElemOfTypedObject(bool* emitted,
|
|||
{
|
||||
MOZ_ASSERT(objPrediction.ofArrayKind());
|
||||
|
||||
ReferenceTypeDescr::Type elemType = elemPrediction.referenceType();
|
||||
ReferenceType elemType = elemPrediction.referenceType();
|
||||
uint32_t elemSize = ReferenceTypeDescr::size(elemType);
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
|
@ -8016,7 +8017,7 @@ IonBuilder::pushScalarLoadFromTypedObject(MDefinition* obj,
|
|||
AbortReasonOr<Ok>
|
||||
IonBuilder::pushReferenceLoadFromTypedObject(MDefinition* typedObj,
|
||||
const LinearSum& byteOffset,
|
||||
ReferenceTypeDescr::Type type,
|
||||
ReferenceType type,
|
||||
PropertyName* name)
|
||||
{
|
||||
// Find location within the owner object.
|
||||
|
@ -8033,7 +8034,7 @@ IonBuilder::pushReferenceLoadFromTypedObject(MDefinition* typedObj,
|
|||
typedObj, name, observedTypes);
|
||||
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY: {
|
||||
case ReferenceType::TYPE_ANY: {
|
||||
// Make sure the barrier reflects the possibility of reading undefined.
|
||||
bool bailOnUndefined = barrier == BarrierKind::NoBarrier &&
|
||||
!observedTypes->hasType(TypeSet::UndefinedType());
|
||||
|
@ -8042,7 +8043,7 @@ IonBuilder::pushReferenceLoadFromTypedObject(MDefinition* typedObj,
|
|||
load = MLoadElement::New(alloc(), elements, scaledOffset, false, false, adjustment);
|
||||
break;
|
||||
}
|
||||
case ReferenceTypeDescr::TYPE_OBJECT: {
|
||||
case ReferenceType::TYPE_OBJECT: {
|
||||
// Make sure the barrier reflects the possibility of reading null. When
|
||||
// there is no other barrier needed we include the null bailout with
|
||||
// MLoadUnboxedObjectOrNull, which avoids the need to box the result
|
||||
|
@ -8056,7 +8057,7 @@ IonBuilder::pushReferenceLoadFromTypedObject(MDefinition* typedObj,
|
|||
adjustment);
|
||||
break;
|
||||
}
|
||||
case ReferenceTypeDescr::TYPE_STRING: {
|
||||
case ReferenceType::TYPE_STRING: {
|
||||
load = MLoadUnboxedString::New(alloc(), elements, scaledOffset, adjustment);
|
||||
observedTypes->addType(TypeSet::StringType(), alloc().lifoAlloc());
|
||||
break;
|
||||
|
@ -8955,7 +8956,7 @@ IonBuilder::setElemTryReferenceElemOfTypedObject(bool* emitted,
|
|||
MDefinition* value,
|
||||
TypedObjectPrediction elemPrediction)
|
||||
{
|
||||
ReferenceTypeDescr::Type elemType = elemPrediction.referenceType();
|
||||
ReferenceType elemType = elemPrediction.referenceType();
|
||||
uint32_t elemSize = ReferenceTypeDescr::size(elemType);
|
||||
|
||||
LinearSum indexAsByteOffset(alloc());
|
||||
|
@ -10603,7 +10604,7 @@ IonBuilder::getPropTryReferencePropOfTypedObject(bool* emitted, MDefinition* typ
|
|||
TypedObjectPrediction fieldPrediction,
|
||||
PropertyName* name)
|
||||
{
|
||||
ReferenceTypeDescr::Type fieldType = fieldPrediction.referenceType();
|
||||
ReferenceType fieldType = fieldPrediction.referenceType();
|
||||
|
||||
TypeSet::ObjectKey* globalKey = TypeSet::ObjectKey::get(&script()->global());
|
||||
if (globalKey->hasFlags(constraints(), OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER))
|
||||
|
@ -11718,7 +11719,7 @@ IonBuilder::setPropTryReferencePropOfTypedObject(bool* emitted,
|
|||
TypedObjectPrediction fieldPrediction,
|
||||
PropertyName* name)
|
||||
{
|
||||
ReferenceTypeDescr::Type fieldType = fieldPrediction.referenceType();
|
||||
ReferenceType fieldType = fieldPrediction.referenceType();
|
||||
|
||||
TypeSet::ObjectKey* globalKey = TypeSet::ObjectKey::get(&script()->global());
|
||||
if (globalKey->hasFlags(constraints(), OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER))
|
||||
|
@ -13563,7 +13564,7 @@ AbortReasonOr<Ok>
|
|||
IonBuilder::setPropTryReferenceTypedObjectValue(bool* emitted,
|
||||
MDefinition* typedObj,
|
||||
const LinearSum& byteOffset,
|
||||
ReferenceTypeDescr::Type type,
|
||||
ReferenceType type,
|
||||
MDefinition* value,
|
||||
PropertyName* name)
|
||||
{
|
||||
|
@ -13571,11 +13572,11 @@ IonBuilder::setPropTryReferenceTypedObjectValue(bool* emitted,
|
|||
|
||||
// Make sure we aren't adding new type information for writes of object and value
|
||||
// references.
|
||||
if (type != ReferenceTypeDescr::TYPE_STRING) {
|
||||
MOZ_ASSERT(type == ReferenceTypeDescr::TYPE_ANY ||
|
||||
type == ReferenceTypeDescr::TYPE_OBJECT);
|
||||
if (type != ReferenceType::TYPE_STRING) {
|
||||
MOZ_ASSERT(type == ReferenceType::TYPE_ANY ||
|
||||
type == ReferenceType::TYPE_OBJECT);
|
||||
MIRType implicitType =
|
||||
(type == ReferenceTypeDescr::TYPE_ANY) ? MIRType::Undefined : MIRType::Null;
|
||||
(type == ReferenceType::TYPE_ANY) ? MIRType::Undefined : MIRType::Null;
|
||||
|
||||
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &typedObj, name, &value,
|
||||
/* canModify = */ true, implicitType))
|
||||
|
@ -13595,20 +13596,20 @@ IonBuilder::setPropTryReferenceTypedObjectValue(bool* emitted,
|
|||
|
||||
MInstruction* store = nullptr; // initialize to silence GCC warning
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
case ReferenceType::TYPE_ANY:
|
||||
if (needsPostBarrier(value))
|
||||
current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
|
||||
store = MStoreElement::New(alloc(), elements, scaledOffset, value, false, adjustment);
|
||||
store->toStoreElement()->setNeedsBarrier();
|
||||
break;
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
case ReferenceType::TYPE_OBJECT:
|
||||
// Note: We cannot necessarily tell at this point whether a post
|
||||
// barrier is needed, because the type policy may insert ToObjectOrNull
|
||||
// instructions later, and those may require a post barrier. Therefore,
|
||||
// defer the insertion of post barriers to the type policy.
|
||||
store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value, typedObj, adjustment);
|
||||
break;
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
case ReferenceType::TYPE_STRING:
|
||||
// See previous comment. The StoreUnboxedString type policy may insert
|
||||
// ToString instructions that require a post barrier.
|
||||
store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value, typedObj, adjustment);
|
||||
|
|
|
@ -288,7 +288,7 @@ class IonBuilder
|
|||
AbortReasonOr<Ok> setPropTryReferenceTypedObjectValue(bool* emitted,
|
||||
MDefinition* typedObj,
|
||||
const LinearSum& byteOffset,
|
||||
ReferenceTypeDescr::Type type,
|
||||
ReferenceType type,
|
||||
MDefinition* value,
|
||||
PropertyName* name);
|
||||
AbortReasonOr<Ok> setPropTryScalarPropOfTypedObject(bool* emitted,
|
||||
|
@ -385,7 +385,7 @@ class IonBuilder
|
|||
ScalarTypeDescr::Type type);
|
||||
AbortReasonOr<Ok> pushReferenceLoadFromTypedObject(MDefinition* typedObj,
|
||||
const LinearSum& byteOffset,
|
||||
ReferenceTypeDescr::Type type,
|
||||
ReferenceType type,
|
||||
PropertyName* name);
|
||||
|
||||
// jsop_setelem() helpers.
|
||||
|
|
|
@ -1695,7 +1695,7 @@ IonCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
|
|||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
int32_t offset = int32StubField(reader.stubOffset());
|
||||
TypedThingLayout layout = reader.typedThingLayout();
|
||||
ReferenceTypeDescr::Type type = reader.referenceTypeDescrType();
|
||||
ReferenceType type = reader.referenceTypeDescrType();
|
||||
|
||||
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
|
||||
|
@ -1704,7 +1704,7 @@ IonCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
|
|||
|
||||
// We don't need to check property types if the property is always a
|
||||
// string.
|
||||
if (type != ReferenceTypeDescr::TYPE_STRING) {
|
||||
if (type != ReferenceType::TYPE_STRING) {
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
@ -1718,7 +1718,7 @@ IonCacheIRCompiler::emitStoreTypedObjectReferenceProperty()
|
|||
|
||||
emitStoreTypedObjectReferenceProp(val, type, dest, scratch2);
|
||||
|
||||
if (needsPostBarrier() && type != ReferenceTypeDescr::TYPE_STRING)
|
||||
if (needsPostBarrier() && type != ReferenceType::TYPE_STRING)
|
||||
emitPostBarrierSlot(obj, val, scratch1);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -68,10 +68,7 @@ class JitCode : public gc::TenuredCell
|
|||
bool hasBytecodeMap_ : 1; // Whether the code object has been registered with
|
||||
// native=>bytecode mapping tables.
|
||||
|
||||
JitCode()
|
||||
: code_(nullptr),
|
||||
pool_(nullptr)
|
||||
{ }
|
||||
JitCode() = delete;
|
||||
JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize, ExecutablePool* pool,
|
||||
CodeKind kind)
|
||||
: code_(code),
|
||||
|
|
|
@ -15,6 +15,7 @@ using mozilla::DebugOnly;
|
|||
ControlFlowGenerator::ControlFlowGenerator(TempAllocator& temp, JSScript* script)
|
||||
: script(script),
|
||||
current(nullptr),
|
||||
pc(nullptr),
|
||||
alloc_(temp),
|
||||
blocks_(temp),
|
||||
cfgStack_(temp),
|
||||
|
|
|
@ -149,7 +149,36 @@ class OptimizationInfo
|
|||
// as a multiplication of inliningWarmUpThreshold.
|
||||
uint32_t inliningRecompileThresholdFactor_;
|
||||
|
||||
OptimizationInfo()
|
||||
constexpr OptimizationInfo()
|
||||
: level_(OptimizationLevel::Normal),
|
||||
eaa_(false),
|
||||
ama_(false),
|
||||
edgeCaseAnalysis_(false),
|
||||
eliminateRedundantChecks_(false),
|
||||
inlineInterpreted_(false),
|
||||
inlineNative_(false),
|
||||
eagerSimdUnbox_(false),
|
||||
gvn_(false),
|
||||
licm_(false),
|
||||
rangeAnalysis_(false),
|
||||
loopUnrolling_(false),
|
||||
reordering_(false),
|
||||
autoTruncate_(false),
|
||||
sincos_(false),
|
||||
sink_(false),
|
||||
registerAllocator_(RegisterAllocator_Backtracking),
|
||||
inlineMaxBytecodePerCallSiteHelperThread_(0),
|
||||
inlineMaxBytecodePerCallSiteMainThread_(0),
|
||||
inlineMaxCalleeInlinedBytecodeLength_(0),
|
||||
inlineMaxTotalBytecodeLength_(0),
|
||||
inliningMaxCallerBytecodeLength_(0),
|
||||
maxInlineDepth_(0),
|
||||
scalarReplacement_(false),
|
||||
smallFunctionMaxInlineDepth_(0),
|
||||
compilerWarmUpThreshold_(0),
|
||||
compilerSmallFunctionWarmUpThreshold_(0),
|
||||
inliningWarmUpThresholdFactor_(0.0),
|
||||
inliningRecompileThresholdFactor_(0)
|
||||
{ }
|
||||
|
||||
void initNormalOptimizationInfo();
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "mozilla/OperatorNewExtensions.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "jit/InlineList.h"
|
||||
#include "jit/Ion.h"
|
||||
|
@ -189,11 +191,13 @@ class TempObjectPool
|
|||
MOZ_ASSERT(freed_.empty());
|
||||
alloc_ = &alloc;
|
||||
}
|
||||
T* allocate() {
|
||||
template <typename... Args>
|
||||
T* allocate(Args&&... args) {
|
||||
MOZ_ASSERT(alloc_);
|
||||
if (freed_.empty())
|
||||
return new(alloc_->fallible()) T();
|
||||
return freed_.popFront();
|
||||
return new (alloc_->fallible()) T(std::forward<Args>(args)...);
|
||||
T* res = freed_.popFront();
|
||||
return new (res) T(std::forward<Args>(args)...);
|
||||
}
|
||||
void free(T* obj) {
|
||||
freed_.pushFront(obj);
|
||||
|
|
|
@ -1541,6 +1541,7 @@ SnapshotIterator::SnapshotIterator()
|
|||
: snapshot_(nullptr, 0, 0, 0),
|
||||
recover_(snapshot_, nullptr, 0),
|
||||
fp_(nullptr),
|
||||
machine_(nullptr),
|
||||
ionScript_(nullptr),
|
||||
instructionResults_(nullptr)
|
||||
{
|
||||
|
@ -2054,7 +2055,9 @@ SnapshotIterator::maybeReadAllocByIndex(size_t index)
|
|||
InlineFrameIterator::InlineFrameIterator(JSContext* cx, const JSJitFrameIter* iter)
|
||||
: calleeTemplate_(cx),
|
||||
calleeRVA_(),
|
||||
script_(cx)
|
||||
script_(cx),
|
||||
pc_(nullptr),
|
||||
numActualArgs_(0)
|
||||
{
|
||||
resetOn(iter);
|
||||
}
|
||||
|
@ -2065,7 +2068,9 @@ InlineFrameIterator::InlineFrameIterator(JSContext* cx, const InlineFrameIterato
|
|||
frameCount_(iter ? iter->frameCount_ : UINT32_MAX),
|
||||
calleeTemplate_(cx),
|
||||
calleeRVA_(),
|
||||
script_(cx)
|
||||
script_(cx),
|
||||
pc_(nullptr),
|
||||
numActualArgs_(0)
|
||||
{
|
||||
if (frame_) {
|
||||
machine_ = iter->machine_;
|
||||
|
|
|
@ -230,8 +230,7 @@ class FrameSizeClass
|
|||
{ }
|
||||
|
||||
public:
|
||||
FrameSizeClass()
|
||||
{ }
|
||||
FrameSizeClass() = delete;
|
||||
|
||||
static FrameSizeClass None() {
|
||||
return FrameSizeClass(NO_FRAME_SIZE_CLASS_ID);
|
||||
|
|
|
@ -32,8 +32,16 @@ class FrameSizeClass;
|
|||
struct EnterJitData
|
||||
{
|
||||
explicit EnterJitData(JSContext* cx)
|
||||
: envChain(cx),
|
||||
result(cx)
|
||||
: jitcode(nullptr),
|
||||
osrFrame(nullptr),
|
||||
calleeToken(nullptr),
|
||||
maxArgv(nullptr),
|
||||
maxArgc(0),
|
||||
numActualArgs(0),
|
||||
osrNumStackValues(0),
|
||||
envChain(cx),
|
||||
result(cx),
|
||||
constructing(false)
|
||||
{}
|
||||
|
||||
uint8_t* jitcode;
|
||||
|
|
|
@ -1464,7 +1464,7 @@ struct SafepointSlotEntry {
|
|||
// Byte offset of the slot, as in LStackSlot or LArgument.
|
||||
uint32_t slot:31;
|
||||
|
||||
SafepointSlotEntry() { }
|
||||
SafepointSlotEntry() : stack(0), slot(0) { }
|
||||
SafepointSlotEntry(bool stack, uint32_t slot)
|
||||
: stack(stack), slot(slot)
|
||||
{ }
|
||||
|
@ -1478,7 +1478,7 @@ struct SafepointNunboxEntry {
|
|||
LAllocation type;
|
||||
LAllocation payload;
|
||||
|
||||
SafepointNunboxEntry() { }
|
||||
SafepointNunboxEntry() : typeVreg(0) { }
|
||||
SafepointNunboxEntry(uint32_t typeVreg, LAllocation type, LAllocation payload)
|
||||
: typeVreg(typeVreg), type(type), payload(payload)
|
||||
{ }
|
||||
|
|
|
@ -489,6 +489,8 @@ MBasicBlock::MBasicBlock(MIRGraph& graph, const CompileInfo& info, BytecodeSite*
|
|||
info_(info),
|
||||
predecessors_(graph.alloc()),
|
||||
stackPosition_(info_.firstStackSlot()),
|
||||
id_(0),
|
||||
domIndex_(0),
|
||||
numDominated_(0),
|
||||
pc_(site->pc()),
|
||||
lir_(nullptr),
|
||||
|
|
|
@ -2808,6 +2808,7 @@ MacroAssembler::MacroAssembler(JSContext* cx)
|
|||
#ifdef DEBUG
|
||||
inCall_(false),
|
||||
#endif
|
||||
dynamicAlignment_(false),
|
||||
emitProfilingInstrumentation_(false)
|
||||
{
|
||||
jitContext_.emplace(cx, (js::jit::TempAllocator*)nullptr);
|
||||
|
@ -2827,6 +2828,7 @@ MacroAssembler::MacroAssembler()
|
|||
#ifdef DEBUG
|
||||
inCall_(false),
|
||||
#endif
|
||||
dynamicAlignment_(false),
|
||||
emitProfilingInstrumentation_(false)
|
||||
{
|
||||
JitContext* jcx = GetJitContext();
|
||||
|
@ -2853,6 +2855,7 @@ MacroAssembler::MacroAssembler(WasmToken, TempAllocator& alloc)
|
|||
#ifdef DEBUG
|
||||
inCall_(false),
|
||||
#endif
|
||||
dynamicAlignment_(false),
|
||||
emitProfilingInstrumentation_(false)
|
||||
{
|
||||
moveResolver_.setAllocator(alloc);
|
||||
|
|
|
@ -2193,7 +2193,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void branchIfNativeIteratorNotReusable(Register ni, Label* notReusable);
|
||||
|
||||
using MacroAssemblerSpecific::extractTag;
|
||||
Register extractTag(const TypedOrValueRegister& reg, Register scratch) {
|
||||
MOZ_MUST_USE Register extractTag(const TypedOrValueRegister& reg, Register scratch) {
|
||||
if (reg.hasValue())
|
||||
return extractTag(reg.valueReg(), scratch);
|
||||
mov(ImmWord(MIRTypeToTag(reg.type())), scratch);
|
||||
|
@ -2201,7 +2201,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
}
|
||||
|
||||
using MacroAssemblerSpecific::extractObject;
|
||||
Register extractObject(const TypedOrValueRegister& reg, Register scratch) {
|
||||
MOZ_MUST_USE Register extractObject(const TypedOrValueRegister& reg, Register scratch) {
|
||||
if (reg.hasValue())
|
||||
return extractObject(reg.valueReg(), scratch);
|
||||
MOZ_ASSERT(reg.type() == MIRType::Object);
|
||||
|
|
|
@ -16,6 +16,7 @@ using namespace js;
|
|||
using namespace js::jit;
|
||||
|
||||
MoveOperand::MoveOperand(MacroAssembler& masm, const ABIArg& arg)
|
||||
: disp_(0)
|
||||
{
|
||||
switch (arg.kind()) {
|
||||
case ABIArg::GPR:
|
||||
|
@ -64,10 +65,9 @@ MoveResolver::addMove(const MoveOperand& from, const MoveOperand& to, MoveOp::Ty
|
|||
{
|
||||
// Assert that we're not doing no-op moves.
|
||||
MOZ_ASSERT(!(from == to));
|
||||
PendingMove* pm = movePool_.allocate();
|
||||
PendingMove* pm = movePool_.allocate(from, to, type);
|
||||
if (!pm)
|
||||
return false;
|
||||
new (pm) PendingMove(from, to, type);
|
||||
pending_.pushBack(pm);
|
||||
return true;
|
||||
}
|
||||
|
@ -205,14 +205,14 @@ MoveResolver::resolve()
|
|||
PendingMove* pm = *iter;
|
||||
|
||||
if (isDoubleAliasedAsSingle(pm->from()) || isDoubleAliasedAsSingle(pm->to())) {
|
||||
PendingMove* lower = movePool_.allocate();
|
||||
MoveOperand fromLower = SplitIntoLowerHalf(pm->from());
|
||||
MoveOperand toLower = SplitIntoLowerHalf(pm->to());
|
||||
|
||||
PendingMove* lower = movePool_.allocate(fromLower, toLower, MoveOp::FLOAT32);
|
||||
if (!lower)
|
||||
return false;
|
||||
|
||||
// Insert the new node before the current position to not affect iteration.
|
||||
MoveOperand fromLower = SplitIntoLowerHalf(pm->from());
|
||||
MoveOperand toLower = SplitIntoLowerHalf(pm->to());
|
||||
new (lower) PendingMove(fromLower, toLower, MoveOp::FLOAT32);
|
||||
pending_.insertBefore(pm, lower);
|
||||
|
||||
// Overwrite pm in place for the upper move. Iteration proceeds as normal.
|
||||
|
|
|
@ -45,11 +45,10 @@ class MoveOperand
|
|||
int32_t disp_;
|
||||
|
||||
public:
|
||||
MoveOperand()
|
||||
MoveOperand() = delete;
|
||||
explicit MoveOperand(Register reg) : kind_(REG), code_(reg.code()), disp_(0)
|
||||
{ }
|
||||
explicit MoveOperand(Register reg) : kind_(REG), code_(reg.code())
|
||||
{ }
|
||||
explicit MoveOperand(FloatRegister reg) : kind_(FLOAT_REG), code_(reg.code())
|
||||
explicit MoveOperand(FloatRegister reg) : kind_(FLOAT_REG), code_(reg.code()), disp_(0)
|
||||
{ }
|
||||
MoveOperand(Register reg, int32_t disp, Kind kind = MEMORY)
|
||||
: kind_(kind),
|
||||
|
@ -207,8 +206,7 @@ class MoveOp
|
|||
Type endCycleType_;
|
||||
|
||||
public:
|
||||
MoveOp()
|
||||
{ }
|
||||
MoveOp() = delete;
|
||||
MoveOp(const MoveOperand& from, const MoveOperand& to, Type type)
|
||||
: from_(from),
|
||||
to_(to),
|
||||
|
@ -270,8 +268,8 @@ class MoveResolver
|
|||
public TempObject,
|
||||
public InlineListNode<PendingMove>
|
||||
{
|
||||
PendingMove()
|
||||
{ }
|
||||
PendingMove() = delete;
|
||||
|
||||
PendingMove(const MoveOperand& from, const MoveOperand& to, Type type)
|
||||
: MoveOp(from, to, type)
|
||||
{ }
|
||||
|
|
|
@ -454,7 +454,9 @@ struct IonTrackedTypeWithAddendum
|
|||
|
||||
explicit IonTrackedTypeWithAddendum(TypeSet::Type type)
|
||||
: type(type),
|
||||
hasAddendum(HasNothing)
|
||||
hasAddendum(HasNothing),
|
||||
script(nullptr),
|
||||
offset(0)
|
||||
{ }
|
||||
|
||||
IonTrackedTypeWithAddendum(TypeSet::Type type, JSScript* script, uint32_t offset)
|
||||
|
|
|
@ -195,15 +195,15 @@ class Range : public TempObject {
|
|||
// exponent computation have to be over-estimations of the actual result. On
|
||||
// the Int32 this over approximation is rectified.
|
||||
|
||||
int32_t lower_;
|
||||
int32_t upper_;
|
||||
MOZ_INIT_OUTSIDE_CTOR int32_t lower_;
|
||||
MOZ_INIT_OUTSIDE_CTOR int32_t upper_;
|
||||
|
||||
bool hasInt32LowerBound_;
|
||||
bool hasInt32UpperBound_;
|
||||
MOZ_INIT_OUTSIDE_CTOR bool hasInt32LowerBound_;
|
||||
MOZ_INIT_OUTSIDE_CTOR bool hasInt32UpperBound_;
|
||||
|
||||
FractionalPartFlag canHaveFractionalPart_ : 1;
|
||||
NegativeZeroFlag canBeNegativeZero_ : 1;
|
||||
uint16_t max_exponent_;
|
||||
MOZ_INIT_OUTSIDE_CTOR FractionalPartFlag canHaveFractionalPart_ : 1;
|
||||
MOZ_INIT_OUTSIDE_CTOR NegativeZeroFlag canBeNegativeZero_ : 1;
|
||||
MOZ_INIT_OUTSIDE_CTOR uint16_t max_exponent_;
|
||||
|
||||
// Any symbolic lower or upper bound computed for this term.
|
||||
const SymbolicBound* symbolicLower_;
|
||||
|
|
|
@ -246,8 +246,7 @@ class ConstantOrRegister
|
|||
|
||||
public:
|
||||
|
||||
ConstantOrRegister()
|
||||
{}
|
||||
ConstantOrRegister() = delete;
|
||||
|
||||
MOZ_IMPLICIT ConstantOrRegister(const Value& value)
|
||||
: constant_(true)
|
||||
|
|
|
@ -36,13 +36,16 @@ RematerializedFrame::RematerializedFrame(JSContext* cx, uint8_t* top, unsigned n
|
|||
InlineFrameIterator& iter, MaybeReadFallback& fallback)
|
||||
: prevUpToDate_(false),
|
||||
isDebuggee_(iter.script()->isDebuggee()),
|
||||
hasInitialEnv_(false),
|
||||
isConstructing_(iter.isConstructing()),
|
||||
hasCachedSavedFrame_(false),
|
||||
top_(top),
|
||||
pc_(iter.pc()),
|
||||
frameNo_(iter.frameNo()),
|
||||
numActualArgs_(numActualArgs),
|
||||
script_(iter.script())
|
||||
script_(iter.script()),
|
||||
envChain_(nullptr),
|
||||
argsObj_(nullptr)
|
||||
{
|
||||
if (iter.isFunctionFrame())
|
||||
callee_ = iter.callee(fallback);
|
||||
|
|
|
@ -395,7 +395,9 @@ SafepointReader::SafepointReader(IonScript* script, const SafepointIndex* si)
|
|||
: stream_(script->safepoints() + si->safepointOffset(),
|
||||
script->safepoints() + script->safepointsSize()),
|
||||
frameSlots_((script->frameSlots() / sizeof(intptr_t)) + 1), // Stack slot counts are inclusive.
|
||||
argumentSlots_(script->argumentSlots() / sizeof(intptr_t))
|
||||
argumentSlots_(script->argumentSlots() / sizeof(intptr_t)),
|
||||
nunboxSlotsRemaining_(0),
|
||||
slotsOrElementsSlotsRemaining_(0)
|
||||
{
|
||||
osiCallPointOffset_ = stream_.readUnsigned();
|
||||
|
||||
|
|
|
@ -374,6 +374,7 @@ const char* ObjectMemoryView::phaseName = "Scalar Replacement of Object";
|
|||
|
||||
ObjectMemoryView::ObjectMemoryView(TempAllocator& alloc, MInstruction* obj)
|
||||
: alloc_(alloc),
|
||||
undefinedVal_(nullptr),
|
||||
obj_(obj),
|
||||
startBlock_(obj->block()),
|
||||
state_(nullptr),
|
||||
|
|
|
@ -2308,11 +2308,11 @@ ScalarTypeFromSimpleTypeDescrKey(uint32_t key)
|
|||
return ScalarTypeDescr::Type(key >> 1);
|
||||
}
|
||||
|
||||
inline ReferenceTypeDescr::Type
|
||||
inline ReferenceType
|
||||
ReferenceTypeFromSimpleTypeDescrKey(uint32_t key)
|
||||
{
|
||||
MOZ_ASSERT(!SimpleTypeDescrKeyIsScalar(key));
|
||||
return ReferenceTypeDescr::Type(key >> 1);
|
||||
return ReferenceType(key >> 1);
|
||||
}
|
||||
|
||||
// JSOP_NEWARRAY
|
||||
|
|
|
@ -53,7 +53,8 @@ class StupidAllocator : public RegisterAllocator
|
|||
|
||||
public:
|
||||
StupidAllocator(MIRGenerator* mir, LIRGenerator* lir, LIRGraph& graph)
|
||||
: RegisterAllocator(mir, lir, graph)
|
||||
: RegisterAllocator(mir, lir, graph),
|
||||
registerCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ TypedObjectPrediction::scalarType() const
|
|||
return extractType<ScalarTypeDescr>();
|
||||
}
|
||||
|
||||
ReferenceTypeDescr::Type
|
||||
ReferenceType
|
||||
TypedObjectPrediction::referenceType() const
|
||||
{
|
||||
return extractType<ReferenceTypeDescr>();
|
||||
|
|
|
@ -118,7 +118,8 @@ class TypedObjectPrediction {
|
|||
// Constructing a prediction. Generally, you start with an empty
|
||||
// prediction and invoke addDescr() repeatedly.
|
||||
|
||||
TypedObjectPrediction() {
|
||||
TypedObjectPrediction()
|
||||
: data_() {
|
||||
kind_ = Empty;
|
||||
}
|
||||
|
||||
|
@ -166,8 +167,8 @@ class TypedObjectPrediction {
|
|||
//
|
||||
// Only valid when |kind()| is Scalar, Reference, or Simd (as appropriate).
|
||||
|
||||
ScalarTypeDescr::Type scalarType() const;
|
||||
ReferenceTypeDescr::Type referenceType() const;
|
||||
Scalar::Type scalarType() const;
|
||||
ReferenceType referenceType() const;
|
||||
SimdType simdType() const;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2784,8 +2784,8 @@ MacroAssemblerARMCompat::testGCThing(Assembler::Condition cond, const Address& a
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
|
||||
Register tag = extractTag(address, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
|
||||
return cond == Equal ? AboveOrEqual : Below;
|
||||
}
|
||||
|
||||
|
@ -2794,8 +2794,8 @@ MacroAssemblerARMCompat::testMagic(Assembler::Condition cond, const Address& add
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_MAGIC));
|
||||
Register tag = extractTag(address, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_MAGIC));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2804,8 +2804,8 @@ MacroAssemblerARMCompat::testInt32(Assembler::Condition cond, const Address& add
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_INT32));
|
||||
Register tag = extractTag(address, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_INT32));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2814,8 +2814,8 @@ MacroAssemblerARMCompat::testDouble(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testDouble(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testDouble(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2823,8 +2823,8 @@ MacroAssemblerARMCompat::testBoolean(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testBoolean(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testBoolean(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2832,8 +2832,8 @@ MacroAssemblerARMCompat::testNull(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testNull(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testNull(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2841,8 +2841,8 @@ MacroAssemblerARMCompat::testUndefined(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testUndefined(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testUndefined(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2850,8 +2850,8 @@ MacroAssemblerARMCompat::testString(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testString(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testString(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2859,8 +2859,8 @@ MacroAssemblerARMCompat::testSymbol(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testSymbol(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testSymbol(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2868,8 +2868,8 @@ MacroAssemblerARMCompat::testObject(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testObject(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testObject(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2877,8 +2877,8 @@ MacroAssemblerARMCompat::testNumber(Condition cond, const Address& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
return testNumber(cond, scratch);
|
||||
Register tag = extractTag(address, scratch);
|
||||
return testNumber(cond, tag);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
|
@ -2903,8 +2903,8 @@ MacroAssemblerARMCompat::testUndefined(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_UNDEFINED));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_UNDEFINED));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2913,8 +2913,8 @@ MacroAssemblerARMCompat::testNull(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_NULL));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_NULL));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2923,8 +2923,8 @@ MacroAssemblerARMCompat::testBoolean(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_BOOLEAN));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_BOOLEAN));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2933,8 +2933,8 @@ MacroAssemblerARMCompat::testString(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_STRING));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_STRING));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2943,8 +2943,8 @@ MacroAssemblerARMCompat::testSymbol(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_SYMBOL));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_SYMBOL));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2953,8 +2953,8 @@ MacroAssemblerARMCompat::testInt32(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_INT32));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_INT32));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2963,8 +2963,8 @@ MacroAssemblerARMCompat::testObject(Condition cond, const BaseIndex& src)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_OBJECT));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_OBJECT));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2974,8 +2974,8 @@ MacroAssemblerARMCompat::testDouble(Condition cond, const BaseIndex& src)
|
|||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
Assembler::Condition actual = (cond == Equal) ? Below : AboveOrEqual;
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(src, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_CLEAR));
|
||||
Register tag = extractTag(src, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_CLEAR));
|
||||
return actual;
|
||||
}
|
||||
|
||||
|
@ -2984,8 +2984,8 @@ MacroAssemblerARMCompat::testMagic(Condition cond, const BaseIndex& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_TAG_MAGIC));
|
||||
Register tag = extractTag(address, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_MAGIC));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -2994,8 +2994,8 @@ MacroAssemblerARMCompat::testGCThing(Condition cond, const BaseIndex& address)
|
|||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
extractTag(address, scratch);
|
||||
ma_cmp(scratch, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
|
||||
Register tag = extractTag(address, scratch);
|
||||
ma_cmp(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
|
||||
return cond == Equal ? AboveOrEqual : Below;
|
||||
}
|
||||
|
||||
|
@ -4931,7 +4931,7 @@ MacroAssembler::branchValueIsNurseryCell(Condition cond, const Address& address,
|
|||
Label done, checkAddress;
|
||||
|
||||
Register tag = temp;
|
||||
extractTag(address, tag);
|
||||
tag = extractTag(address, tag);
|
||||
branchTestObject(Assembler::Equal, tag, &checkAddress);
|
||||
branchTestString(Assembler::NotEqual, tag, cond == Assembler::Equal ? &done : label);
|
||||
|
||||
|
|
|
@ -825,24 +825,24 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
// Extended unboxing API. If the payload is already in a register, returns
|
||||
// that register. Otherwise, provides a move to the given scratch register,
|
||||
// and returns that.
|
||||
Register extractObject(const Address& address, Register scratch);
|
||||
Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractObject(const Address& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT);
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL);
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractTag(const Address& address, Register scratch);
|
||||
Register extractTag(const BaseIndex& address, Register scratch);
|
||||
Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractTag(const Address& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractTag(const BaseIndex& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
return value.typeReg();
|
||||
}
|
||||
|
||||
|
|
|
@ -799,7 +799,6 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct
|
|||
|
||||
// Copy any arguments.
|
||||
for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
|
||||
MoveOperand from;
|
||||
switch (f.argProperties(explicitArg)) {
|
||||
case VMFunction::WordByValue:
|
||||
masm.passABIArg(MoveOperand(argsBase, argDisp), MoveOp::GENERAL);
|
||||
|
|
|
@ -994,7 +994,7 @@ MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value, R
|
|||
Label done;
|
||||
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
|
||||
|
||||
extractObject(value, temp);
|
||||
unboxObject(value, temp);
|
||||
orPtr(Imm32(gc::ChunkMask), temp);
|
||||
branch32(cond, Address(temp, gc::ChunkLocationOffsetFromLastByte),
|
||||
Imm32(int32_t(gc::ChunkLocation::Nursery)), label);
|
||||
|
|
|
@ -400,33 +400,33 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
|
|||
void splitTag(Register src, Register dest) {
|
||||
ubfx(ARMRegister(dest, 64), ARMRegister(src, 64), JSVAL_TAG_SHIFT, (64 - JSVAL_TAG_SHIFT));
|
||||
}
|
||||
Register extractTag(const Address& address, Register scratch) {
|
||||
MOZ_MUST_USE Register extractTag(const Address& address, Register scratch) {
|
||||
loadPtr(address, scratch);
|
||||
splitTag(scratch, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
splitTag(value.valueReg(), scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractObject(const Address& address, Register scratch) {
|
||||
MOZ_MUST_USE Register extractObject(const Address& address, Register scratch) {
|
||||
loadPtr(address, scratch);
|
||||
unboxObject(scratch, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
unboxObject(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
unboxSymbol(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
unboxInt32(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
unboxBoolean(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
|
|
|
@ -615,7 +615,6 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct
|
|||
|
||||
// Copy arguments.
|
||||
for (uint32_t explicitArg = 0; explicitArg < f.explicitArgs; explicitArg++) {
|
||||
MoveOperand from;
|
||||
switch (f.argProperties(explicitArg)) {
|
||||
case VMFunction::WordByValue:
|
||||
masm.passABIArg(MoveOperand(argsBase, argDisp),
|
||||
|
|
|
@ -396,25 +396,25 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
|
|||
// Extended unboxing API. If the payload is already in a register, returns
|
||||
// that register. Otherwise, provides a move to the given scratch register,
|
||||
// and returns that.
|
||||
Register extractObject(const Address& address, Register scratch);
|
||||
Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractObject(const Address& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractString(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractString(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
return value.payloadReg();
|
||||
}
|
||||
Register extractTag(const Address& address, Register scratch);
|
||||
Register extractTag(const BaseIndex& address, Register scratch);
|
||||
Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractTag(const Address& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractTag(const BaseIndex& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
return value.typeReg();
|
||||
}
|
||||
|
||||
|
|
|
@ -2158,7 +2158,7 @@ MacroAssembler::branchValueIsNurseryObject(Condition cond, ValueOperand value,
|
|||
Label done;
|
||||
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
|
||||
|
||||
extractObject(value, SecondScratchReg);
|
||||
unboxObject(value, SecondScratchReg);
|
||||
orPtr(Imm32(gc::ChunkMask), SecondScratchReg);
|
||||
branch32(cond, Address(SecondScratchReg, gc::ChunkLocationOffsetFromLastByte),
|
||||
Imm32(int32_t(gc::ChunkLocation::Nursery)), label);
|
||||
|
|
|
@ -452,30 +452,30 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
|
|||
// Extended unboxing API. If the payload is already in a register, returns
|
||||
// that register. Otherwise, provides a move to the given scratch register,
|
||||
// and returns that.
|
||||
Register extractObject(const Address& address, Register scratch);
|
||||
Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractObject(const Address& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractObject(const ValueOperand& value, Register scratch) {
|
||||
unboxObject(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractString(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractString(const ValueOperand& value, Register scratch) {
|
||||
unboxString(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractSymbol(const ValueOperand& value, Register scratch) {
|
||||
unboxSymbol(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractInt32(const ValueOperand& value, Register scratch) {
|
||||
unboxInt32(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractBoolean(const ValueOperand& value, Register scratch) {
|
||||
unboxBoolean(value, scratch);
|
||||
return scratch;
|
||||
}
|
||||
Register extractTag(const Address& address, Register scratch);
|
||||
Register extractTag(const BaseIndex& address, Register scratch);
|
||||
Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
MOZ_MUST_USE Register extractTag(const Address& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractTag(const BaseIndex& address, Register scratch);
|
||||
MOZ_MUST_USE Register extractTag(const ValueOperand& value, Register scratch) {
|
||||
MOZ_ASSERT(scratch != ScratchRegister);
|
||||
splitTag(value, scratch);
|
||||
return scratch;
|
||||
|
|
|
@ -332,12 +332,12 @@ class MacroAssemblerNone : public Assembler
|
|||
void unboxNonDouble(const Address&, Register, JSValueType) { MOZ_CRASH();}
|
||||
void unboxGCThingForPreBarrierTrampoline(const Address&, Register) { MOZ_CRASH(); }
|
||||
void notBoolean(ValueOperand) { MOZ_CRASH(); }
|
||||
Register extractObject(Address, Register) { MOZ_CRASH(); }
|
||||
Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
Register extractSymbol(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
Register extractInt32(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
Register extractBoolean(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
template <typename T> Register extractTag(T, Register) { MOZ_CRASH(); }
|
||||
MOZ_MUST_USE Register extractObject(Address, Register) { MOZ_CRASH(); }
|
||||
MOZ_MUST_USE Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
MOZ_MUST_USE Register extractSymbol(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
MOZ_MUST_USE Register extractInt32(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
MOZ_MUST_USE Register extractBoolean(ValueOperand, Register) { MOZ_CRASH(); }
|
||||
template <typename T> MOZ_MUST_USE Register extractTag(T, Register) { MOZ_CRASH(); }
|
||||
|
||||
void convertFloat32ToInt32(FloatRegister, Register, Label*, bool v = true) { MOZ_CRASH(); }
|
||||
void convertDoubleToInt32(FloatRegister, Register, Label*, bool v = true) { MOZ_CRASH(); }
|
||||
|
|
|
@ -75,7 +75,8 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator* gen, LIRGraph* graph, Mac
|
|||
checkOsiPointRegisters(JitOptions.checkOsiPointRegisters),
|
||||
#endif
|
||||
frameDepth_(graph->paddedLocalSlotsSize() + graph->argumentsSize()),
|
||||
frameInitialAdjustment_(0)
|
||||
frameInitialAdjustment_(0),
|
||||
frameClass_(FrameSizeClass::None())
|
||||
{
|
||||
if (gen->isProfilerInstrumentationEnabled())
|
||||
masm.enableProfilingInstrumentation();
|
||||
|
@ -107,7 +108,7 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator* gen, LIRGraph* graph, Mac
|
|||
|
||||
// FrameSizeClass is only used for bailing, which cannot happen in
|
||||
// wasm code.
|
||||
frameClass_ = FrameSizeClass::None();
|
||||
MOZ_ASSERT(frameClass_ == FrameSizeClass::None());
|
||||
} else {
|
||||
frameClass_ = FrameSizeClass::FromDepth(frameDepth_);
|
||||
}
|
||||
|
|
|
@ -243,6 +243,7 @@ class BranchDeadlineSet
|
|||
|
||||
public:
|
||||
explicit BranchDeadlineSet(LifoAlloc& alloc)
|
||||
: earliestRange_(0)
|
||||
{
|
||||
// Manually construct vectors in the uninitialized aligned storage.
|
||||
// This is because C++ arrays can otherwise only be constructed with
|
||||
|
|
|
@ -37,6 +37,7 @@ class LIRGeneratorShared
|
|||
: gen(gen),
|
||||
graph(graph),
|
||||
lirGraph_(lirGraph),
|
||||
current(nullptr),
|
||||
lastResumePoint_(nullptr),
|
||||
cachedRecoverInfo_(nullptr),
|
||||
osiPoint_(nullptr)
|
||||
|
|
|
@ -262,7 +262,9 @@ class RelocationIterator
|
|||
|
||||
public:
|
||||
explicit RelocationIterator(CompactBufferReader& reader)
|
||||
: reader_(reader)
|
||||
: reader_(reader),
|
||||
offset_(0),
|
||||
extOffset_(0)
|
||||
{
|
||||
tableStart_ = reader_.readFixedUint32_t();
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ class BailoutStack
|
|||
|
||||
BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
|
||||
BailoutStack* bailout)
|
||||
: machine_(bailout->machineState())
|
||||
: machine_(bailout->machineState()),
|
||||
activation_(nullptr)
|
||||
{
|
||||
uint8_t* sp = bailout->parentStackPointer();
|
||||
framePointer_ = sp + bailout->frameSize();
|
||||
|
@ -62,7 +63,8 @@ BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
|
|||
|
||||
BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
|
||||
InvalidationBailoutStack* bailout)
|
||||
: machine_(bailout->machine())
|
||||
: machine_(bailout->machine()),
|
||||
activation_(nullptr)
|
||||
{
|
||||
framePointer_ = (uint8_t*) bailout->fp();
|
||||
topFrameSize_ = framePointer_ - bailout->sp();
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче