Merge autoland to mozilla-central. a=merge

This commit is contained in:
Ciure Andrei 2019-05-24 00:51:34 +03:00
Родитель 48cbbb3137 a875b0a496
Коммит 90fa4c6afd
343 изменённых файлов: 4460 добавлений и 2481 удалений

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

@ -537,7 +537,22 @@ Accessible* Accessible::ChildAtPoint(int32_t aX, int32_t aY,
// This happens in mobile platforms with async pinch zooming.
offset = offset.RemoveResolution(presContext->PresShell()->GetResolution());
nsIFrame* foundFrame = nsLayoutUtils::GetFrameForPoint(startFrame, offset);
// We need to translate with the offset of the edge of the visual
// viewport from top edge of the layout viewport.
offset += presContext->PresShell()->GetVisualViewportOffset() -
presContext->PresShell()->GetLayoutViewportOffset();
EnumSet<nsLayoutUtils::FrameForPointOption> options = {
#ifdef MOZ_WIDGET_ANDROID
// This is needed in Android to ignore the clipping of the scroll frame
// when zoomed in. May regress something on other platforms, so
// keeping it Android-exclusive for now.
nsLayoutUtils::FrameForPointOption::IgnoreRootScrollFrame
#endif
};
nsIFrame* foundFrame =
nsLayoutUtils::GetFrameForPoint(startFrame, offset, options);
nsIContent* content = nullptr;
if (!foundFrame || !(content = foundFrame->GetContent()))
@ -645,11 +660,18 @@ nsRect Accessible::BoundsInAppUnits() const {
return nsRect();
}
PresShell* presShell = mDoc->PresContext()->PresShell();
// We need to inverse translate with the offset of the edge of the visual
// viewport from top edge of the layout viewport.
nsPoint viewportOffset = presShell->GetVisualViewportOffset() -
presShell->GetLayoutViewportOffset();
unionRectTwips.MoveBy(-viewportOffset);
// We need to take into account a non-1 resolution set on the presshell.
// This happens in mobile platforms with async pinch zooming. Here we
// scale the bounds before adding the screen-relative offset.
unionRectTwips.ScaleRoundOut(
mDoc->PresContext()->PresShell()->GetResolution());
unionRectTwips.ScaleRoundOut(presShell->GetResolution());
// We have the union of the rectangle, now we need to put it in absolute
// screen coords.
nsRect orgRectPixels = boundingFrame->GetScreenRectInAppUnits();

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

@ -304,7 +304,7 @@ bool HTMLComboboxAccessible::RemoveChild(Accessible* aChild) {
}
void HTMLComboboxAccessible::Shutdown() {
MOZ_ASSERT(mDoc->IsDefunct() || !mListAccessible);
MOZ_ASSERT(!mDoc || mDoc->IsDefunct() || !mListAccessible);
if (mListAccessible) {
mListAccessible->Shutdown();
mListAccessible = nullptr;

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

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<blocklist lastupdate="1558349549359" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<blocklist lastupdate="1558536765550" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
<prefs/>
@ -2997,6 +2997,38 @@
<prefs/>
<versionRange minVersion="0" maxVersion="2.9.1.0" severity="3"/>
</emItem>
<emItem blockID="0225ae55-626d-42b2-8f48-46ec95ec89f8" id="/^((\{2b3eed60-8f6e-4afc-99f1-38d12f4253da\})|(\{3a6f9dac-3a93-4f6f-8b74-9ebc0f501306\})|(\{46bba8e9-7a75-4dd6-932e-bdd74141cb87\})|(\{4b480ab6-b63a-43f8-b4f4-d312972ab086\})|(\{6106687e-ca0c-4d7e-93bc-115929e4d299\})|(\{717ce133-3c0a-448e-b6ed-fc7d22b76534\})|(\{7224f1ae-c342-4bb5-8441-d324a8951624\})|(\{768e9638-2eba-42e4-a13a-4f3f1df391a2\})|(\{7b655f43-c871-46d2-8f6d-31989e8ee939\})|(\{7e46c692-9488-4671-8c39-7830f92628b0\})|(\{83bc6b56-545f-4ba1-a80b-f82d55cc0f68\})|(\{970a774e-b7a7-498f-b3f2-d88b14b4dab1\})|(\{9d2e8731-3287-46eb-9c19-ece63fe693c7\})|(\{a37ccd20-e04f-4949-b055-98ca58639606\})|(\{af85f82c-3e8f-4ee5-ab53-b8d3aaac34ec\})|(\{b35c6d47-8b07-4d49-89a9-dfe8c10f58f6\})|(\{c2485579-368c-4593-a1cd-985b2fa0b990\})|(\{c85c16ba-78b4-41b3-9201-f80fa662c52f\})|(\{c97e5535-6f2e-4d34-a5a3-0e6e07f7fd13\})|(\{ce7db166-9564-482f-91d9-3a450ec3216d\})|(\{d64a2c73-ff21-4e3e-998f-ec2dc42ad725\})|(\{db6d93c3-67a0-410c-b7bd-f72f267f0cec\})|(\{e513775f-359f-47aa-a3d9-eddc946aabe0\})|(\{f70258e4-643b-4ec2-9c84-de89009eec61\})|(\{f8794e87-82b2-4df4-bce6-db207f62c165\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="2212748f-ad60-497f-af7b-50d20b326e40" id="{da993d54-9605-42f7-a32f-9f565245070c}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="41137e55-8a11-4259-a009-42c29daadf17" id="{ac4be7d1-4db6-4b4c-bf48-e345350bcb59}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="a5fa8f77-7761-4996-a11d-d8cf723103da" id="{dc6176c4-a192-4a92-849f-ad13abe889ad}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="efecef61-549b-4c13-8a52-394c636dd24b" id="/^((\{ec19994c-c5a5-46d9-bd4d-0fc417c6f4b8\})|(\{a0be7e8d-b0a3-460b-8a52-429c79e49ee2\})|(\{1814dd58-4147-4cca-a0a3-c5aa35966d9c\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="9c5f5681-8547-4e65-9c05-5796e483b8e1" id="/^((\{3e20d1e2-a7ee-4ce2-ab9c-51c8300a8ff6\})|(\{30906bbc-0942-445b-89c8-f74dac0edb8f\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="7e86024e-5621-4ded-bc16-184f94fa2e29" id="{a37a7625-b64e-45f3-8b79-f71634f14438}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="43966df2-e95c-415b-bffc-13814e1d2b11" id="{3fc1db2b-e7db-4512-b24e-1faf4d3a1b4d}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
</emItems>
<pluginItems>
<pluginItem blockID="p332">

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

@ -1,3 +1,5 @@
[DEFAULT]
[browser_file_menu_import_wizard.js]
[browser_window_menu_list.js]
skip-if = os != "mac" # Mac only feature

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

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function test_window_menu_list() {
// This title is different depending on the build. For example, it's "Nightly"
// for a local build, "Mozilla Firefox" for an official release build.
const windowTitle = window.document.title;
await checkWindowMenu([windowTitle, "Browser chrome tests"]);
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
await checkWindowMenu([windowTitle, "Browser chrome tests", windowTitle]);
await BrowserTestUtils.closeWindow(newWindow);
});
async function checkWindowMenu(labels) {
let menu = document.querySelector("#windowMenu");
// We can't toggle menubar items on OSX, so mocking instead.
await new Promise(resolve => {
menu.addEventListener("popupshown", resolve, { once: true });
menu.dispatchEvent(new MouseEvent("popupshowing"));
menu.dispatchEvent(new MouseEvent("popupshown"));
});
let menuitems = [...menu.querySelectorAll("menuseparator ~ menuitem")];
is(menuitems.length, labels.length, "Correct number of windows in the menu");
is(menuitems.map(item => item.label).join(","), labels.join(","), "Correct labels on menuitems");
for (let menuitem of menuitems) {
ok(menuitem instanceof customElements.get("menuitem"), "sibling is menuitem");
}
// We can't toggle menubar items on OSX, so mocking instead.
await new Promise(resolve => {
menu.addEventListener("popuphidden", resolve, { once: true });
menu.dispatchEvent(new MouseEvent("popuphiding"));
menu.dispatchEvent(new MouseEvent("popuphidden"));
});
}

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

@ -289,16 +289,6 @@ const startupPhases = {
read: 3,
close: 3,
},
{
path: "UChrm:userChrome.css",
condition: WIN,
stat: 1,
},
{ // bug 1541233
path: "UChrm:userContent.css",
condition: WIN,
stat: 1,
},
{ // bug 1541246
path: "XREUSysExt:",
condition: WIN,

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

@ -22,3 +22,9 @@ export MOZ_PACKAGE_JSSHELL=1
if test -n "$MOZ_ARTIFACT_TASK_WIN32_OPT"; then
ac_add_options --enable-eme=widevine
fi
# Temporary signal to toolchain.configure that our compiler is patched to
# support CFG, until such support can be assumed.
if test -z "$USE_ARTIFACT"; then
ac_add_options --enable-hardening
fi

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

@ -1,9 +1,3 @@
# This file is used by all AArch64 Win64 builds
ac_add_options --target=aarch64-windows-mingw32
# Temporary signal to toolchain.configure that our compiler is patched to
# support CFG, until such support can be assumed.
if test -z "$USE_ARTIFACT"; then
ac_add_options --enable-hardening
fi

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

@ -288,6 +288,7 @@
@RESPATH@/greprefs.js
@RESPATH@/defaults/autoconfig/prefcalls.js
@RESPATH@/browser/defaults/permissions
; Remote Settings JSON dumps
@RESPATH@/browser/defaults/settings/blocklists
@RESPATH@/browser/defaults/settings/pinning
@RESPATH@/browser/defaults/settings/main

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

@ -11,7 +11,10 @@ import platform
import subprocess
import sys
import uuid
import __builtin__
if sys.version_info[0] < 3:
import __builtin__ as builtins
else:
import builtins
from types import ModuleType
@ -434,4 +437,4 @@ class ImportHook(object):
# Install our hook
__builtin__.__import__ = ImportHook(__builtin__.__import__)
builtins.__import__ = ImportHook(builtins.__import__)

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

@ -714,11 +714,8 @@ $(foreach f,$(HOST_CSRCS) $(HOST_CPPSRCS) $(HOST_CMSRCS) $(HOST_CMMSRCS),$(eval
# The Rust compiler only outputs library objects, and so we need different
# mangling to generate dependency rules for it.
mk_libname = $(basename lib$(notdir $1)).rlib
src_libdep = $(call mk_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
mk_global_crate_libname = $(basename lib$(notdir $1)).$(LIB_SUFFIX)
crate_src_libdep = $(call mk_global_crate_libname,$1): $1 $$(call mkdir_deps,$$(MDDEPDIR))
$(foreach f,$(RSSRCS),$(eval $(call src_libdep,$(f))))
$(foreach f,$(RS_STATICLIB_CRATE_SRC),$(eval $(call crate_src_libdep,$(f))))
$(OBJS) $(HOST_OBJS) $(PROGOBJS) $(HOST_PROGOBJS): $(GLOBAL_DEPS)

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

@ -101,7 +101,6 @@ devtools.jar:
skin/breadcrumbs.css (themes/breadcrumbs.css)
skin/chart.css (themes/chart.css)
skin/widgets.css (themes/widgets.css)
skin/images/alerticon-unused.svg (themes/images/alerticon-unused.svg)
skin/rules.css (themes/rules.css)
skin/images/command-paintflashing.svg (themes/images/command-paintflashing.svg)
skin/images/command-screenshot.svg (themes/images/command-screenshot.svg)

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

@ -552,6 +552,10 @@ netmonitor.toolbar.method=Method
# in the network table toolbar, above the "file" column.
netmonitor.toolbar.file=File
# LOCALIZATION NOTE (netmonitor.toolbar.url): This is the label displayed
# in the network table toolbar, above the "url" column.
netmonitor.toolbar.url=URL
# LOCALIZATION NOTE (netmonitor.toolbar.protocol): This is the label displayed
# in the network table toolbar, above the "protocol" column.
netmonitor.toolbar.protocol=Protocol

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

@ -4,14 +4,12 @@
"use strict";
const { Component } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const { td } = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { getFormattedIPAndPort } = require("../utils/format-utils");
const { L10N } = require("../utils/l10n");
const { propertiesEqual } = require("../utils/request-utils");
const { div } = dom;
const SecurityState = createFactory(require("./SecurityState"));
const UPDATED_DOMAIN_PROPS = [
"remoteAddress",
@ -32,38 +30,26 @@ class RequestListColumnDomain extends Component {
}
render() {
const { item, onSecurityIconMouseDown } = this.props;
const { remoteAddress, remotePort, securityState,
urlDetails: { host, isLocal } } = item;
const iconClassList = ["requests-security-state-icon"];
let iconTitle;
const {
item,
onSecurityIconMouseDown,
} = this.props;
const {
remoteAddress,
remotePort,
urlDetails: {
host,
isLocal,
},
} = item;
const title = host + (remoteAddress ?
` (${getFormattedIPAndPort(remoteAddress, remotePort)})` : "");
let realSecurityState = securityState;
// Locally delivered files such as http://localhost and file:// paths
// are considered to have been delivered securely.
if (isLocal) {
realSecurityState = "secure";
}
if (realSecurityState) {
iconClassList.push(`security-state-${realSecurityState}`);
iconTitle = L10N.getStr(`netmonitor.security.state.${realSecurityState}`);
}
return (
dom.td({ className: "requests-list-column requests-list-domain", title },
div({
className: iconClassList.join(" "),
onMouseDown: onSecurityIconMouseDown,
title: iconTitle,
}),
item.isThirdPartyTrackingResource && div({
className: "tracking-resource",
title: L10N.getStr("netmonitor.trackingResource.tooltip"),
}),
td({ className: "requests-list-column requests-list-domain", title },
SecurityState({item, onSecurityIconMouseDown, isLocal}),
host,
)
);

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

@ -0,0 +1,75 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const { td } = require("devtools/client/shared/vendor/react-dom-factories");
const { L10N } = require("../utils/l10n");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { getFormattedIPAndPort } = require("../utils/format-utils");
const { propertiesEqual } = require("../utils/request-utils");
const SecurityState = createFactory(require("./SecurityState"));
const UPDATED_FILE_PROPS = [
"remoteAddress",
"securityState",
"urlDetails",
];
class RequestListColumnUrl extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_FILE_PROPS, this.props.item, nextProps.item);
}
render() {
const {
item: { urlDetails },
} = this.props;
const {
item,
onSecurityIconMouseDown,
} = this.props;
const {
remoteAddress,
remotePort,
urlDetails: {
isLocal,
},
} = item;
const title = (remoteAddress ?
` (${getFormattedIPAndPort(remoteAddress, remotePort)})` : "");
// deals with returning whole url
const originalURL = urlDetails.url;
const decodedFileURL = urlDetails.unicodeUrl;
const ORIGINAL_FILE_URL = L10N.getFormatStr("netRequest.originalFileURL.tooltip",
originalURL);
const DECODED_FILE_URL = L10N.getFormatStr("netRequest.decodedFileURL.tooltip",
decodedFileURL);
const urlToolTip = originalURL === decodedFileURL ?
originalURL : ORIGINAL_FILE_URL + "\n\n" + DECODED_FILE_URL;
return (
td({
className: "requests-list-column requests-list-url",
title: urlToolTip + title,
},
SecurityState({item, onSecurityIconMouseDown, isLocal}),
originalURL
)
);
}
}
module.exports = RequestListColumnUrl;

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

@ -30,6 +30,7 @@ const { RESPONSE_HEADERS } = require("../constants");
RequestListColumnTime,
RequestListColumnTransferredSize,
RequestListColumnType,
RequestListColumnUrl,
RequestListColumnWaterfall
*/
@ -48,6 +49,9 @@ loader.lazyGetter(this, "RequestListColumnDomain", function() {
loader.lazyGetter(this, "RequestListColumnFile", function() {
return createFactory(require("./RequestListColumnFile"));
});
loader.lazyGetter(this, "RequestListColumnUrl", function() {
return createFactory(require("./RequestListColumnUrl"));
});
loader.lazyGetter(this, "RequestListColumnMethod", function() {
return createFactory(require("./RequestListColumnMethod"));
});
@ -227,6 +231,10 @@ class RequestListItem extends Component {
onSecurityIconMouseDown,
}),
columns.file && RequestListColumnFile({ item }),
columns.url && RequestListColumnUrl({
item,
onSecurityIconMouseDown,
}),
columns.protocol && RequestListColumnProtocol({ item }),
columns.scheme && RequestListColumnScheme({ item }),
columns.remoteip && RequestListColumnRemoteIP({ item }),

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

@ -0,0 +1,75 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Component } = require("devtools/client/shared/vendor/react");
const { div } = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { L10N } = require("../utils/l10n");
const { propertiesEqual } = require("../utils/request-utils");
const UPDATED_DOMAIN_PROPS = [
"remoteAddress",
"securityState",
"urlDetails",
];
class SecurityState extends Component {
static get propTypes() {
return {
item: PropTypes.object.isRequired,
onSecurityIconMouseDown: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps) {
return !propertiesEqual(UPDATED_DOMAIN_PROPS, this.props.item, nextProps.item);
}
render() {
const {
item,
onSecurityIconMouseDown,
} = this.props;
const {
securityState,
urlDetails: {
isLocal,
},
} = item;
const iconClassList = ["requests-security-state-icon"];
let iconTitle;
let realSecurityState = securityState;
// Locally delivered files such as http://localhost and file:// paths
// are considered to have been delivered securely.
if (isLocal) {
realSecurityState = "secure";
}
if (realSecurityState) {
iconClassList.push(`security-state-${realSecurityState}`);
iconTitle = L10N.getStr(`netmonitor.security.state.${realSecurityState}`);
}
return (
div({},
div({
className: iconClassList.join(" "),
onMouseDown: onSecurityIconMouseDown,
title: iconTitle,
}),
item.isThirdPartyTrackingResource && div({
className: "tracking-resource",
title: L10N.getStr("netmonitor.trackingResource.tooltip"),
}),
)
);
}
}
module.exports = SecurityState;

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

@ -30,6 +30,7 @@ DevToolsModules(
'RequestListColumnTime.js',
'RequestListColumnTransferredSize.js',
'RequestListColumnType.js',
'RequestListColumnUrl.js',
'RequestListColumnWaterfall.js',
'RequestListContent.js',
'RequestListEmptyNotice.js',
@ -37,6 +38,7 @@ DevToolsModules(
'RequestListItem.js',
'ResponsePanel.js',
'SecurityPanel.js',
'SecurityState.js',
'SourceEditor.js',
'StackTracePanel.js',
'StatisticsPanel.js',

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

@ -198,6 +198,10 @@ const HEADERS = [
name: "file",
canFilter: false,
},
{
name: "url",
canFilter: true,
},
{
name: "protocol",
canFilter: true,

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

@ -30,6 +30,7 @@ const cols = {
method: true,
domain: true,
file: true,
url: false,
protocol: false,
scheme: false,
remoteip: false,

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

@ -25,15 +25,23 @@ add_task(async function() {
"There were two requests due to redirect.");
const [
initialSecurityIcon,
redirectSecurityIcon,
initialDomainSecurityIcon,
initialUrlSecurityIcon,
redirectDomainSecurityIcon,
redirectUrlSecurityIcon,
] = document.querySelectorAll(".requests-security-state-icon");
ok(initialSecurityIcon.classList.contains("security-state-insecure"),
"Initial request was marked insecure.");
ok(initialDomainSecurityIcon.classList.contains("security-state-insecure"),
"Initial request was marked insecure for domain column.");
ok(redirectSecurityIcon.classList.contains("security-state-secure"),
"Redirected request was marked secure.");
ok(redirectDomainSecurityIcon.classList.contains("security-state-secure"),
"Redirected request was marked secure for domain column.");
ok(initialUrlSecurityIcon.classList.contains("security-state-insecure"),
"Initial request was marked insecure for URL column.");
ok(redirectUrlSecurityIcon.classList.contains("security-state-secure"),
"Redirected request was marked secure for URL column.");
await teardown(monitor);
});

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

@ -30,8 +30,12 @@ add_task(async function() {
// Execute request with third party tracking protection flag.
await performRequests(monitor, tab, 1);
const requests = document.querySelectorAll(".request-list-item .tracking-resource");
is(requests.length, 1, "There should be one tracking request");
const domainRequests =
document.querySelectorAll(".requests-list-domain .tracking-resource");
const UrlRequests = document.querySelectorAll(".requests-list-url .tracking-resource");
is(domainRequests.length, 1, "There should be one domain column tracking request");
is(UrlRequests.length, 1, "There should be one URL column tracking request");
await teardown(monitor);
});

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

@ -118,7 +118,7 @@ const gDefaultFilters = Services.prefs.getCharPref("devtools.netmonitor.filters"
Services.prefs.setCharPref(
"devtools.netmonitor.visibleColumns",
"[\"cause\",\"contentSize\",\"cookies\",\"domain\",\"duration\"," +
"\"endTime\",\"file\",\"latency\",\"method\",\"protocol\"," +
"\"endTime\",\"file\",\"url\",\"latency\",\"method\",\"protocol\"," +
"\"remoteip\",\"responseTime\",\"scheme\",\"setCookies\"," +
"\"startTime\",\"status\",\"transferred\",\"type\",\"waterfall\"]"
);
@ -128,6 +128,7 @@ Services.prefs.setCharPref("devtools.netmonitor.columnsData",
'{"name":"method","minWidth":30,"width":5},' +
'{"name":"domain","minWidth":30,"width":10},' +
'{"name":"file","minWidth":30,"width":25},' +
'{"name":"url","minWidth":30,"width":25},' +
'{"name":"cause","minWidth":30,"width":10},' +
'{"name":"type","minWidth":30,"width":5},' +
'{"name":"transferred","minWidth":30,"width":10},' +

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

@ -168,7 +168,7 @@ pref("devtools.netmonitor.visibleColumns",
"[\"status\",\"method\",\"domain\",\"file\",\"cause\",\"type\",\"transferred\",\"contentSize\",\"waterfall\"]"
);
pref("devtools.netmonitor.columnsData",
'[{"name":"status","minWidth":30,"width":5}, {"name":"method","minWidth":30,"width":5}, {"name":"domain","minWidth":30,"width":10}, {"name":"file","minWidth":30,"width":25}, {"name":"cause","minWidth":30,"width":10},{"name":"type","minWidth":30,"width":5},{"name":"transferred","minWidth":30,"width":10},{"name":"contentSize","minWidth":30,"width":5},{"name":"waterfall","minWidth":150,"width":25}]');
'[{"name":"status","minWidth":30,"width":5}, {"name":"method","minWidth":30,"width":5}, {"name":"domain","minWidth":30,"width":10}, {"name":"file","minWidth":30,"width":25}, {"name":"url","minWidth":30,"width":25}, {"name":"cause","minWidth":30,"width":10},{"name":"type","minWidth":30,"width":5},{"name":"transferred","minWidth":30,"width":10},{"name":"contentSize","minWidth":30,"width":5},{"name":"waterfall","minWidth":150,"width":25}]');
// Support for columns resizing pref is now enabled (after merge date 03/18/19).
pref("devtools.netmonitor.features.resizeColumns", true);

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

@ -32,7 +32,7 @@ class SearchBox extends PureComponent {
onFocus: PropTypes.func,
onKeyDown: PropTypes.func,
placeholder: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
type: PropTypes.string,
};
}

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

@ -1,6 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13.5 12.7" width="12" height="12">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
<path fill="context-fill" d="M6 0a1 1 0 0 1 .89.54l5 9.6A1 1 0 0 1 11 11.6H1a1 1 0 0 1-.89-1.46l5-9.6A1 1 0 0 1 6 0zm-.25 8a.75.75 0 0 0-.75.75v.5c0 .41.34.75.75.75h.5c.41 0 .75-.34.75-.75v-.5A.75.75 0 0 0 6.25 8h-.5zM7 3.7a1 1 0 1 0-2 0v2.6a1 1 0 1 0 2 0V3.7z" />
</svg>

До

Ширина:  |  Высота:  |  Размер: 574 B

После

Ширина:  |  Высота:  |  Размер: 570 B

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

@ -1,8 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 14 14">
<path stroke="context-stroke" fill="none" d="M13 7C13 10.31 10.31 13 7 13C3.69 13 1 10.31 1 7C1 3.69 3.69 1 7 1C10.31 1 13 3.69 13 7Z"/>
<path fill="context-fill" d="M7.54 5.88C8.02 5.88 8.41 6.26 8.41 6.74C8.41 7.6 8.41 9.29 8.41 10.15C8.41 10.63 8.02 11.02 7.54 11.02C7.2 11.02 7.05 11.02 6.71 11.02C6.23 11.02 5.84 10.63 5.84 10.15C5.84 9.29 5.84 7.6 5.84 6.74C5.84 6.26 6.23 5.88 6.71 5.88C7.05 5.88 7.2 5.88 7.54 5.88Z"/>
<path fill="context-fill" d="M8.41 4.11C8.41 4.82 7.83 5.4 7.12 5.4C6.42 5.4 5.84 4.82 5.84 4.11C5.84 3.4 6.42 2.83 7.12 2.83C7.83 2.83 8.41 3.4 8.41 4.11Z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 895 B

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

@ -365,22 +365,20 @@
display: inline-block;
width: 12px;
height: 12px;
background-size: cover;
background-size: 12px;
background-repeat: no-repeat;
-moz-context-properties: fill;
}
.ruleview-warning {
background-image: url(chrome://devtools/skin/images/alert.svg);
background-position: 0.73px 0.4px;
-moz-context-properties: fill;
fill: var(--yellow-60);
}
.ruleview-unused-warning {
background-image: url(chrome://devtools/skin/images/alerticon-unused.svg);
background-image: url(chrome://devtools/skin/images/webconsole/info.svg);
background-color: var(--theme-sidebar-background);
-moz-context-properties: fill, stroke;
fill: var(--theme-icon-dimmed-color);
stroke: var(--theme-icon-dimmed-color);
}
.ruleview-unused-warning:hover {

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

@ -28,7 +28,6 @@ class FilterBar extends Component {
return {
dispatch: PropTypes.func.isRequired,
filter: PropTypes.object.isRequired,
attachRefToWebConsoleUI: PropTypes.func.isRequired,
persistLogs: PropTypes.bool.isRequired,
hidePersistLogsCheckbox: PropTypes.bool.isRequired,
showContentMessages: PropTypes.bool.isRequired,

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

@ -1664,14 +1664,15 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
sourceActor = this.sources.createSourceActor(source);
}
if (this._onLoadBreakpointURLs.has(source.url)) {
this.setBreakpoint({ sourceUrl: source.url, line: 1 }, {});
const sourceUrl = sourceActor.url;
if (this._onLoadBreakpointURLs.has(sourceUrl)) {
this.setBreakpoint({ sourceUrl, line: 1 }, {});
}
const bpActors = this.breakpointActorMap.findActors()
.filter((actor) => {
return actor.location.sourceUrl && actor.location.sourceUrl == source.url;
});
.filter((actor) =>
actor.location.sourceUrl && actor.location.sourceUrl == sourceUrl
);
for (const actor of bpActors) {
sourceActor.applyBreakpoint(actor);

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

@ -0,0 +1,29 @@
/* eslint-disable max-nested-callbacks */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Bug 1552453 - Verify that breakpoints are hit for evaluated
* scripts that contain a source url pragma.
*/
add_task(threadClientTest(async ({ threadClient, targetFront }) => {
await threadClient.setBreakpoint(
{ sourceUrl: "http://example.com/code.js", line: 2, column: 1 },
{}
);
info("Create a new script with the displayUrl code.js");
const consoleFront = await targetFront.getFront("console");
consoleFront.evaluateJSAsync("function f() {\n return 5; \n}\n//# sourceURL=http://example.com/code.js");
const sourcePacket = await waitForEvent(threadClient, "newSource");
equal(sourcePacket.source.url, "http://example.com/code.js");
info("Evaluate f() and pause at line 2");
consoleFront.evaluateJSAsync("f()");
const pausedPacket = await waitForPause(threadClient);
equal(pausedPacket.why.type, "breakpoint");
equal(pausedPacket.frame.where.line, 2);
}));

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

@ -132,6 +132,7 @@ reason = bug 1104838
[test_breakpoint-21.js]
[test_breakpoint-22.js]
skip-if = true # breakpoint sliding is not supported bug 1525685
[test_breakpoint-23.js]
[test_conditional_breakpoint-01.js]
[test_conditional_breakpoint-02.js]
[test_conditional_breakpoint-03.js]

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

@ -5,12 +5,24 @@
"use strict";
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
const {
arg,
DebuggerClient,
} = require("devtools/shared/client/debugger-client");
const eventSource = require("devtools/shared/client/event-source");
const {ThreadStateTypes} = require("devtools/shared/client/constants");
const { ThreadStateTypes } = require("devtools/shared/client/constants");
loader.lazyRequireGetter(this, "ObjectClient", "devtools/shared/client/object-client");
loader.lazyRequireGetter(this, "SourceFront", "devtools/shared/fronts/source", true);
loader.lazyRequireGetter(
this,
"ObjectClient",
"devtools/shared/client/object-client"
);
loader.lazyRequireGetter(
this,
"SourceFront",
"devtools/shared/fronts/source",
true
);
/**
* Creates a thread client for the remote debugging protocol server. This client
@ -50,7 +62,9 @@ ThreadClient.prototype = {
_assertPaused: function(command) {
if (!this.paused) {
throw Error(command + " command sent while not paused. Currently " + this._state);
throw Error(
command + " command sent while not paused. Currently " + this._state
);
}
},
@ -67,11 +81,13 @@ ThreadClient.prototype = {
* than proceeding forwards. This parameter has no effect if the
* server does not support rewinding.
*/
_doResume: DebuggerClient.requester({
_doResume: DebuggerClient.requester(
{
type: "resume",
resumeLimit: arg(0),
rewind: arg(1),
}, {
},
{
before: function(packet) {
this._assertPaused("resume");
@ -96,7 +112,8 @@ ThreadClient.prototype = {
delete this._previousState;
return response;
},
}),
}
),
/**
* Reconfigure the thread actor.
@ -214,14 +231,17 @@ ThreadClient.prototype = {
/**
* Detach from the thread actor.
*/
detach: DebuggerClient.requester({
detach: DebuggerClient.requester(
{
type: "detach",
}, {
},
{
after: function(response) {
this.client.unregisterClient(this);
return response;
},
}),
}
),
/**
* Promote multiple pause-lifetime object actors to thread-lifetime ones.

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

@ -3291,11 +3291,7 @@ CORSMode Element::AttrValueToCORSMode(const nsAttrValue* aValue) {
}
static const char* GetFullscreenError(CallerType aCallerType) {
if (!nsContentUtils::IsRequestFullscreenAllowed(aCallerType)) {
return "FullscreenDeniedNotInputDriven";
}
return nullptr;
return nsContentUtils::CheckRequestFullscreenAllowed(aCallerType);
}
already_AddRefed<Promise> Element::RequestFullscreen(CallerType aCallerType,

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

@ -6581,24 +6581,36 @@ bool nsContentUtils::ChannelShouldInheritPrincipal(
}
/* static */
bool nsContentUtils::IsRequestFullscreenAllowed(CallerType aCallerType) {
// If more time has elapsed since the user input than is specified by the
// dom.event.handling-user-input-time-limit pref (default 1 second), this
// function also returns false.
const char* nsContentUtils::CheckRequestFullscreenAllowed(
CallerType aCallerType) {
if (!StaticPrefs::full_screen_api_allow_trusted_requests_only() ||
aCallerType == CallerType::System) {
return true;
return nullptr;
}
if (EventStateManager::IsHandlingUserInput()) {
if (!EventStateManager::IsHandlingUserInput()) {
return "FullscreenDeniedNotInputDriven";
}
// If more time has elapsed since the user input than is specified by the
// dom.event.handling-user-input-time-limit pref (default 1 second),
// disallow fullscreen
TimeDuration timeout = HandlingUserInputTimeout();
return timeout <= TimeDuration(nullptr) ||
(TimeStamp::Now() - EventStateManager::GetHandlingInputStart()) <=
timeout;
if (timeout > TimeDuration(nullptr) &&
(TimeStamp::Now() - EventStateManager::GetHandlingInputStart()) >
timeout) {
return "FullscreenDeniedNotInputDriven";
}
return false;
// Entering full-screen on mouse mouse event is only allowed with left mouse
// button
if (StaticPrefs::full_screen_api_mouse_event_allow_left_button_only() &&
(EventStateManager::sCurrentMouseBtn == MouseButton::eMiddle ||
EventStateManager::sCurrentMouseBtn == MouseButton::eRight)) {
return "FullscreenDeniedMouseEventOnlyLeftBtn";
}
return nullptr;
}
/* static */

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

@ -2332,12 +2332,14 @@ class nsContentUtils {
static bool IsFocusedContent(const nsIContent* aContent);
/**
* Returns true if requests for fullscreen are allowed in the current
* Returns nullptr if requests for fullscreen are allowed in the current
* context. Requests are only allowed if the user initiated them (like with
* a mouse-click or key press), unless this check has been disabled by
* setting the pref "full-screen-api.allow-trusted-requests-only" to false.
* If fullscreen is not allowed, a key for the error message is returned.
*/
static bool IsRequestFullscreenAllowed(mozilla::dom::CallerType aCallerType);
static const char* CheckRequestFullscreenAllowed(
mozilla::dom::CallerType aCallerType);
/**
* Returns true if calling execCommand with 'cut' or 'copy' arguments is

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

@ -179,6 +179,25 @@ class EncodingScope {
bool EncodingScope::IsLimited() const { return mSelection || mRange || mNode; }
struct RangeBoundaryPathsAndOffsets {
using ContainerPath = AutoTArray<nsIContent*, 8>;
using ContainerOffsets = AutoTArray<int32_t, 8>;
// The first node is the range's boundary node, the following ones the
// ancestors.
ContainerPath mStartContainerPath;
// The first offset represents where at the boundary node the range starts.
// Each other offset is the index of the child relative to its parent.
ContainerOffsets mStartContainerOffsets;
// The first node is the range's boundary node, the following one the
// ancestors.
ContainerPath mEndContainerPath;
// The first offset represents where at the boundary node the range ends.
// Each other offset is the index of the child relative to its parent.
ContainerOffsets mEndContainerOffsets;
};
class nsDocumentEncoder : public nsIDocumentEncoder {
public:
nsDocumentEncoder();
@ -263,7 +282,7 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
virtual bool IncludeInContext(nsINode* aNode);
void Clear();
void ReleaseDocumentReferenceAndInitialize(bool aClearCachedSerializer);
class MOZ_STACK_CLASS AutoReleaseDocumentIfNeeded final {
public:
@ -272,7 +291,8 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
~AutoReleaseDocumentIfNeeded() {
if (mEncoder->mFlags & RequiresReinitAfterOutput) {
mEncoder->Clear();
const bool clearCachedSerializer = false;
mEncoder->ReleaseDocumentReferenceAndInitialize(clearCachedSerializer);
}
}
@ -296,10 +316,7 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
int32_t mStartRootIndex;
int32_t mEndRootIndex;
AutoTArray<nsINode*, 8> mCommonAncestors;
AutoTArray<nsIContent*, 8> mStartNodes;
AutoTArray<int32_t, 8> mStartOffsets;
AutoTArray<nsIContent*, 8> mEndNodes;
AutoTArray<int32_t, 8> mEndOffsets;
RangeBoundaryPathsAndOffsets mRangeBoundaryPathsAndOffsets;
AutoTArray<AutoTArray<nsINode*, 8>, 8> mRangeContexts;
// Whether the serializer cares about being notified to scan elements to
// keep track of whether they are preformatted. This stores the out
@ -314,7 +331,8 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
};
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocumentEncoder)
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsDocumentEncoder, Clear())
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(
nsDocumentEncoder, ReleaseDocumentReferenceAndInitialize(true))
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocumentEncoder)
NS_INTERFACE_MAP_ENTRY(nsIDocumentEncoder)
@ -342,6 +360,9 @@ void nsDocumentEncoder::Initialize(bool aClearCachedSerializer) {
mHaltRangeHint = false;
mDisableContextSerialize = false;
mEncodingScope = {};
mCommonParent = nullptr;
mNodeFixup = nullptr;
mRangeBoundaryPathsAndOffsets = {};
if (aClearCachedSerializer) {
mSerializer = nullptr;
}
@ -771,13 +792,18 @@ nsresult nsDocumentEncoder::SerializeRangeNodes(nsRange* const aRange,
// get start and end nodes for this recursion level
nsCOMPtr<nsIContent> startNode, endNode;
{
auto& startContainerPath =
mRangeBoundaryPathsAndOffsets.mStartContainerPath;
auto& endContainerPath = mRangeBoundaryPathsAndOffsets.mEndContainerPath;
int32_t start = mStartRootIndex - aDepth;
if (start >= 0 && (uint32_t)start <= mStartNodes.Length())
startNode = mStartNodes[start];
if (start >= 0 && (uint32_t)start <= startContainerPath.Length()) {
startNode = startContainerPath[start];
}
int32_t end = mEndRootIndex - aDepth;
if (end >= 0 && (uint32_t)end <= mEndNodes.Length())
endNode = mEndNodes[end];
if (end >= 0 && (uint32_t)end <= endContainerPath.Length()) {
endNode = endContainerPath[end];
}
}
if (startNode != content && endNode != content) {
@ -816,13 +842,19 @@ nsresult nsDocumentEncoder::SerializeRangeNodes(nsRange* const aRange,
NS_ENSURE_SUCCESS(rv, rv);
}
const auto& startContainerOffsets =
mRangeBoundaryPathsAndOffsets.mStartContainerOffsets;
const auto& endContainerOffsets =
mRangeBoundaryPathsAndOffsets.mEndContainerOffsets;
// do some calculations that will tell us which children of this
// node are in the range.
int32_t startOffset = 0, endOffset = -1;
if (startNode == content && mStartRootIndex >= aDepth)
startOffset = mStartOffsets[mStartRootIndex - aDepth];
if (endNode == content && mEndRootIndex >= aDepth)
endOffset = mEndOffsets[mEndRootIndex - aDepth];
if (startNode == content && mStartRootIndex >= aDepth) {
startOffset = startContainerOffsets[mStartRootIndex - aDepth];
}
if (endNode == content && mEndRootIndex >= aDepth) {
endOffset = endContainerOffsets[mEndRootIndex - aDepth];
}
// generated content will cause offset values of -1 to be returned.
uint32_t childCount = content->GetChildCount();
@ -944,20 +976,24 @@ nsresult nsDocumentEncoder::SerializeRangeToString(nsRange* aRange,
mStartDepth = mEndDepth = 0;
mCommonAncestors.Clear();
mStartNodes.Clear();
mStartOffsets.Clear();
mEndNodes.Clear();
mEndOffsets.Clear();
mRangeBoundaryPathsAndOffsets = {};
auto& startContainerPath = mRangeBoundaryPathsAndOffsets.mStartContainerPath;
auto& startContainerOffsets =
mRangeBoundaryPathsAndOffsets.mStartContainerOffsets;
auto& endContainerPath = mRangeBoundaryPathsAndOffsets.mEndContainerPath;
auto& endContainerOffsets =
mRangeBoundaryPathsAndOffsets.mEndContainerOffsets;
nsContentUtils::GetAncestors(mCommonParent, mCommonAncestors);
nsContentUtils::GetAncestorsAndOffsets(startContainer, startOffset,
&mStartNodes, &mStartOffsets);
nsContentUtils::GetAncestorsAndOffsets(endContainer, endOffset, &mEndNodes,
&mEndOffsets);
nsContentUtils::GetAncestorsAndOffsets(
startContainer, startOffset, &startContainerPath, &startContainerOffsets);
nsContentUtils::GetAncestorsAndOffsets(
endContainer, endOffset, &endContainerPath, &endContainerOffsets);
nsCOMPtr<nsIContent> commonContent = do_QueryInterface(mCommonParent);
mStartRootIndex = mStartNodes.IndexOf(commonContent);
mEndRootIndex = mEndNodes.IndexOf(commonContent);
mStartRootIndex = startContainerPath.IndexOf(commonContent);
mEndRootIndex = endContainerPath.IndexOf(commonContent);
nsresult rv = NS_OK;
@ -991,12 +1027,11 @@ nsresult nsDocumentEncoder::SerializeRangeToString(nsRange* aRange,
return rv;
}
void nsDocumentEncoder::Clear() {
void nsDocumentEncoder::ReleaseDocumentReferenceAndInitialize(
bool aClearCachedSerializer) {
mDocument = nullptr;
mCommonParent = nullptr;
mNodeFixup = nullptr;
Initialize(false);
Initialize(aClearCachedSerializer);
}
NS_IMETHODIMP

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

@ -231,6 +231,7 @@ interface nsIDocumentEncoder : nsISupports
/**
* Initialize with a pointer to the document and the mime type.
* Resets wrap column to 72 and resets node fixup.
* @param aDocument Document to encode.
* @param aMimeType MimeType to use. May also be set by SetMimeType.
* @param aFlags Flags to use while encoding. May also be set by SetFlags.

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

@ -396,7 +396,7 @@ partial namespace ChromeUtils {
void resetLastExternalProtocolIframeAllowed();
[ChromeOnly, Throws]
void registerWindowActor(DOMString aName, WindowActorOptions aOptions);
void registerWindowActor(DOMString aName, optional WindowActorOptions aOptions);
[ChromeOnly]
void unregisterWindowActor(DOMString aName);
@ -621,13 +621,13 @@ dictionary WindowActorOptions {
sequence<DOMString> remoteTypes;
/** This fields are used for configuring individual sides of the actor. */
required WindowActorSidedOptions parent;
required WindowActorChildOptions child;
WindowActorSidedOptions parent = null;
WindowActorChildOptions child = null;
};
dictionary WindowActorSidedOptions {
/** The module path which should be loaded for the actor on this side. */
required ByteString moduleURI;
ByteString moduleURI;
};
dictionary WindowActorChildOptions : WindowActorSidedOptions {

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

@ -197,6 +197,7 @@ static uint32_t sESMInstanceCount = 0;
int32_t EventStateManager::sUserInputEventDepth = 0;
int32_t EventStateManager::sUserKeyboardEventDepth = 0;
bool EventStateManager::sNormalLMouseEventInProcess = false;
int16_t EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
EventStateManager* EventStateManager::sActiveESM = nullptr;
Document* EventStateManager::sMouseOverDocument = nullptr;
AutoWeakFrame EventStateManager::sLastDragOverFrame = nullptr;
@ -6280,6 +6281,12 @@ AutoHandlingUserInputStatePusher::AutoHandlingUserInputStatePusher(
mMouseButtonEventHandlingDocument =
fm->SetMouseButtonHandlingDocument(aDocument);
}
if (NeedsToUpdateCurrentMouseBtnState()) {
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
if (mouseEvent) {
EventStateManager::sCurrentMouseBtn = mouseEvent->mButton;
}
}
}
AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher() {
@ -6296,6 +6303,9 @@ AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher() {
nsCOMPtr<Document> handlingDocument =
fm->SetMouseButtonHandlingDocument(mMouseButtonEventHandlingDocument);
}
if (NeedsToUpdateCurrentMouseBtnState()) {
EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
}
}
} // namespace mozilla

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

@ -1262,6 +1262,7 @@ class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
static int32_t sUserKeyboardEventDepth;
static bool sNormalLMouseEventInProcess;
static int16_t sCurrentMouseBtn;
static EventStateManager* sActiveESM;
@ -1298,6 +1299,11 @@ class MOZ_RAII AutoHandlingUserInputStatePusher final {
bool NeedsToResetFocusManagerMouseButtonHandlingState() const {
return mMessage == eMouseDown || mMessage == eMouseUp;
}
bool NeedsToUpdateCurrentMouseBtnState() const {
return mMessage == eMouseDown || mMessage == eMouseUp ||
mMessage == ePointerDown || mMessage == ePointerUp;
}
};
} // namespace mozilla

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

@ -112,14 +112,49 @@ function testLongRunningEventHandler() {
addFullscreenErrorContinuation(() => {
ok(!document.fullscreenElement,
"Should not grant request in long-running event handler.");
// Restore the pref environment we changed before
// entering testNonTrustContext.
SpecialPowers.popPrefEnv(finish);
SimpleTest.executeSoon(testFullscreenMouseBtn);
});
window.addEventListener("keypress", longRunningHandler);
sendString("a");
}
function requestFullscreenMouseBtn(event, button) {
let clickEl = document.createElement("p");
clickEl.innerText = "Click Me";
function eventHandler(event) {
document.body.requestFullscreen();
event.target.removeEventListener(event, this);
}
clickEl.addEventListener(event, eventHandler);
document.body.appendChild(clickEl);
synthesizeMouseAtCenter(clickEl, { button });
}
async function testFullscreenMouseBtn(event, button, next) {
await SpecialPowers.pushPrefEnv({
"set": [["full-screen-api.mouse-event-allow-left-button-only", true]]
});
let fsRequestEvents = ["mousedown", "mouseup", "pointerdown", "pointerup"];
let mouseButtons = [1, 2];
for (let i = 0; i < fsRequestEvents.length; i++) {
let event = fsRequestEvents[i];
for (let j = 0; j < mouseButtons.length; j++) {
let mouseButton = mouseButtons[j];
let fsDenied = addFullscreenErrorContinuation();
requestFullscreenMouseBtn(event, mouseButton);
await fsDenied;
ok(!document.fullscreenElement, `Should not grant request on '${event}' triggered by mouse button ${mouseButton}`);
}
}
// Restore the pref environment we changed before
// entering testNonTrustContext.
await SpecialPowers.popPrefEnv();
finish();
}
function finish() {
opener.nextTest();
}

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

@ -72,12 +72,19 @@ function addFullscreenChangeContinuation(type, callback, inDoc) {
// Calls |callback| when the next fullscreenerror is dispatched to inDoc||document.
function addFullscreenErrorContinuation(callback, inDoc) {
var doc = inDoc || document;
var listener = function(event) {
return new Promise((resolve) => {
let doc = inDoc || document;
let listener = function(event) {
doc.removeEventListener("fullscreenerror", listener);
setTimeout(function(){callback(event);}, 0);
setTimeout(function(){
if(callback) {
callback(event);
}
resolve();
}, 0);
};
doc.addEventListener("fullscreenerror", listener);
})
}
// Waits until the window has both the load event and a MozAfterPaint called on

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

@ -47,7 +47,7 @@ JSWindowActorProtocol::FromIPC(const JSWindowActorInfo& aInfo) {
proto->mAllFrames = aInfo.allFrames();
proto->mMatches = aInfo.matches();
proto->mRemoteTypes = aInfo.remoteTypes();
proto->mChild.mModuleURI.Assign(aInfo.url());
proto->mChild.mModuleURI = aInfo.url();
proto->mChild.mEvents.SetCapacity(aInfo.events().Length());
for (auto& ipc : aInfo.events()) {
@ -111,8 +111,13 @@ JSWindowActorProtocol::FromWebIDLOptions(const nsAString& aName,
proto->mRemoteTypes = aOptions.mRemoteTypes.Value();
}
proto->mParent.mModuleURI = aOptions.mParent.mModuleURI;
proto->mChild.mModuleURI = aOptions.mChild.mModuleURI;
if (aOptions.mParent.mModuleURI.WasPassed()) {
proto->mParent.mModuleURI.emplace(aOptions.mParent.mModuleURI.Value());
}
if (aOptions.mChild.mModuleURI.WasPassed()) {
proto->mChild.mModuleURI.emplace(aOptions.mChild.mModuleURI.Value());
}
// For each event declared in the source dictionary, initialize the
// corresponding envent declaration entry in the JSWindowActorProtocol.

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

@ -51,7 +51,7 @@ class JSWindowActorProtocol final : public nsIObserver,
ErrorResult& aRv);
struct Sided {
nsCString mModuleURI;
Maybe<nsCString> mModuleURI;
};
struct ParentSide : public Sided {};

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

@ -227,7 +227,7 @@ struct JSWindowActorInfo
{
nsString name;
bool allFrames;
nsCString url;
nsCString? url;
JSWindowActorEventDecl[] events;
nsCString[] observers;

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

@ -9,6 +9,8 @@
#include "mozJSComponentLoader.h"
#include "mozilla/Logging.h"
#include "mozilla/dom/JSWindowActorService.h"
#include "mozilla/dom/JSWindowActorParent.h"
#include "mozilla/dom/JSWindowActorChild.h"
namespace mozilla {
namespace dom {
@ -57,7 +59,28 @@ void WindowGlobalActor::ConstructActor(const nsAString& aName,
side = &proto->Child();
}
aRv = loader->Import(cx, side->mModuleURI, &global, &exports);
// Support basic functionally such as SendAsyncMessage and SendQuery for
// unspecified moduleURI.
if (!side->mModuleURI) {
RefPtr<JSWindowActor> actor;
if (actorType == JSWindowActor::Type::Parent) {
actor = new JSWindowActorParent();
} else {
actor = new JSWindowActorChild();
}
JS::Rooted<JS::Value> wrapper(cx);
if (!ToJSValue(cx, actor, &wrapper)) {
aRv.NoteJSContextException(cx);
return;
}
MOZ_ASSERT(wrapper.isObject());
aActor.set(&wrapper.toObject());
return;
}
aRv = loader->Import(cx, side->mModuleURI.ref(), &global, &exports);
if (aRv.Failed()) {
return;
}

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

@ -63,6 +63,7 @@ FullscreenDeniedFocusedPlugin=Request for fullscreen was denied because a window
FullscreenDeniedHidden=Request for fullscreen was denied because the document is no longer visible.
FullscreenDeniedContainerNotAllowed=Request for fullscreen was denied because at least one of the documents containing elements is not an iframe or does not have an “allowfullscreen” attribute.
FullscreenDeniedNotInputDriven=Request for fullscreen was denied because Element.requestFullscreen() was not called from inside a short running user-generated event handler.
FullscreenDeniedMouseEventOnlyLeftBtn=Request for fullscreen was denied because Element.requestFullscreen() was called from inside a mouse event handler not triggered by left mouse button.
FullscreenDeniedNotHTMLSVGOrMathML=Request for fullscreen was denied because requesting element is not <svg>, <math>, or an HTML element.
FullscreenDeniedNotInDocument=Request for fullscreen was denied because requesting element is no longer in its document.
FullscreenDeniedMovedDocument=Request for fullscreen was denied because requesting element has moved document.

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

@ -758,7 +758,8 @@ void DecodedStream::SendVideo(bool aIsSameOrigin,
for (uint32_t i = 0; i < video.Length(); ++i) {
VideoData* v = video[i];
TimeUnit lastStart = mData->mLastVideoStartTime.valueOr(mStartTime.ref());
TimeUnit lastStart = mData->mLastVideoStartTime.valueOr(
mStartTime.ref() - TimeUnit::FromMicroseconds(1));
TimeUnit lastEnd = mData->mLastVideoEndTime.valueOr(mStartTime.ref());
if (lastEnd < v->mTime) {
@ -777,7 +778,10 @@ void DecodedStream::SendVideo(bool aIsSameOrigin,
mData->WriteVideoToSegment(mData->mLastVideoImage, lastEnd, v->mTime,
mData->mLastVideoImageDisplaySize, t, &output,
aPrincipalHandle);
} else if (lastStart < v->mTime) {
lastEnd = v->mTime;
}
if (lastStart < v->mTime) {
// This frame starts after the last frame's start. Note that this could be
// before the last frame's end time for some videos. This only matters for
// the track's lifetime in the MSG, as rendering is based on timestamps,

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

@ -278,7 +278,7 @@ var gPlayTests = [
{ name:"test-7-6.1.opus", type:"audio/ogg; codecs=opus", duration:11.690 },
{ name:"test-8-7.1.opus", type:"audio/ogg; codecs=opus", duration:13.478 },
{ name:"gizmo-short.mp4", type:"video/mp4", duration:0.27 },
{ name:"gizmo-short.mp4", type:"video/mp4", duration:0.27, contentDuration:0.267 },
// Test playback of a MP4 file with a non-zero start time (and audio starting
// a second later).
{ name:"bipbop-lateaudio.mp4", type:"video/mp4" },

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

@ -78,6 +78,14 @@ already_AddRefed<MessageChannel> MessageChannel::Constructor(
channel->mPort1->UnshippedEntangle(channel->mPort2);
channel->mPort2->UnshippedEntangle(channel->mPort1);
// MessagePorts should not work if created from a disconnected window.
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
if (window && !window->GetDocShell()) {
// The 2 ports are entangled. We can close one of them to close the other
// too.
channel->mPort1->CloseForced();
}
return channel.forget();
}

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

@ -29,3 +29,4 @@ skip-if = (os == "win" && processor == "aarch64") #bug 1535784
[test_messageChannel_bug1178076.html]
[test_messageChannel_bug1224825.html]
[test_messageChannel_worker_forceClose.html]
[test_removedWindow.html]

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

@ -0,0 +1,55 @@
<!DOCTYPE html>
<title>MessagePort should not work when created from a disconnected window</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<body>
<script>
"use strict";
SimpleTest.waitForExplicitFinish();
runTest();
async function runTest() {
let ifr = document.createElement('iframe');
await new Promise(resolve => {
ifr.onload = resolve;
ifr.src = 'support/empty.html';
document.body.appendChild(ifr);
});
let w = ifr.contentWindow;
let pre = new w.MessageChannel();
ok(!!pre, "We have a channel");
ifr.remove();
let post = new w.MessageChannel();
ok(!!post, "We have a channel");
// This should silently fail.
pre.port1.postMessage(42);
pre.port2.onmessage = e => {
ok(false, "No messages should be received!");
}
// This should silently fail.
post.port1.postMessage(42);
post.port2.onmessage = e => {
ok(false, "No messages should be received!");
}
// Let's use another MessagePort just to be sure no messages are received by
// port2.
let mc = new MessageChannel();
mc.port1.postMessage(42);
mc.port2.onmessage = e => {
ok(true, "Ready to complete the test");
SimpleTest.finish();
}
}
</script>
</body>

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

@ -771,7 +771,7 @@ struct RealmStats {
MACRO(Other, MallocHeap, baselineData) \
MACRO(Other, MallocHeap, baselineStubsFallback) \
MACRO(Other, MallocHeap, ionData) \
MACRO(Other, MallocHeap, typeInferenceTypeScripts) \
MACRO(Other, MallocHeap, jitScripts) \
MACRO(Other, MallocHeap, typeInferenceAllocationSiteTables) \
MACRO(Other, MallocHeap, typeInferenceArrayTypeTables) \
MACRO(Other, MallocHeap, typeInferenceObjectTypeTables) \

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

@ -2531,7 +2531,7 @@ void GCRuntime::sweepTypesAfterCompacting(Zone* zone) {
for (auto script = zone->cellIterUnsafe<JSScript>(); !script.done();
script.next()) {
AutoSweepTypeScript sweep(script);
AutoSweepJitScript sweep(script);
}
for (auto group = zone->cellIterUnsafe<ObjectGroup>(); !group.done();
group.next()) {
@ -5916,7 +5916,7 @@ static void SweepThing(Shape* shape) {
}
}
static void SweepThing(JSScript* script) { AutoSweepTypeScript sweep(script); }
static void SweepThing(JSScript* script) { AutoSweepJitScript sweep(script); }
static void SweepThing(ObjectGroup* group) {
AutoSweepObjectGroup sweep(group);
@ -8102,7 +8102,7 @@ void GCRuntime::mergeRealms(Realm* source, Realm* target) {
script.next()) {
MOZ_ASSERT(script->realm() == source);
script->realm_ = target;
MOZ_ASSERT(!script->types());
MOZ_ASSERT(!script->jitScript());
}
GlobalObject* global = target->maybeGlobal();

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

@ -16,8 +16,9 @@
namespace js {
namespace gc {
// Mark colors to pass to markIfUnmarked.
enum class MarkColor : uint32_t { Black = 0, Gray };
// Mark colors. Order is important here: the greater value the 'more marked' a
// cell is.
enum class MarkColor : uint8_t { Gray = 1, Black = 2 };
// The phases of an incremental GC.
#define GCSTATES(D) \

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

@ -17,9 +17,12 @@ namespace js {
namespace gc {
// Like gc::MarkColor but allows the possibility of the cell being
// unmarked. Order is important here, with white being 'least marked'
// and black being 'most marked'.
enum class CellColor : uint8_t { White = 0, Gray = 1, Black = 2 };
// unmarked.
enum class CellColor : uint8_t {
White = 0,
Gray = uint8_t(MarkColor::Gray),
Black = uint8_t(MarkColor::Black)
};
static constexpr CellColor AllCellColors[] = {
CellColor::White, CellColor::Gray, CellColor::Black

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

@ -207,16 +207,16 @@ void Zone::discardJitCode(FreeOp* fop,
if (discardBaselineCode || releaseTypes) {
#ifdef DEBUG
// Assert no TypeScripts are marked as active.
// Assert no JitScripts are marked as active.
for (auto script = cellIter<JSScript>(); !script.done(); script.next()) {
if (TypeScript* types = script.unbarrieredGet()->types()) {
MOZ_ASSERT(!types->active());
if (JitScript* jitScript = script.unbarrieredGet()->jitScript()) {
MOZ_ASSERT(!jitScript->active());
}
}
#endif
// Mark TypeScripts on the stack as active.
jit::MarkActiveTypeScripts(this);
// Mark JitScripts on the stack as active.
jit::MarkActiveJitScripts(this);
}
// Invalidate all Ion code in this zone.
@ -228,7 +228,7 @@ void Zone::discardJitCode(FreeOp* fop,
// Discard baseline script if it's not marked as active.
if (discardBaselineCode && script->hasBaselineScript()) {
if (script->types()->active()) {
if (script->jitScript()->active()) {
// ICs will be purged so the script will need to warm back up before it
// can be inlined during Ion compilation.
script->baselineScript()->clearIonCompiledOrInlined();
@ -248,24 +248,22 @@ void Zone::discardJitCode(FreeOp* fop,
script->baselineScript()->setControlFlowGraph(nullptr);
}
// Try to release the script's TypeScript. This should happen after
// Try to release the script's JitScript. This should happen after
// releasing JIT code because we can't do this when the script still has
// JIT code.
if (releaseTypes) {
script->maybeReleaseTypes();
script->maybeReleaseJitScript();
}
// The optimizedStubSpace will be purged below so make sure ICScript
// doesn't point into it. We do this after (potentially) releasing types
// because TypeScript contains the ICScript* and there's no need to
// purge stubs if we just destroyed the Typescript.
if (discardBaselineCode && script->hasICScript()) {
script->icScript()->purgeOptimizedStubs(script);
if (JitScript* jitScript = script->jitScript()) {
// If we did not release the JitScript, we need to purge optimized IC
// stubs because the optimizedStubSpace will be purged below.
if (discardBaselineCode) {
jitScript->purgeOptimizedStubs(script);
}
// Finally, reset the active flag.
if (TypeScript* types = script->types()) {
types->resetActive();
jitScript->resetActive();
}
}
@ -527,10 +525,11 @@ void MemoryTracker::adopt(MemoryTracker& other) {
static const char* MemoryUseName(MemoryUse use) {
switch (use) {
#define DEFINE_CASE(Name) \
case MemoryUse::Name: return #Name;
JS_FOR_EACH_MEMORY_USE(DEFINE_CASE)
#undef DEFINE_CASE
# define DEFINE_CASE(Name) \
case MemoryUse::Name: \
return #Name;
JS_FOR_EACH_MEMORY_USE(DEFINE_CASE)
# undef DEFINE_CASE
}
MOZ_CRASH("Unknown memory use");
@ -551,8 +550,7 @@ MemoryTracker::~MemoryTracker() {
fprintf(stderr, "Missing calls to JS::RemoveAssociatedMemory:\n");
for (auto r = map.all(); !r.empty(); r.popFront()) {
fprintf(stderr, " %p 0x%zx %s\n", r.front().key().cell,
r.front().value(),
fprintf(stderr, " %p 0x%zx %s\n", r.front().key().cell, r.front().value(),
MemoryUseName(r.front().key().use));
}

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

@ -1073,7 +1073,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
const uint32_t pcOff = script->pcToOffset(pc);
BaselineScript* baselineScript = script->baselineScript();
ICScript* icScript = script->icScript();
JitScript* jitScript = script->jitScript();
#ifdef DEBUG
uint32_t expectedDepth;
@ -1136,7 +1136,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
// Not every monitored op has a monitored fallback stub, e.g.
// JSOP_NEWOBJECT, which always returns the same type for a
// particular script/pc location.
ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
if (fallbackStub->isMonitoredFallback()) {
enterMonitorChain = true;
@ -1153,7 +1153,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
builder.setResumeFramePtr(prevFramePtr);
if (enterMonitorChain) {
ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
MOZ_ASSERT(fallbackStub->isMonitoredFallback());
JitSpew(JitSpew_BaselineBailouts, " [TYPE-MONITOR CHAIN]");
@ -1337,7 +1337,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
// Calculate and write out return address.
// The icEntry in question MUST have an inlinable fallback stub.
ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
MOZ_ASSERT(IsInlinableFallback(icEntry.firstStub()->getChainFallback()));
RetAddrEntry& retAddrEntry =

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

@ -162,8 +162,8 @@ MethodStatus BaselineCompiler::compile() {
AutoTraceLog logScript(logger, scriptEvent);
AutoTraceLog logCompile(logger, TraceLogger_BaselineCompilation);
AutoKeepTypeScripts keepTypes(cx);
if (!script->ensureHasTypes(cx, keepTypes)) {
AutoKeepJitScripts keepJitScript(cx);
if (!script->ensureHasJitScript(cx, keepJitScript)) {
return Method_Error;
}
@ -542,8 +542,8 @@ bool BaselineCodeGen<Handler>::emitOutOfLinePostBarrierSlot() {
template <>
bool BaselineCompilerCodeGen::emitNextIC() {
// Emit a call to an IC stored in ICScript. Calls to this must match the
// ICEntry order in ICScript: first the non-op IC entries for |this| and
// Emit a call to an IC stored in JitScript. Calls to this must match the
// ICEntry order in JitScript: first the non-op IC entries for |this| and
// formal arguments, then the for-op IC entries for JOF_IC ops.
JSScript* script = handler.script();
@ -553,7 +553,7 @@ bool BaselineCompilerCodeGen::emitNextIC() {
// to loop until we find an ICEntry for the current pc.
const ICEntry* entry;
do {
entry = &script->icScript()->icEntry(handler.icEntryIndex());
entry = &script->jitScript()->icEntry(handler.icEntryIndex());
handler.moveToNextICEntry();
} while (entry->pcOffset() < pcOffset);
@ -1111,10 +1111,9 @@ void BaselineInterpreterCodeGen::emitInitFrameFields() {
masm.storePtr(scratch1, frame.addressOfInterpreterScript());
// Initialize interpreterICEntry.
masm.loadPtr(Address(scratch1, JSScript::offsetOfTypes()), scratch2);
masm.loadPtr(Address(scratch2, TypeScript::offsetOfICScript()), scratch2);
masm.computeEffectiveAddress(Address(scratch2, ICScript::offsetOfICEntries()),
scratch2);
masm.loadPtr(Address(scratch1, JSScript::offsetOfJitScript()), scratch2);
masm.computeEffectiveAddress(
Address(scratch2, JitScript::offsetOfICEntries()), scratch2);
masm.storePtr(scratch2, frame.addressOfInterpreterICEntry());
// Initialize interpreterPC.
@ -5897,7 +5896,7 @@ bool BaselineCodeGen<Handler>::emitGeneratorResume(
ValueOperand retVal = regs.takeAnyValue();
masm.loadValue(frame.addressOfStackValue(-1), retVal);
// Branch to interpret if the script does not have a TypeScript or
// Branch to interpret if the script does not have a JitScript or
// BaselineScript (depending on whether the Baseline Interpreter is enabled).
// Note that we don't relazify generator scripts, so the function is
// guaranteed to be non-lazy.
@ -5906,8 +5905,9 @@ bool BaselineCodeGen<Handler>::emitGeneratorResume(
masm.loadPtr(Address(callee, JSFunction::offsetOfScript()), scratch1);
Address baselineAddr(scratch1, JSScript::offsetOfBaselineScript());
if (JitOptions.baselineInterpreter) {
Address typesAddr(scratch1, JSScript::offsetOfTypes());
masm.branchPtr(Assembler::Equal, typesAddr, ImmPtr(nullptr), &interpret);
Address jitScriptAddr(scratch1, JSScript::offsetOfJitScript());
masm.branchPtr(Assembler::Equal, jitScriptAddr, ImmPtr(nullptr),
&interpret);
} else {
masm.branchPtr(Assembler::BelowOrEqual, baselineAddr,
ImmPtr(BASELINE_DISABLED_SCRIPT), &interpret);
@ -6126,7 +6126,7 @@ bool BaselineCodeGen<Handler>::emitGeneratorResume(
masm.implicitPop((fun.explicitStackSlots() + 1) * sizeof(void*));
}
// Call into the VM to run in the C++ interpreter if there's no TypeScript or
// Call into the VM to run in the C++ interpreter if there's no JitScript or
// BaselineScript.
masm.bind(&interpret);
@ -6264,10 +6264,9 @@ bool BaselineInterpreterCodeGen::emit_JSOP_JUMPTARGET() {
// Compute ICEntry* and store to frame->interpreterICEntry.
loadScript(scratch2);
masm.loadPtr(Address(scratch2, JSScript::offsetOfTypes()), scratch2);
masm.loadPtr(Address(scratch2, TypeScript::offsetOfICScript()), scratch2);
masm.loadPtr(Address(scratch2, JSScript::offsetOfJitScript()), scratch2);
masm.computeEffectiveAddress(
BaseIndex(scratch2, scratch1, TimesOne, ICScript::offsetOfICEntries()),
BaseIndex(scratch2, scratch1, TimesOne, JitScript::offsetOfICEntries()),
scratch2);
masm.storePtr(scratch2, frame.addressOfInterpreterICEntry());
return true;

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

@ -526,7 +526,7 @@ class BaselineCompilerHandler {
JSScript* script_;
jsbytecode* pc_;
// Index of the current ICEntry in the script's ICScript.
// Index of the current ICEntry in the script's JitScript.
uint32_t icEntryIndex_;
bool compileDebugInstrumentation_;

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

@ -615,7 +615,7 @@ static bool RecompileBaselineScriptForDebugMode(
script->filename(), script->lineno(), script->column(),
observing ? "DEBUGGING" : "NORMAL EXECUTION");
AutoKeepTypeScripts keepTypes(cx);
AutoKeepJitScripts keepJitScripts(cx);
script->setBaselineScript(cx->runtime(), nullptr);
MethodStatus status =

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

@ -110,9 +110,9 @@ bool BaselineFrame::pushVarEnvironment(JSContext* cx, HandleScope scope) {
void BaselineFrame::setInterpreterPC(jsbytecode* pc) {
uint32_t pcOffset = script()->pcToOffset(pc);
ICScript* icScript = script()->icScript();
JitScript* jitScript = script()->jitScript();
interpreterPC_ = pc;
interpreterICEntry_ = icScript->interpreterICEntryFromPCOffset(pcOffset);
interpreterICEntry_ = jitScript->interpreterICEntryFromPCOffset(pcOffset);
}
bool BaselineFrame::initForOsr(InterpreterFrame* fp, uint32_t numStackValues) {

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

@ -156,36 +156,25 @@ class MOZ_RAII FallbackStubAllocator {
}
};
/* static */
UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
} // namespace jit
bool JitScript::initICEntries(JSContext* cx, JSScript* script) {
MOZ_ASSERT(cx->realm()->jitRealm());
MOZ_ASSERT(jit::IsBaselineEnabled(cx));
const uint32_t numICEntries = script->numICEntries();
MOZ_ASSERT(numICEntries() == script->numICEntries());
// Allocate the ICScript.
UniquePtr<ICScript> icScript(
script->zone()->pod_malloc_with_extra<ICScript, ICEntry>(numICEntries));
if (!icScript) {
ReportOutOfMemory(cx);
return nullptr;
}
new (icScript.get()) ICScript(numICEntries);
// TODO(bug 1551796): move JitScript into jit namespace so we don't need this.
using namespace js::jit;
// We need to call prepareForDestruction on ICScript before we |delete| it.
auto prepareForDestruction = mozilla::MakeScopeExit(
[&] { icScript->prepareForDestruction(cx->zone()); });
FallbackStubAllocator alloc(cx, icScript->fallbackStubSpace_);
FallbackStubAllocator alloc(cx, fallbackStubSpace_);
// Index of the next ICEntry to initialize.
uint32_t icEntryIndex = 0;
using Kind = BaselineICFallbackKind;
ICScript* icScriptPtr = icScript.get();
auto addIC = [cx, icScriptPtr, &icEntryIndex, script](jsbytecode* pc,
ICStub* stub) {
auto addIC = [cx, this, &icEntryIndex, script](jsbytecode* pc, ICStub* stub) {
if (!stub) {
MOZ_ASSERT(cx->isExceptionPending());
mozilla::Unused << cx; // Silence -Wunused-lambda-capture in opt builds.
@ -194,7 +183,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
// Initialize the ICEntry.
uint32_t offset = pc ? script->pcToOffset(pc) : ICEntry::ProloguePCOffset;
ICEntry& entryRef = icScriptPtr->icEntry(icEntryIndex);
ICEntry& entryRef = icEntry(icEntryIndex);
icEntryIndex++;
new (&entryRef) ICEntry(stub, offset);
@ -215,14 +204,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
ICStub* stub =
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr, 0);
if (!addIC(nullptr, stub)) {
return nullptr;
return false;
}
for (size_t i = 0; i < fun->nargs(); i++) {
ICStub* stub = alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor,
nullptr, i + 1);
if (!addIC(nullptr, stub)) {
return nullptr;
return false;
}
}
}
@ -248,7 +237,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_IFNE: {
ICStub* stub = alloc.newStub<ICToBool_Fallback>(Kind::ToBool);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -258,7 +247,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_DEC: {
ICStub* stub = alloc.newStub<ICUnaryArith_Fallback>(Kind::UnaryArith);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -276,7 +265,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_POW: {
ICStub* stub = alloc.newStub<ICBinaryArith_Fallback>(Kind::BinaryArith);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -290,7 +279,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_STRICTNE: {
ICStub* stub = alloc.newStub<ICCompare_Fallback>(Kind::Compare);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -298,7 +287,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
ICStub* stub =
alloc.newStub<ICWarmUpCounter_Fallback>(Kind::WarmUpCounter);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -306,12 +295,12 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
ObjectGroup* group =
ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
if (!group) {
return nullptr;
return false;
}
ICStub* stub =
alloc.newStub<ICNewArray_Fallback>(Kind::NewArray, group);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -319,7 +308,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_NEWINIT: {
ICStub* stub = alloc.newStub<ICNewObject_Fallback>(Kind::NewObject);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -331,7 +320,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_STRICTSETELEM: {
ICStub* stub = alloc.newStub<ICSetElem_Fallback>(Kind::SetElem);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -347,7 +336,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_STRICTSETGNAME: {
ICStub* stub = alloc.newStub<ICSetProp_Fallback>(Kind::SetProp);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -357,14 +346,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_GETBOUNDNAME: {
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetProp);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
case JSOP_GETPROP_SUPER: {
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetPropSuper);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -372,28 +361,28 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_CALLELEM: {
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElem);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
case JSOP_GETELEM_SUPER: {
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElemSuper);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
case JSOP_IN: {
ICStub* stub = alloc.newStub<ICIn_Fallback>(Kind::In);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
case JSOP_HASOWN: {
ICStub* stub = alloc.newStub<ICHasOwn_Fallback>(Kind::HasOwn);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -401,7 +390,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_GETGNAME: {
ICStub* stub = alloc.newStub<ICGetName_Fallback>(Kind::GetName);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -409,7 +398,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_BINDGNAME: {
ICStub* stub = alloc.newStub<ICBindName_Fallback>(Kind::BindName);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -418,7 +407,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
ICStub* stub =
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -426,7 +415,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
ICStub* stub =
alloc.newStub<ICGetIntrinsic_Fallback>(Kind::GetIntrinsic);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -439,7 +428,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_STRICTEVAL: {
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::Call);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -447,7 +436,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_NEW: {
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::CallConstructing);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -456,7 +445,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_STRICTSPREADEVAL: {
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::SpreadCall);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -465,14 +454,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
ICStub* stub =
alloc.newStub<ICCall_Fallback>(Kind::SpreadCallConstructing);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
case JSOP_INSTANCEOF: {
ICStub* stub = alloc.newStub<ICInstanceOf_Fallback>(Kind::InstanceOf);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -480,14 +469,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
case JSOP_TYPEOFEXPR: {
ICStub* stub = alloc.newStub<ICTypeOf_Fallback>(Kind::TypeOf);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
case JSOP_ITER: {
ICStub* stub = alloc.newStub<ICGetIterator_Fallback>(Kind::GetIterator);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -496,12 +485,12 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
cx, nullptr, 0, TenuredObject,
ObjectGroup::NewArrayKind::UnknownIndex);
if (!templateObject) {
return nullptr;
return false;
}
ICStub* stub =
alloc.newStub<ICRest_Fallback>(Kind::Rest, templateObject);
if (!addIC(pc, stub)) {
return nullptr;
return false;
}
break;
}
@ -511,13 +500,13 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
}
// Assert all ICEntries have been initialized.
MOZ_ASSERT(icEntryIndex == numICEntries);
MOZ_ASSERT(icEntryIndex == numICEntries());
prepareForDestruction.release();
return icScript;
return true;
}
namespace jit {
ICStubConstIterator& ICStubConstIterator::operator++() {
MOZ_ASSERT(currentStub_ != nullptr);
currentStub_ = currentStub_->next();
@ -1098,7 +1087,7 @@ bool ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx,
JSScript* script) {
MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
ICStubSpace* space = script->icScript()->fallbackStubSpace();
ICStubSpace* space = script->jitScript()->fallbackStubSpace();
FallbackStubAllocator alloc(cx, *space);
auto* stub = alloc.newStub<ICTypeMonitor_Fallback>(
BaselineICFallbackKind::TypeMonitor, this);
@ -1127,9 +1116,9 @@ static MOZ_MUST_USE bool TypeMonitorResult(JSContext* cx,
BaselineFrame* frame,
HandleScript script, jsbytecode* pc,
HandleValue val) {
AutoSweepTypeScript sweep(script);
StackTypeSet* types = script->types()->bytecodeTypes(sweep, script, pc);
TypeScript::MonitorBytecodeType(cx, script, pc, types, val);
AutoSweepJitScript sweep(script);
StackTypeSet* types = script->jitScript()->bytecodeTypes(sweep, script, pc);
JitScript::MonitorBytecodeType(cx, script, pc, types, val);
return stub->addMonitorStubForValue(cx, frame, types, val);
}
@ -1152,7 +1141,7 @@ bool ICCacheIR_Updated::initUpdatingChain(JSContext* cx, ICStubSpace* space) {
ICStubSpace* ICStubCompiler::StubSpaceForStub(bool makesGCCalls,
JSScript* script) {
if (makesGCCalls) {
return script->icScript()->fallbackStubSpace();
return script->jitScript()->fallbackStubSpace();
}
return script->zone()->jitZone()->optimizedStubSpace();
}
@ -1297,15 +1286,19 @@ void ICStubCompilerBase::PushStubPayload(MacroAssembler& masm,
masm.adjustFrame(sizeof(intptr_t));
}
void ICScript::noteAccessedGetter(uint32_t pcOffset) {
ICEntry& entry = icEntryFromPCOffset(pcOffset);
ICFallbackStub* stub = entry.fallbackStub();
} // namespace jit
void JitScript::noteAccessedGetter(uint32_t pcOffset) {
jit::ICEntry& entry = icEntryFromPCOffset(pcOffset);
jit::ICFallbackStub* stub = entry.fallbackStub();
if (stub->isGetProp_Fallback()) {
stub->toGetProp_Fallback()->noteAccessedGetter();
}
}
namespace jit {
// TypeMonitor_Fallback
//
@ -1514,29 +1507,29 @@ bool DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame,
*GetNextPc(pc) == JSOP_CHECKTHISREINIT ||
*GetNextPc(pc) == JSOP_CHECKRETURN);
if (stub->monitorsThis()) {
TypeScript::MonitorThisType(cx, script, TypeSet::UnknownType());
JitScript::MonitorThisType(cx, script, TypeSet::UnknownType());
} else {
TypeScript::MonitorBytecodeType(cx, script, pc, TypeSet::UnknownType());
JitScript::MonitorBytecodeType(cx, script, pc, TypeSet::UnknownType());
}
return true;
}
TypeScript* typeScript = script->types();
AutoSweepTypeScript sweep(script);
JitScript* jitScript = script->jitScript();
AutoSweepJitScript sweep(script);
StackTypeSet* types;
uint32_t argument;
if (stub->monitorsArgument(&argument)) {
MOZ_ASSERT(pc == script->code());
types = typeScript->argTypes(sweep, script, argument);
TypeScript::MonitorArgType(cx, script, argument, value);
types = jitScript->argTypes(sweep, script, argument);
JitScript::MonitorArgType(cx, script, argument, value);
} else if (stub->monitorsThis()) {
MOZ_ASSERT(pc == script->code());
types = typeScript->thisTypes(sweep, script);
TypeScript::MonitorThisType(cx, script, value);
types = jitScript->thisTypes(sweep, script);
JitScript::MonitorThisType(cx, script, value);
} else {
types = typeScript->bytecodeTypes(sweep, script, pc);
TypeScript::MonitorBytecodeType(cx, script, pc, types, value);
types = jitScript->bytecodeTypes(sweep, script, pc);
JitScript::MonitorBytecodeType(cx, script, pc, types, value);
}
return stub->addMonitorStubForValue(cx, frame, types, value);
@ -2493,15 +2486,19 @@ bool FallbackICCodeCompiler::emit_SetElem() {
return tailCallVM<Fn, DoSetElemFallback>(masm);
}
void ICScript::noteHasDenseAdd(uint32_t pcOffset) {
ICEntry& entry = icEntryFromPCOffset(pcOffset);
ICFallbackStub* stub = entry.fallbackStub();
} // namespace jit
void JitScript::noteHasDenseAdd(uint32_t pcOffset) {
jit::ICEntry& entry = icEntryFromPCOffset(pcOffset);
jit::ICFallbackStub* stub = entry.fallbackStub();
if (stub->isSetElem_Fallback()) {
stub->toSetElem_Fallback()->noteHasDenseAdd();
}
}
namespace jit {
template <typename T>
void StoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
const ValueOperand& value, const T& dest,
@ -2779,7 +2776,7 @@ bool DoGetIntrinsicFallback(JSContext* cx, BaselineFrame* frame,
// needs to be monitored once. Attach a stub to load the resulting constant
// directly.
TypeScript::MonitorBytecodeType(cx, script, pc, res);
JitScript::MonitorBytecodeType(cx, script, pc, res);
TryAttachStub<GetIntrinsicIRGenerator>("GetIntrinsic", cx, frame, stub,
BaselineCacheIRStubKind::Regular, res);

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

@ -269,102 +269,6 @@ class ICEntry {
void trace(JSTracer* trc);
};
// [SMDOC] ICScript
//
// ICScript contains IC data used by Baseline (Ion has its own IC chains, stored
// in IonScript).
//
// For each IC we store an ICEntry, which points to the first ICStub in the
// chain. Note that multiple stubs in the same zone can share Baseline IC code.
// This works because the stub data is stored in the ICStub instead of baked in
// in the stub code.
//
// Storing this separate from BaselineScript simplifies debug mode OSR because
// the ICScript can be reused when we replace the BaselineScript. It also makes
// it easier to experiment with interpreter ICs in the future because the
// interpreter and Baseline JIT will be able to use exactly the same IC data.
//
// ICScript contains the following:
//
// * Fallback stub space: this stores all fallback stubs and the "can GC" stubs.
// These stubs are never purged before destroying the ICScript. (Other stubs
// are stored in the optimized stub space stored in JitZone and can be
// discarded more eagerly. See ICScript::purgeOptimizedStubs.)
//
// * List of IC entries, in the following order:
//
// - Type monitor IC for |this|.
// - Type monitor IC for each formal argument.
// - IC for each JOF_IC bytecode op.
//
// ICScript is stored in TypeScript and allocated/destroyed at the same time.
class ICScript {
// Allocated space for fallback stubs.
FallbackICStubSpace fallbackStubSpace_ = {};
uint32_t numICEntries_;
explicit ICScript(uint32_t numICEntries) : numICEntries_(numICEntries) {}
ICEntry* icEntryList() {
return (ICEntry*)(reinterpret_cast<uint8_t*>(this) + sizeof(ICScript));
}
public:
static MOZ_MUST_USE js::UniquePtr<ICScript> create(JSContext* cx,
JSScript* script);
~ICScript() {
// The contents of the fallback stub space are removed and freed
// separately after the next minor GC. See prepareForDestruction.
MOZ_ASSERT(fallbackStubSpace_.isEmpty());
}
void prepareForDestruction(Zone* zone) {
// When the script contains pointers to nursery things, the store buffer can
// contain entries that point into the fallback stub space. Since we can
// destroy scripts outside the context of a GC, this situation could result
// in us trying to mark invalid store buffer entries.
//
// Defer freeing any allocated blocks until after the next minor GC.
fallbackStubSpace_.freeAllAfterMinorGC(zone);
}
FallbackICStubSpace* fallbackStubSpace() { return &fallbackStubSpace_; }
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
size_t* fallbackStubs) const {
*data += mallocSizeOf(this);
// |data| already includes the ICStubSpace itself, so use
// sizeOfExcludingThis.
*fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
}
size_t numICEntries() const { return numICEntries_; }
ICEntry& icEntry(size_t index) {
MOZ_ASSERT(index < numICEntries());
return icEntryList()[index];
}
void noteAccessedGetter(uint32_t pcOffset);
void noteHasDenseAdd(uint32_t pcOffset);
void trace(JSTracer* trc);
void purgeOptimizedStubs(JSScript* script);
ICEntry* interpreterICEntryFromPCOffset(uint32_t pcOffset);
ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
ICEntry* prevLookedUpEntry);
ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
ICEntry& icEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry);
static constexpr size_t offsetOfICEntries() { return sizeof(ICScript); }
};
class ICMonitoredStub;
class ICMonitoredFallbackStub;

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

@ -127,7 +127,10 @@ static bool GetCacheIRReceiverForNativeSetSlot(ICCacheIR_Updated* stub,
return true;
}
ICScript* BaselineInspector::icScript() const { return script->icScript(); }
JitScript* BaselineInspector::jitScript() const {
MOZ_ASSERT(script->hasJitScript());
return script->jitScript();
}
ICEntry& BaselineInspector::icEntryFromPC(jsbytecode* pc) {
ICEntry* entry = maybeICEntryFromPC(pc);
@ -136,9 +139,8 @@ ICEntry& BaselineInspector::icEntryFromPC(jsbytecode* pc) {
}
ICEntry* BaselineInspector::maybeICEntryFromPC(jsbytecode* pc) {
MOZ_ASSERT(hasICScript());
MOZ_ASSERT(isValidPC(pc));
ICEntry* ent = icScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
ICEntry* ent = jitScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
prevLookedUpEntry);
if (!ent) {
return nullptr;
@ -156,10 +158,6 @@ bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc,
// uncacheable access.
MOZ_ASSERT(receivers.empty());
if (!hasICScript()) {
return true;
}
MOZ_ASSERT(isValidPC(pc));
const ICEntry& entry = icEntryFromPC(pc);
@ -203,10 +201,6 @@ bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc,
}
ICStub* BaselineInspector::monomorphicStub(jsbytecode* pc) {
if (!hasICScript()) {
return nullptr;
}
// IonBuilder::analyzeNewLoopTypes may call this (via expectedResultType
// below) on code that's unreachable, according to BytecodeAnalysis. Use
// maybeICEntryFromPC to handle this.
@ -227,10 +221,6 @@ ICStub* BaselineInspector::monomorphicStub(jsbytecode* pc) {
bool BaselineInspector::dimorphicStub(jsbytecode* pc, ICStub** pfirst,
ICStub** psecond) {
if (!hasICScript()) {
return false;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* stub = entry.firstStub();
@ -575,10 +565,6 @@ static bool TryToSpecializeBinaryArithOp(ICStub** stubs, uint32_t nstubs,
}
MIRType BaselineInspector::expectedBinaryArithSpecialization(jsbytecode* pc) {
if (!hasICScript()) {
return MIRType::None;
}
MIRType result;
ICStub* stubs[2];
@ -610,10 +596,6 @@ MIRType BaselineInspector::expectedBinaryArithSpecialization(jsbytecode* pc) {
}
bool BaselineInspector::hasSeenNonIntegerIndex(jsbytecode* pc) {
if (!hasICScript()) {
return false;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* stub = entry.fallbackStub();
@ -623,10 +605,6 @@ bool BaselineInspector::hasSeenNonIntegerIndex(jsbytecode* pc) {
}
bool BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode* pc) {
if (!hasICScript()) {
return false;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* stub = entry.fallbackStub();
@ -637,10 +615,6 @@ bool BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode* pc) {
}
bool BaselineInspector::hasSeenAccessedGetter(jsbytecode* pc) {
if (!hasICScript()) {
return false;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* stub = entry.fallbackStub();
@ -651,10 +625,6 @@ bool BaselineInspector::hasSeenAccessedGetter(jsbytecode* pc) {
}
bool BaselineInspector::hasSeenDoubleResult(jsbytecode* pc) {
if (!hasICScript()) {
return false;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* stub = entry.fallbackStub();
@ -720,10 +690,6 @@ JSObject* MaybeTemplateObject(ICStub* stub, MetaTwoByteKind kind,
}
JSObject* BaselineInspector::getTemplateObject(jsbytecode* pc) {
if (!hasICScript()) {
return nullptr;
}
const ICEntry& entry = icEntryFromPC(pc);
for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
switch (stub->kind()) {
@ -760,10 +726,6 @@ JSObject* BaselineInspector::getTemplateObject(jsbytecode* pc) {
}
ObjectGroup* BaselineInspector::getTemplateObjectGroup(jsbytecode* pc) {
if (!hasICScript()) {
return nullptr;
}
const ICEntry& entry = icEntryFromPC(pc);
for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
switch (stub->kind()) {
@ -780,10 +742,6 @@ ObjectGroup* BaselineInspector::getTemplateObjectGroup(jsbytecode* pc) {
JSFunction* BaselineInspector::getSingleCallee(jsbytecode* pc) {
MOZ_ASSERT(*pc == JSOP_NEW);
if (!hasICScript()) {
return nullptr;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* stub = entry.firstStub();
@ -815,10 +773,6 @@ JSFunction* BaselineInspector::getSingleCallee(jsbytecode* pc) {
JSObject* BaselineInspector::getTemplateObjectForNative(jsbytecode* pc,
Native native) {
if (!hasICScript()) {
return nullptr;
}
const ICEntry& entry = icEntryFromPC(pc);
for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
if (stub->isCall_Native() &&
@ -845,10 +799,6 @@ JSObject* BaselineInspector::getTemplateObjectForNative(jsbytecode* pc,
JSObject* BaselineInspector::getTemplateObjectForClassHook(jsbytecode* pc,
const Class* clasp) {
if (!hasICScript()) {
return nullptr;
}
const ICEntry& entry = icEntryFromPC(pc);
for (ICStub* stub = entry.firstStub(); stub; stub = stub->next()) {
if (stub->isCall_ClassHook() &&
@ -1204,10 +1154,6 @@ bool BaselineInspector::commonGetPropFunction(
jsbytecode* pc, jsid id, bool innerized, JSObject** holder,
Shape** holderShape, JSFunction** commonGetter, Shape** globalShape,
bool* isOwnProperty, ReceiverVector& receivers) {
if (!hasICScript()) {
return false;
}
MOZ_ASSERT(IsGetPropPC(pc) || IsGetElemPC(pc) || JSOp(*pc) == JSOP_GETGNAME);
MOZ_ASSERT(receivers.empty());
@ -1286,10 +1232,6 @@ static JSFunction* GetMegamorphicGetterSetterFunction(
bool BaselineInspector::megamorphicGetterSetterFunction(
jsbytecode* pc, jsid id, bool isGetter, JSFunction** getterOrSetter) {
if (!hasICScript()) {
return false;
}
MOZ_ASSERT(IsGetPropPC(pc) || IsGetElemPC(pc) || IsSetPropPC(pc) ||
JSOp(*pc) == JSOP_GETGNAME || JSOp(*pc) == JSOP_INITGLEXICAL ||
JSOp(*pc) == JSOP_INITPROP || JSOp(*pc) == JSOP_INITLOCKEDPROP ||
@ -1451,10 +1393,6 @@ bool BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder,
JSFunction** commonSetter,
bool* isOwnProperty,
ReceiverVector& receivers) {
if (!hasICScript()) {
return false;
}
MOZ_ASSERT(IsSetPropPC(pc) || JSOp(*pc) == JSOP_INITGLEXICAL ||
JSOp(*pc) == JSOP_INITPROP || JSOp(*pc) == JSOP_INITLOCKEDPROP ||
JSOp(*pc) == JSOP_INITHIDDENPROP);
@ -1551,10 +1489,6 @@ bool BaselineInspector::maybeInfoForProtoReadSlot(jsbytecode* pc,
MOZ_ASSERT(receivers.empty());
MOZ_ASSERT(!*holder);
if (!hasICScript()) {
return true;
}
MOZ_ASSERT(isValidPC(pc));
const ICEntry& entry = icEntryFromPC(pc);
@ -1614,10 +1548,6 @@ static MIRType GetCacheIRExpectedInputType(ICCacheIR_Monitored* stub) {
}
MIRType BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc) {
if (!hasICScript()) {
return MIRType::Value;
}
const ICEntry& entry = icEntryFromPC(pc);
MIRType type = MIRType::None;
@ -1653,9 +1583,6 @@ bool BaselineInspector::instanceOfData(jsbytecode* pc, Shape** shape,
uint32_t* slot,
JSObject** prototypeObject) {
MOZ_ASSERT(*pc == JSOP_INSTANCEOF);
if (!hasICScript()) {
return false;
}
const ICEntry& entry = icEntryFromPC(pc);
ICStub* firstStub = entry.firstStub();

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

@ -47,9 +47,7 @@ class BaselineInspector {
MOZ_ASSERT(script);
}
bool hasICScript() const { return script->hasICScript(); }
ICScript* icScript() const;
JitScript* jitScript() const;
private:
#ifdef DEBUG
@ -62,11 +60,8 @@ class BaselineInspector {
template <typename ICInspectorType>
ICInspectorType makeICInspector(jsbytecode* pc,
ICStub::Kind expectedFallbackKind) {
ICEntry* ent = nullptr;
if (hasICScript()) {
ent = &icEntryFromPC(pc);
ICEntry* ent = &icEntryFromPC(pc);
MOZ_ASSERT(ent->fallbackStub()->kind() == expectedFallbackKind);
}
return ICInspectorType(this, pc, ent);
}

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

@ -320,7 +320,7 @@ static MethodStatus CanEnterBaselineInterpreter(JSContext* cx,
MOZ_ASSERT(jit::IsBaselineEnabled(cx));
MOZ_ASSERT(JitOptions.baselineInterpreter);
if (script->types()) {
if (script->jitScript()) {
return Method_Compiled;
}
@ -338,8 +338,8 @@ static MethodStatus CanEnterBaselineInterpreter(JSContext* cx,
return Method_Error;
}
AutoKeepTypeScripts keepTypes(cx);
if (!script->ensureHasTypes(cx, keepTypes)) {
AutoKeepJitScripts keepJitScript(cx);
if (!script->ensureHasJitScript(cx, keepJitScript)) {
return Method_Error;
}
@ -517,7 +517,7 @@ void BaselineScript::trace(JSTracer* trc) {
TraceNullableEdge(trc, &templateEnv_, "baseline-template-environment");
}
void ICScript::trace(JSTracer* trc) {
void JitScript::trace(JSTracer* trc) {
// Mark all IC stub codes hanging off the IC stub entries.
for (size_t i = 0; i < numICEntries(); i++) {
ICEntry& ent = icEntry(i);
@ -620,12 +620,12 @@ CompactBufferReader BaselineScript::pcMappingReader(size_t indexEntry) {
}
struct ICEntries {
ICScript* const icScript_;
JitScript* const jitScript_;
explicit ICEntries(ICScript* icScript) : icScript_(icScript) {}
explicit ICEntries(JitScript* jitScript) : jitScript_(jitScript) {}
size_t numEntries() const { return icScript_->numICEntries(); }
ICEntry& operator[](size_t index) const { return icScript_->icEntry(index); }
size_t numEntries() const { return jitScript_->numICEntries(); }
ICEntry& operator[](size_t index) const { return jitScript_->icEntry(index); }
};
struct RetAddrEntries {
@ -712,7 +712,7 @@ uint8_t* BaselineScript::returnAddressForEntry(const RetAddrEntry& ent) {
return method()->raw() + ent.returnOffset().offset();
}
ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
ICEntry* JitScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
// This method ignores prologue IC entries. There can be at most one
// non-prologue IC per bytecode op.
@ -729,13 +729,13 @@ ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
return &entry;
}
ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset) {
ICEntry& JitScript::icEntryFromPCOffset(uint32_t pcOffset) {
ICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
MOZ_RELEASE_ASSERT(entry);
return *entry;
}
ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
ICEntry* JitScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
ICEntry* prevLookedUpEntry) {
// Do a linear forward search from the last queried PC offset, or fallback to
// a binary search if the last offset is too far away.
@ -756,14 +756,14 @@ ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
return maybeICEntryFromPCOffset(pcOffset);
}
ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset,
ICEntry& JitScript::icEntryFromPCOffset(uint32_t pcOffset,
ICEntry* prevLookedUpEntry) {
ICEntry* entry = maybeICEntryFromPCOffset(pcOffset, prevLookedUpEntry);
MOZ_RELEASE_ASSERT(entry);
return *entry;
}
ICEntry* ICScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
ICEntry* JitScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
// We have to return the entry to store in BaselineFrame::interpreterICEntry
// when resuming in the Baseline Interpreter at pcOffset. The bytecode op at
// pcOffset does not necessarily have an ICEntry, so we want to return the
@ -1197,8 +1197,8 @@ void BaselineInterpreter::toggleCodeCoverageInstrumentation(bool enable) {
toggleCodeCoverageInstrumentationUnchecked(enable);
}
void ICScript::purgeOptimizedStubs(JSScript* script) {
MOZ_ASSERT(script->icScript() == this);
void JitScript::purgeOptimizedStubs(JSScript* script) {
MOZ_ASSERT(script->jitScript() == this);
Zone* zone = script->zone();
if (zone->isGCSweeping() && IsAboutToBeFinalizedDuringSweep(*script)) {
@ -1294,18 +1294,18 @@ bool HasEnteredCounters(ICEntry& entry) {
}
void jit::JitSpewBaselineICStats(JSScript* script, const char* dumpReason) {
MOZ_ASSERT(script->hasICScript());
MOZ_ASSERT(script->hasJitScript());
JSContext* cx = TlsContext.get();
AutoStructuredSpewer spew(cx, SpewChannel::BaselineICStats, script);
if (!spew) {
return;
}
ICScript* icScript = script->icScript();
JitScript* jitScript = script->jitScript();
spew->property("reason", dumpReason);
spew->beginListProperty("entries");
for (size_t i = 0; i < icScript->numICEntries(); i++) {
ICEntry& entry = icScript->icEntry(i);
for (size_t i = 0; i < jitScript->numICEntries(); i++) {
ICEntry& entry = jitScript->icEntry(i);
if (!HasEnteredCounters(entry)) {
continue;
}
@ -1343,7 +1343,7 @@ void jit::JitSpewBaselineICStats(JSScript* script, const char* dumpReason) {
void jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script) {
MOZ_ASSERT(script->hasBaselineScript());
MOZ_ASSERT(!script->types()->active());
MOZ_ASSERT(!script->jitScript()->active());
BaselineScript* baseline = script->baselineScript();
script->setBaselineScript(fop->runtime(), nullptr);
@ -1352,13 +1352,7 @@ void jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script) {
void jit::AddSizeOfBaselineData(JSScript* script,
mozilla::MallocSizeOf mallocSizeOf,
size_t* data, size_t* fallbackStubs) {
if (script->hasICScript()) {
// ICScript is stored in TypeScript but we report its size here and not
// in TypeScript::sizeOfIncludingThis.
script->icScript()->addSizeOfIncludingThis(mallocSizeOf, data,
fallbackStubs);
}
size_t* data) {
if (script->hasBaselineScript()) {
script->baselineScript()->addSizeOfIncludingThis(mallocSizeOf, data);
}
@ -1416,13 +1410,13 @@ void jit::ToggleBaselineTraceLoggerEngine(JSRuntime* runtime, bool enable) {
}
#endif
static void MarkActiveTypeScripts(JSContext* cx,
static void MarkActiveJitScripts(JSContext* cx,
const JitActivationIterator& activation) {
for (OnlyJSJitFrameIter iter(activation); !iter.done(); ++iter) {
const JSJitFrameIter& frame = iter.frame();
switch (frame.type()) {
case FrameType::BaselineJS:
frame.script()->types()->setActive();
frame.script()->jitScript()->setActive();
break;
case FrameType::Exit:
if (frame.exitFrame()->is<LazyLinkExitFrameLayout>()) {
@ -1430,17 +1424,17 @@ static void MarkActiveTypeScripts(JSContext* cx,
frame.exitFrame()->as<LazyLinkExitFrameLayout>();
JSScript* script =
ScriptFromCalleeToken(ll->jsFrame()->calleeToken());
script->types()->setActive();
script->jitScript()->setActive();
}
break;
case FrameType::Bailout:
case FrameType::IonJS: {
// Keep the TypeScript and BaselineScript around, since bailouts from
// Keep the JitScript and BaselineScript around, since bailouts from
// the ion jitcode need to re-enter into the Baseline code.
frame.script()->types()->setActive();
frame.script()->jitScript()->setActive();
for (InlineFrameIterator inlineIter(cx, &frame); inlineIter.more();
++inlineIter) {
inlineIter.script()->types()->setActive();
inlineIter.script()->jitScript()->setActive();
}
break;
}
@ -1449,14 +1443,14 @@ static void MarkActiveTypeScripts(JSContext* cx,
}
}
void jit::MarkActiveTypeScripts(Zone* zone) {
void jit::MarkActiveJitScripts(Zone* zone) {
if (zone->isAtomsZone()) {
return;
}
JSContext* cx = TlsContext.get();
for (JitActivationIterator iter(cx); !iter.done(); ++iter) {
if (iter->compartment()->zone() == zone) {
MarkActiveTypeScripts(cx, iter);
MarkActiveJitScripts(cx, iter);
}
}
}

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

@ -575,7 +575,7 @@ bool BaselineCompileFromBaselineInterpreter(JSContext* cx, BaselineFrame* frame,
void FinishDiscardBaselineScript(FreeOp* fop, JSScript* script);
void AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf,
size_t* data, size_t* fallbackStubs);
size_t* data);
void ToggleBaselineProfiling(JSRuntime* runtime, bool enable);
@ -638,9 +638,9 @@ MOZ_MUST_USE bool BailoutIonToBaseline(
bool invalidate, BaselineBailoutInfo** bailoutInfo,
const ExceptionBailoutInfo* exceptionInfo);
// Mark TypeScripts on the stack as active, so that they are not discarded
// Mark JitScripts on the stack as active, so that they are not discarded
// during GC.
void MarkActiveTypeScripts(Zone* zone);
void MarkActiveJitScripts(Zone* zone);
MethodStatus BaselineCompile(JSContext* cx, JSScript* script,
bool forceDebugInstrumentation = false);

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

@ -3146,8 +3146,8 @@ void jit::TraceJitScripts(JSTracer* trc, JSScript* script) {
jit::BaselineScript::Trace(trc, script->baselineScript());
}
if (script->hasICScript()) {
script->icScript()->trace(trc);
if (script->hasJitScript()) {
script->jitScript()->trace(trc);
}
}

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

@ -4554,7 +4554,7 @@ bool jit::AnalyzeNewScriptDefiniteProperties(
}
}
TypeScript::MonitorThisType(cx, script, TypeSet::ObjectType(group));
JitScript::MonitorThisType(cx, script, TypeSet::ObjectType(group));
MIRGraph graph(&temp);
InlineScriptTree* inlineScriptTree =
@ -4800,8 +4800,8 @@ bool jit::AnalyzeArgumentsUsage(JSContext* cx, JSScript* scriptArg) {
return false;
}
AutoKeepTypeScripts keepTypes(cx);
if (!script->ensureHasTypes(cx, keepTypes)) {
AutoKeepJitScripts keepJitScript(cx);
if (!script->ensureHasJitScript(cx, keepJitScript)) {
return false;
}

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

@ -755,7 +755,7 @@ AbortReasonOr<Ok> IonBuilder::analyzeNewLoopTypes(
AbortReasonOr<Ok> IonBuilder::init() {
{
LifoAlloc::AutoFallibleScope fallibleAllocator(alloc().lifoAlloc());
if (!TypeScript::FreezeTypeSets(constraints(), script(), &thisTypes,
if (!JitScript::FreezeTypeSets(constraints(), script(), &thisTypes,
&argTypes, &typeArray)) {
return abort(AbortReason::Alloc);
}
@ -773,7 +773,7 @@ AbortReasonOr<Ok> IonBuilder::init() {
argTypes = nullptr;
}
bytecodeTypeMap = script()->types()->bytecodeTypeMap();
bytecodeTypeMap = script()->jitScript()->bytecodeTypeMap();
return Ok();
}
@ -4050,8 +4050,9 @@ IonBuilder::InliningResult IonBuilder::inlineScriptedCall(CallInfo& callInfo,
// Improve type information of |this| when not set.
if (callInfo.constructing() && !callInfo.thisArg()->resultTypeSet()) {
AutoSweepTypeScript sweep(calleeScript);
StackTypeSet* types = calleeScript->types()->thisTypes(sweep, calleeScript);
AutoSweepJitScript sweep(calleeScript);
StackTypeSet* types =
calleeScript->jitScript()->thisTypes(sweep, calleeScript);
if (!types->unknown()) {
TemporaryTypeSet* clonedTypes = types->clone(alloc_->lifoAlloc());
if (!clonedTypes) {
@ -5332,13 +5333,13 @@ MDefinition* IonBuilder::createThisScriptedSingleton(JSFunction* target) {
}
JSScript* targetScript = target->nonLazyScript();
TypeScript* typeScript = targetScript->types();
if (!typeScript) {
JitScript* jitScript = targetScript->jitScript();
if (!jitScript) {
return nullptr;
}
AutoSweepTypeScript sweep(targetScript);
StackTypeSet* thisTypes = typeScript->thisTypes(sweep, targetScript);
AutoSweepJitScript sweep(targetScript);
StackTypeSet* thisTypes = jitScript->thisTypes(sweep, targetScript);
if (!thisTypes->hasType(TypeSet::ObjectType(templateObject))) {
return nullptr;
}
@ -5402,13 +5403,13 @@ MDefinition* IonBuilder::createThisScriptedBaseline(MDefinition* callee) {
}
JSScript* targetScript = target->nonLazyScript();
TypeScript* typeScript = targetScript->types();
if (!typeScript) {
JitScript* jitScript = targetScript->jitScript();
if (!jitScript) {
return nullptr;
}
AutoSweepTypeScript sweep(targetScript);
StackTypeSet* thisTypes = typeScript->thisTypes(sweep, targetScript);
AutoSweepJitScript sweep(targetScript);
StackTypeSet* thisTypes = jitScript->thisTypes(sweep, targetScript);
if (!thisTypes->hasType(TypeSet::ObjectType(templateObject))) {
return nullptr;
}
@ -6095,25 +6096,25 @@ bool IonBuilder::testNeedsArgumentCheck(JSFunction* target,
}
JSScript* targetScript = target->nonLazyScript();
TypeScript* typeScript = targetScript->types();
if (!typeScript) {
JitScript* jitScript = targetScript->jitScript();
if (!jitScript) {
return true;
}
AutoSweepTypeScript sweep(targetScript);
AutoSweepJitScript sweep(targetScript);
if (!ArgumentTypesMatch(callInfo.thisArg(),
typeScript->thisTypes(sweep, targetScript))) {
jitScript->thisTypes(sweep, targetScript))) {
return true;
}
uint32_t expected_args = Min<uint32_t>(callInfo.argc(), target->nargs());
for (size_t i = 0; i < expected_args; i++) {
if (!ArgumentTypesMatch(callInfo.getArg(i),
typeScript->argTypes(sweep, targetScript, i))) {
jitScript->argTypes(sweep, targetScript, i))) {
return true;
}
}
for (size_t i = callInfo.argc(); i < target->nargs(); i++) {
StackTypeSet* types = typeScript->argTypes(sweep, targetScript, i);
StackTypeSet* types = jitScript->argTypes(sweep, targetScript, i);
if (!types->mightBeMIRType(MIRType::Undefined)) {
return true;
}
@ -13585,8 +13586,8 @@ MInstruction* IonBuilder::addSharedTypedArrayGuard(MDefinition* obj) {
}
TemporaryTypeSet* IonBuilder::bytecodeTypes(jsbytecode* pc) {
return TypeScript::BytecodeTypes(script(), pc, bytecodeTypeMap,
&typeArrayHint, typeArray);
return JitScript::BytecodeTypes(script(), pc, bytecodeTypeMap, &typeArrayHint,
typeArray);
}
TypedObjectPrediction IonBuilder::typedObjectPrediction(MDefinition* typedObj) {

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

@ -228,7 +228,7 @@ bool IonGetPropertyIC::update(JSContext* cx, HandleScript outerScript,
if (!ic->idempotent()) {
// Monitor changes to cache entry.
if (!ic->monitoredResult()) {
TypeScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
JitScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
}
}
@ -263,7 +263,7 @@ bool IonGetPropSuperIC::update(JSContext* cx, HandleScript outerScript,
}
// Monitor changes to cache entry.
TypeScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
JitScript::MonitorBytecodeType(cx, ic->script(), ic->pc(), res);
return true;
}
@ -425,7 +425,7 @@ bool IonGetNameIC::update(JSContext* cx, HandleScript outerScript,
}
}
// No need to call TypeScript::Monitor, IonBuilder always inserts a type
// No need to call JitScript::Monitor, IonBuilder always inserts a type
// barrier after GetName ICs.
return true;

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

@ -141,7 +141,7 @@ EnterJitStatus js::jit::MaybeEnterJit(JSContext* cx, RunState& state) {
// Make sure we can enter Baseline Interpreter or JIT code. Note that
// the prologue has warm-up checks to tier up if needed.
if (JitOptions.baselineInterpreter) {
if (script->types()) {
if (script->jitScript()) {
break;
}
} else {

106
js/src/jit/JitScript-inl.h Normal file
Просмотреть файл

@ -0,0 +1,106 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_JitScript_inl_h
#define jit_JitScript_inl_h
#include "jit/JitScript.h"
#include "mozilla/BinarySearch.h"
#include "vm/JSScript.h"
#include "vm/TypeInference.h"
#include "vm/JSContext-inl.h"
namespace js {
inline StackTypeSet* JitScript::thisTypes(const AutoSweepJitScript& sweep,
JSScript* script) {
return typeArray(sweep) + script->numBytecodeTypeSets();
}
/*
* Note: for non-escaping arguments, argTypes reflect only the initial type of
* the variable (e.g. passed values for argTypes, or undefined for localTypes)
* and not types from subsequent assignments.
*/
inline StackTypeSet* JitScript::argTypes(const AutoSweepJitScript& sweep,
JSScript* script, unsigned i) {
MOZ_ASSERT(i < script->functionNonDelazifying()->nargs());
return typeArray(sweep) + script->numBytecodeTypeSets() + 1 /* this */ + i;
}
template <typename TYPESET>
/* static */ inline TYPESET* JitScript::BytecodeTypes(JSScript* script,
jsbytecode* pc,
uint32_t* bytecodeMap,
uint32_t* hint,
TYPESET* typeArray) {
MOZ_ASSERT(CodeSpec[*pc].format & JOF_TYPESET);
uint32_t offset = script->pcToOffset(pc);
// See if this pc is the next typeset opcode after the last one looked up.
size_t numBytecodeTypeSets = script->numBytecodeTypeSets();
if ((*hint + 1) < numBytecodeTypeSets && bytecodeMap[*hint + 1] == offset) {
(*hint)++;
return typeArray + *hint;
}
// See if this pc is the same as the last one looked up.
if (bytecodeMap[*hint] == offset) {
return typeArray + *hint;
}
// Fall back to a binary search. We'll either find the exact offset, or
// there are more JOF_TYPESET opcodes than nTypeSets in the script (as can
// happen if the script is very long) and we'll use the last location.
size_t loc;
bool found =
mozilla::BinarySearch(bytecodeMap, 0, numBytecodeTypeSets, offset, &loc);
if (found) {
MOZ_ASSERT(bytecodeMap[loc] == offset);
} else {
MOZ_ASSERT(numBytecodeTypeSets == JSScript::MaxBytecodeTypeSets);
loc = numBytecodeTypeSets - 1;
}
*hint = mozilla::AssertedCast<uint32_t>(loc);
return typeArray + *hint;
}
inline StackTypeSet* JitScript::bytecodeTypes(const AutoSweepJitScript& sweep,
JSScript* script,
jsbytecode* pc) {
MOZ_ASSERT(CurrentThreadCanAccessZone(script->zone()));
return BytecodeTypes(script, pc, bytecodeTypeMap(), bytecodeTypeMapHint(),
typeArray(sweep));
}
inline AutoKeepJitScripts::AutoKeepJitScripts(JSContext* cx)
: zone_(cx->zone()->types), prev_(zone_.keepJitScripts) {
zone_.keepJitScripts = true;
}
inline AutoKeepJitScripts::~AutoKeepJitScripts() {
MOZ_ASSERT(zone_.keepJitScripts);
zone_.keepJitScripts = prev_;
}
inline bool JitScript::typesNeedsSweep(Zone* zone) const {
MOZ_ASSERT(!js::TlsContext.get()->inUnsafeCallWithABI);
return typesGeneration() != zone->types.generation;
}
} // namespace js
inline bool JSScript::ensureHasJitScript(JSContext* cx,
js::AutoKeepJitScripts&) {
return jitScript() || createJitScript(cx);
}
#endif /* jit_JitScript_inl_h */

237
js/src/jit/JitScript.cpp Normal file
Просмотреть файл

@ -0,0 +1,237 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/JitScript-inl.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Move.h"
#include "mozilla/ScopeExit.h"
#include "jit/BaselineIC.h"
#include "vm/JSScript.h"
#include "vm/TypeInference.h"
#include "vm/JSScript-inl.h"
#include "vm/TypeInference-inl.h"
using namespace js;
using namespace js::jit;
static void FillBytecodeTypeMap(JSScript* script, uint32_t* bytecodeMap) {
uint32_t added = 0;
for (jsbytecode* pc = script->code(); pc < script->codeEnd();
pc += GetBytecodeLength(pc)) {
JSOp op = JSOp(*pc);
if (CodeSpec[op].format & JOF_TYPESET) {
bytecodeMap[added++] = script->pcToOffset(pc);
if (added == script->numBytecodeTypeSets()) {
break;
}
}
}
MOZ_ASSERT(added == script->numBytecodeTypeSets());
}
static size_t NumTypeSets(JSScript* script) {
// We rely on |num| not overflowing below.
static_assert(JSScript::MaxBytecodeTypeSets == UINT16_MAX,
"JSScript typesets should have safe range to avoid overflow");
static_assert(JSFunction::NArgsBits == 16,
"JSFunction nargs should have safe range to avoid overflow");
size_t num = script->numBytecodeTypeSets() + 1 /* this */;
if (JSFunction* fun = script->functionNonDelazifying()) {
num += fun->nargs();
}
return num;
}
JitScript::JitScript(JSScript* script, uint32_t typeSetOffset,
uint32_t bytecodeTypeMapOffset)
: typeSetOffset_(typeSetOffset),
bytecodeTypeMapOffset_(bytecodeTypeMapOffset) {
setTypesGeneration(script->zone()->types.generation);
StackTypeSet* array = typeArrayDontCheckGeneration();
for (uint32_t i = 0, len = numTypeSets(); i < len; i++) {
new (&array[i]) StackTypeSet();
}
FillBytecodeTypeMap(script, bytecodeTypeMap());
}
bool JSScript::createJitScript(JSContext* cx) {
MOZ_ASSERT(!jitScript_);
cx->check(this);
// Scripts that will never run in the Baseline Interpreter or the JITs don't
// need a JitScript.
MOZ_ASSERT(!hasForceInterpreterOp());
AutoEnterAnalysis enter(cx);
// Run the arguments-analysis if needed. Both the Baseline Interpreter and
// Compiler rely on this.
if (!ensureHasAnalyzedArgsUsage(cx)) {
return false;
}
// If ensureHasAnalyzedArgsUsage allocated the JitScript we're done.
if (jitScript_) {
return true;
}
size_t numTypeSets = NumTypeSets(this);
static_assert(sizeof(JitScript) % sizeof(uintptr_t) == 0,
"Trailing arrays must be aligned properly");
static_assert(sizeof(ICEntry) % sizeof(uintptr_t) == 0,
"Trailing arrays must be aligned properly");
static_assert(sizeof(StackTypeSet) % sizeof(uintptr_t) == 0,
"Trailing arrays must be aligned properly");
// Calculate allocation size.
CheckedInt<uint32_t> allocSize = sizeof(JitScript);
allocSize += CheckedInt<uint32_t>(numICEntries()) * sizeof(ICEntry);
allocSize += CheckedInt<uint32_t>(numTypeSets) * sizeof(StackTypeSet);
allocSize += CheckedInt<uint32_t>(numBytecodeTypeSets()) * sizeof(uint32_t);
if (!allocSize.isValid()) {
ReportAllocationOverflow(cx);
return false;
}
void* raw = cx->pod_malloc<uint8_t>(allocSize.value());
MOZ_ASSERT(uintptr_t(raw) % alignof(JitScript) == 0);
if (!raw) {
return false;
}
uint32_t typeSetOffset = sizeof(JitScript) + numICEntries() * sizeof(ICEntry);
uint32_t bytecodeTypeMapOffset =
typeSetOffset + numTypeSets * sizeof(StackTypeSet);
UniquePtr<JitScript> jitScript(
new (raw) JitScript(this, typeSetOffset, bytecodeTypeMapOffset));
// Sanity check the length computations.
MOZ_ASSERT(jitScript->numICEntries() == numICEntries());
MOZ_ASSERT(jitScript->numTypeSets() == numTypeSets);
// We need to call prepareForDestruction on JitScript before we |delete| it.
auto prepareForDestruction = mozilla::MakeScopeExit(
[&] { jitScript->prepareForDestruction(cx->zone()); });
if (!jitScript->initICEntries(cx, this)) {
return false;
}
MOZ_ASSERT(!jitScript_);
prepareForDestruction.release();
jitScript_ = jitScript.release();
// We have a JitScript so we can set the script's jitCodeRaw_ pointer to the
// Baseline Interpreter code.
updateJitCodeRaw(cx->runtime());
#ifdef DEBUG
AutoSweepJitScript sweep(this);
StackTypeSet* typeArray = jitScript_->typeArrayDontCheckGeneration();
for (unsigned i = 0; i < numBytecodeTypeSets(); i++) {
InferSpew(ISpewOps, "typeSet: %sT%p%s bytecode%u %p",
InferSpewColor(&typeArray[i]), &typeArray[i],
InferSpewColorReset(), i, this);
}
StackTypeSet* thisTypes = jitScript_->thisTypes(sweep, this);
InferSpew(ISpewOps, "typeSet: %sT%p%s this %p", InferSpewColor(thisTypes),
thisTypes, InferSpewColorReset(), this);
unsigned nargs =
functionNonDelazifying() ? functionNonDelazifying()->nargs() : 0;
for (unsigned i = 0; i < nargs; i++) {
StackTypeSet* types = jitScript_->argTypes(sweep, this, i);
InferSpew(ISpewOps, "typeSet: %sT%p%s arg%u %p", InferSpewColor(types),
types, InferSpewColorReset(), i, this);
}
#endif
return true;
}
void JSScript::maybeReleaseJitScript() {
if (!jitScript_ || zone()->types.keepJitScripts || hasBaselineScript() ||
jitScript_->active()) {
return;
}
MOZ_ASSERT(!hasIonScript());
jitScript_->destroy(zone());
jitScript_ = nullptr;
updateJitCodeRaw(runtimeFromMainThread());
}
void JitScript::destroy(Zone* zone) {
prepareForDestruction(zone);
js_delete(this);
}
#ifdef DEBUG
void JitScript::printTypes(JSContext* cx, HandleScript script) {
AutoSweepJitScript sweep(script);
MOZ_ASSERT(script->jitScript() == this);
AutoEnterAnalysis enter(nullptr, script->zone());
Fprinter out(stderr);
if (script->functionNonDelazifying()) {
fprintf(stderr, "Function");
} else if (script->isForEval()) {
fprintf(stderr, "Eval");
} else {
fprintf(stderr, "Main");
}
fprintf(stderr, " %#" PRIxPTR " %s:%u ", uintptr_t(script.get()),
script->filename(), script->lineno());
if (script->functionNonDelazifying()) {
if (JSAtom* name = script->functionNonDelazifying()->explicitName()) {
name->dumpCharsNoNewline(out);
}
}
fprintf(stderr, "\n this:");
thisTypes(sweep, script)->print();
for (unsigned i = 0; script->functionNonDelazifying() &&
i < script->functionNonDelazifying()->nargs();
i++) {
fprintf(stderr, "\n arg%u:", i);
argTypes(sweep, script, i)->print();
}
fprintf(stderr, "\n");
for (jsbytecode* pc = script->code(); pc < script->codeEnd();
pc += GetBytecodeLength(pc)) {
{
fprintf(stderr, "%p:", script.get());
Sprinter sprinter(cx);
if (!sprinter.init()) {
return;
}
Disassemble1(cx, script, pc, script->pcToOffset(pc), true, &sprinter);
fprintf(stderr, "%s", sprinter.string());
}
if (CodeSpec[*pc].format & JOF_TYPESET) {
StackTypeSet* types = bytecodeTypes(sweep, script, pc);
fprintf(stderr, " typeset %u:", unsigned(types - typeArray(sweep)));
types->print();
fprintf(stderr, "\n");
}
}
fprintf(stderr, "\n");
}
#endif /* DEBUG */

308
js/src/jit/JitScript.h Normal file
Просмотреть файл

@ -0,0 +1,308 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_JitScript_h
#define jit_JitScript_h
#include "jit/BaselineIC.h"
#include "js/UniquePtr.h"
#include "vm/TypeInference.h"
class JSScript;
namespace js {
// [SMDOC] JitScript
//
// JitScript stores type inference data, Baseline ICs and other JIT-related data
// for a script. Scripts with a JitScript can run in the Baseline Interpreter.
//
// IC Data
// -------
//
// JitScript contains IC data used by Baseline (Interpreter and JIT). Ion has
// its own IC chains stored in IonScript.
//
// For each IC we store an ICEntry, which points to the first ICStub in the
// chain. Note that multiple stubs in the same zone can share Baseline IC code.
// This works because the stub data is stored in the ICStub instead of baked in
// in the stub code.
//
// Storing this separate from BaselineScript allows us to use the same ICs in
// the Baseline Interpreter and Baseline JIT. It also simplifies debug mode OSR
// because the JitScript can be reused when we have to recompile the
// BaselineScript.
//
// JitScript contains the following IC data structures:
//
// * Fallback stub space: this stores all fallback stubs and the "can GC" stubs.
// These stubs are never purged before destroying the JitScript. (Other stubs
// are stored in the optimized stub space stored in JitZone and can be
// discarded more eagerly. See JitScript::purgeOptimizedStubs.)
//
// * List of IC entries, in the following order:
//
// - Type monitor IC for |this|.
// - Type monitor IC for each formal argument.
// - IC for each JOF_IC bytecode op.
//
// Memory Layout
// -------------
//
// JitScript has various trailing (variable-length) arrays. The memory layout is
// as follows:
//
// Item | Offset
// ------------------------+------------------------
// JitScript | 0
// ICEntry[] | sizeof(JitScript)
// StackTypeSet[] | typeSetOffset_
// uint32_t[] | bytecodeTypeMapOffset_
// (= bytecode type map) |
//
// These offsets are also used to compute numICEntries and numTypeSets.
class alignas(uintptr_t) JitScript final {
friend class ::JSScript;
// Allocated space for fallback IC stubs.
jit::FallbackICStubSpace fallbackStubSpace_ = {};
// The freeze constraints added to stack type sets will only directly
// invalidate the script containing those stack type sets. This Vector
// contains compilations that inlined this script, so we can invalidate
// them as well.
RecompileInfoVector inlinedCompilations_;
// Offset of the StackTypeSet array.
uint32_t typeSetOffset_ = 0;
// Offset of the bytecode type map.
uint32_t bytecodeTypeMapOffset_ = 0;
// This field is used to avoid binary searches for the sought entry when
// bytecode map queries are in linear order.
uint32_t bytecodeTypeMapHint_ = 0;
struct Flags {
// Flag set when discarding JIT code to indicate this script is on the stack
// and type information and JIT code should not be discarded.
bool active : 1;
// Generation for type sweeping. If out of sync with the TypeZone's
// generation, this JitScript needs to be swept.
bool typesGeneration : 1;
// Whether freeze constraints for stack type sets have been generated.
bool hasFreezeConstraints : 1;
};
Flags flags_ = {}; // Zero-initialize flags.
jit::ICEntry* icEntries() {
uint8_t* base = reinterpret_cast<uint8_t*>(this);
return reinterpret_cast<jit::ICEntry*>(base + offsetOfICEntries());
}
StackTypeSet* typeArrayDontCheckGeneration() {
uint8_t* base = reinterpret_cast<uint8_t*>(this);
return reinterpret_cast<StackTypeSet*>(base + typeSetOffset_);
}
uint32_t typesGeneration() const { return uint32_t(flags_.typesGeneration); }
void setTypesGeneration(uint32_t generation) {
MOZ_ASSERT(generation <= 1);
flags_.typesGeneration = generation;
}
public:
JitScript(JSScript* script, uint32_t typeSetOffset,
uint32_t bytecodeTypeMapOffset);
#ifdef DEBUG
~JitScript() {
// The contents of the fallback stub space are removed and freed
// separately after the next minor GC. See prepareForDestruction.
MOZ_ASSERT(fallbackStubSpace_.isEmpty());
}
#endif
MOZ_MUST_USE bool initICEntries(JSContext* cx, JSScript* script);
bool hasFreezeConstraints(const js::AutoSweepJitScript& sweep) const {
MOZ_ASSERT(sweep.jitScript() == this);
return flags_.hasFreezeConstraints;
}
void setHasFreezeConstraints(const js::AutoSweepJitScript& sweep) {
MOZ_ASSERT(sweep.jitScript() == this);
flags_.hasFreezeConstraints = true;
}
inline bool typesNeedsSweep(Zone* zone) const;
void sweepTypes(const js::AutoSweepJitScript& sweep, Zone* zone);
RecompileInfoVector& inlinedCompilations(
const js::AutoSweepJitScript& sweep) {
MOZ_ASSERT(sweep.jitScript() == this);
return inlinedCompilations_;
}
MOZ_MUST_USE bool addInlinedCompilation(const js::AutoSweepJitScript& sweep,
RecompileInfo info) {
MOZ_ASSERT(sweep.jitScript() == this);
if (!inlinedCompilations_.empty() && inlinedCompilations_.back() == info) {
return true;
}
return inlinedCompilations_.append(info);
}
uint32_t numICEntries() const {
return (typeSetOffset_ - offsetOfICEntries()) / sizeof(jit::ICEntry);
}
uint32_t numTypeSets() const {
return (bytecodeTypeMapOffset_ - typeSetOffset_) / sizeof(StackTypeSet);
}
uint32_t* bytecodeTypeMapHint() { return &bytecodeTypeMapHint_; }
bool active() const { return flags_.active; }
void setActive() { flags_.active = true; }
void resetActive() { flags_.active = false; }
/* Array of type sets for variables and JOF_TYPESET ops. */
StackTypeSet* typeArray(const js::AutoSweepJitScript& sweep) {
MOZ_ASSERT(sweep.jitScript() == this);
return typeArrayDontCheckGeneration();
}
uint32_t* bytecodeTypeMap() {
uint8_t* base = reinterpret_cast<uint8_t*>(this);
return reinterpret_cast<uint32_t*>(base + bytecodeTypeMapOffset_);
}
inline StackTypeSet* thisTypes(const AutoSweepJitScript& sweep,
JSScript* script);
inline StackTypeSet* argTypes(const AutoSweepJitScript& sweep,
JSScript* script, unsigned i);
/* Get the type set for values observed at an opcode. */
inline StackTypeSet* bytecodeTypes(const AutoSweepJitScript& sweep,
JSScript* script, jsbytecode* pc);
template <typename TYPESET>
static inline TYPESET* BytecodeTypes(JSScript* script, jsbytecode* pc,
uint32_t* bytecodeMap, uint32_t* hint,
TYPESET* typeArray);
/*
* Monitor a bytecode pushing any value. This must be called for any opcode
* which is JOF_TYPESET, and where either the script has not been analyzed
* by type inference or where the pc has type barriers. For simplicity, we
* always monitor JOF_TYPESET opcodes in the interpreter and stub calls,
* and only look at barriers when generating JIT code for the script.
*/
static void MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, const js::Value& val);
static void MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, TypeSet::Type type);
static inline void MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, StackTypeSet* types,
const js::Value& val);
private:
static void MonitorBytecodeTypeSlow(JSContext* cx, JSScript* script,
jsbytecode* pc, StackTypeSet* types,
TypeSet::Type type);
public:
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
static inline void MonitorAssign(JSContext* cx, HandleObject obj, jsid id);
/* Add a type for a variable in a script. */
static inline void MonitorThisType(JSContext* cx, JSScript* script,
TypeSet::Type type);
static inline void MonitorThisType(JSContext* cx, JSScript* script,
const js::Value& value);
static inline void MonitorArgType(JSContext* cx, JSScript* script,
unsigned arg, TypeSet::Type type);
static inline void MonitorArgType(JSContext* cx, JSScript* script,
unsigned arg, const js::Value& value);
/*
* Freeze all the stack type sets in a script, for a compilation. Returns
* copies of the type sets which will be checked against the actual ones
* under FinishCompilation, to detect any type changes.
*/
static bool FreezeTypeSets(CompilerConstraintList* constraints,
JSScript* script, TemporaryTypeSet** pThisTypes,
TemporaryTypeSet** pArgTypes,
TemporaryTypeSet** pBytecodeTypes);
void destroy(Zone* zone);
static constexpr size_t offsetOfICEntries() { return sizeof(JitScript); }
#ifdef DEBUG
void printTypes(JSContext* cx, HandleScript script);
#endif
void prepareForDestruction(Zone* zone) {
// When the script contains pointers to nursery things, the store buffer can
// contain entries that point into the fallback stub space. Since we can
// destroy scripts outside the context of a GC, this situation could result
// in us trying to mark invalid store buffer entries.
//
// Defer freeing any allocated blocks until after the next minor GC.
fallbackStubSpace_.freeAllAfterMinorGC(zone);
}
jit::FallbackICStubSpace* fallbackStubSpace() { return &fallbackStubSpace_; }
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
size_t* fallbackStubs) const {
*data += mallocSizeOf(this);
// |data| already includes the ICStubSpace itself, so use
// sizeOfExcludingThis.
*fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
}
jit::ICEntry& icEntry(size_t index) {
MOZ_ASSERT(index < numICEntries());
return icEntries()[index];
}
void noteAccessedGetter(uint32_t pcOffset);
void noteHasDenseAdd(uint32_t pcOffset);
void trace(JSTracer* trc);
void purgeOptimizedStubs(JSScript* script);
jit::ICEntry* interpreterICEntryFromPCOffset(uint32_t pcOffset);
jit::ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
jit::ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
jit::ICEntry* prevLookedUpEntry);
jit::ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
jit::ICEntry& icEntryFromPCOffset(uint32_t pcOffset,
jit::ICEntry* prevLookedUpEntry);
};
// Ensures no JitScripts are purged in the current zone.
class MOZ_RAII AutoKeepJitScripts {
TypeZone& zone_;
bool prev_;
AutoKeepJitScripts(const AutoKeepJitScripts&) = delete;
void operator=(const AutoKeepJitScripts&) = delete;
public:
explicit inline AutoKeepJitScripts(JSContext* cx);
inline ~AutoKeepJitScripts();
};
} // namespace js
#endif /* jit_JitScript_h */

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

@ -464,7 +464,7 @@ bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval) {
if (rval.isUndefined()) {
jsbytecode* pc;
JSScript* script = cx->currentScript(&pc);
TypeScript::MonitorBytecodeType(cx, script, pc, rval);
JitScript::MonitorBytecodeType(cx, script, pc, rval);
}
return true;
}
@ -530,7 +530,7 @@ bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval) {
if (rval.isUndefined()) {
jsbytecode* pc;
JSScript* script = cx->currentScript(&pc);
TypeScript::MonitorBytecodeType(cx, script, pc, rval);
JitScript::MonitorBytecodeType(cx, script, pc, rval);
}
return true;
}
@ -691,7 +691,7 @@ bool GetIntrinsicValue(JSContext* cx, HandlePropertyName name,
// type info will not be reflowed. Manually monitor here.
jsbytecode* pc;
JSScript* script = cx->currentScript(&pc);
TypeScript::MonitorBytecodeType(cx, script, pc, rval);
JitScript::MonitorBytecodeType(cx, script, pc, rval);
return true;
}
@ -2008,8 +2008,8 @@ bool DoConcatStringObject(JSContext* cx, HandleValue lhs, HandleValue rhs,
}
}
// Technically, we need to call TypeScript::MonitorString for this PC, however
// it was called when this stub was attached so it's OK.
// Note: we don't have to call JitScript::MonitorBytecodeType because we
// monitored the string-type when attaching the IC stub.
res.setString(str);
return true;

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

@ -67,6 +67,7 @@ UNIFIED_SOURCES += [
'JitcodeMap.cpp',
'JitFrames.cpp',
'JitOptions.cpp',
'JitScript.cpp',
'JitSpewer.cpp',
'JSJitFrameIter.cpp',
'JSONSpewer.cpp',

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

@ -514,7 +514,7 @@ static bool MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id,
if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
argsobj->setElement(cx, arg, v);
if (arg < script->functionNonDelazifying()->nargs()) {
TypeScript::MonitorArgType(cx, script, arg, v);
JitScript::MonitorArgType(cx, script, arg, v);
}
return result.succeed();
}
@ -730,7 +730,7 @@ bool MappedArgumentsObject::obj_defineProperty(JSContext* cx, HandleObject obj,
}
argsobj->setElement(cx, arg, desc.value());
if (arg < script->functionNonDelazifying()->nargs()) {
TypeScript::MonitorArgType(cx, script, arg, desc.value());
JitScript::MonitorArgType(cx, script, arg, desc.value());
}
}
if (desc.hasWritable() && !desc.writable()) {

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

@ -2574,7 +2574,7 @@ JS_FRIEND_API void js::StopPCCountProfiling(JSContext* cx) {
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
for (auto script = zone->cellIter<JSScript>(); !script.done();
script.next()) {
if (script->hasScriptCounts() && script->types()) {
if (script->hasScriptCounts() && script->jitScript()) {
if (!vec->append(script)) {
return;
}

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

@ -2922,10 +2922,10 @@ bool Debugger::updateExecutionObservabilityOfFrames(
return true;
}
static inline void MarkTypeScriptActiveIfObservable(
static inline void MarkJitScriptActiveIfObservable(
JSScript* script, const Debugger::ExecutionObservableSet& obs) {
if (obs.shouldRecompileOrInvalidate(script)) {
script->types()->setActive();
script->jitScript()->setActive();
}
}
@ -2988,13 +2988,13 @@ static bool UpdateExecutionObservabilityOfScriptsInZone(
const JSJitFrameIter& frame = iter.frame();
switch (frame.type()) {
case FrameType::BaselineJS:
MarkTypeScriptActiveIfObservable(frame.script(), obs);
MarkJitScriptActiveIfObservable(frame.script(), obs);
break;
case FrameType::IonJS:
MarkTypeScriptActiveIfObservable(frame.script(), obs);
MarkJitScriptActiveIfObservable(frame.script(), obs);
for (InlineFrameIterator inlineIter(cx, &frame); inlineIter.more();
++inlineIter) {
MarkTypeScriptActiveIfObservable(inlineIter.script(), obs);
MarkJitScriptActiveIfObservable(inlineIter.script(), obs);
}
break;
default:;
@ -3007,10 +3007,10 @@ static bool UpdateExecutionObservabilityOfScriptsInZone(
// discard the BaselineScript on scripts that have no IonScript.
for (size_t i = 0; i < scripts.length(); i++) {
MOZ_ASSERT_IF(scripts[i]->isDebuggee(), observing);
if (!scripts[i]->types()->active()) {
if (!scripts[i]->jitScript()->active()) {
FinishDiscardBaselineScript(fop, scripts[i]);
}
scripts[i]->types()->resetActive();
scripts[i]->jitScript()->resetActive();
}
// Iterate through all wasm instances to find ones that need to be updated.

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

@ -1574,7 +1574,7 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler {
}
if (action == SET) {
TypeScript::MonitorArgType(cx, script, i, vp);
JitScript::MonitorArgType(cx, script, i, vp);
}
}

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

@ -1546,15 +1546,15 @@ static MOZ_ALWAYS_INLINE bool SetObjectElementOperation(
// receiver != obj happens only at super[expr], where we expect to find the
// property. People probably aren't building hashtables with |super|
// anyway.
TypeScript::MonitorAssign(cx, obj, id);
JitScript::MonitorAssign(cx, obj, id);
if (obj->isNative() && JSID_IS_INT(id)) {
uint32_t length = obj->as<NativeObject>().getDenseInitializedLength();
int32_t i = JSID_TO_INT(id);
if ((uint32_t)i >= length) {
// Annotate script if provided with information (e.g. baseline)
if (script && script->hasICScript() && IsSetElemPC(pc)) {
script->icScript()->noteHasDenseAdd(script->pcToOffset(pc));
if (script && script->hasJitScript() && IsSetElemPC(pc)) {
script->jitScript()->noteHasDenseAdd(script->pcToOffset(pc));
}
}
}
@ -2123,7 +2123,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
ADVANCE_AND_DISPATCH(JSOP_RESUME_LENGTH);
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, REGS.sp[-1]);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, REGS.sp[-1]);
MOZ_ASSERT(CodeSpec[*REGS.pc].length == JSOP_CALL_LENGTH);
ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
}
@ -2773,7 +2773,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
goto error;
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, lval);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, lval);
cx->debugOnlyCheck(lval);
}
END_CASE(JSOP_GETPROP)
@ -2787,7 +2787,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
goto error;
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, rref);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, rref);
cx->debugOnlyCheck(rref);
REGS.sp--;
@ -2802,7 +2802,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
goto error;
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
cx->debugOnlyCheck(rval);
}
END_CASE(JSOP_GETBOUNDNAME)
@ -2895,7 +2895,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
}
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, res);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, res);
REGS.sp--;
}
END_CASE(JSOP_GETELEM)
@ -2915,7 +2915,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
goto error;
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, res);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, res);
REGS.sp -= 2;
}
END_CASE(JSOP_GETELEM_SUPER)
@ -2980,7 +2980,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
}
REGS.sp = args.spAfterCall();
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, REGS.sp[-1]);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, REGS.sp[-1]);
}
END_CASE(JSOP_EVAL)
@ -3087,7 +3087,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
}
}
Value* newsp = args.spAfterCall();
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, newsp[-1]);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, newsp[-1]);
REGS.sp = newsp;
ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
}
@ -3237,7 +3237,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
}
PUSH_COPY(rval);
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
static_assert(JSOP_GETNAME_LENGTH == JSOP_GETGNAME_LENGTH,
"We're sharing the END_CASE so the lengths better match");
}
@ -3251,7 +3251,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
goto error;
}
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
}
END_CASE(JSOP_GETIMPORT)
@ -3262,7 +3262,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
}
PUSH_COPY(rval);
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, rval);
}
END_CASE(JSOP_GETINTRINSIC)
@ -3424,7 +3424,7 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
}
#endif
PUSH_COPY(val);
TypeScript::MonitorBytecodeType(cx, script, REGS.pc, REGS.sp[-1]);
JitScript::MonitorBytecodeType(cx, script, REGS.pc, REGS.sp[-1]);
}
END_CASE(JSOP_GETALIASEDVAR)
@ -5105,7 +5105,7 @@ bool js::SpreadCallOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
}
}
TypeScript::MonitorBytecodeType(cx, script, pc, res);
JitScript::MonitorBytecodeType(cx, script, pc, res);
return true;
}

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

@ -1156,7 +1156,7 @@ JSObject* js::CreateThisForFunctionWithProto(
if (!script) {
return nullptr;
}
TypeScript::MonitorThisType(cx, script, TypeSet::ObjectType(res));
JitScript::MonitorThisType(cx, script, TypeSet::ObjectType(res));
}
return res;
@ -1225,7 +1225,7 @@ JSObject* js::CreateThisForFunction(JSContext* cx, HandleFunction callee,
NativeObject::clear(cx, nobj);
JSScript* calleeScript = callee->nonLazyScript();
TypeScript::MonitorThisType(cx, calleeScript, TypeSet::ObjectType(nobj));
JitScript::MonitorThisType(cx, calleeScript, TypeSet::ObjectType(nobj));
return nobj;
}

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

@ -13,6 +13,7 @@
#include "jit/BaselineJIT.h"
#include "jit/IonAnalysis.h"
#include "jit/JitScript.h"
#include "vm/EnvironmentObject.h"
#include "vm/RegExpObject.h"
#include "wasm/AsmJS.h"
@ -181,9 +182,4 @@ inline bool JSScript::isDebuggee() const {
return realm_->debuggerObservesAllExecution() || hasDebugScript();
}
inline js::jit::ICScript* JSScript::icScript() const {
MOZ_ASSERT(hasICScript());
return types_->icScript();
}
#endif /* vm_JSScript_inl_h */

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

@ -1725,8 +1725,7 @@ class ScriptSource::LoadSourceMatcher {
}
if (!ss_->setRetrievedSource(
cx_,
EntryUnits<Utf8Unit>(reinterpret_cast<Utf8Unit*>(utf8Source)),
cx_, EntryUnits<Utf8Unit>(reinterpret_cast<Utf8Unit*>(utf8Source)),
*length)) {
return false;
}
@ -2748,8 +2747,8 @@ XDRResult ScriptSource::codeBinASTData(XDRState<mode>* const xdr,
// XDR the BinAST data.
Maybe<SharedImmutableString> binASTData;
if (mode == XDR_DECODE) {
auto bytes = xdr->cx()->template make_pod_array<char>(Max<size_t>(
binASTLength, 1));
auto bytes =
xdr->cx()->template make_pod_array<char>(Max<size_t>(binASTLength, 1));
if (!bytes) {
return xdr->fail(JS::TranscodeResult_Throw);
}
@ -2820,7 +2819,8 @@ XDRResult ScriptSource::codeBinASTData(XDRState<mode>* const xdr,
JSAtom** atomsBase = binASTMetadata->atomsBase();
auto slices = binASTMetadata->sliceBase();
const char* sourceBase =
(mode == XDR_ENCODE ? ss->data.as<BinAST>().string : *binASTData).chars();
(mode == XDR_ENCODE ? ss->data.as<BinAST>().string : *binASTData)
.chars();
for (uint32_t i = 0; i < numStrings; i++) {
uint8_t isNull;
@ -3373,7 +3373,8 @@ void js::FreeScriptData(JSRuntime* rt) {
#ifdef DEBUG
if (numLive > 0) {
fprintf(stderr, "ERROR: GC found %zu live SharedScriptData at shutdown\n", numLive);
fprintf(stderr, "ERROR: GC found %zu live SharedScriptData at shutdown\n",
numLive);
}
#endif
@ -4039,8 +4040,15 @@ size_t JSScript::sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const {
return mallocSizeOf(data_);
}
size_t JSScript::sizeOfTypeScript(mozilla::MallocSizeOf mallocSizeOf) const {
return types_ ? types_->sizeOfIncludingThis(mallocSizeOf) : 0;
void JSScript::addSizeOfJitScript(mozilla::MallocSizeOf mallocSizeOf,
size_t* sizeOfJitScript,
size_t* sizeOfBaselineFallbackStubs) const {
if (!jitScript_) {
return;
}
jitScript_->addSizeOfIncludingThis(mallocSizeOf, sizeOfJitScript,
sizeOfBaselineFallbackStubs);
}
js::GlobalObject& JSScript::uninlinedGlobal() const { return global(); }
@ -4061,8 +4069,8 @@ void JSScript::finalize(FreeOp* fop) {
fop->runtime()->geckoProfiler().onScriptFinalized(this);
if (types_) {
types_->destroy(zone());
if (jitScript_) {
jitScript_->destroy(zone());
}
jit::DestroyJitScripts(fop, this);
@ -5428,7 +5436,7 @@ void JSScript::updateJitCodeRaw(JSRuntime* rt) {
} else if (hasBaselineScript()) {
jitCodeRaw_ = baseline->method()->raw();
jitCodeSkipArgCheck_ = jitCodeRaw_;
} else if (types() && js::jit::JitOptions.baselineInterpreter) {
} else if (jitScript() && js::jit::JitOptions.baselineInterpreter) {
jitCodeRaw_ = rt->jitRuntime()->baselineInterpreter().codeRaw();
jitCodeSkipArgCheck_ = jitCodeRaw_;
} else {
@ -5511,14 +5519,16 @@ JS::ubi::Base::Size JS::ubi::Concrete<JSScript>::size(
Size size = gc::Arena::thingSize(get().asTenured().getAllocKind());
size += get().sizeOfData(mallocSizeOf);
size += get().sizeOfTypeScript(mallocSizeOf);
size_t jitScriptSize = 0;
size_t fallbackStubSize = 0;
get().addSizeOfJitScript(mallocSizeOf, &jitScriptSize, &fallbackStubSize);
size += jitScriptSize;
size += fallbackStubSize;
size_t baselineSize = 0;
size_t baselineStubsSize = 0;
jit::AddSizeOfBaselineData(&get(), mallocSizeOf, &baselineSize,
&baselineStubsSize);
jit::AddSizeOfBaselineData(&get(), mallocSizeOf, &baselineSize);
size += baselineSize;
size += baselineStubsSize;
size += jit::SizeOfIonData(&get(), mallocSizeOf);

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

@ -55,7 +55,6 @@ namespace js {
namespace jit {
struct BaselineScript;
class ICScript;
struct IonScriptCounts;
} // namespace jit
@ -65,8 +64,8 @@ struct IonScriptCounts;
#define BASELINE_DISABLED_SCRIPT ((js::jit::BaselineScript*)0x1)
class AutoKeepTypeScripts;
class AutoSweepTypeScript;
class AutoKeepJitScripts;
class AutoSweepJitScript;
class BreakpointSite;
class Debugger;
class GCParallelTask;
@ -75,7 +74,7 @@ class ModuleObject;
class RegExpObject;
class SourceCompressionTask;
class Shape;
class TypeScript;
class JitScript;
namespace frontend {
struct BytecodeEmitter;
@ -1568,7 +1567,7 @@ class alignas(uintptr_t) SharedScriptData final {
// Index into the scopes array of the body scope.
uint32_t bodyScopeIndex = 0;
// Number of IC entries to allocate in ICScript for Baseline ICs.
// Number of IC entries to allocate in JitScript for Baseline ICs.
uint32_t numICEntries = 0;
// ES6 function length.
@ -1741,8 +1740,8 @@ class JSScript : public js::gc::TenuredCell {
JS::Realm* realm_ = nullptr;
private:
/* Persistent type information retained across GCs. */
js::TypeScript* types_ = nullptr;
// JIT and type inference data for this script. May be purged on GC.
js::JitScript* jitScript_ = nullptr;
// This script's ScriptSourceObject.
js::GCPtr<js::ScriptSourceObject*> sourceObject_ = {};
@ -2429,7 +2428,9 @@ class JSScript : public js::gc::TenuredCell {
static constexpr size_t offsetOfScriptData() {
return offsetof(JSScript, scriptData_);
}
static constexpr size_t offsetOfTypes() { return offsetof(JSScript, types_); }
static constexpr size_t offsetOfJitScript() {
return offsetof(JSScript, jitScript_);
}
bool hasAnyIonScript() const { return hasIonScript(); }
@ -2465,14 +2466,6 @@ class JSScript : public js::gc::TenuredCell {
inline void setBaselineScript(JSRuntime* rt,
js::jit::BaselineScript* baselineScript);
inline js::jit::ICScript* icScript() const;
bool hasICScript() const {
// ICScript is stored in TypeScript so we have an ICScript iff we have a
// TypeScript.
return !!types_;
}
void updateJitCodeRaw(JSRuntime* rt);
static size_t offsetOfBaselineScript() {
@ -2487,7 +2480,7 @@ class JSScript : public js::gc::TenuredCell {
}
uint8_t* jitCodeRaw() const { return jitCodeRaw_; }
// We don't relazify functions with a TypeScript or JIT code, but some
// We don't relazify functions with a JitScript or JIT code, but some
// callers (XDR, testing functions) want to know whether this script is
// relazifiable ignoring (or after) discarding JIT code.
bool isRelazifiableIgnoringJitCode() const {
@ -2496,8 +2489,8 @@ class JSScript : public js::gc::TenuredCell {
!hasFlag(MutableFlags::DoNotRelazify);
}
bool isRelazifiable() const {
MOZ_ASSERT_IF(hasBaselineScript() || hasIonScript(), types_);
return isRelazifiableIgnoringJitCode() && !types_;
MOZ_ASSERT_IF(hasBaselineScript() || hasIonScript(), jitScript_);
return isRelazifiableIgnoringJitCode() && !jitScript_;
}
void setLazyScript(js::LazyScript* lazy) { lazyScript = lazy; }
js::LazyScript* maybeLazyScript() { return lazyScript; }
@ -2599,12 +2592,13 @@ class JSScript : public js::gc::TenuredCell {
*/
bool isTopLevel() { return code() && !functionNonDelazifying(); }
/* Ensure the script has a TypeScript. */
inline bool ensureHasTypes(JSContext* cx, js::AutoKeepTypeScripts&);
/* Ensure the script has a JitScript. */
inline bool ensureHasJitScript(JSContext* cx, js::AutoKeepJitScripts&);
js::TypeScript* types() { return types_; }
bool hasJitScript() const { return jitScript_ != nullptr; }
js::JitScript* jitScript() { return jitScript_; }
void maybeReleaseTypes();
void maybeReleaseJitScript();
inline js::GlobalObject& global() const;
inline bool hasGlobal(const js::GlobalObject* global) const;
@ -2655,7 +2649,7 @@ class JSScript : public js::gc::TenuredCell {
js::Scope* enclosingScope() const { return outermostScope()->enclosing(); }
private:
bool makeTypes(JSContext* cx);
bool createJitScript(JSContext* cx);
bool createSharedScriptData(JSContext* cx, uint32_t codeLength,
uint32_t noteLength, uint32_t natoms);
@ -2732,7 +2726,10 @@ class JSScript : public js::gc::TenuredCell {
*/
size_t computedSizeOfData() const;
size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const;
size_t sizeOfTypeScript(mozilla::MallocSizeOf mallocSizeOf) const;
void addSizeOfJitScript(mozilla::MallocSizeOf mallocSizeOf,
size_t* sizeOfJitScript,
size_t* sizeOfBaselineFallbackStubs) const;
size_t dataSize() const { return dataSize_; }

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

@ -445,11 +445,10 @@ static void StatsCellCallback(JSRuntime* rt, void* data, void* thing,
realmStats.scriptsGCHeap += thingSize;
realmStats.scriptsMallocHeapData +=
script->sizeOfData(rtStats->mallocSizeOf_);
realmStats.typeInferenceTypeScripts +=
script->sizeOfTypeScript(rtStats->mallocSizeOf_);
jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_,
&realmStats.baselineData,
script->addSizeOfJitScript(rtStats->mallocSizeOf_, &realmStats.jitScripts,
&realmStats.baselineStubsFallback);
jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_,
&realmStats.baselineData);
realmStats.ionData += jit::SizeOfIonData(script, rtStats->mallocSizeOf_);
CollectScriptSourceStats<granularity>(closure, script->scriptSource());
break;

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

@ -2248,12 +2248,12 @@ static MOZ_ALWAYS_INLINE bool GetExistingProperty(
{
jsbytecode* pc;
JSScript* script = cx->currentScript(&pc);
if (script && script->hasICScript()) {
if (script && script->hasJitScript()) {
switch (JSOp(*pc)) {
case JSOP_GETPROP:
case JSOP_CALLPROP:
case JSOP_LENGTH:
script->icScript()->noteAccessedGetter(script->pcToOffset(pc));
script->jitScript()->noteAccessedGetter(script->pcToOffset(pc));
break;
default:
break;

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

@ -1523,7 +1523,7 @@ bool ObjectGroup::setAllocationSiteObjectGroup(JSContext* cx,
* objects, as these may not be created until after the script
* has been analyzed.
*/
TypeScript::MonitorBytecodeType(cx, script, pc, ObjectValue(*obj));
JitScript::MonitorBytecodeType(cx, script, pc, ObjectValue(*obj));
} else {
ObjectGroup* group = allocationSiteGroup(cx, script, pc, key);
if (!group) {

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

@ -20,6 +20,7 @@
#include "builtin/Symbol.h"
#include "gc/GC.h"
#include "jit/BaselineJIT.h"
#include "jit/JitScript.h"
#include "js/HeapAPI.h"
#include "vm/ArrayObject.h"
#include "vm/BooleanObject.h"
@ -32,6 +33,7 @@
#include "vm/StringObject.h"
#include "vm/TypedArrayObject.h"
#include "jit/JitScript-inl.h"
#include "vm/JSContext-inl.h"
#include "vm/ObjectGroup-inl.h"
@ -443,7 +445,7 @@ inline void TypeMonitorCall(JSContext* cx, const js::CallArgs& args,
bool constructing) {
if (args.callee().is<JSFunction>()) {
JSFunction* fun = &args.callee().as<JSFunction>();
if (fun->isInterpreted() && fun->nonLazyScript()->types()) {
if (fun->isInterpreted() && fun->nonLazyScript()->jitScript()) {
TypeMonitorCallSlow(cx, &args.callee(), args, constructing);
}
}
@ -586,75 +588,10 @@ inline void MarkObjectStateChange(JSContext* cx, JSObject* obj) {
}
}
/////////////////////////////////////////////////////////////////////
// Script interface functions
/////////////////////////////////////////////////////////////////////
inline StackTypeSet* TypeScript::thisTypes(const AutoSweepTypeScript& sweep,
JSScript* script) {
return typeArray(sweep) + script->numBytecodeTypeSets();
}
/*
* Note: for non-escaping arguments, argTypes reflect only the initial type of
* the variable (e.g. passed values for argTypes, or undefined for localTypes)
* and not types from subsequent assignments.
*/
inline StackTypeSet* TypeScript::argTypes(const AutoSweepTypeScript& sweep,
JSScript* script, unsigned i) {
MOZ_ASSERT(i < script->functionNonDelazifying()->nargs());
return typeArray(sweep) + script->numBytecodeTypeSets() + 1 /* this */ + i;
}
template <typename TYPESET>
/* static */ inline TYPESET* TypeScript::BytecodeTypes(JSScript* script,
jsbytecode* pc,
uint32_t* bytecodeMap,
uint32_t* hint,
TYPESET* typeArray) {
MOZ_ASSERT(CodeSpec[*pc].format & JOF_TYPESET);
uint32_t offset = script->pcToOffset(pc);
// See if this pc is the next typeset opcode after the last one looked up.
size_t numBytecodeTypeSets = script->numBytecodeTypeSets();
if ((*hint + 1) < numBytecodeTypeSets && bytecodeMap[*hint + 1] == offset) {
(*hint)++;
return typeArray + *hint;
}
// See if this pc is the same as the last one looked up.
if (bytecodeMap[*hint] == offset) {
return typeArray + *hint;
}
// Fall back to a binary search. We'll either find the exact offset, or
// there are more JOF_TYPESET opcodes than nTypeSets in the script (as can
// happen if the script is very long) and we'll use the last location.
size_t loc;
bool found =
mozilla::BinarySearch(bytecodeMap, 0, numBytecodeTypeSets, offset, &loc);
if (found) {
MOZ_ASSERT(bytecodeMap[loc] == offset);
} else {
MOZ_ASSERT(numBytecodeTypeSets == JSScript::MaxBytecodeTypeSets);
loc = numBytecodeTypeSets - 1;
}
*hint = mozilla::AssertedCast<uint32_t>(loc);
return typeArray + *hint;
}
inline StackTypeSet* TypeScript::bytecodeTypes(const AutoSweepTypeScript& sweep,
/* static */ inline void JitScript::MonitorBytecodeType(JSContext* cx,
JSScript* script,
jsbytecode* pc) {
MOZ_ASSERT(CurrentThreadCanAccessZone(script->zone()));
return BytecodeTypes(script, pc, bytecodeTypeMap(), bytecodeTypeMapHint(),
typeArray(sweep));
}
/* static */ inline void TypeScript::MonitorBytecodeType(
JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
jsbytecode* pc,
StackTypeSet* types,
const js::Value& rval) {
TypeSet::Type type = TypeSet::GetValueType(rval);
if (!types->hasType(type)) {
@ -662,7 +599,7 @@ inline StackTypeSet* TypeScript::bytecodeTypes(const AutoSweepTypeScript& sweep,
}
}
/* static */ inline void TypeScript::MonitorAssign(JSContext* cx,
/* static */ inline void JitScript::MonitorAssign(JSContext* cx,
HandleObject obj, jsid id) {
if (!obj->isSingleton()) {
/*
@ -689,18 +626,18 @@ inline StackTypeSet* TypeScript::bytecodeTypes(const AutoSweepTypeScript& sweep,
}
}
/* static */ inline void TypeScript::MonitorThisType(JSContext* cx,
/* static */ inline void JitScript::MonitorThisType(JSContext* cx,
JSScript* script,
TypeSet::Type type) {
cx->check(script, type);
TypeScript* typeScript = script->types();
if (!typeScript) {
JitScript* jitScript = script->jitScript();
if (!jitScript) {
return;
}
AutoSweepTypeScript sweep(script);
StackTypeSet* types = typeScript->thisTypes(sweep, script);
AutoSweepJitScript sweep(script);
StackTypeSet* types = jitScript->thisTypes(sweep, script);
if (!types->hasType(type)) {
AutoEnterAnalysis enter(cx);
@ -711,25 +648,25 @@ inline StackTypeSet* TypeScript::bytecodeTypes(const AutoSweepTypeScript& sweep,
}
}
/* static */ inline void TypeScript::MonitorThisType(JSContext* cx,
/* static */ inline void JitScript::MonitorThisType(JSContext* cx,
JSScript* script,
const js::Value& value) {
MonitorThisType(cx, script, TypeSet::GetValueType(value));
}
/* static */ inline void TypeScript::MonitorArgType(JSContext* cx,
/* static */ inline void JitScript::MonitorArgType(JSContext* cx,
JSScript* script,
unsigned arg,
TypeSet::Type type) {
cx->check(script->compartment(), type);
TypeScript* typeScript = script->types();
if (!typeScript) {
JitScript* jitScript = script->jitScript();
if (!jitScript) {
return;
}
AutoSweepTypeScript sweep(script);
StackTypeSet* types = typeScript->argTypes(sweep, script, arg);
AutoSweepJitScript sweep(script);
StackTypeSet* types = jitScript->argTypes(sweep, script, arg);
if (!types->hasType(type)) {
AutoEnterAnalysis enter(cx);
@ -740,23 +677,13 @@ inline StackTypeSet* TypeScript::bytecodeTypes(const AutoSweepTypeScript& sweep,
}
}
/* static */ inline void TypeScript::MonitorArgType(JSContext* cx,
/* static */ inline void JitScript::MonitorArgType(JSContext* cx,
JSScript* script,
unsigned arg,
const js::Value& value) {
MonitorArgType(cx, script, arg, TypeSet::GetValueType(value));
}
inline AutoKeepTypeScripts::AutoKeepTypeScripts(JSContext* cx)
: zone_(cx->zone()->types), prev_(zone_.keepTypeScripts) {
zone_.keepTypeScripts = true;
}
inline AutoKeepTypeScripts::~AutoKeepTypeScripts() {
MOZ_ASSERT(zone_.keepTypeScripts);
zone_.keepTypeScripts = prev_;
}
/////////////////////////////////////////////////////////////////////
// TypeHashSet
/////////////////////////////////////////////////////////////////////
@ -1363,36 +1290,27 @@ inline AutoSweepObjectGroup::~AutoSweepObjectGroup() {
}
#endif
inline AutoSweepTypeScript::AutoSweepTypeScript(JSScript* script)
inline AutoSweepJitScript::AutoSweepJitScript(JSScript* script)
#ifdef DEBUG
: zone_(script->zone()),
typeScript_(script->types())
jitScript_(script->jitScript())
#endif
{
if (TypeScript* types = script->types()) {
if (JitScript* jitScript = script->jitScript()) {
Zone* zone = script->zone();
if (types->typesNeedsSweep(zone)) {
types->sweepTypes(*this, zone);
if (jitScript->typesNeedsSweep(zone)) {
jitScript->sweepTypes(*this, zone);
}
}
}
#ifdef DEBUG
inline AutoSweepTypeScript::~AutoSweepTypeScript() {
inline AutoSweepJitScript::~AutoSweepJitScript() {
// This should still hold.
MOZ_ASSERT_IF(typeScript_, !typeScript_->typesNeedsSweep(zone_));
MOZ_ASSERT_IF(jitScript_, !jitScript_->typesNeedsSweep(zone_));
}
#endif
inline bool TypeScript::typesNeedsSweep(Zone* zone) const {
MOZ_ASSERT(!js::TlsContext.get()->inUnsafeCallWithABI);
return typesGeneration() != zone->types.generation;
}
} // namespace js
inline bool JSScript::ensureHasTypes(JSContext* cx, js::AutoKeepTypeScripts&) {
return types() || makeTypes(cx);
}
#endif /* vm_TypeInference_inl_h */

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

@ -1186,16 +1186,16 @@ CompilerConstraintList* js::NewCompilerConstraintList(
}
/* static */
bool TypeScript::FreezeTypeSets(CompilerConstraintList* constraints,
bool JitScript::FreezeTypeSets(CompilerConstraintList* constraints,
JSScript* script, TemporaryTypeSet** pThisTypes,
TemporaryTypeSet** pArgTypes,
TemporaryTypeSet** pBytecodeTypes) {
LifoAlloc* alloc = constraints->alloc();
AutoSweepTypeScript sweep(script);
TypeScript* typeScript = script->types();
StackTypeSet* existing = typeScript->typeArray(sweep);
AutoSweepJitScript sweep(script);
JitScript* jitScript = script->jitScript();
StackTypeSet* existing = jitScript->typeArray(sweep);
size_t count = typeScript->numTypeSets();
size_t count = jitScript->numTypeSets();
TemporaryTypeSet* types =
alloc->newArrayUninitialized<TemporaryTypeSet>(count);
if (!types) {
@ -1208,12 +1208,12 @@ bool TypeScript::FreezeTypeSets(CompilerConstraintList* constraints,
}
}
size_t thisTypesIndex = typeScript->thisTypes(sweep, script) - existing;
size_t thisTypesIndex = jitScript->thisTypes(sweep, script) - existing;
*pThisTypes = types + thisTypesIndex;
if (script->functionNonDelazifying() &&
script->functionNonDelazifying()->nargs() > 0) {
size_t firstArgIndex = typeScript->argTypes(sweep, script, 0) - existing;
size_t firstArgIndex = jitScript->argTypes(sweep, script, 0) - existing;
*pArgTypes = types + firstArgIndex;
} else {
*pArgTypes = nullptr;
@ -1426,7 +1426,7 @@ bool HeapTypeSetKey::instantiate(JSContext* cx) {
return maybeTypes_ != nullptr;
}
static bool CheckFrozenTypeSet(const AutoSweepTypeScript& sweep, JSContext* cx,
static bool CheckFrozenTypeSet(const AutoSweepJitScript& sweep, JSContext* cx,
TemporaryTypeSet* frozen, StackTypeSet* actual) {
// Return whether the types frozen for a script during compilation are
// still valid. Also check for any new types added to the frozen set during
@ -1509,8 +1509,8 @@ bool js::FinishCompilation(JSContext* cx, HandleScript script,
for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
const CompilerConstraintList::FrozenScript& entry =
constraints->frozenScript(i);
TypeScript* types = entry.script->types();
if (!types) {
JitScript* jitScript = entry.script->jitScript();
if (!jitScript) {
succeeded = false;
break;
}
@ -1523,10 +1523,9 @@ bool js::FinishCompilation(JSContext* cx, HandleScript script,
break;
}
AutoSweepTypeScript sweep(entry.script);
TypeScript* typeScript = entry.script->types();
AutoSweepJitScript sweep(entry.script);
if (!CheckFrozenTypeSet(sweep, cx, entry.thisTypes,
typeScript->thisTypes(sweep, entry.script))) {
jitScript->thisTypes(sweep, entry.script))) {
succeeded = false;
}
unsigned nargs = entry.script->functionNonDelazifying()
@ -1534,13 +1533,13 @@ bool js::FinishCompilation(JSContext* cx, HandleScript script,
: 0;
for (size_t i = 0; i < nargs; i++) {
if (!CheckFrozenTypeSet(sweep, cx, &entry.argTypes[i],
typeScript->argTypes(sweep, entry.script, i))) {
jitScript->argTypes(sweep, entry.script, i))) {
succeeded = false;
}
}
for (size_t i = 0; i < entry.script->numBytecodeTypeSets(); i++) {
if (!CheckFrozenTypeSet(sweep, cx, &entry.bytecodeTypes[i],
&types->typeArray(sweep)[i])) {
&jitScript->typeArray(sweep)[i])) {
succeeded = false;
}
}
@ -1548,19 +1547,19 @@ bool js::FinishCompilation(JSContext* cx, HandleScript script,
// Add this compilation to the inlinedCompilations list of each inlined
// script, so we can invalidate it on changes to stack type sets.
if (entry.script != script) {
if (!types->addInlinedCompilation(sweep, recompileInfo)) {
if (!jitScript->addInlinedCompilation(sweep, recompileInfo)) {
succeeded = false;
}
}
// If necessary, add constraints to trigger invalidation on the script
// after any future changes to the stack type sets.
if (types->hasFreezeConstraints(sweep)) {
if (jitScript->hasFreezeConstraints(sweep)) {
continue;
}
size_t count = types->numTypeSets();
StackTypeSet* array = types->typeArray(sweep);
size_t count = jitScript->numTypeSets();
StackTypeSet* array = jitScript->typeArray(sweep);
for (size_t i = 0; i < count; i++) {
if (!array[i].addConstraint(
cx,
@ -1571,7 +1570,7 @@ bool js::FinishCompilation(JSContext* cx, HandleScript script,
}
if (succeeded) {
types->setHasFreezeConstraints(sweep);
jitScript->setHasFreezeConstraints(sweep);
}
}
@ -1585,7 +1584,7 @@ bool js::FinishCompilation(JSContext* cx, HandleScript script,
return true;
}
static void CheckDefinitePropertiesTypeSet(const AutoSweepTypeScript& sweep,
static void CheckDefinitePropertiesTypeSet(const AutoSweepJitScript& sweep,
JSContext* cx,
TemporaryTypeSet* frozen,
StackTypeSet* actual) {
@ -1615,22 +1614,22 @@ void js::FinishDefinitePropertiesAnalysis(JSContext* cx,
const CompilerConstraintList::FrozenScript& entry =
constraints->frozenScript(i);
JSScript* script = entry.script;
TypeScript* typeScript = script->types();
MOZ_ASSERT(typeScript);
JitScript* jitScript = script->jitScript();
MOZ_ASSERT(jitScript);
AutoSweepTypeScript sweep(script);
MOZ_ASSERT(typeScript->thisTypes(sweep, script)->isSubset(entry.thisTypes));
AutoSweepJitScript sweep(script);
MOZ_ASSERT(jitScript->thisTypes(sweep, script)->isSubset(entry.thisTypes));
unsigned nargs = entry.script->functionNonDelazifying()
? entry.script->functionNonDelazifying()->nargs()
: 0;
for (size_t j = 0; j < nargs; j++) {
StackTypeSet* argTypes = typeScript->argTypes(sweep, script, j);
StackTypeSet* argTypes = jitScript->argTypes(sweep, script, j);
MOZ_ASSERT(argTypes->isSubset(&entry.argTypes[j]));
}
for (size_t j = 0; j < script->numBytecodeTypeSets(); j++) {
MOZ_ASSERT(script->types()->typeArray(sweep)[j].isSubset(
MOZ_ASSERT(script->jitScript()->typeArray(sweep)[j].isSubset(
&entry.bytecodeTypes[j]));
}
}
@ -1640,26 +1639,26 @@ void js::FinishDefinitePropertiesAnalysis(JSContext* cx,
const CompilerConstraintList::FrozenScript& entry =
constraints->frozenScript(i);
JSScript* script = entry.script;
TypeScript* types = script->types();
if (!types) {
JitScript* jitScript = script->jitScript();
if (!jitScript) {
MOZ_CRASH();
}
AutoSweepTypeScript sweep(script);
AutoSweepJitScript sweep(script);
CheckDefinitePropertiesTypeSet(sweep, cx, entry.thisTypes,
types->thisTypes(sweep, script));
jitScript->thisTypes(sweep, script));
unsigned nargs = script->functionNonDelazifying()
? script->functionNonDelazifying()->nargs()
: 0;
for (size_t j = 0; j < nargs; j++) {
StackTypeSet* argTypes = types->argTypes(sweep, script, j);
StackTypeSet* argTypes = jitScript->argTypes(sweep, script, j);
CheckDefinitePropertiesTypeSet(sweep, cx, &entry.argTypes[j], argTypes);
}
for (size_t j = 0; j < script->numBytecodeTypeSets(); j++) {
CheckDefinitePropertiesTypeSet(sweep, cx, &entry.bytecodeTypes[j],
&types->typeArray(sweep)[j]);
&jitScript->typeArray(sweep)[j]);
}
}
}
@ -2696,12 +2695,12 @@ void TypeZone::addPendingRecompile(JSContext* cx, JSScript* script) {
}
// Trigger recompilation of any callers inlining this script.
if (TypeScript* types = script->types()) {
AutoSweepTypeScript sweep(script);
for (const RecompileInfo& info : types->inlinedCompilations(sweep)) {
if (JitScript* jitScript = script->jitScript()) {
AutoSweepJitScript sweep(script);
for (const RecompileInfo& info : jitScript->inlinedCompilations(sweep)) {
addPendingRecompile(cx, info);
}
types->inlinedCompilations(sweep).clearAndFree();
jitScript->inlinedCompilations(sweep).clearAndFree();
}
}
@ -2733,8 +2732,8 @@ void js::PrintTypes(JSContext* cx, Compartment* comp, bool force) {
RootedScript script(cx);
for (auto iter = zone->cellIter<JSScript>(); !iter.done(); iter.next()) {
script = iter;
if (TypeScript* types = script->types()) {
types->printTypes(cx, script);
if (JitScript* jitScript = script->jitScript()) {
jitScript->printTypes(cx, script);
}
}
@ -3334,10 +3333,10 @@ bool js::AddClearDefiniteFunctionUsesInScript(JSContext* cx, ObjectGroup* group,
TypeSet::ObjectKey* calleeKey =
TypeSet::ObjectType(calleeScript->functionNonDelazifying()).objectKey();
AutoSweepTypeScript sweep(script);
TypeScript* typeScript = script->types();
unsigned count = typeScript->numTypeSets();
StackTypeSet* typeArray = typeScript->typeArray(sweep);
AutoSweepJitScript sweep(script);
JitScript* jitScript = script->jitScript();
unsigned count = jitScript->numTypeSets();
StackTypeSet* typeArray = jitScript->typeArray(sweep);
for (unsigned i = 0; i < count; i++) {
StackTypeSet* types = &typeArray[i];
@ -3381,7 +3380,7 @@ void js::TypeMonitorCallSlow(JSContext* cx, JSObject* callee,
JSScript* script = callee->as<JSFunction>().nonLazyScript();
if (!constructing) {
TypeScript::MonitorThisType(cx, script, args.thisv());
JitScript::MonitorThisType(cx, script, args.thisv());
}
/*
@ -3391,39 +3390,24 @@ void js::TypeMonitorCallSlow(JSContext* cx, JSObject* callee,
*/
unsigned arg = 0;
for (; arg < args.length() && arg < nargs; arg++) {
TypeScript::MonitorArgType(cx, script, arg, args[arg]);
JitScript::MonitorArgType(cx, script, arg, args[arg]);
}
/* Watch for fewer actuals than formals to the call. */
for (; arg < nargs; arg++) {
TypeScript::MonitorArgType(cx, script, arg, UndefinedValue());
JitScript::MonitorArgType(cx, script, arg, UndefinedValue());
}
}
static void FillBytecodeTypeMap(JSScript* script, uint32_t* bytecodeMap) {
uint32_t added = 0;
for (jsbytecode* pc = script->code(); pc < script->codeEnd();
pc += GetBytecodeLength(pc)) {
JSOp op = JSOp(*pc);
if (CodeSpec[op].format & JOF_TYPESET) {
bytecodeMap[added++] = script->pcToOffset(pc);
if (added == script->numBytecodeTypeSets()) {
break;
}
}
}
MOZ_ASSERT(added == script->numBytecodeTypeSets());
}
/* static */
void TypeScript::MonitorBytecodeType(JSContext* cx, JSScript* script,
void JitScript::MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, TypeSet::Type type) {
cx->check(script, type);
AutoEnterAnalysis enter(cx);
AutoSweepTypeScript sweep(script);
StackTypeSet* types = script->types()->bytecodeTypes(sweep, script, pc);
AutoSweepJitScript sweep(script);
StackTypeSet* types = script->jitScript()->bytecodeTypes(sweep, script, pc);
if (types->hasType(type)) {
return;
}
@ -3434,16 +3418,16 @@ void TypeScript::MonitorBytecodeType(JSContext* cx, JSScript* script,
}
/* static */
void TypeScript::MonitorBytecodeTypeSlow(JSContext* cx, JSScript* script,
void JitScript::MonitorBytecodeTypeSlow(JSContext* cx, JSScript* script,
jsbytecode* pc, StackTypeSet* types,
TypeSet::Type type) {
cx->check(script, type);
AutoEnterAnalysis enter(cx);
AutoSweepTypeScript sweep(script);
AutoSweepJitScript sweep(script);
MOZ_ASSERT(types == script->types()->bytecodeTypes(sweep, script, pc));
MOZ_ASSERT(types == script->jitScript()->bytecodeTypes(sweep, script, pc));
MOZ_ASSERT(!types->hasType(type));
InferSpew(ISpewOps, "bytecodeType: %p %05zu: %s", script,
@ -3452,130 +3436,17 @@ void TypeScript::MonitorBytecodeTypeSlow(JSContext* cx, JSScript* script,
}
/* static */
void TypeScript::MonitorBytecodeType(JSContext* cx, JSScript* script,
void JitScript::MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, const js::Value& rval) {
MOZ_ASSERT(CodeSpec[*pc].format & JOF_TYPESET);
if (!script->types()) {
if (!script->jitScript()) {
return;
}
MonitorBytecodeType(cx, script, pc, TypeSet::GetValueType(rval));
}
/////////////////////////////////////////////////////////////////////
// TypeScript
/////////////////////////////////////////////////////////////////////
static size_t NumTypeSets(JSScript* script) {
size_t num = script->numBytecodeTypeSets() + 1 /* this */;
if (JSFunction* fun = script->functionNonDelazifying()) {
num += fun->nargs();
}
// We rely on |num| being in a safe range to prevent overflow when allocating
// TypeScript.
static_assert(JSScript::MaxBytecodeTypeSets == UINT16_MAX,
"JSScript typesets should have safe range to avoid overflow");
static_assert(JSFunction::NArgsBits == 16,
"JSFunction nargs should have safe range to avoid overflow");
return num;
}
TypeScript::TypeScript(JSScript* script, ICScriptPtr&& icScript,
uint32_t numTypeSets)
: icScript_(std::move(icScript)), numTypeSets_(numTypeSets) {
setTypesGeneration(script->zone()->types.generation);
StackTypeSet* array = typeArrayDontCheckGeneration();
for (unsigned i = 0; i < numTypeSets; i++) {
new (&array[i]) StackTypeSet();
}
FillBytecodeTypeMap(script, bytecodeTypeMap());
}
bool JSScript::makeTypes(JSContext* cx) {
MOZ_ASSERT(!types_);
cx->check(this);
// Scripts that will never run in the Baseline Interpreter or the JITs don't
// need a TypeScript.
MOZ_ASSERT(!hasForceInterpreterOp());
AutoEnterAnalysis enter(cx);
// Run the arguments-analysis if needed. Both the Baseline Interpreter and
// Compiler rely on this.
if (!ensureHasAnalyzedArgsUsage(cx)) {
return false;
}
// If ensureHasAnalyzedArgsUsage allocated the TypeScript we're done.
if (types_) {
return true;
}
UniquePtr<jit::ICScript> icScript(jit::ICScript::create(cx, this));
if (!icScript) {
return false;
}
// We need to call prepareForDestruction on ICScript before we |delete| it.
auto prepareForDestruction = mozilla::MakeScopeExit(
[&] { icScript->prepareForDestruction(cx->zone()); });
size_t numTypeSets = NumTypeSets(this);
size_t bytecodeTypeMapEntries = numBytecodeTypeSets();
// Calculate allocation size. This cannot overflow, see comment in
// NumTypeSets.
static_assert(sizeof(TypeScript) ==
sizeof(StackTypeSet) + offsetof(TypeScript, typeArray_),
"typeArray_ must be last member of TypeScript");
size_t allocSize =
(offsetof(TypeScript, typeArray_) + numTypeSets * sizeof(StackTypeSet) +
bytecodeTypeMapEntries * sizeof(uint32_t));
auto typeScript =
reinterpret_cast<TypeScript*>(cx->pod_malloc<uint8_t>(allocSize));
if (!typeScript) {
return false;
}
prepareForDestruction.release();
MOZ_ASSERT(!types_);
types_ = new (typeScript) TypeScript(this, std::move(icScript), numTypeSets);
// We have a TypeScript so we can set the script's jitCodeRaw_ pointer to the
// Baseline Interpreter code.
updateJitCodeRaw(cx->runtime());
#ifdef DEBUG
AutoSweepTypeScript sweep(this);
StackTypeSet* typeArray = typeScript->typeArrayDontCheckGeneration();
for (unsigned i = 0; i < numBytecodeTypeSets(); i++) {
InferSpew(ISpewOps, "typeSet: %sT%p%s bytecode%u %p",
InferSpewColor(&typeArray[i]), &typeArray[i],
InferSpewColorReset(), i, this);
}
StackTypeSet* thisTypes = typeScript->thisTypes(sweep, this);
InferSpew(ISpewOps, "typeSet: %sT%p%s this %p", InferSpewColor(thisTypes),
thisTypes, InferSpewColorReset(), this);
unsigned nargs =
functionNonDelazifying() ? functionNonDelazifying()->nargs() : 0;
for (unsigned i = 0; i < nargs; i++) {
StackTypeSet* types = typeScript->argTypes(sweep, this, i);
InferSpew(ISpewOps, "typeSet: %sT%p%s arg%u %p", InferSpewColor(types),
types, InferSpewColorReset(), i, this);
}
#endif
return true;
}
/* static */
bool JSFunction::setTypeForScriptedFunction(JSContext* cx, HandleFunction fun,
bool singleton /* = false */) {
@ -4498,7 +4369,7 @@ void ObjectGroup::sweep(const AutoSweepObjectGroup& sweep) {
}
/* static */
void TypeScript::sweepTypes(const js::AutoSweepTypeScript& sweep, Zone* zone) {
void JitScript::sweepTypes(const js::AutoSweepJitScript& sweep, Zone* zone) {
MOZ_ASSERT(typesGeneration() != zone->types.generation);
setTypesGeneration(zone->types.generation);
@ -4539,25 +4410,6 @@ void TypeScript::sweepTypes(const js::AutoSweepTypeScript& sweep, Zone* zone) {
}
}
void JSScript::maybeReleaseTypes() {
if (!types_ || zone()->types.keepTypeScripts || hasBaselineScript() ||
types_->active()) {
return;
}
MOZ_ASSERT(!hasIonScript());
types_->destroy(zone());
types_ = nullptr;
updateJitCodeRaw(runtimeFromMainThread());
}
void TypeScript::destroy(Zone* zone) {
icScript_->prepareForDestruction(zone);
js_delete(this);
}
void Zone::addSizeOfIncludingThis(
mozilla::MallocSizeOf mallocSizeOf, size_t* typePool, size_t* regexpZone,
size_t* jitZone, size_t* baselineStubsOptimized, size_t* cachedCFG,
@ -4590,12 +4442,12 @@ TypeZone::TypeZone(Zone* zone)
sweepTypeLifoAlloc(zone, (size_t)TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
sweepingTypes(zone, false),
oomSweepingTypes(zone, false),
keepTypeScripts(zone, false),
keepJitScripts(zone, false),
activeAnalysis(zone, nullptr) {}
TypeZone::~TypeZone() {
MOZ_RELEASE_ASSERT(!sweepingTypes);
MOZ_ASSERT(!keepTypeScripts);
MOZ_ASSERT(!keepJitScripts);
}
void TypeZone::beginSweep() {
@ -4638,65 +4490,6 @@ AutoClearTypeInferenceStateOnOOM::~AutoClearTypeInferenceStateOnOOM() {
zone->types.setSweepingTypes(false);
}
#ifdef DEBUG
void TypeScript::printTypes(JSContext* cx, HandleScript script) {
AutoSweepTypeScript sweep(script);
MOZ_ASSERT(script->types() == this);
AutoEnterAnalysis enter(nullptr, script->zone());
Fprinter out(stderr);
if (script->functionNonDelazifying()) {
fprintf(stderr, "Function");
} else if (script->isForEval()) {
fprintf(stderr, "Eval");
} else {
fprintf(stderr, "Main");
}
fprintf(stderr, " %#" PRIxPTR " %s:%u ", uintptr_t(script.get()),
script->filename(), script->lineno());
if (script->functionNonDelazifying()) {
if (JSAtom* name = script->functionNonDelazifying()->explicitName()) {
name->dumpCharsNoNewline(out);
}
}
fprintf(stderr, "\n this:");
thisTypes(sweep, script)->print();
for (unsigned i = 0; script->functionNonDelazifying() &&
i < script->functionNonDelazifying()->nargs();
i++) {
fprintf(stderr, "\n arg%u:", i);
argTypes(sweep, script, i)->print();
}
fprintf(stderr, "\n");
for (jsbytecode* pc = script->code(); pc < script->codeEnd();
pc += GetBytecodeLength(pc)) {
{
fprintf(stderr, "%p:", script.get());
Sprinter sprinter(cx);
if (!sprinter.init()) {
return;
}
Disassemble1(cx, script, pc, script->pcToOffset(pc), true, &sprinter);
fprintf(stderr, "%s", sprinter.string());
}
if (CodeSpec[*pc].format & JOF_TYPESET) {
StackTypeSet* types = bytecodeTypes(sweep, script, pc);
fprintf(stderr, " typeset %u:", unsigned(types - typeArray(sweep)));
types->print();
fprintf(stderr, "\n");
}
}
fprintf(stderr, "\n");
}
#endif /* DEBUG */
JS::ubi::Node::Size JS::ubi::Concrete<js::ObjectGroup>::size(
mozilla::MallocSizeOf mallocSizeOf) const {
Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind());

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

@ -31,14 +31,13 @@
namespace js {
class TypeConstraint;
class TypeScript;
class JitScript;
class TypeZone;
class CompilerConstraintList;
class HeapTypeSetKey;
namespace jit {
class ICScript;
struct IonScript;
class TempAllocator;
@ -84,20 +83,20 @@ class MOZ_RAII AutoSweepObjectGroup : public AutoSweepBase {
#endif
};
// Sweep a TypeScript. Functions that expect a swept script should take a
// reference to this class.
class MOZ_RAII AutoSweepTypeScript : public AutoSweepBase {
// Sweep the type inference data in a JitScript. Functions that expect a swept
// script should take a reference to this class.
class MOZ_RAII AutoSweepJitScript : public AutoSweepBase {
#ifdef DEBUG
Zone* zone_;
TypeScript* typeScript_;
JitScript* jitScript_;
#endif
public:
inline explicit AutoSweepTypeScript(JSScript* script);
inline explicit AutoSweepJitScript(JSScript* script);
#ifdef DEBUG
inline ~AutoSweepTypeScript();
inline ~AutoSweepJitScript();
TypeScript* typeScript() const { return typeScript_; }
JitScript* jitScript() const { return jitScript_; }
Zone* zone() const { return zone_; }
#endif
};
@ -201,206 +200,6 @@ class RecompileInfo {
// single IonScript doesn't require an allocation.
typedef Vector<RecompileInfo, 1, SystemAllocPolicy> RecompileInfoVector;
/* Persistent type information for a script, retained across GCs. */
class TypeScript {
friend class ::JSScript;
// The freeze constraints added to stack type sets will only directly
// invalidate the script containing those stack type sets. This Vector
// contains compilations that inlined this script, so we can invalidate
// them as well.
RecompileInfoVector inlinedCompilations_;
// ICScript and TypeScript have the same lifetimes, so we store a pointer to
// ICScript here to not increase sizeof(JSScript).
using ICScriptPtr = js::UniquePtr<js::jit::ICScript>;
ICScriptPtr icScript_;
// Number of TypeSets in typeArray_.
uint32_t numTypeSets_;
// This field is used to avoid binary searches for the sought entry when
// bytecode map queries are in linear order.
uint32_t bytecodeTypeMapHint_ = 0;
struct Flags {
// Flag set when discarding JIT code to indicate this script is on the stack
// and type information and JIT code should not be discarded.
bool active : 1;
// Generation for type sweeping. If out of sync with the TypeZone's
// generation, this TypeScript needs to be swept.
bool typesGeneration : 1;
// Whether freeze constraints for stack type sets have been generated.
bool hasFreezeConstraints : 1;
};
Flags flags_ = {}; // Zero-initialize flags.
// Variable-size array. This is followed by the bytecode type map.
StackTypeSet typeArray_[1];
StackTypeSet* typeArrayDontCheckGeneration() {
// Ensure typeArray_ is the last data member of TypeScript.
static_assert(sizeof(TypeScript) ==
sizeof(typeArray_) + offsetof(TypeScript, typeArray_),
"typeArray_ must be the last member of TypeScript");
return const_cast<StackTypeSet*>(typeArray_);
}
uint32_t typesGeneration() const { return uint32_t(flags_.typesGeneration); }
void setTypesGeneration(uint32_t generation) {
MOZ_ASSERT(generation <= 1);
flags_.typesGeneration = generation;
}
public:
TypeScript(JSScript* script, ICScriptPtr&& icScript, uint32_t numTypeSets);
bool hasFreezeConstraints(const js::AutoSweepTypeScript& sweep) const {
MOZ_ASSERT(sweep.typeScript() == this);
return flags_.hasFreezeConstraints;
}
void setHasFreezeConstraints(const js::AutoSweepTypeScript& sweep) {
MOZ_ASSERT(sweep.typeScript() == this);
flags_.hasFreezeConstraints = true;
}
inline bool typesNeedsSweep(Zone* zone) const;
void sweepTypes(const js::AutoSweepTypeScript& sweep, Zone* zone);
RecompileInfoVector& inlinedCompilations(
const js::AutoSweepTypeScript& sweep) {
MOZ_ASSERT(sweep.typeScript() == this);
return inlinedCompilations_;
}
MOZ_MUST_USE bool addInlinedCompilation(const js::AutoSweepTypeScript& sweep,
RecompileInfo info) {
MOZ_ASSERT(sweep.typeScript() == this);
if (!inlinedCompilations_.empty() && inlinedCompilations_.back() == info) {
return true;
}
return inlinedCompilations_.append(info);
}
uint32_t numTypeSets() const { return numTypeSets_; }
uint32_t* bytecodeTypeMapHint() { return &bytecodeTypeMapHint_; }
bool active() const { return flags_.active; }
void setActive() { flags_.active = true; }
void resetActive() { flags_.active = false; }
jit::ICScript* icScript() const {
MOZ_ASSERT(icScript_);
return icScript_.get();
}
/* Array of type sets for variables and JOF_TYPESET ops. */
StackTypeSet* typeArray(const js::AutoSweepTypeScript& sweep) {
MOZ_ASSERT(sweep.typeScript() == this);
return typeArrayDontCheckGeneration();
}
uint32_t* bytecodeTypeMap() {
MOZ_ASSERT(numTypeSets_ > 0);
return reinterpret_cast<uint32_t*>(typeArray_ + numTypeSets_);
}
inline StackTypeSet* thisTypes(const AutoSweepTypeScript& sweep,
JSScript* script);
inline StackTypeSet* argTypes(const AutoSweepTypeScript& sweep,
JSScript* script, unsigned i);
/* Get the type set for values observed at an opcode. */
inline StackTypeSet* bytecodeTypes(const AutoSweepTypeScript& sweep,
JSScript* script, jsbytecode* pc);
template <typename TYPESET>
static inline TYPESET* BytecodeTypes(JSScript* script, jsbytecode* pc,
uint32_t* bytecodeMap, uint32_t* hint,
TYPESET* typeArray);
/*
* Monitor a bytecode pushing any value. This must be called for any opcode
* which is JOF_TYPESET, and where either the script has not been analyzed
* by type inference or where the pc has type barriers. For simplicity, we
* always monitor JOF_TYPESET opcodes in the interpreter and stub calls,
* and only look at barriers when generating JIT code for the script.
*/
static void MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, const js::Value& val);
static void MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, TypeSet::Type type);
static inline void MonitorBytecodeType(JSContext* cx, JSScript* script,
jsbytecode* pc, StackTypeSet* types,
const js::Value& val);
private:
static void MonitorBytecodeTypeSlow(JSContext* cx, JSScript* script,
jsbytecode* pc, StackTypeSet* types,
TypeSet::Type type);
public:
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
static inline void MonitorAssign(JSContext* cx, HandleObject obj, jsid id);
/* Add a type for a variable in a script. */
static inline void MonitorThisType(JSContext* cx, JSScript* script,
TypeSet::Type type);
static inline void MonitorThisType(JSContext* cx, JSScript* script,
const js::Value& value);
static inline void MonitorArgType(JSContext* cx, JSScript* script,
unsigned arg, TypeSet::Type type);
static inline void MonitorArgType(JSContext* cx, JSScript* script,
unsigned arg, const js::Value& value);
/*
* Freeze all the stack type sets in a script, for a compilation. Returns
* copies of the type sets which will be checked against the actual ones
* under FinishCompilation, to detect any type changes.
*/
static bool FreezeTypeSets(CompilerConstraintList* constraints,
JSScript* script, TemporaryTypeSet** pThisTypes,
TemporaryTypeSet** pArgTypes,
TemporaryTypeSet** pBytecodeTypes);
void destroy(Zone* zone);
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
// Note: icScript_ size is reported in jit::AddSizeOfBaselineData.
return mallocSizeOf(this);
}
static constexpr size_t offsetOfICScript() {
// Note: icScript_ is a UniquePtr that stores the raw pointer. If that ever
// changes and this assertion fails, we should stop using UniquePtr.
static_assert(sizeof(icScript_) == sizeof(uintptr_t),
"JIT code assumes icScript_ is pointer-sized");
return offsetof(TypeScript, icScript_);
}
#ifdef DEBUG
void printTypes(JSContext* cx, HandleScript script);
#endif
};
// Ensures no TypeScripts are purged in the current zone.
class MOZ_RAII AutoKeepTypeScripts {
TypeZone& zone_;
bool prev_;
AutoKeepTypeScripts(const AutoKeepTypeScripts&) = delete;
void operator=(const AutoKeepTypeScripts&) = delete;
public:
explicit inline AutoKeepTypeScripts(JSContext* cx);
inline ~AutoKeepTypeScripts();
};
class RecompileInfo;
// Generate the type constraints for the compilation. Sets |isValidOut| based on
// whether the type constraints still hold.
bool FinishCompilation(JSContext* cx, HandleScript script,
@ -438,7 +237,7 @@ class TypeZone {
ZoneData<bool> sweepingTypes;
ZoneData<bool> oomSweepingTypes;
ZoneData<bool> keepTypeScripts;
ZoneData<bool> keepJitScripts;
// The topmost AutoEnterAnalysis on the stack, if there is one.
ZoneData<AutoEnterAnalysis*> activeAnalysis;

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

@ -235,7 +235,7 @@ class TemporaryTypeSet;
* Information about the set of types associated with an lvalue. There are
* three kinds of type sets:
*
* - StackTypeSet are associated with TypeScripts, for arguments and values
* - StackTypeSet are associated with JitScripts, for arguments and values
* observed at property reads. These are implicitly frozen on compilation
* and only have constraints added to them which can trigger invalidation of
* TypeNewScript information.
@ -672,7 +672,7 @@ class ConstraintTypeSet : public TypeSet {
}
// This takes a reference to AutoSweepBase to ensure we swept the owning
// ObjectGroup or TypeScript.
// ObjectGroup or JitScript.
TypeConstraint* constraintList(const AutoSweepBase& sweep) const {
checkMagic();
if (constraintList_) {

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

@ -188,17 +188,17 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
}
// Ensure the argument types are included in the argument TypeSets stored in
// the TypeScript. This is necessary for Ion, because the import will use
// the JitScript. This is necessary for Ion, because the import will use
// the skip-arg-checks entry point.
//
// Note that the TypeScript is never discarded while the script has a
// Note that the JitScript is never discarded while the script has a
// BaselineScript, so if those checks hold now they must hold at least until
// the BaselineScript is discarded and when that happens the import is
// patched back.
AutoSweepTypeScript sweep(script);
TypeScript* typeScript = script->types();
AutoSweepJitScript sweep(script);
JitScript* jitScript = script->jitScript();
StackTypeSet* thisTypes = typeScript->thisTypes(sweep, script);
StackTypeSet* thisTypes = jitScript->thisTypes(sweep, script);
if (!thisTypes->hasType(TypeSet::UndefinedType())) {
return true;
}
@ -233,7 +233,7 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
MOZ_CRASH("NullRef not expressible");
}
StackTypeSet* argTypes = typeScript->argTypes(sweep, script, i);
StackTypeSet* argTypes = jitScript->argTypes(sweep, script, i);
if (!argTypes->hasType(type)) {
return true;
}
@ -243,7 +243,7 @@ bool Instance::callImport(JSContext* cx, uint32_t funcImportIndex,
// arguments rectifier: check that the imported function can handle
// undefined there.
for (uint32_t i = importArgs.length(); i < importFun->nargs(); i++) {
StackTypeSet* argTypes = typeScript->argTypes(sweep, script, i);
StackTypeSet* argTypes = jitScript->argTypes(sweep, script, i);
if (!argTypes->hasType(TypeSet::UndefinedType())) {
return true;
}

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

@ -1828,9 +1828,9 @@ static void ReportRealmStats(const JS::RealmStats& realmStats,
"The IonMonkey JIT's compilation data (IonScripts).");
ZRREPORT_BYTES(
realmJSPathPrefix + NS_LITERAL_CSTRING("type-inference/type-scripts"),
realmStats.typeInferenceTypeScripts,
"Type sets associated with scripts.");
realmJSPathPrefix + NS_LITERAL_CSTRING("jit-scripts"),
realmStats.jitScripts,
"JIT and Type Inference data associated with scripts.");
ZRREPORT_BYTES(
realmJSPathPrefix +

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

@ -3583,8 +3583,14 @@ bool PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame, const nsRect& aRect,
targetRect = targetRect.Intersect(sf->GetScrolledRect());
}
{
AutoWeakFrame wf(container);
ScrollToShowRect(this, sf, targetRect, aVertical, aHorizontal,
aScrollFlags);
if (!wf.IsAlive()) {
return didScroll;
}
}
nsPoint newPosition = sf->LastScrollDestination();
// If the scroll position increased, that means our content moved up,

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

@ -2180,17 +2180,6 @@ void ScrollFrameHelper::ScrollToCSSPixels(
aOrigin = nsGkAtoms::other;
}
if (aSnap == nsIScrollableFrame::ENABLE_SNAP) {
if (currentCSSPixels.x == aScrollPosition.x) {
pt.x = current.x;
}
if (currentCSSPixels.y == aScrollPosition.y) {
pt.y = current.y;
}
ScrollTo(pt, aMode, aOrigin, nullptr /* range */, aSnap);
return;
}
nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f);
nsRect range(pt.x - halfPixel, pt.y - halfPixel, 2 * halfPixel - 1,
2 * halfPixel - 1);
@ -2238,9 +2227,10 @@ void ScrollFrameHelper::ScrollToWithOrigin(
mRestorePos.x = mRestorePos.y = -1;
}
bool willSnap = false;
if (aSnap == nsIScrollableFrame::ENABLE_SNAP) {
GetSnapPointForDestination(nsIScrollableFrame::DEVICE_PIXELS, mDestination,
aScrollPosition);
willSnap = GetSnapPointForDestination(nsIScrollableFrame::DEVICE_PIXELS,
mDestination, aScrollPosition);
}
nsRect scrollRange = GetLayoutScrollRange();
@ -2252,7 +2242,8 @@ void ScrollFrameHelper::ScrollToWithOrigin(
aOrigin = nsGkAtoms::other;
}
nsRect range = aRange ? *aRange : nsRect(aScrollPosition, nsSize(0, 0));
nsRect range =
aRange && !willSnap ? *aRange : nsRect(aScrollPosition, nsSize(0, 0));
if (aMode != ScrollMode::SmoothMsd) {
// If we get a non-smooth-scroll, reset the cached APZ scroll destination,
@ -4315,17 +4306,6 @@ void ScrollFrameHelper::ScrollByCSSPixels(
aOrigin = nsGkAtoms::other;
}
if (aSnap == nsIScrollableFrame::ENABLE_SNAP) {
if (aDelta.x == 0.0f) {
pt.x = current.x;
}
if (aDelta.y == 0.0f) {
pt.y = current.y;
}
ScrollToWithOrigin(pt, aMode, aOrigin, nullptr /* range */, aSnap);
return;
}
nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f);
nsRect range(pt.x - halfPixel, pt.y - halfPixel, 2 * halfPixel - 1,
2 * halfPixel - 1);
@ -6747,6 +6727,13 @@ static void CollectScrollPositionsForSnap(
WritingMode aWritingModeOnScroller, ScrollSnapInfo& aSnapInfo) {
MOZ_ASSERT(StaticPrefs::layout_css_scroll_snap_v1_enabled());
// Snap positions only affect the nearest ancestor scroll container on the
// element's containing block chain.
nsIScrollableFrame* sf = do_QueryFrame(aFrame);
if (sf) {
return;
}
nsIFrame::ChildListIterator childLists(aFrame);
for (; !childLists.IsDone(); childLists.Next()) {
nsFrameList::Enumerator childFrames(childLists.CurrentList());

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

@ -416,6 +416,10 @@ nsLayoutStylesheetCache* nsLayoutStylesheetCache::Singleton() {
}
void nsLayoutStylesheetCache::InitFromProfile() {
if (!Preferences::GetBool(PREF_LEGACY_STYLESHEET_CUSTOMIZATION)) {
return;
}
nsCOMPtr<nsIXULRuntime> appInfo =
do_GetService("@mozilla.org/xre/app-info;1");
if (appInfo) {
@ -442,28 +446,6 @@ void nsLayoutStylesheetCache::InitFromProfile() {
eLogToConsole);
LoadSheetFile(chromeFile, &mUserChromeSheet, eUserSheetFeatures,
eLogToConsole);
if (XRE_IsParentProcess()) {
if (mUserChromeSheet || mUserContentSheet) {
// Bug 1541233 aims to avoid stat'ing or loading userContent.css or
// userChrome.css during start-up by default. After that point,
// PREF_LEGACY_STYLESHEET_CUSTOMIZATION pref is how users can opt-in
// to continuing to use userChrome.css or userContent.css.
//
// Before bug 1541233 lands though, we'll ship a release which
// continues to look for those files on start-up and sets a pref.
// That way, in a subsequent release when loading those files is
// off by default, those users will still get their userChrome.css
// and userContent.css customizations without having to manually
// set the pref themselves.
Preferences::SetBool(PREF_LEGACY_STYLESHEET_CUSTOMIZATION, true);
}
// We're interested specifically in potential chrome customizations,
// so we only need data points from the parent process
Telemetry::Accumulate(Telemetry::USER_CHROME_CSS_LOADED,
mUserChromeSheet != nullptr);
}
}
void nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,

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