mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 08:35:26 +00:00
Merge m-c to b-i
This commit is contained in:
commit
5f221e9991
@ -296,7 +296,6 @@ skip-if = e10s
|
||||
[browser_contextSearchTabPosition.js]
|
||||
skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash
|
||||
[browser_ctrlTab.js]
|
||||
[browser_customize_popupNotification.js]
|
||||
[browser_datareporting_notification.js]
|
||||
skip-if = !datareporting
|
||||
[browser_devedition.js]
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
let newWin = OpenBrowserWindow();
|
||||
registerCleanupFunction(() => {
|
||||
newWin.close()
|
||||
newWin = null;
|
||||
});
|
||||
whenDelayedStartupFinished(newWin, function () {
|
||||
// Remove the URL bar
|
||||
newWin.gURLBar.parentNode.removeChild(newWin.gURLBar);
|
||||
|
||||
waitForFocus(function () {
|
||||
let PN = newWin.PopupNotifications;
|
||||
try {
|
||||
let panelPromise = promisePopupShown(PN.panel);
|
||||
let notification = PN.show(newWin.gBrowser.selectedBrowser, "some-notification", "Some message");
|
||||
panelPromise.then(function() {
|
||||
ok(notification, "showed the notification");
|
||||
ok(PN.isPanelOpen, "panel is open");
|
||||
is(PN.panel.anchorNode, newWin.gBrowser.selectedTab, "notification is correctly anchored to the tab");
|
||||
PN.panel.hidePopup();
|
||||
finish();
|
||||
});
|
||||
} catch (ex) {
|
||||
ok(false, "threw exception: " + ex);
|
||||
finish();
|
||||
}
|
||||
}, newWin);
|
||||
});
|
||||
}
|
@ -1535,13 +1535,29 @@ this.MozLoopService = {
|
||||
let urlStr = this.getLoopPref("gettingStarted.url");
|
||||
let url = new URL(Services.urlFormatter.formatURL(urlStr));
|
||||
for (let paramName in aAdditionalParams) {
|
||||
url.searchParams.append(paramName, aAdditionalParams[paramName]);
|
||||
url.searchParams.set(paramName, aAdditionalParams[paramName]);
|
||||
}
|
||||
if (aSrc) {
|
||||
url.searchParams.set("utm_source", "firefox-browser");
|
||||
url.searchParams.set("utm_medium", "firefox-browser");
|
||||
url.searchParams.set("utm_campaign", aSrc);
|
||||
}
|
||||
|
||||
// Find the most recent pageID that has the Loop prefix.
|
||||
let mostRecentLoopPageID = {id: null, lastSeen: null};
|
||||
for (let pageID of UITour.pageIDsForSession) {
|
||||
if (pageID[0] && pageID[0].startsWith("hello-tour_OpenPanel_") &&
|
||||
pageID[1] && pageID[1].lastSeen > mostRecentLoopPageID.lastSeen) {
|
||||
mostRecentLoopPageID.id = pageID[0];
|
||||
mostRecentLoopPageID.lastSeen = pageID[1].lastSeen;
|
||||
}
|
||||
}
|
||||
|
||||
const PAGE_ID_EXPIRATION_MS = 60 * 60 * 1000;
|
||||
if (mostRecentLoopPageID.id &&
|
||||
mostRecentLoopPageID.lastSeen > Date.now() - PAGE_ID_EXPIRATION_MS) {
|
||||
url.searchParams.set("utm_content", mostRecentLoopPageID.id);
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
|
@ -74,6 +74,9 @@ XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
this.UITour = {
|
||||
url: null,
|
||||
seenPageIDs: null,
|
||||
// This map is not persisted and is used for
|
||||
// building the content source of a potential tour.
|
||||
pageIDsForSession: new Map(),
|
||||
pageIDSourceBrowsers: new WeakMap(),
|
||||
/* Map from browser chrome windows to a Set of <browser>s in which a tour is open (both visible and hidden) */
|
||||
tourBrowsersByWindow: new WeakMap(),
|
||||
@ -375,16 +378,22 @@ this.UITour = {
|
||||
|
||||
switch (action) {
|
||||
case "registerPageID": {
|
||||
// This is only relevant if Telemtry is enabled.
|
||||
if (typeof data.pageID != "string") {
|
||||
log.warn("registerPageID: pageID must be a string");
|
||||
break;
|
||||
}
|
||||
|
||||
this.pageIDsForSession.set(data.pageID, {lastSeen: Date.now()});
|
||||
|
||||
// The rest is only relevant if Telemetry is enabled.
|
||||
if (!UITelemetry.enabled) {
|
||||
log.debug("registerPageID: Telemery disabled, not doing anything");
|
||||
log.debug("registerPageID: Telemetry disabled, not doing anything");
|
||||
break;
|
||||
}
|
||||
|
||||
// We don't want to allow BrowserUITelemetry.BUCKET_SEPARATOR in the
|
||||
// pageID, as it could make parsing the telemetry bucket name difficult.
|
||||
if (typeof data.pageID != "string" ||
|
||||
data.pageID.contains(BrowserUITelemetry.BUCKET_SEPARATOR)) {
|
||||
if (data.pageID.contains(BrowserUITelemetry.BUCKET_SEPARATOR)) {
|
||||
log.warn("registerPageID: Invalid page ID specified");
|
||||
break;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_heartbeat.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_loop.js]
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
skip-if = os == "linux" || e10s # Bug 941428 - UITour.jsm not e10s friendly.
|
||||
[browser_UITour_modalDialog.js]
|
||||
run-if = os == "mac" # modal dialog disabling only working on OS X
|
||||
skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
|
||||
|
@ -172,12 +172,12 @@ let tests = [
|
||||
info("'Heartbeat:Voted' notification received (timestamp " + aData.timestamp.toString() + ").");
|
||||
ok(Number.isFinite(aData.timestamp), "Timestamp must be a number.");
|
||||
is(aData.score, expectedScore, "Should report a score of " + expectedScore);
|
||||
done();
|
||||
break;
|
||||
}
|
||||
case "Heartbeat:NotificationClosed": {
|
||||
info("'Heartbeat:NotificationClosed' notification received (timestamp " + aData.timestamp.toString() + ").");
|
||||
ok(Number.isFinite(aData.timestamp), "Timestamp must be a number.");
|
||||
done();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -197,6 +197,7 @@ let tests = [
|
||||
let flowId = "ui-ratefirefox-" + Math.random();
|
||||
let originalTabCount = gBrowser.tabs.length;
|
||||
const expectedTabCount = originalTabCount + 1;
|
||||
let heartbeatVoteSeen = false;
|
||||
|
||||
gContentAPI.observe(function (aEventName, aData) {
|
||||
switch (aEventName) {
|
||||
@ -210,9 +211,11 @@ let tests = [
|
||||
case "Heartbeat:Voted": {
|
||||
info("'Heartbeat:Voted' notification received (timestamp " + aData.timestamp.toString() + ").");
|
||||
ok(Number.isFinite(aData.timestamp), "Timestamp must be a number.");
|
||||
heartbeatVoteSeen = true;
|
||||
break;
|
||||
}
|
||||
case "Heartbeat:NotificationClosed": {
|
||||
ok(heartbeatVoteSeen, "Heartbeat vote should have been received");
|
||||
info("'Heartbeat:NotificationClosed' notification received (timestamp " + aData.timestamp.toString() + ").");
|
||||
ok(Number.isFinite(aData.timestamp), "Timestamp must be a number.");
|
||||
is(gBrowser.tabs.length, expectedTabCount, "Engagement URL should open in a new tab.");
|
||||
|
@ -27,7 +27,84 @@ function runOffline(fun) {
|
||||
}
|
||||
|
||||
let tests = [
|
||||
taskify(function* test_gettingStartedClicked_linkOpenedWithExpectedParams() {
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.seen", false);
|
||||
Services.prefs.setCharPref("loop.gettingStarted.url", "http://example.com");
|
||||
ise(loopButton.open, false, "Menu should initially be closed");
|
||||
loopButton.click();
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopButton.open;
|
||||
}, "Menu should be visible after showMenu()");
|
||||
|
||||
gContentAPI.registerPageID("hello-tour_OpenPanel_testPage");
|
||||
yield new Promise(resolve => {
|
||||
gContentAPI.ping(() => resolve());
|
||||
});
|
||||
|
||||
let loopDoc = document.getElementById("loop-notification-panel").children[0].contentDocument;
|
||||
let gettingStartedButton = loopDoc.getElementById("fte-button");
|
||||
ok(gettingStartedButton, "Getting Started button should be found");
|
||||
|
||||
let newTabPromise = waitForConditionPromise(() => {
|
||||
return gBrowser.currentURI.path.contains("utm_source=firefox-browser");
|
||||
}, "New tab with utm_content=testPageNewID should have opened");
|
||||
|
||||
gettingStartedButton.click();
|
||||
yield newTabPromise;
|
||||
ok(gBrowser.currentURI.path.contains("utm_content=hello-tour_OpenPanel_testPage"),
|
||||
"Expected URL opened (" + gBrowser.currentURI.path + ")");
|
||||
yield gBrowser.removeCurrentTab();
|
||||
|
||||
checkLoopPanelIsHidden();
|
||||
}),
|
||||
taskify(function* test_gettingStartedClicked_linkOpenedWithExpectedParams2() {
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.seen", false);
|
||||
// Force a refresh of the loop panel since going from seen -> unseen doesn't trigger
|
||||
// automatic re-rendering.
|
||||
let loopWin = document.getElementById("loop-notification-panel").children[0].contentWindow;
|
||||
var event = new loopWin.CustomEvent("GettingStartedSeen");
|
||||
loopWin.dispatchEvent(event);
|
||||
|
||||
UITour.pageIDsForSession.clear();
|
||||
Services.prefs.setCharPref("loop.gettingStarted.url", "http://example.com");
|
||||
ise(loopButton.open, false, "Menu should initially be closed");
|
||||
loopButton.click();
|
||||
|
||||
yield waitForConditionPromise(() => {
|
||||
return loopButton.open;
|
||||
}, "Menu should be visible after showMenu()");
|
||||
|
||||
|
||||
gContentAPI.registerPageID("hello-tour_OpenPanel_testPageOldId");
|
||||
yield new Promise(resolve => {
|
||||
gContentAPI.ping(() => resolve());
|
||||
});
|
||||
// Set the time of the page ID to 10 hours earlier, so that it is considered "expired".
|
||||
UITour.pageIDsForSession.set("hello-tour_OpenPanel_testPageOldId",
|
||||
{lastSeen: Date.now() - (10 * 60 * 60 * 1000)});
|
||||
|
||||
let loopDoc = loopWin.document;
|
||||
let gettingStartedButton = loopDoc.getElementById("fte-button");
|
||||
ok(gettingStartedButton, "Getting Started button should be found");
|
||||
|
||||
let newTabPromise = waitForConditionPromise(() => {
|
||||
Services.console.logStringMessage(gBrowser.currentURI.path);
|
||||
return gBrowser.currentURI.path.contains("utm_source=firefox-browser");
|
||||
}, "New tab with utm_content=testPageNewID should have opened");
|
||||
|
||||
gettingStartedButton.click();
|
||||
yield newTabPromise;
|
||||
ok(!gBrowser.currentURI.path.contains("utm_content=hello-tour_OpenPanel_testPageOldId"),
|
||||
"Expected URL opened without the utm_content parameter (" +
|
||||
gBrowser.currentURI.path + ")");
|
||||
yield gBrowser.removeCurrentTab();
|
||||
|
||||
checkLoopPanelIsHidden();
|
||||
}),
|
||||
taskify(function* test_menu_show_hide() {
|
||||
// The targets to highlight only appear after getting started is launched.
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.seen", true);
|
||||
ise(loopButton.open, false, "Menu should initially be closed");
|
||||
gContentAPI.showMenu("loop");
|
||||
|
||||
@ -277,8 +354,6 @@ function setupFakeRoom() {
|
||||
|
||||
if (Services.prefs.getBoolPref("loop.enabled")) {
|
||||
loopButton = window.LoopUI.toolbarButton.node;
|
||||
// The targets to highlight only appear after getting started is launched.
|
||||
Services.prefs.setBoolPref("loop.gettingStarted.seen", true);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
|
||||
|
@ -53,7 +53,8 @@ function getStringPref(pref, def) {
|
||||
}
|
||||
|
||||
function log(str) {
|
||||
dump(str + '\n');
|
||||
var msg = 'ShumwayBootstrapUtils.jsm: ' + str;
|
||||
Services.console.logStringMessage(msg);
|
||||
}
|
||||
|
||||
// Register/unregister a constructor as a factory.
|
||||
@ -80,6 +81,19 @@ Factory.prototype = {
|
||||
let converterFactory = new Factory();
|
||||
let overlayConverterFactory = new Factory();
|
||||
|
||||
function allowedPlatformForMedia() {
|
||||
var oscpu = Cc["@mozilla.org/network/protocol;1?name=http"]
|
||||
.getService(Ci.nsIHttpProtocolHandler).oscpu;
|
||||
if (oscpu.indexOf('Windows NT') === 0) {
|
||||
return oscpu.indexOf('Windows NT 5') < 0; // excluding Windows XP
|
||||
}
|
||||
if (oscpu.indexOf('Intel Mac OS X') === 0) {
|
||||
return true;
|
||||
}
|
||||
// Other platforms are not supported yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
var ShumwayBootstrapUtils = {
|
||||
register: function () {
|
||||
// Register the components.
|
||||
@ -88,7 +102,15 @@ var ShumwayBootstrapUtils = {
|
||||
|
||||
if (registerOverlayPreview) {
|
||||
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
|
||||
var whitelist = getStringPref(PREF_WHITELIST);
|
||||
var whitelist = getStringPref(PREF_WHITELIST);
|
||||
// Some platforms cannot support video playback, and our whitelist targets
|
||||
// only video players atm. We need to disable Shumway for those platforms.
|
||||
if (whitelist && !Services.prefs.prefHasUserValue(PREF_WHITELIST) &&
|
||||
!allowedPlatformForMedia()) {
|
||||
log('Default SWF whitelist is used on an unsupported platform -- ' +
|
||||
'using demo whitelist.');
|
||||
whitelist = 'http://www.areweflashyet.com/*.swf';
|
||||
}
|
||||
Ph.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP,
|
||||
undefined, whitelist);
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ function isShumwayEnabledFor(actions) {
|
||||
function getVersionInfo() {
|
||||
var deferred = Promise.defer();
|
||||
var versionInfo = {
|
||||
version: 'unknown',
|
||||
geckoVersion: 'unknown',
|
||||
geckoBuildID: 'unknown',
|
||||
shumwayVersion: 'unknown'
|
||||
};
|
||||
@ -230,18 +230,30 @@ function getVersionInfo() {
|
||||
versionInfo.geckoVersion = appInfo.version;
|
||||
versionInfo.geckoBuildID = appInfo.appBuildID;
|
||||
} catch (e) {
|
||||
log('Error encountered while getting platform version info:', e);
|
||||
log('Error encountered while getting platform version info: ' + e);
|
||||
}
|
||||
try {
|
||||
var addonId = "shumway@research.mozilla.org";
|
||||
AddonManager.getAddonByID(addonId, function(addon) {
|
||||
versionInfo.shumwayVersion = addon ? addon.version : 'n/a';
|
||||
deferred.resolve(versionInfo);
|
||||
});
|
||||
} catch (e) {
|
||||
log('Error encountered while getting Shumway version info:', e);
|
||||
var xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open('GET', 'resource://shumway/version.txt', true);
|
||||
xhr.overrideMimeType('text/plain');
|
||||
xhr.onload = function () {
|
||||
try {
|
||||
// Trying to merge version.txt lines into something like:
|
||||
// "version (sha) details"
|
||||
var lines = xhr.responseText.split(/\n/g);
|
||||
lines[1] = '(' + lines[1] + ')';
|
||||
versionInfo.shumwayVersion = lines.join(' ');
|
||||
} catch (e) {
|
||||
log('Error while parsing version info: ' + e);
|
||||
}
|
||||
deferred.resolve(versionInfo);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
log('Error while reading version info: ' + xhr.error);
|
||||
deferred.resolve(versionInfo);
|
||||
};
|
||||
xhr.send();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
@ -754,6 +766,7 @@ function activateShumwayScripts(window, requestListener) {
|
||||
}
|
||||
|
||||
function initExternalCom(wrappedWindow, wrappedObject, targetWindow) {
|
||||
var traceExternalInterface = getBoolPref('shumway.externalInterface.trace', false);
|
||||
if (!wrappedWindow.__flash__initialized) {
|
||||
wrappedWindow.__flash__initialized = true;
|
||||
wrappedWindow.__flash__toXML = function __flash__toXML(obj) {
|
||||
@ -786,29 +799,32 @@ function initExternalCom(wrappedWindow, wrappedObject, targetWindow) {
|
||||
}
|
||||
};
|
||||
wrappedWindow.__flash__eval = function (expr) {
|
||||
this.console.log('__flash__eval: ' + expr);
|
||||
traceExternalInterface && this.console.log('__flash__eval: ' + expr);
|
||||
// allowScriptAccess protects page from unwanted swf scripts,
|
||||
// we can execute script in the page context without restrictions.
|
||||
return this.eval(expr);
|
||||
var result = this.eval(expr);
|
||||
traceExternalInterface && this.console.log('__flash__eval (result): ' + result);
|
||||
return result;
|
||||
}.bind(wrappedWindow);
|
||||
wrappedWindow.__flash__call = function (expr) {
|
||||
this.console.log('__flash__call (ignored): ' + expr);
|
||||
traceExternalInterface && this.console.log('__flash__call (ignored): ' + expr);
|
||||
};
|
||||
}
|
||||
wrappedObject.__flash__registerCallback = function (functionName) {
|
||||
wrappedWindow.console.log('__flash__registerCallback: ' + functionName);
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__registerCallback: ' + functionName);
|
||||
Components.utils.exportFunction(function () {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
wrappedWindow.console.log('__flash__callIn: ' + functionName);
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__callIn: ' + functionName);
|
||||
var result;
|
||||
if (targetWindow.wrappedJSObject.onExternalCallback) {
|
||||
result = targetWindow.wrappedJSObject.onExternalCallback({functionName: functionName, args: args});
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__callIn (result): ' + result);
|
||||
}
|
||||
return wrappedWindow.eval(result);
|
||||
}, this, { defineAs: functionName });
|
||||
};
|
||||
wrappedObject.__flash__unregisterCallback = function (functionName) {
|
||||
wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
|
||||
delete this[functionName];
|
||||
};
|
||||
}
|
||||
@ -909,7 +925,11 @@ ShumwayStreamConverterBase.prototype = {
|
||||
throw new Error('Movie url is not specified');
|
||||
}
|
||||
|
||||
baseUrl = objectParams.base || pageUrl;
|
||||
if (objectParams.base) {
|
||||
baseUrl = Services.io.newURI(objectParams.base, null, pageUrl).spec;
|
||||
} else {
|
||||
baseUrl = pageUrl;
|
||||
}
|
||||
|
||||
var movieParams = {};
|
||||
if (objectParams.flashvars) {
|
||||
|
@ -17,6 +17,7 @@ var EXPORTED_SYMBOLS = ["ShumwayUtils"];
|
||||
|
||||
const PREF_PREFIX = 'shumway.';
|
||||
const PREF_DISABLED = PREF_PREFIX + 'disabled';
|
||||
const PREF_WHITELIST = PREF_PREFIX + 'swf.whitelist';
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
@ -43,6 +44,7 @@ let ShumwayUtils = {
|
||||
_registered: false,
|
||||
|
||||
init: function init() {
|
||||
this.migratePreferences();
|
||||
if (this.enabled)
|
||||
this._ensureRegistered();
|
||||
else
|
||||
@ -56,6 +58,19 @@ let ShumwayUtils = {
|
||||
Services.prefs.addObserver(PREF_DISABLED, this, false);
|
||||
},
|
||||
|
||||
migratePreferences: function migratePreferences() {
|
||||
// At one point we had shumway.disabled set to true by default,
|
||||
// and we are trying to replace it with shumway.swf.whitelist:
|
||||
// checking if the user already changed it before to reset
|
||||
// the whitelist to '*'.
|
||||
if (Services.prefs.prefHasUserValue(PREF_DISABLED) &&
|
||||
!Services.prefs.prefHasUserValue(PREF_WHITELIST) &&
|
||||
!getBoolPref(PREF_DISABLED, false)) {
|
||||
// The user is already using Shumway -- enabling all web sites.
|
||||
Services.prefs.setCharPref(PREF_WHITELIST, '*');
|
||||
}
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if (this.enabled)
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,2 @@
|
||||
0.9.3693
|
||||
217e2e2
|
||||
0.9.3775
|
||||
a82ac47
|
||||
|
@ -111,7 +111,7 @@ limitations under the License.
|
||||
<menuitem label="Open in Inspector" id="inspectorMenu"></menuitem>
|
||||
<menuitem label="Report Problems" id="reportMenu"></menuitem>
|
||||
<menuitem label="Reload in Adobe Flash Player" id="fallbackMenu" hidden></menuitem>
|
||||
<menuitem label="About Shumway" id="aboutMenu"></menuitem>
|
||||
<menuitem label="About Shumway %version%..." id="aboutMenu"></menuitem>
|
||||
</menu>
|
||||
</section>
|
||||
|
||||
|
@ -161,6 +161,10 @@ function runViewer() {
|
||||
document.getElementById('inspectorMenu').addEventListener('click', showInInspector);
|
||||
document.getElementById('reportMenu').addEventListener('click', reportIssue);
|
||||
document.getElementById('aboutMenu').addEventListener('click', showAbout);
|
||||
|
||||
var version = Shumway.version || '';
|
||||
document.getElementById('aboutMenu').label =
|
||||
document.getElementById('aboutMenu').label.replace('%version%', version);
|
||||
}
|
||||
|
||||
function showURL() {
|
||||
|
@ -44,7 +44,7 @@ function runSwfPlayer(flashParams) {
|
||||
Shumway.AVM2.Verifier.enabled.value = compilerSettings.verifier;
|
||||
|
||||
Shumway.createAVM2(builtinPath, viewerPlayerglobalInfo, sysMode, appMode, function (avm2) {
|
||||
function runSWF(file) {
|
||||
function runSWF(file, buffer, baseUrl) {
|
||||
var player = new Shumway.Player.Window.WindowPlayer(window, window.parent);
|
||||
player.defaultStageColor = flashParams.bgcolor;
|
||||
player.movieParams = flashParams.movieParams;
|
||||
@ -54,17 +54,18 @@ function runSwfPlayer(flashParams) {
|
||||
|
||||
Shumway.ExternalInterfaceService.instance = player.createExternalInterfaceService();
|
||||
|
||||
player.load(file);
|
||||
player.pageUrl = baseUrl;
|
||||
player.load(file, buffer);
|
||||
}
|
||||
Shumway.FileLoadingService.instance.setBaseUrl(baseUrl);
|
||||
if (asyncLoading) {
|
||||
runSWF(movieUrl);
|
||||
runSWF(movieUrl, undefined, baseUrl);
|
||||
} else {
|
||||
new Shumway.BinaryFileReader(movieUrl).readAll(null, function(buffer, error) {
|
||||
if (!buffer) {
|
||||
throw "Unable to open the file " + movieUrl + ": " + error;
|
||||
}
|
||||
runSWF(movieUrl, buffer);
|
||||
runSWF(movieUrl, buffer, baseUrl);
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -127,6 +128,11 @@ function setupServices() {
|
||||
this.onprogress && this.onprogress(args.array, {bytesLoaded: args.loaded, bytesTotal: args.total});
|
||||
break;
|
||||
}
|
||||
},
|
||||
close: function () {
|
||||
if (Shumway.FileLoadingService.instance.sessions[sessionId]) {
|
||||
// TODO send abort
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -1808,25 +1808,33 @@ void
|
||||
ContentChild::ProcessingError(Result aCode, const char* aReason)
|
||||
{
|
||||
switch (aCode) {
|
||||
case MsgDropped:
|
||||
NS_WARNING("MsgDropped in ContentChild");
|
||||
return;
|
||||
case MsgNotKnown:
|
||||
NS_RUNTIMEABORT("aborting because of MsgNotKnown");
|
||||
case MsgNotAllowed:
|
||||
NS_RUNTIMEABORT("aborting because of MsgNotAllowed");
|
||||
case MsgPayloadError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgPayloadError");
|
||||
case MsgProcessingError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgProcessingError");
|
||||
case MsgRouteError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgRouteError");
|
||||
case MsgValueError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgValueError");
|
||||
case MsgDropped:
|
||||
NS_WARNING("MsgDropped in ContentChild");
|
||||
return;
|
||||
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
case MsgNotKnown:
|
||||
case MsgNotAllowed:
|
||||
case MsgPayloadError:
|
||||
case MsgProcessingError:
|
||||
case MsgRouteError:
|
||||
case MsgValueError:
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
}
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
|
||||
if (ManagedPCrashReporterChild().Length() > 0) {
|
||||
CrashReporterChild* crashReporter =
|
||||
static_cast<CrashReporterChild*>(ManagedPCrashReporterChild()[0]);
|
||||
nsDependentCString reason(aReason);
|
||||
crashReporter->SendAnnotateCrashReport(
|
||||
NS_LITERAL_CSTRING("ipc_channel_error"),
|
||||
reason);
|
||||
}
|
||||
#endif
|
||||
NS_RUNTIMEABORT("Content child abort due to IPC error");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -497,10 +497,10 @@ SystemMessageInternal.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return the |msg| of each pending message (drop the |msgID|).
|
||||
// Return the |msg| of each pending message.
|
||||
let pendingMessages = [];
|
||||
page.pendingMessages.forEach(function(aMessage) {
|
||||
pendingMessages.push(aMessage.msg);
|
||||
pendingMessages.push({ msg: aMessage.msg, msgID: aMessage.msgID });
|
||||
});
|
||||
|
||||
// Clear the pending queue for this page. This is OK since we'll store
|
||||
|
@ -267,7 +267,7 @@ SystemMessageManager.prototype = {
|
||||
}
|
||||
|
||||
let messages = (aMessage.name == "SystemMessageManager:Message")
|
||||
? [msg.msg]
|
||||
? [{ msg: msg.msg, msgID: msg.msgID }]
|
||||
: msg.msgQueue;
|
||||
|
||||
// We only dispatch messages when a handler is registered.
|
||||
@ -285,7 +285,7 @@ SystemMessageManager.prototype = {
|
||||
}
|
||||
|
||||
messages.forEach(function(aMsg) {
|
||||
this._dispatchMessage(msg.type, dispatcher, aMsg, msg.msgID);
|
||||
this._dispatchMessage(msg.type, dispatcher, aMsg.msg, aMsg.msgID);
|
||||
}, this);
|
||||
|
||||
} else {
|
||||
|
@ -535,13 +535,13 @@ TryEnablingJit(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t
|
||||
// BaselineScript, so if those checks hold now they must hold at least until
|
||||
// the BaselineScript is discarded and when that happens the FFI exit is
|
||||
// patched back.
|
||||
if (!types::TypeScript::ThisTypes(script)->hasType(types::Type::UndefinedType()))
|
||||
if (!TypeScript::ThisTypes(script)->hasType(TypeSet::UndefinedType()))
|
||||
return true;
|
||||
for (uint32_t i = 0; i < fun->nargs(); i++) {
|
||||
types::StackTypeSet *typeset = types::TypeScript::ArgTypes(script, i);
|
||||
types::Type type = types::Type::DoubleType();
|
||||
StackTypeSet *typeset = TypeScript::ArgTypes(script, i);
|
||||
TypeSet::Type type = TypeSet::DoubleType();
|
||||
if (!argv[i].isDouble())
|
||||
type = types::Type::PrimitiveType(argv[i].extractNonDoubleType());
|
||||
type = TypeSet::PrimitiveType(argv[i].extractNonDoubleType());
|
||||
if (!typeset->hasType(type))
|
||||
return true;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "vm/Shape-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using js::frontend::IsIdentifier;
|
||||
using mozilla::ArrayLength;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::Maybe;
|
||||
|
@ -2729,7 +2729,7 @@ js::StoreReference##T::Func(JSContext *cx, unsigned argc, Value *vp) \
|
||||
int32_t offset = args[1].toInt32(); \
|
||||
\
|
||||
jsid id = args[2].isString() \
|
||||
? types::IdToTypeId(AtomToId(&args[2].toString()->asAtom())) \
|
||||
? IdToTypeId(AtomToId(&args[2].toString()->asAtom())) \
|
||||
: JSID_VOID; \
|
||||
\
|
||||
/* Should be guaranteed by the typed objects API: */ \
|
||||
@ -2795,8 +2795,8 @@ StoreReferenceHeapValue::store(JSContext *cx, HeapValue *heap, const Value &v,
|
||||
// considered to contain undefined.
|
||||
if (!v.isUndefined()) {
|
||||
if (cx->isJSContext())
|
||||
types::AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!types::HasTypePropertyId(obj, id, v))
|
||||
AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!HasTypePropertyId(obj, id, v))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2815,8 +2815,8 @@ StoreReferenceHeapPtrObject::store(JSContext *cx, HeapPtrObject *heap, const Val
|
||||
// considered to contain null.
|
||||
if (v.isObject()) {
|
||||
if (cx->isJSContext())
|
||||
types::AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!types::HasTypePropertyId(obj, id, v))
|
||||
AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!HasTypePropertyId(obj, id, v))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1902,7 +1902,7 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
* has no object to stand in the static scope chain, 2. to minimize memory
|
||||
* bloat where a single live function keeps its whole global script
|
||||
* alive.), ScopeCoordinateToTypeSet is not able to find the var/let's
|
||||
* associated types::TypeSet.
|
||||
* associated TypeSet.
|
||||
*/
|
||||
if (skip) {
|
||||
BytecodeEmitter *bceSkipped = bce;
|
||||
@ -3704,7 +3704,7 @@ EmitDestructuringOpsObjectHelper(ExclusiveContext *cx, BytecodeEmitter *bce, Par
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(name);
|
||||
if (id != types::IdToTypeId(id)) {
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!EmitTree(cx, bce, key)) // ... OBJ OBJ KEY
|
||||
return false;
|
||||
} else {
|
||||
@ -6622,7 +6622,7 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simpliciation of downstream analysis.
|
||||
jsid id = NameToId(key->pn_atom->asPropertyName());
|
||||
if (id != types::IdToTypeId(id)) {
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!EmitTree(cx, bce, key))
|
||||
return false;
|
||||
isIndex = true;
|
||||
|
@ -834,7 +834,7 @@ Fold(ExclusiveContext *cx, ParseNode **pnp,
|
||||
}
|
||||
}
|
||||
|
||||
if (name && NameToId(name) == types::IdToTypeId(NameToId(name))) {
|
||||
if (name && NameToId(name) == IdToTypeId(NameToId(name))) {
|
||||
// Optimization 3: We have pn1["foo"] where foo is not an index.
|
||||
// Convert to a property access (like pn1.foo) which we optimize
|
||||
// better downstream. Don't bother with this for names which TI
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
JS_STATIC_ASSERT(AllocKinds == FINALIZE_LIMIT);
|
||||
JS_STATIC_ASSERT(LastObjectAllocKind == FINALIZE_OBJECT_LAST);
|
||||
|
@ -787,18 +787,18 @@ gc::MarkValueRoot(JSTracer *trc, Value *v, const char *name)
|
||||
}
|
||||
|
||||
void
|
||||
gc::MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name)
|
||||
TypeSet::MarkTypeRoot(JSTracer *trc, TypeSet::Type *v, const char *name)
|
||||
{
|
||||
JS_ROOT_MARKING_ASSERT(trc);
|
||||
trc->setTracingName(name);
|
||||
if (v->isSingleton()) {
|
||||
JSObject *obj = v->singleton();
|
||||
MarkInternal(trc, &obj);
|
||||
*v = types::Type::ObjectType(obj);
|
||||
*v = TypeSet::ObjectType(obj);
|
||||
} else if (v->isGroup()) {
|
||||
ObjectGroup *group = v->group();
|
||||
MarkInternal(trc, &group);
|
||||
*v = types::Type::ObjectType(group);
|
||||
*v = TypeSet::ObjectType(group);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1426,7 +1426,7 @@ ScanObjectGroup(GCMarker *gcmarker, ObjectGroup *group)
|
||||
{
|
||||
unsigned count = group->getPropertyCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (types::Property *prop = group->getProperty(i))
|
||||
if (ObjectGroup::Property *prop = group->getProperty(i))
|
||||
MarkId(gcmarker, &prop->id, "ObjectGroup property id");
|
||||
}
|
||||
|
||||
@ -1454,8 +1454,7 @@ gc::MarkChildren(JSTracer *trc, ObjectGroup *group)
|
||||
{
|
||||
unsigned count = group->getPropertyCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
types::Property *prop = group->getProperty(i);
|
||||
if (prop)
|
||||
if (ObjectGroup::Property *prop = group->getProperty(i))
|
||||
MarkId(trc, &prop->id, "group_property");
|
||||
}
|
||||
|
||||
|
@ -37,10 +37,6 @@ struct IonScript;
|
||||
struct VMFunction;
|
||||
}
|
||||
|
||||
namespace types {
|
||||
class Type;
|
||||
}
|
||||
|
||||
namespace gc {
|
||||
|
||||
/*** Object Marking ***/
|
||||
@ -213,9 +209,6 @@ MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
|
||||
MarkValueRootRange(trc, end - begin, begin, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name);
|
||||
|
||||
bool
|
||||
IsValueMarked(Value *v);
|
||||
|
||||
|
@ -112,7 +112,7 @@ MarkExactStackRootsAcrossTypes(T context, JSTracer *trc)
|
||||
MarkExactStackRootList<LazyScript *, MarkLazyScriptRoot>(trc, context, "exact-lazy-script");
|
||||
MarkExactStackRootList<jsid, MarkIdRoot>(trc, context, "exact-id");
|
||||
MarkExactStackRootList<Value, MarkValueRoot>(trc, context, "exact-value");
|
||||
MarkExactStackRootList<types::Type, MarkTypeRoot>(trc, context, "types::Type");
|
||||
MarkExactStackRootList<TypeSet::Type, TypeSet::MarkTypeRoot>(trc, context, "TypeSet::Type");
|
||||
MarkExactStackRootList<Bindings, MarkBindingsRoot>(trc, context, "Bindings");
|
||||
MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
|
||||
trc, context, "JSPropertyDescriptor");
|
||||
|
@ -115,7 +115,7 @@ Zone::beginSweepTypes(FreeOp *fop, bool releaseTypes)
|
||||
if (active)
|
||||
releaseTypes = false;
|
||||
|
||||
types::AutoClearTypeInferenceStateOnOOM oom(this);
|
||||
AutoClearTypeInferenceStateOnOOM oom(this);
|
||||
types.beginSweep(fop, releaseTypes, oom);
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ struct Zone : public JS::shadow::Zone,
|
||||
public:
|
||||
js::gc::ArenaLists arenas;
|
||||
|
||||
js::types::TypeZone types;
|
||||
js::TypeZone types;
|
||||
|
||||
// The set of compartments in this zone.
|
||||
typedef js::Vector<JSCompartment *, 1, js::SystemAllocPolicy> CompartmentVector;
|
||||
|
@ -90,7 +90,7 @@ BaselineCompiler::compile()
|
||||
return Method_Error;
|
||||
|
||||
// Pin analysis info during compilation.
|
||||
types::AutoEnterAnalysis autoEnterAnalysis(cx);
|
||||
AutoEnterAnalysis autoEnterAnalysis(cx);
|
||||
|
||||
MOZ_ASSERT(!script->hasBaselineScript());
|
||||
|
||||
@ -250,7 +250,7 @@ BaselineCompiler::compile()
|
||||
#endif
|
||||
|
||||
uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
|
||||
types::FillBytecodeTypeMap(script, bytecodeMap);
|
||||
FillBytecodeTypeMap(script, bytecodeMap);
|
||||
|
||||
// The last entry in the last index found, and is used to avoid binary
|
||||
// searches for the sought entry when queries are in linear order.
|
||||
|
@ -771,7 +771,7 @@ CloneOldBaselineStub(JSContext *cx, DebugModeOSREntryVector &entries, size_t ent
|
||||
static bool
|
||||
InvalidateScriptsInZone(JSContext *cx, Zone *zone, const Vector<DebugModeOSREntry> &entries)
|
||||
{
|
||||
types::RecompileInfoVector invalid;
|
||||
RecompileInfoVector invalid;
|
||||
for (UniqueScriptOSREntryIter iter(entries); !iter.done(); ++iter) {
|
||||
JSScript *script = iter.entry().script;
|
||||
if (script->compartment()->zone() != zone)
|
||||
|
@ -1197,12 +1197,12 @@ DoTypeMonitorFallback(JSContext *cx, BaselineFrame *frame, ICTypeMonitor_Fallbac
|
||||
uint32_t argument;
|
||||
if (stub->monitorsThis()) {
|
||||
MOZ_ASSERT(pc == script->code());
|
||||
types::TypeScript::SetThis(cx, script, value);
|
||||
TypeScript::SetThis(cx, script, value);
|
||||
} else if (stub->monitorsArgument(&argument)) {
|
||||
MOZ_ASSERT(pc == script->code());
|
||||
types::TypeScript::SetArgument(cx, script, argument, value);
|
||||
TypeScript::SetArgument(cx, script, argument, value);
|
||||
} else {
|
||||
types::TypeScript::Monitor(cx, script, pc, value);
|
||||
TypeScript::Monitor(cx, script, pc, value);
|
||||
}
|
||||
|
||||
if (!stub->addMonitorStubForValue(cx, script, value))
|
||||
@ -1324,12 +1324,12 @@ ICUpdatedStub::addUpdateStubForValue(JSContext *cx, HandleScript script, HandleO
|
||||
return true;
|
||||
}
|
||||
|
||||
types::EnsureTrackPropertyTypes(cx, obj, id);
|
||||
EnsureTrackPropertyTypes(cx, obj, id);
|
||||
|
||||
// Make sure that undefined values are explicitly included in the property
|
||||
// types for an object if generating a stub to write an undefined value.
|
||||
if (val.isUndefined() && types::CanHaveEmptyPropertyTypesForOwnProperty(obj))
|
||||
types::AddTypePropertyId(cx, obj, id, val);
|
||||
if (val.isUndefined() && CanHaveEmptyPropertyTypesForOwnProperty(obj))
|
||||
AddTypePropertyId(cx, obj, id, val);
|
||||
|
||||
if (val.isPrimitive()) {
|
||||
JSValueType type = val.isDouble() ? JSVAL_TYPE_DOUBLE : val.extractNonDoubleType();
|
||||
@ -1423,7 +1423,7 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
|
||||
case ICStub::SetElem_DenseAdd: {
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
id = JSID_VOID;
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
break;
|
||||
}
|
||||
case ICStub::SetProp_Native:
|
||||
@ -1435,7 +1435,7 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
|
||||
id = NameToId(ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc));
|
||||
else
|
||||
id = NameToId(script->getName(pc));
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
break;
|
||||
}
|
||||
case ICStub::SetProp_TypedObject: {
|
||||
@ -1448,12 +1448,12 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
|
||||
// and non-object non-null values will cause the stub to fail to
|
||||
// match shortly and we will end up doing the assignment in the VM.
|
||||
if (value.isObject())
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
} else {
|
||||
// Ignore undefined values, which are included implicitly in type
|
||||
// information for this property.
|
||||
if (!value.isUndefined())
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3975,13 +3975,13 @@ DoGetElemFallback(JSContext *cx, BaselineFrame *frame, ICGetElem_Fallback *stub_
|
||||
if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs))
|
||||
return false;
|
||||
if (isOptimizedArgs)
|
||||
types::TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
}
|
||||
|
||||
if (!isOptimizedArgs) {
|
||||
if (!GetElementOperation(cx, op, &lhsCopy, rhs, res))
|
||||
return false;
|
||||
types::TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
}
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
@ -5803,7 +5803,7 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
|
||||
// Instantiate this global property, for use during Ion compilation.
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, current, id);
|
||||
EnsureTrackPropertyTypes(cx, current, id);
|
||||
|
||||
if (shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
|
||||
@ -6006,7 +6006,7 @@ DoGetNameFallback(JSContext *cx, BaselineFrame *frame, ICGetName_Fallback *stub_
|
||||
return false;
|
||||
}
|
||||
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
@ -6195,7 +6195,7 @@ DoGetIntrinsicFallback(JSContext *cx, BaselineFrame *frame, ICGetIntrinsic_Fallb
|
||||
// needs to be monitored once. Attach a stub to load the resulting constant
|
||||
// directly.
|
||||
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
@ -6383,7 +6383,7 @@ HasUnanalyzedNewScript(JSObject *obj)
|
||||
if (obj->isSingleton())
|
||||
return false;
|
||||
|
||||
types::TypeNewScript *newScript = obj->group()->newScript();
|
||||
TypeNewScript *newScript = obj->group()->newScript();
|
||||
if (newScript && !newScript->analyzed())
|
||||
return true;
|
||||
|
||||
@ -6451,7 +6451,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
|
||||
// Instantiate this property for singleton holders, for use during Ion compilation.
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, holder, NameToId(name));
|
||||
EnsureTrackPropertyTypes(cx, holder, NameToId(name));
|
||||
|
||||
ICStub::Kind kind;
|
||||
if (obj == holder)
|
||||
@ -6741,7 +6741,7 @@ TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc
|
||||
// Instantiate this property, for use during Ion compilation.
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, proto, id);
|
||||
EnsureTrackPropertyTypes(cx, proto, id);
|
||||
|
||||
// For now, only look for properties directly set on the prototype.
|
||||
RootedShape shape(cx, proto->lookup(cx, id));
|
||||
@ -6869,7 +6869,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_
|
||||
if (!ComputeGetPropResult(cx, frame, op, name, val, res))
|
||||
return false;
|
||||
|
||||
types::TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
@ -8054,8 +8054,8 @@ TryAttachSetValuePropStub(JSContext *cx, HandleScript script, jsbytecode *pc, IC
|
||||
// properties, TI will not mark the property as having been
|
||||
// overwritten. Don't attach a stub in this case, so that we don't
|
||||
// execute another write to the property without TI seeing that write.
|
||||
types::EnsureTrackPropertyTypes(cx, obj, id);
|
||||
if (!types::PropertyHasBeenMarkedNonConstant(obj, id)) {
|
||||
EnsureTrackPropertyTypes(cx, obj, id);
|
||||
if (!PropertyHasBeenMarkedNonConstant(obj, id)) {
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
@ -9327,7 +9327,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
// Keep track of the function's |prototype| property in type
|
||||
// information, for use during Ion compilation.
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, fun, NameToId(cx->names().prototype));
|
||||
EnsureTrackPropertyTypes(cx, fun, NameToId(cx->names().prototype));
|
||||
|
||||
// Remember the template object associated with any script being called
|
||||
// as a constructor, for later use during Ion compilation.
|
||||
@ -9345,7 +9345,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||
// stub. After the analysis is performed, CreateThisForFunction may
|
||||
// start returning objects with a different type, and the Ion
|
||||
// compiler might get confused.
|
||||
types::TypeNewScript *newScript = templateObject->group()->newScript();
|
||||
TypeNewScript *newScript = templateObject->group()->newScript();
|
||||
if (newScript && !newScript->analyzed()) {
|
||||
// Clear the object just created from the preliminary objects
|
||||
// on the TypeNewScript, as it will not be used or filled in by
|
||||
@ -9573,7 +9573,7 @@ DoCallFallback(JSContext *cx, BaselineFrame *frame, ICCall_Fallback *stub_, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
@ -11234,7 +11234,7 @@ DoInstanceOfFallback(JSContext *cx, BaselineFrame *frame, ICInstanceOf_Fallback
|
||||
|
||||
// For functions, keep track of the |prototype| property in type information,
|
||||
// for use during Ion compilation.
|
||||
types::EnsureTrackPropertyTypes(cx, obj, NameToId(cx->names().prototype));
|
||||
EnsureTrackPropertyTypes(cx, obj, NameToId(cx->names().prototype));
|
||||
|
||||
if (stub->numOptimizedStubs() >= ICInstanceOf_Fallback::MAX_OPTIMIZED_STUBS)
|
||||
return true;
|
||||
|
@ -3395,7 +3395,7 @@ CodeGenerator::generateArgumentsChecks(bool bailout)
|
||||
for (uint32_t i = info.startArgSlot(); i < info.endArgSlot(); i++) {
|
||||
// All initial parameters are guaranteed to be MParameters.
|
||||
MParameter *param = rp->getOperand(i)->toParameter();
|
||||
const types::TypeSet *types = param->resultTypeSet();
|
||||
const TypeSet *types = param->resultTypeSet();
|
||||
if (!types || types->unknown())
|
||||
continue;
|
||||
|
||||
@ -7215,11 +7215,11 @@ CodeGenerator::generate()
|
||||
struct AutoDiscardIonCode
|
||||
{
|
||||
JSContext *cx;
|
||||
types::RecompileInfo *recompileInfo;
|
||||
RecompileInfo *recompileInfo;
|
||||
IonScript *ionScript;
|
||||
bool keep;
|
||||
|
||||
AutoDiscardIonCode(JSContext *cx, types::RecompileInfo *recompileInfo)
|
||||
AutoDiscardIonCode(JSContext *cx, RecompileInfo *recompileInfo)
|
||||
: cx(cx), recompileInfo(recompileInfo), ionScript(nullptr), keep(false) {}
|
||||
|
||||
~AutoDiscardIonCode() {
|
||||
@ -7240,7 +7240,7 @@ struct AutoDiscardIonCode
|
||||
};
|
||||
|
||||
bool
|
||||
CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
|
||||
CodeGenerator::link(JSContext *cx, CompilerConstraintList *constraints)
|
||||
{
|
||||
RootedScript script(cx, gen->info().script());
|
||||
OptimizationLevel optimizationLevel = gen->optimizationInfo().level();
|
||||
@ -7261,8 +7261,8 @@ CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
|
||||
// Check to make sure we didn't have a mid-build invalidation. If so, we
|
||||
// will trickle to jit::Compile() and return Method_Skipped.
|
||||
uint32_t warmUpCount = script->getWarmUpCount();
|
||||
types::RecompileInfo recompileInfo;
|
||||
if (!types::FinishCompilation(cx, script, constraints, &recompileInfo))
|
||||
RecompileInfo recompileInfo;
|
||||
if (!FinishCompilation(cx, script, constraints, &recompileInfo))
|
||||
return true;
|
||||
|
||||
// IonMonkey could have inferred better type information during
|
||||
|
@ -56,7 +56,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
public:
|
||||
bool generate();
|
||||
bool generateAsmJS(AsmJSFunctionLabels *labels);
|
||||
bool link(JSContext *cx, types::CompilerConstraintList *constraints);
|
||||
bool link(JSContext *cx, CompilerConstraintList *constraints);
|
||||
|
||||
void visitLabel(LLabel *lir);
|
||||
void visitNop(LNop *lir);
|
||||
|
@ -471,7 +471,7 @@ jit::LazyLinkTopActivation(JSContext *cx)
|
||||
IonBuilder *builder = it.script()->ionScript()->pendingBuilder();
|
||||
it.script()->setPendingIonBuilder(cx, nullptr);
|
||||
|
||||
types::AutoEnterAnalysis enterTypes(cx);
|
||||
AutoEnterAnalysis enterTypes(cx);
|
||||
RootedScript script(cx, builder->script());
|
||||
|
||||
// Remove from pending.
|
||||
@ -749,7 +749,7 @@ IonScript::IonScript()
|
||||
}
|
||||
|
||||
IonScript *
|
||||
IonScript::New(JSContext *cx, types::RecompileInfo recompileInfo,
|
||||
IonScript::New(JSContext *cx, RecompileInfo recompileInfo,
|
||||
uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
|
||||
size_t snapshotsListSize, size_t snapshotsRVATableSize,
|
||||
size_t recoversSize, size_t bailoutEntries,
|
||||
@ -1600,7 +1600,7 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
if (!ion)
|
||||
return;
|
||||
|
||||
types::AutoEnterAnalysis enterTypes(cx);
|
||||
AutoEnterAnalysis enterTypes(cx);
|
||||
AutoLockHelperThreadState lock;
|
||||
|
||||
GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
|
||||
@ -1758,7 +1758,7 @@ TrackAllProperties(JSContext *cx, JSObject *obj)
|
||||
MOZ_ASSERT(obj->isSingleton());
|
||||
|
||||
for (Shape::Range<NoGC> range(obj->lastProperty()); !range.empty(); range.popFront())
|
||||
types::EnsureTrackPropertyTypes(cx, obj, range.front().propid());
|
||||
EnsureTrackPropertyTypes(cx, obj, range.front().propid());
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1839,7 +1839,7 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
|
||||
JitContext jctx(cx, temp);
|
||||
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!cx->compartment()->ensureJitCompartmentExists(cx))
|
||||
return AbortReason_Alloc;
|
||||
@ -1872,7 +1872,7 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
return AbortReason_Alloc;
|
||||
}
|
||||
|
||||
types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(*temp);
|
||||
CompilerConstraintList *constraints = NewCompilerConstraintList(*temp);
|
||||
if (!constraints)
|
||||
return AbortReason_Alloc;
|
||||
|
||||
@ -2645,8 +2645,8 @@ jit::InvalidateAll(FreeOp *fop, Zone *zone)
|
||||
|
||||
|
||||
void
|
||||
jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
const types::RecompileInfoVector &invalid, bool resetUses,
|
||||
jit::Invalidate(TypeZone &types, FreeOp *fop,
|
||||
const RecompileInfoVector &invalid, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
JitSpew(JitSpew_IonInvalidate, "Start invalidation.");
|
||||
@ -2655,7 +2655,7 @@ jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
// to the traversal which frames have been invalidated.
|
||||
size_t numInvalidations = 0;
|
||||
for (size_t i = 0; i < invalid.length(); i++) {
|
||||
const types::CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
const CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
if (!co)
|
||||
continue;
|
||||
MOZ_ASSERT(co->isValid());
|
||||
@ -2688,7 +2688,7 @@ jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
// IonScript will be immediately destroyed. Otherwise, it will be held live
|
||||
// until its last invalidated frame is destroyed.
|
||||
for (size_t i = 0; i < invalid.length(); i++) {
|
||||
types::CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
if (!co)
|
||||
continue;
|
||||
MOZ_ASSERT(co->isValid());
|
||||
@ -2716,7 +2716,7 @@ jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
}
|
||||
|
||||
void
|
||||
jit::Invalidate(JSContext *cx, const types::RecompileInfoVector &invalid, bool resetUses,
|
||||
jit::Invalidate(JSContext *cx, const RecompileInfoVector &invalid, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
jit::Invalidate(cx->zone()->types, cx->runtime()->defaultFreeOp(), invalid, resetUses,
|
||||
@ -2727,7 +2727,7 @@ bool
|
||||
jit::IonScript::invalidate(JSContext *cx, bool resetUses, const char *reason)
|
||||
{
|
||||
JitSpew(JitSpew_IonInvalidate, " Invalidate IonScript %p: %s", this, reason);
|
||||
types::RecompileInfoVector list;
|
||||
RecompileInfoVector list;
|
||||
if (!list.append(recompileInfo()))
|
||||
return false;
|
||||
Invalidate(cx, list, resetUses, true);
|
||||
@ -2760,7 +2760,7 @@ jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffT
|
||||
js_free(buf);
|
||||
}
|
||||
|
||||
types::RecompileInfoVector scripts;
|
||||
RecompileInfoVector scripts;
|
||||
MOZ_ASSERT(script->hasIonScript());
|
||||
if (!scripts.append(script->ionScript()->recompileInfo()))
|
||||
return false;
|
||||
@ -2772,11 +2772,11 @@ jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffT
|
||||
static void
|
||||
FinishInvalidationOf(FreeOp *fop, JSScript *script, IonScript *ionScript)
|
||||
{
|
||||
types::TypeZone &types = script->zone()->types;
|
||||
TypeZone &types = script->zone()->types;
|
||||
|
||||
// Note: If the script is about to be swept, the compiler output may have
|
||||
// already been destroyed.
|
||||
if (types::CompilerOutput *output = ionScript->recompileInfo().compilerOutput(types))
|
||||
if (CompilerOutput *output = ionScript->recompileInfo().compilerOutput(types))
|
||||
output->invalidate();
|
||||
|
||||
// If this script has Ion code on the stack, invalidated() will return
|
||||
|
@ -122,10 +122,10 @@ JitExecStatus IonCannon(JSContext *cx, RunState &state);
|
||||
JitExecStatus FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args);
|
||||
|
||||
// Walk the stack and invalidate active Ion frames for the invalid scripts.
|
||||
void Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
const types::RecompileInfoVector &invalid, bool resetUses = true,
|
||||
void Invalidate(TypeZone &types, FreeOp *fop,
|
||||
const RecompileInfoVector &invalid, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
void Invalidate(JSContext *cx, const types::RecompileInfoVector &invalid, bool resetUses = true,
|
||||
void Invalidate(JSContext *cx, const RecompileInfoVector &invalid, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
|
@ -2484,8 +2484,8 @@ TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
|
||||
{
|
||||
MOZ_ASSERT(!*eliminated);
|
||||
|
||||
const types::TemporaryTypeSet *barrierTypes = barrier->resultTypeSet();
|
||||
const types::TemporaryTypeSet *inputTypes = barrier->input()->resultTypeSet();
|
||||
const TemporaryTypeSet *barrierTypes = barrier->resultTypeSet();
|
||||
const TemporaryTypeSet *inputTypes = barrier->input()->resultTypeSet();
|
||||
|
||||
// Disregard the possible unbox added before the Typebarrier.
|
||||
if (barrier->input()->isUnbox() && barrier->input()->toUnbox()->mode() != MUnbox::Fallible)
|
||||
@ -2494,8 +2494,8 @@ TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
|
||||
if (!barrierTypes || !inputTypes)
|
||||
return true;
|
||||
|
||||
bool filtersNull = barrierTypes->filtersType(inputTypes, types::Type::NullType());
|
||||
bool filtersUndefined = barrierTypes->filtersType(inputTypes, types::Type::UndefinedType());
|
||||
bool filtersNull = barrierTypes->filtersType(inputTypes, TypeSet::NullType());
|
||||
bool filtersUndefined = barrierTypes->filtersType(inputTypes, TypeSet::UndefinedType());
|
||||
|
||||
if (!filtersNull && !filtersUndefined)
|
||||
return true;
|
||||
@ -2883,7 +2883,7 @@ static bool
|
||||
AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
||||
MDefinition *thisValue, MInstruction *ins, bool definitelyExecuted,
|
||||
HandlePlainObject baseobj,
|
||||
Vector<types::TypeNewScript::Initializer> *initializerList,
|
||||
Vector<TypeNewScript::Initializer> *initializerList,
|
||||
Vector<PropertyName *> *accessedProperties,
|
||||
bool *phandled)
|
||||
{
|
||||
@ -2926,7 +2926,7 @@ AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
||||
return true;
|
||||
|
||||
RootedId id(cx, NameToId(setprop->name()));
|
||||
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
if (!AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
// The prototype chain already contains a getter/setter for this
|
||||
// property, or type information is too imprecise.
|
||||
return true;
|
||||
@ -2952,15 +2952,15 @@ AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
||||
for (int i = callerResumePoints.length() - 1; i >= 0; i--) {
|
||||
MResumePoint *rp = callerResumePoints[i];
|
||||
JSScript *script = rp->block()->info().script();
|
||||
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP_FRAME,
|
||||
script->pcToOffset(rp->pc()));
|
||||
TypeNewScript::Initializer entry(TypeNewScript::Initializer::SETPROP_FRAME,
|
||||
script->pcToOffset(rp->pc()));
|
||||
if (!initializerList->append(entry))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSScript *script = ins->block()->info().script();
|
||||
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP,
|
||||
script->pcToOffset(setprop->resumePoint()->pc()));
|
||||
TypeNewScript::Initializer entry(TypeNewScript::Initializer::SETPROP,
|
||||
script->pcToOffset(setprop->resumePoint()->pc()));
|
||||
if (!initializerList->append(entry))
|
||||
return false;
|
||||
|
||||
@ -2986,7 +2986,7 @@ AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
||||
if (!baseobj->lookup(cx, id) && !accessedProperties->append(get->name()))
|
||||
return false;
|
||||
|
||||
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
if (!AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
// The |this| value can escape if any property reads it does go
|
||||
// through a getter.
|
||||
return true;
|
||||
@ -3014,7 +3014,7 @@ CmpInstructions(const void *a, const void *b)
|
||||
bool
|
||||
jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
ObjectGroup *group, HandlePlainObject baseobj,
|
||||
Vector<types::TypeNewScript::Initializer> *initializerList)
|
||||
Vector<TypeNewScript::Initializer> *initializerList)
|
||||
{
|
||||
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
|
||||
|
||||
@ -3050,7 +3050,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
return true;
|
||||
}
|
||||
|
||||
types::TypeScript::SetThis(cx, script, types::Type::ObjectType(group));
|
||||
TypeScript::SetThis(cx, script, TypeSet::ObjectType(group));
|
||||
|
||||
MIRGraph graph(&temp);
|
||||
InlineScriptTree *inlineScriptTree = InlineScriptTree::New(&temp, nullptr, nullptr, script);
|
||||
@ -3065,7 +3065,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
|
||||
const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_Normal);
|
||||
|
||||
types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
|
||||
CompilerConstraintList *constraints = NewCompilerConstraintList(temp);
|
||||
if (!constraints) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -3083,7 +3083,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
return true;
|
||||
}
|
||||
|
||||
types::FinishDefinitePropertiesAnalysis(cx, constraints);
|
||||
FinishDefinitePropertiesAnalysis(cx, constraints);
|
||||
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return false;
|
||||
@ -3183,7 +3183,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
if (MResumePoint *rp = block->callerResumePoint()) {
|
||||
if (block->numPredecessors() == 1 && block->getPredecessor(0) == rp->block()) {
|
||||
JSScript *script = rp->block()->info().script();
|
||||
if (!types::AddClearDefiniteFunctionUsesInScript(cx, group, script, block->info().script()))
|
||||
if (!AddClearDefiniteFunctionUsesInScript(cx, group, script, block->info().script()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -3234,7 +3234,7 @@ bool
|
||||
jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
{
|
||||
RootedScript script(cx, scriptArg);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
MOZ_ASSERT(!script->analyzedArgsUsage());
|
||||
|
||||
@ -3293,7 +3293,7 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
|
||||
const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_Normal);
|
||||
|
||||
types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
|
||||
CompilerConstraintList *constraints = NewCompilerConstraintList(temp);
|
||||
if (!constraints)
|
||||
return false;
|
||||
|
||||
|
@ -171,7 +171,7 @@ ConvertLinearInequality(TempAllocator &alloc, MBasicBlock *block, const LinearSu
|
||||
bool
|
||||
AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
ObjectGroup *group, HandlePlainObject baseobj,
|
||||
Vector<types::TypeNewScript::Initializer> *initializerList);
|
||||
Vector<TypeNewScript::Initializer> *initializerList);
|
||||
|
||||
bool
|
||||
AnalyzeArgumentsUsage(JSContext *cx, JSScript *script);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -218,7 +218,7 @@ class IonBuilder
|
||||
public:
|
||||
IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
|
||||
const JitCompileOptions &options, TempAllocator *temp,
|
||||
MIRGraph *graph, types::CompilerConstraintList *constraints,
|
||||
MIRGraph *graph, CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, CompileInfo *info,
|
||||
const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
|
||||
size_t inliningDepth = 0, uint32_t loopDepth = 0);
|
||||
@ -240,8 +240,8 @@ class IonBuilder
|
||||
|
||||
MInstruction *constantMaybeNursery(JSObject *obj);
|
||||
|
||||
JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
|
||||
bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
|
||||
JSFunction *getSingleCallTarget(TemporaryTypeSet *calleeTypes);
|
||||
bool getPolyCallTargets(TemporaryTypeSet *calleeTypes, bool constructing,
|
||||
ObjectVector &targets, uint32_t maxTargets);
|
||||
|
||||
void popCfgStack();
|
||||
@ -318,7 +318,7 @@ class IonBuilder
|
||||
// Incorporates a type/typeSet into an OSR value for a loop, after the loop
|
||||
// body has been processed.
|
||||
bool addOsrValueTypeBarrier(uint32_t slot, MInstruction **def,
|
||||
MIRType type, types::TemporaryTypeSet *typeSet);
|
||||
MIRType type, TemporaryTypeSet *typeSet);
|
||||
bool maybeAddOsrTypeBarriers();
|
||||
|
||||
// Restarts processing of a loop if the type information at its header was
|
||||
@ -358,18 +358,18 @@ class IonBuilder
|
||||
bool improveTypesAtCompare(MCompare *ins, bool trueBranch, MTest *test);
|
||||
// Used to detect triangular structure at test.
|
||||
bool detectAndOrStructure(MPhi *ins, bool *branchIsTrue);
|
||||
bool replaceTypeSet(MDefinition *subject, types::TemporaryTypeSet *type, MTest *test);
|
||||
bool replaceTypeSet(MDefinition *subject, TemporaryTypeSet *type, MTest *test);
|
||||
|
||||
// Add a guard which ensure that the set of type which goes through this
|
||||
// generated code correspond to the observed types for the bytecode.
|
||||
MDefinition *addTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed,
|
||||
MDefinition *addTypeBarrier(MDefinition *def, TemporaryTypeSet *observed,
|
||||
BarrierKind kind, MTypeBarrier **pbarrier = nullptr);
|
||||
bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, BarrierKind kind);
|
||||
bool pushTypeBarrier(MDefinition *def, TemporaryTypeSet *observed, BarrierKind kind);
|
||||
|
||||
// As pushTypeBarrier, but will compute the needBarrier boolean itself based
|
||||
// on observed and the JSFunction that we're planning to call. The
|
||||
// JSFunction must be a DOM method or getter.
|
||||
bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
|
||||
bool pushDOMTypeBarrier(MInstruction *ins, TemporaryTypeSet *observed, JSFunction* func);
|
||||
|
||||
// If definiteType is not known or def already has the right type, just
|
||||
// returns def. Otherwise, returns an MInstruction that has that definite
|
||||
@ -378,7 +378,7 @@ class IonBuilder
|
||||
MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType);
|
||||
|
||||
// Creates a MDefinition based on the given def improved with type as TypeSet.
|
||||
MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);
|
||||
MDefinition *ensureDefiniteTypeSet(MDefinition* def, TemporaryTypeSet *types);
|
||||
|
||||
JSObject *getSingletonPrototype(JSFunction *target);
|
||||
|
||||
@ -404,9 +404,9 @@ class IonBuilder
|
||||
|
||||
bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall);
|
||||
bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
|
||||
MDefinition *value, bool needsBarrier,
|
||||
MIRType slotType = MIRType_None);
|
||||
@ -418,19 +418,19 @@ class IonBuilder
|
||||
// jsop_getprop() helpers.
|
||||
bool checkIsDefinitelyOptimizedArguments(MDefinition *obj, bool *isOptimizedArgs);
|
||||
bool getPropTryInferredConstant(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryArgumentsLength(bool *emitted, MDefinition *obj);
|
||||
bool getPropTryArgumentsCallee(bool *emitted, MDefinition *obj, PropertyName *name);
|
||||
bool getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTryUnboxed(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryInlineAccess(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTryTypedObject(bool *emitted, MDefinition *obj, PropertyName *name);
|
||||
bool getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
@ -444,25 +444,25 @@ class IonBuilder
|
||||
TypedObjectPrediction fieldTypeReprs,
|
||||
size_t fieldIndex);
|
||||
bool getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
|
||||
// jsop_setprop() helpers.
|
||||
bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value);
|
||||
bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
|
||||
MDefinition *value, JSFunction *setter,
|
||||
types::TemporaryTypeSet *objTypes);
|
||||
TemporaryTypeSet *objTypes);
|
||||
bool setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
bool setPropTryUnboxed(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
bool setPropTryInlineAccess(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
bool setPropTryTypedObject(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value);
|
||||
bool setPropTryReferencePropOfTypedObject(bool *emitted,
|
||||
@ -478,11 +478,11 @@ class IonBuilder
|
||||
TypedObjectPrediction fieldTypeReprs);
|
||||
bool setPropTryCache(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
|
||||
// binary data lookup helpers.
|
||||
TypedObjectPrediction typedObjectPrediction(MDefinition *typedObj);
|
||||
TypedObjectPrediction typedObjectPrediction(types::TemporaryTypeSet *types);
|
||||
TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet *types);
|
||||
bool typedObjectHasField(MDefinition *typedObj,
|
||||
PropertyName *name,
|
||||
size_t *fieldOffset,
|
||||
@ -650,7 +650,7 @@ class IonBuilder
|
||||
bool jsop_getelem_dense(MDefinition *obj, MDefinition *index);
|
||||
bool jsop_getelem_typed(MDefinition *obj, MDefinition *index, ScalarTypeDescr::Type arrayType);
|
||||
bool jsop_setelem();
|
||||
bool jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion conversion,
|
||||
bool jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
|
||||
SetElemSafety safety,
|
||||
MDefinition *object, MDefinition *index, MDefinition *value);
|
||||
bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
|
||||
@ -726,7 +726,7 @@ class IonBuilder
|
||||
// Native inlining helpers.
|
||||
// The typeset for the return value of our function. These are
|
||||
// the types it's been observed returning in the past.
|
||||
types::TemporaryTypeSet *getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *getInlineReturnTypeSet();
|
||||
// The known MIR type of getInlineReturnTypeSet.
|
||||
MIRType getInlineReturnType();
|
||||
|
||||
@ -863,18 +863,18 @@ class IonBuilder
|
||||
MBasicBlock *bottom);
|
||||
MDefinition *specializeInlinedReturn(MDefinition *rdef, MBasicBlock *exit);
|
||||
|
||||
bool objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
bool objectsHaveCommonPrototype(TemporaryTypeSet *types, PropertyName *name,
|
||||
bool isGetter, JSObject *foundProto, bool *guardGlobal);
|
||||
void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
void freezePropertiesForCommonPrototype(TemporaryTypeSet *types, PropertyName *name,
|
||||
JSObject *foundProto, bool allowEmptyTypesForGlobal = false);
|
||||
/*
|
||||
* Callers must pass a non-null globalGuard if they pass a non-null globalShape.
|
||||
*/
|
||||
bool testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
bool testCommonGetterSetter(TemporaryTypeSet *types, PropertyName *name,
|
||||
bool isGetter, JSObject *foundProto, Shape *lastProperty,
|
||||
MDefinition **guard, Shape *globalShape = nullptr,
|
||||
MDefinition **globalGuard = nullptr);
|
||||
bool testShouldDOMCall(types::TypeSet *inTypes,
|
||||
bool testShouldDOMCall(TypeSet *inTypes,
|
||||
JSFunction *func, JSJitInfo::OpType opType);
|
||||
|
||||
MDefinition *addShapeGuardsForGetterSetter(MDefinition *obj, JSObject *holder, Shape *holderShape,
|
||||
@ -882,27 +882,27 @@ class IonBuilder
|
||||
bool isOwnProperty);
|
||||
|
||||
bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
|
||||
types::TemporaryTypeSet *objTypes,
|
||||
types::TemporaryTypeSet *pushedTypes);
|
||||
TemporaryTypeSet *objTypes,
|
||||
TemporaryTypeSet *pushedTypes);
|
||||
|
||||
MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
|
||||
|
||||
JSObject *testSingletonProperty(JSObject *obj, PropertyName *name);
|
||||
bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name,
|
||||
bool *testObject, bool *testString);
|
||||
uint32_t getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name);
|
||||
uint32_t getUnboxedOffset(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet *types, PropertyName *name);
|
||||
uint32_t getUnboxedOffset(TemporaryTypeSet *types, PropertyName *name,
|
||||
JSValueType *punboxedType);
|
||||
MInstruction *loadUnboxedProperty(MDefinition *obj, size_t offset, JSValueType unboxedType,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
MInstruction *storeUnboxedProperty(MDefinition *obj, size_t offset, JSValueType unboxedType,
|
||||
MDefinition *value);
|
||||
bool freezePropTypeSets(types::TemporaryTypeSet *types,
|
||||
bool freezePropTypeSets(TemporaryTypeSet *types,
|
||||
JSObject *foundProto, PropertyName *name);
|
||||
bool canInlinePropertyOpShapes(const BaselineInspector::ShapeVector &nativeShapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups);
|
||||
|
||||
types::TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
|
||||
TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
|
||||
|
||||
// Use one of the below methods for updating the current block, rather than
|
||||
// updating |current| directly. setCurrent() should only be used in cases
|
||||
@ -946,7 +946,7 @@ class IonBuilder
|
||||
CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; }
|
||||
void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; }
|
||||
|
||||
types::CompilerConstraintList *constraints() {
|
||||
CompilerConstraintList *constraints() {
|
||||
return constraints_;
|
||||
}
|
||||
|
||||
@ -978,7 +978,7 @@ class IonBuilder
|
||||
BaselineFrameInspector *baselineFrame_;
|
||||
|
||||
// Constraints for recording dependencies on type information.
|
||||
types::CompilerConstraintList *constraints_;
|
||||
CompilerConstraintList *constraints_;
|
||||
|
||||
// Basic analysis information about the script.
|
||||
BytecodeAnalysis analysis_;
|
||||
@ -986,7 +986,7 @@ class IonBuilder
|
||||
return analysis_;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
|
||||
TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
|
||||
uint32_t typeArrayHint;
|
||||
uint32_t *bytecodeTypeMap;
|
||||
|
||||
@ -1119,7 +1119,7 @@ class IonBuilder
|
||||
// unchecked variants, despite the unchecked variants having no other
|
||||
// callers.
|
||||
void trackTypeInfo(JS::TrackedTypeSite site, MIRType mirType,
|
||||
types::TemporaryTypeSet *typeSet)
|
||||
TemporaryTypeSet *typeSet)
|
||||
{
|
||||
if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
|
||||
trackTypeInfoUnchecked(site, mirType, typeSet);
|
||||
@ -1156,7 +1156,7 @@ class IonBuilder
|
||||
// Out-of-line variants that don't check if optimization tracking is
|
||||
// enabled.
|
||||
void trackTypeInfoUnchecked(JS::TrackedTypeSite site, MIRType mirType,
|
||||
types::TemporaryTypeSet *typeSet);
|
||||
TemporaryTypeSet *typeSet);
|
||||
void trackTypeInfoUnchecked(JS::TrackedTypeSite site, JSObject *obj);
|
||||
void trackTypeInfoUnchecked(CallInfo &callInfo);
|
||||
void trackOptimizationAttemptUnchecked(JS::TrackedStrategy strategy);
|
||||
@ -1292,7 +1292,7 @@ class CallInfo
|
||||
}
|
||||
};
|
||||
|
||||
bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes);
|
||||
bool TypeSetIncludes(TypeSet *types, MIRType input, TypeSet *inputTypes);
|
||||
|
||||
bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
|
||||
|
||||
|
@ -1268,10 +1268,9 @@ GetPropertyIC::allowArrayLength(Context cx, HandleObject obj) const
|
||||
CacheLocation *locs = ion->getCacheLocs(locationIndex);
|
||||
for (size_t i = 0; i < numLocations; i++) {
|
||||
CacheLocation &curLoc = locs[i];
|
||||
types::StackTypeSet *bcTypes =
|
||||
types::TypeScript::BytecodeTypes(curLoc.script, curLoc.pc);
|
||||
StackTypeSet *bcTypes = TypeScript::BytecodeTypes(curLoc.script, curLoc.pc);
|
||||
|
||||
if (!bcTypes->hasType(types::Type::Int32Type()))
|
||||
if (!bcTypes->hasType(TypeSet::Int32Type()))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1855,7 +1854,7 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
|
||||
|
||||
// Monitor changes to cache entry.
|
||||
if (!cache.monitoredResult())
|
||||
types::TypeScript::Monitor(cx, script, pc, vp);
|
||||
TypeScript::Monitor(cx, script, pc, vp);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1900,11 +1899,11 @@ CheckTypeSetForWrite(MacroAssembler &masm, JSObject *obj, jsid id,
|
||||
ObjectGroup *group = obj->group();
|
||||
if (group->unknownProperties())
|
||||
return;
|
||||
types::HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
MOZ_ASSERT(propTypes);
|
||||
|
||||
// guardTypeSet can read from type sets without triggering read barriers.
|
||||
types::TypeSet::readBarrier(propTypes);
|
||||
TypeSet::readBarrier(propTypes);
|
||||
|
||||
Register scratch = object;
|
||||
masm.guardTypeSet(valReg, propTypes, BarrierKind::TypeSet, scratch, failure);
|
||||
@ -2581,7 +2580,7 @@ CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *
|
||||
bool shouldCheck = false;
|
||||
ObjectGroup *group = obj->group();
|
||||
if (!group->unknownProperties()) {
|
||||
types::HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
if (!propTypes)
|
||||
return false;
|
||||
if (!propTypes->unknown()) {
|
||||
@ -2590,7 +2589,7 @@ CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *
|
||||
shouldCheck = true;
|
||||
if (val.constant()) {
|
||||
// If the input is a constant, then don't bother if the barrier will always fail.
|
||||
if (!propTypes->hasType(types::GetValueType(val.value())))
|
||||
if (!propTypes->hasType(TypeSet::GetValueType(val.value())))
|
||||
return false;
|
||||
shouldCheck = false;
|
||||
} else {
|
||||
@ -2601,7 +2600,7 @@ CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *
|
||||
// contains the specific object, but doesn't have ANYOBJECT set.
|
||||
if (reg.hasTyped() && reg.type() != MIRType_Object) {
|
||||
JSValueType valType = ValueTypeFromMIRType(reg.type());
|
||||
if (!propTypes->hasType(types::Type::PrimitiveType(valType)))
|
||||
if (!propTypes->hasType(TypeSet::PrimitiveType(valType)))
|
||||
return false;
|
||||
shouldCheck = false;
|
||||
}
|
||||
@ -3409,7 +3408,7 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
if (!GetObjectElementOperation(cx, JSOp(*pc), obj, idval, res))
|
||||
return false;
|
||||
if (!cache.monitoredResult())
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3463,7 +3462,7 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
}
|
||||
|
||||
if (!cache.monitoredResult())
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4143,7 +4142,7 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
||||
}
|
||||
|
||||
// Monitor changes to cache entry.
|
||||
types::TypeScript::Monitor(cx, script, pc, vp);
|
||||
TypeScript::Monitor(cx, script, pc, vp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ struct IonScript
|
||||
uint32_t invalidationCount_;
|
||||
|
||||
// Identifier of the compilation which produced this code.
|
||||
types::RecompileInfo recompileInfo_;
|
||||
RecompileInfo recompileInfo_;
|
||||
|
||||
// The optimization level this script was compiled in.
|
||||
OptimizationLevel optimizationLevel_;
|
||||
@ -332,7 +332,7 @@ struct IonScript
|
||||
// Do not call directly, use IonScript::New. This is public for cx->new_.
|
||||
IonScript();
|
||||
|
||||
static IonScript *New(JSContext *cx, types::RecompileInfo recompileInfo,
|
||||
static IonScript *New(JSContext *cx, RecompileInfo recompileInfo,
|
||||
uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
|
||||
size_t snapshotsListSize, size_t snapshotsRVATableSize,
|
||||
size_t recoversSize, size_t bailoutEntries,
|
||||
@ -541,10 +541,10 @@ struct IonScript
|
||||
if (!invalidationCount_)
|
||||
Destroy(fop, this);
|
||||
}
|
||||
const types::RecompileInfo& recompileInfo() const {
|
||||
const RecompileInfo& recompileInfo() const {
|
||||
return recompileInfo_;
|
||||
}
|
||||
types::RecompileInfo& recompileInfoRef() {
|
||||
RecompileInfo& recompileInfoRef() {
|
||||
return recompileInfo_;
|
||||
}
|
||||
OptimizationLevel optimizationLevel() const {
|
||||
|
@ -2115,7 +2115,7 @@ SnapshotIterator::computeInstructionResults(JSContext *cx, RInstructionResults *
|
||||
|
||||
// Use AutoEnterAnalysis to avoid invoking the object metadata callback,
|
||||
// which could try to walk the stack while bailing out.
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
// Fill with the results of recover instructions.
|
||||
SnapshotIterator s(*this);
|
||||
|
@ -2295,7 +2295,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
||||
// Requesting a non-GC pointer is safe here since we never re-enter C++
|
||||
// from inside a type barrier test.
|
||||
|
||||
const types::TemporaryTypeSet *types = ins->resultTypeSet();
|
||||
const TemporaryTypeSet *types = ins->resultTypeSet();
|
||||
bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
|
||||
|
||||
MIRType inputType = ins->getOperand(0)->type();
|
||||
@ -2325,7 +2325,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
||||
}
|
||||
|
||||
// Handle typebarrier with specific ObjectGroup/SingleObjects.
|
||||
if (inputType == MIRType_Object && !types->hasType(types::Type::AnyObjectType()) &&
|
||||
if (inputType == MIRType_Object && !types->hasType(TypeSet::AnyObjectType()) &&
|
||||
ins->barrierKind() != BarrierKind::TypeTagOnly)
|
||||
{
|
||||
LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
|
||||
@ -2346,7 +2346,7 @@ LIRGenerator::visitMonitorTypes(MMonitorTypes *ins)
|
||||
// Requesting a non-GC pointer is safe here since we never re-enter C++
|
||||
// from inside a type check.
|
||||
|
||||
const types::TemporaryTypeSet *types = ins->typeSet();
|
||||
const TemporaryTypeSet *types = ins->typeSet();
|
||||
bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
|
||||
LDefinition tmp = needTemp ? temp() : tempToUnbox();
|
||||
|
||||
|
@ -274,7 +274,7 @@ IonBuilder::inlineNativeGetter(CallInfo &callInfo, JSFunction *target)
|
||||
if (!optimizationInfo().inlineNative())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
MOZ_ASSERT(callInfo.argc() == 0);
|
||||
|
||||
// Try to optimize typed array lengths. There is one getter on
|
||||
@ -321,7 +321,7 @@ IonBuilder::inlineNonFunctionCall(CallInfo &callInfo, JSObject *target)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *
|
||||
TemporaryTypeSet *
|
||||
IonBuilder::getInlineReturnTypeSet()
|
||||
{
|
||||
return bytecodeTypes(pc);
|
||||
@ -330,7 +330,7 @@ IonBuilder::getInlineReturnTypeSet()
|
||||
MIRType
|
||||
IonBuilder::getInlineReturnType()
|
||||
{
|
||||
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
return returnTypes->getKnownMIRType();
|
||||
}
|
||||
|
||||
@ -377,9 +377,9 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
||||
initLength = callInfo.argc();
|
||||
allocating = NewArray_FullyAllocating;
|
||||
|
||||
types::TypeSetObjectKey *key = types::TypeSetObjectKey::get(templateArray);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(templateArray);
|
||||
if (!key->unknownProperties()) {
|
||||
types::HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
|
||||
for (uint32_t i = 0; i < initLength; i++) {
|
||||
MDefinition *value = callInfo.getArg(i);
|
||||
@ -391,9 +391,9 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
||||
}
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
TemporaryTypeSet::DoubleConversion conversion =
|
||||
getInlineReturnTypeSet()->convertDoubleElements(constraints());
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateArray->setShouldConvertDoubleElements();
|
||||
else
|
||||
templateArray->clearShouldConvertDoubleElements();
|
||||
@ -461,7 +461,7 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
||||
current->add(id);
|
||||
|
||||
MDefinition *value = callInfo.getArg(i);
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles) {
|
||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles) {
|
||||
MInstruction *valueDouble = MToDouble::New(alloc(), value);
|
||||
current->add(valueDouble);
|
||||
value = valueDouble;
|
||||
@ -512,7 +512,7 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
||||
OBJECT_FLAG_ITERATED;
|
||||
|
||||
MDefinition *obj = callInfo.thisArg();
|
||||
types::TemporaryTypeSet *thisTypes = obj->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes || thisTypes->getKnownClass(constraints()) != &ArrayObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
if (thisTypes->hasObjectFlags(constraints(), unhandledFlags)) {
|
||||
@ -520,7 +520,7 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
if (types::ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
if (ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -529,9 +529,9 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
||||
|
||||
obj = addMaybeCopyElementsForWrite(obj);
|
||||
|
||||
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_NON_PACKED);
|
||||
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
|
||||
bool maybeUndefined = returnTypes->hasType(TypeSet::UndefinedType());
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, nullptr, returnTypes);
|
||||
@ -640,7 +640,7 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
if (!thisTypes || thisTypes->getKnownClass(constraints()) != &ArrayObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
|
||||
@ -650,14 +650,14 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
if (types::ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
if (ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
TemporaryTypeSet::DoubleConversion conversion =
|
||||
thisTypes->convertDoubleElements(constraints());
|
||||
if (conversion == types::TemporaryTypeSet::AmbiguousDoubleConversion) {
|
||||
if (conversion == TemporaryTypeSet::AmbiguousDoubleConversion) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ArrayDoubleConversion);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -665,8 +665,8 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
value = callInfo.getArg(0);
|
||||
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles ||
|
||||
conversion == types::TemporaryTypeSet::MaybeConvertToDoubles)
|
||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles ||
|
||||
conversion == TemporaryTypeSet::MaybeConvertToDoubles)
|
||||
{
|
||||
MInstruction *valueDouble = MToDouble::New(alloc(), value);
|
||||
current->add(valueDouble);
|
||||
@ -704,8 +704,8 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// |this| and the argument must be dense arrays.
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
types::TemporaryTypeSet *argTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *argTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!thisTypes || !argTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -728,7 +728,7 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
||||
}
|
||||
|
||||
// Watch out for indexed properties on the prototype.
|
||||
if (types::ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
if (ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -741,7 +741,7 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
||||
ObjectGroup *thisGroup = thisTypes->getGroup(0);
|
||||
if (!thisGroup)
|
||||
return InliningStatus_NotInlined;
|
||||
types::TypeSetObjectKey *thisKey = types::TypeSetObjectKey::get(thisGroup);
|
||||
TypeSet::ObjectKey *thisKey = TypeSet::ObjectKey::get(thisGroup);
|
||||
if (thisKey->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -757,21 +757,21 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
||||
// Constraints modeling this concat have not been generated by inference,
|
||||
// so check that type information already reflects possible side effects of
|
||||
// this call.
|
||||
types::HeapTypeSetKey thisElemTypes = thisKey->property(JSID_VOID);
|
||||
HeapTypeSetKey thisElemTypes = thisKey->property(JSID_VOID);
|
||||
|
||||
types::TemporaryTypeSet *resTypes = getInlineReturnTypeSet();
|
||||
if (!resTypes->hasType(types::Type::ObjectType(thisKey)))
|
||||
TemporaryTypeSet *resTypes = getInlineReturnTypeSet();
|
||||
if (!resTypes->hasType(TypeSet::ObjectType(thisKey)))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
for (unsigned i = 0; i < argTypes->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = argTypes->getObject(i);
|
||||
TypeSet::ObjectKey *key = argTypes->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
if (key->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
if (!elemTypes.knownSubset(constraints(), thisElemTypes))
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -1236,11 +1236,11 @@ IonBuilder::inlineMathFRound(CallInfo &callInfo)
|
||||
|
||||
// MIRType can't be Float32, as this point, as getInlineReturnType uses JSVal types
|
||||
// to infer the returned MIR type.
|
||||
types::TemporaryTypeSet *returned = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returned = getInlineReturnTypeSet();
|
||||
if (returned->empty()) {
|
||||
// As there's only one possible returned type, just add it to the observed
|
||||
// returned typeset
|
||||
returned->addType(types::Type::DoubleType(), alloc_->lifoAlloc());
|
||||
returned->addType(TypeSet::DoubleType(), alloc_->lifoAlloc());
|
||||
} else {
|
||||
MIRType returnType = getInlineReturnType();
|
||||
if (!IsNumberType(returnType))
|
||||
@ -1377,15 +1377,15 @@ IonBuilder::inlineStringSplit(CallInfo &callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
MOZ_ASSERT(templateObject->is<ArrayObject>());
|
||||
|
||||
types::TypeSetObjectKey *retKey = types::TypeSetObjectKey::get(templateObject);
|
||||
TypeSet::ObjectKey *retKey = TypeSet::ObjectKey::get(templateObject);
|
||||
if (retKey->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::HeapTypeSetKey key = retKey->property(JSID_VOID);
|
||||
HeapTypeSetKey key = retKey->property(JSID_VOID);
|
||||
if (!key.maybeTypes())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (!key.maybeTypes()->hasType(types::Type::StringType())) {
|
||||
if (!key.maybeTypes()->hasType(TypeSet::StringType())) {
|
||||
key.freeze(constraints());
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -1547,7 +1547,7 @@ IonBuilder::inlineRegExpExec(CallInfo &callInfo)
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
const Class *clasp = thisTypes ? thisTypes->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp != &RegExpObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
@ -1588,7 +1588,7 @@ IonBuilder::inlineRegExpTest(CallInfo &callInfo)
|
||||
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
const Class *clasp = thisTypes ? thisTypes->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp != &RegExpObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
@ -1627,7 +1627,7 @@ IonBuilder::inlineStrReplace(CallInfo &callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Arg 0: RegExp.
|
||||
types::TemporaryTypeSet *arg0Type = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *arg0Type = callInfo.getArg(0)->resultTypeSet();
|
||||
const Class *clasp = arg0Type ? arg0Type->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp != &RegExpObject::class_ && callInfo.getArg(0)->type() != MIRType_String)
|
||||
return InliningStatus_NotInlined;
|
||||
@ -1704,7 +1704,7 @@ IonBuilder::inlineObjectCreate(CallInfo &callInfo)
|
||||
if (IsInsideNursery(proto))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *types = arg->resultTypeSet();
|
||||
TemporaryTypeSet *types = arg->resultTypeSet();
|
||||
if (!types || types->maybeSingleton() != proto)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
@ -1851,7 +1851,7 @@ IonBuilder::inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base)
|
||||
MDefinition *id = callInfo.getArg(base + 1);
|
||||
MDefinition *elem = callInfo.getArg(base + 2);
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
TemporaryTypeSet::DoubleConversion conversion =
|
||||
obj->resultTypeSet()->convertDoubleElements(constraints());
|
||||
if (!jsop_setelem_dense(conversion, SetElem_Unsafe, obj, id, elem))
|
||||
return false;
|
||||
@ -1913,7 +1913,7 @@ IonBuilder::inlineHasClass(CallInfo &callInfo,
|
||||
if (getInlineReturnType() != MIRType_Boolean)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
const Class *knownClass = types ? types->getKnownClass(constraints()) : nullptr;
|
||||
if (knownClass) {
|
||||
pushConstant(BooleanValue(knownClass == clasp1 ||
|
||||
@ -1966,20 +1966,20 @@ IonBuilder::inlineIsTypedArray(CallInfo &callInfo)
|
||||
// The test is elaborate: in-line only if there is exact
|
||||
// information.
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!types)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
bool result = false;
|
||||
switch (types->forAllClasses(constraints(), IsTypedArrayClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
result = false;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
result = true;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
case TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
@ -2026,20 +2026,20 @@ IonBuilder::inlineObjectIsTypeDescr(CallInfo &callInfo)
|
||||
// The test is elaborate: in-line only if there is exact
|
||||
// information.
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!types)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
bool result = false;
|
||||
switch (types->forAllClasses(constraints(), IsTypeDescrClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
result = false;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
result = true;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
case TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
@ -2070,15 +2070,15 @@ IonBuilder::inlineSetTypedObjectOffset(CallInfo &callInfo)
|
||||
// with TI or because of something else -- but we'll just let it
|
||||
// fall through to the SetTypedObjectOffset intrinsic in such
|
||||
// cases.
|
||||
types::TemporaryTypeSet *types = typedObj->resultTypeSet();
|
||||
TemporaryTypeSet *types = typedObj->resultTypeSet();
|
||||
if (typedObj->type() != MIRType_Object || !types)
|
||||
return InliningStatus_NotInlined;
|
||||
switch (types->forAllClasses(constraints(), IsTypedObjectClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2188,7 +2188,7 @@ IonBuilder::inlineIsCallable(CallInfo &callInfo)
|
||||
isCallableKnown = true;
|
||||
isCallableConstant = false;
|
||||
} else {
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
const Class *clasp = types ? types->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp && !clasp->isProxy()) {
|
||||
isCallableKnown = true;
|
||||
@ -2588,7 +2588,7 @@ IonBuilder::atomicsMeetsPreconditions(CallInfo &callInfo, Scalar::Type *arrayTyp
|
||||
// optimize and that the return type is suitable for that element
|
||||
// type.
|
||||
|
||||
types::TemporaryTypeSet *arg0Types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *arg0Types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!arg0Types)
|
||||
return false;
|
||||
|
||||
|
@ -270,7 +270,7 @@ MDefinition::mightBeMagicType() const
|
||||
if (MIRType_Value != type())
|
||||
return false;
|
||||
|
||||
return !resultTypeSet() || resultTypeSet()->hasType(types::Type::MagicArgType());
|
||||
return !resultTypeSet() || resultTypeSet()->hasType(TypeSet::MagicArgType());
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
@ -339,12 +339,12 @@ MInstruction::clearResumePoint()
|
||||
}
|
||||
|
||||
static bool
|
||||
MaybeEmulatesUndefined(types::CompilerConstraintList *constraints, MDefinition *op)
|
||||
MaybeEmulatesUndefined(CompilerConstraintList *constraints, MDefinition *op)
|
||||
{
|
||||
if (!op->mightBeType(MIRType_Object))
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = op->resultTypeSet();
|
||||
TemporaryTypeSet *types = op->resultTypeSet();
|
||||
if (!types)
|
||||
return true;
|
||||
|
||||
@ -352,12 +352,12 @@ MaybeEmulatesUndefined(types::CompilerConstraintList *constraints, MDefinition *
|
||||
}
|
||||
|
||||
static bool
|
||||
MaybeCallable(types::CompilerConstraintList *constraints, MDefinition *op)
|
||||
MaybeCallable(CompilerConstraintList *constraints, MDefinition *op)
|
||||
{
|
||||
if (!op->mightBeType(MIRType_Object))
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = op->resultTypeSet();
|
||||
TemporaryTypeSet *types = op->resultTypeSet();
|
||||
if (!types)
|
||||
return true;
|
||||
|
||||
@ -371,7 +371,7 @@ MTest::New(TempAllocator &alloc, MDefinition *ins, MBasicBlock *ifTrue, MBasicBl
|
||||
}
|
||||
|
||||
void
|
||||
MTest::cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints)
|
||||
MTest::cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(operandMightEmulateUndefined());
|
||||
|
||||
@ -621,13 +621,13 @@ MDefinition::emptyResultTypeSet() const
|
||||
}
|
||||
|
||||
MConstant *
|
||||
MConstant::New(TempAllocator &alloc, const Value &v, types::CompilerConstraintList *constraints)
|
||||
MConstant::New(TempAllocator &alloc, const Value &v, CompilerConstraintList *constraints)
|
||||
{
|
||||
return new(alloc) MConstant(v, constraints);
|
||||
}
|
||||
|
||||
MConstant *
|
||||
MConstant::NewTypedValue(TempAllocator &alloc, const Value &v, MIRType type, types::CompilerConstraintList *constraints)
|
||||
MConstant::NewTypedValue(TempAllocator &alloc, const Value &v, MIRType type, CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(!IsSimdType(type));
|
||||
MConstant *constant = new(alloc) MConstant(v, constraints);
|
||||
@ -647,29 +647,29 @@ MConstant::NewConstraintlessObject(TempAllocator &alloc, JSObject *v)
|
||||
return new(alloc) MConstant(v);
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *
|
||||
jit::MakeSingletonTypeSet(types::CompilerConstraintList *constraints, JSObject *obj)
|
||||
TemporaryTypeSet *
|
||||
jit::MakeSingletonTypeSet(CompilerConstraintList *constraints, JSObject *obj)
|
||||
{
|
||||
// Invalidate when this object's ObjectGroup gets unknown properties. This
|
||||
// happens for instance when we mutate an object's __proto__, in this case
|
||||
// we want to invalidate and mark this TypeSet as containing AnyObject
|
||||
// (because mutating __proto__ will change an object's ObjectGroup).
|
||||
MOZ_ASSERT(constraints);
|
||||
types::TypeSetObjectKey *key = types::TypeSetObjectKey::get(obj);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(obj);
|
||||
key->hasStableClassAndProto(constraints);
|
||||
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
return alloc->new_<types::TemporaryTypeSet>(alloc, types::Type::ObjectType(obj));
|
||||
return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::ObjectType(obj));
|
||||
}
|
||||
|
||||
static types::TemporaryTypeSet *
|
||||
static TemporaryTypeSet *
|
||||
MakeUnknownTypeSet()
|
||||
{
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
return alloc->new_<types::TemporaryTypeSet>(alloc, types::Type::UnknownType());
|
||||
return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::UnknownType());
|
||||
}
|
||||
|
||||
MConstant::MConstant(const js::Value &vp, types::CompilerConstraintList *constraints)
|
||||
MConstant::MConstant(const js::Value &vp, CompilerConstraintList *constraints)
|
||||
: value_(vp)
|
||||
{
|
||||
setResultType(MIRTypeFromValue(vp));
|
||||
@ -806,7 +806,7 @@ MConstant::canProduceFloat32() const
|
||||
return true;
|
||||
}
|
||||
|
||||
MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, types::CompilerConstraintList *constraints)
|
||||
MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, CompilerConstraintList *constraints)
|
||||
: index_(index)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
@ -820,7 +820,7 @@ MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, types::CompilerCon
|
||||
|
||||
MNurseryObject *
|
||||
MNurseryObject::New(TempAllocator &alloc, JSObject *obj, uint32_t index,
|
||||
types::CompilerConstraintList *constraints)
|
||||
CompilerConstraintList *constraints)
|
||||
{
|
||||
return new(alloc) MNurseryObject(obj, index, constraints);
|
||||
}
|
||||
@ -1107,7 +1107,7 @@ MMathFunction::foldsTo(TempAllocator &alloc)
|
||||
}
|
||||
|
||||
MParameter *
|
||||
MParameter::New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types)
|
||||
MParameter::New(TempAllocator &alloc, int32_t index, TemporaryTypeSet *types)
|
||||
{
|
||||
return new(alloc) MParameter(index, types);
|
||||
}
|
||||
@ -1624,20 +1624,20 @@ MPhi::congruentTo(const MDefinition *ins) const
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
static inline types::TemporaryTypeSet *
|
||||
static inline TemporaryTypeSet *
|
||||
MakeMIRTypeSet(MIRType type)
|
||||
{
|
||||
MOZ_ASSERT(type != MIRType_Value);
|
||||
types::Type ntype = type == MIRType_Object
|
||||
? types::Type::AnyObjectType()
|
||||
: types::Type::PrimitiveType(ValueTypeFromMIRType(type));
|
||||
TypeSet::Type ntype = type == MIRType_Object
|
||||
? TypeSet::AnyObjectType()
|
||||
: TypeSet::PrimitiveType(ValueTypeFromMIRType(type));
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
return alloc->new_<types::TemporaryTypeSet>(alloc, ntype);
|
||||
return alloc->new_<TemporaryTypeSet>(alloc, ntype);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, types::TemporaryTypeSet *newTypeSet)
|
||||
jit::MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, TemporaryTypeSet *newTypeSet)
|
||||
{
|
||||
if (newTypeSet && newTypeSet->empty())
|
||||
return true;
|
||||
@ -1664,7 +1664,7 @@ jit::MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
|
||||
}
|
||||
if (newTypeSet) {
|
||||
if (!newTypeSet->isSubset(*ptypeSet))
|
||||
*ptypeSet = types::TypeSet::unionSets(*ptypeSet, newTypeSet, alloc);
|
||||
*ptypeSet = TypeSet::unionSets(*ptypeSet, newTypeSet, alloc);
|
||||
} else {
|
||||
*ptypeSet = nullptr;
|
||||
}
|
||||
@ -1694,7 +1694,7 @@ MPhi::specializeType()
|
||||
}
|
||||
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
for (size_t i = start; i < inputs_.length(); i++) {
|
||||
MDefinition *def = getOperand(i);
|
||||
@ -1708,13 +1708,13 @@ MPhi::specializeType()
|
||||
}
|
||||
|
||||
bool
|
||||
MPhi::addBackedgeType(MIRType type, types::TemporaryTypeSet *typeSet)
|
||||
MPhi::addBackedgeType(MIRType type, TemporaryTypeSet *typeSet)
|
||||
{
|
||||
MOZ_ASSERT(!specialized_);
|
||||
|
||||
if (hasBackedgeType_) {
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
if (!MergeTypes(&resultType, &resultTypeSet, type, typeSet))
|
||||
return false;
|
||||
@ -1735,7 +1735,7 @@ MPhi::typeIncludes(MDefinition *def)
|
||||
if (def->type() == MIRType_Int32 && this->type() == MIRType_Double)
|
||||
return true;
|
||||
|
||||
if (types::TemporaryTypeSet *types = def->resultTypeSet()) {
|
||||
if (TemporaryTypeSet *types = def->resultTypeSet()) {
|
||||
if (this->resultTypeSet())
|
||||
return types->isSubset(this->resultTypeSet());
|
||||
if (this->type() == MIRType_Value || types->empty())
|
||||
@ -1756,7 +1756,7 @@ bool
|
||||
MPhi::checkForTypeChange(MDefinition *ins, bool *ptypeChange)
|
||||
{
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
if (!MergeTypes(&resultType, &resultTypeSet, ins->type(), ins->resultTypeSet()))
|
||||
return false;
|
||||
@ -2468,7 +2468,7 @@ MBinaryArithInstruction::inferFallback(BaselineInspector *inspector,
|
||||
// either to avoid degrading subsequent analysis.
|
||||
if (getOperand(0)->emptyResultTypeSet() || getOperand(1)->emptyResultTypeSet()) {
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
types::TemporaryTypeSet *types = alloc->new_<types::TemporaryTypeSet>();
|
||||
TemporaryTypeSet *types = alloc->new_<TemporaryTypeSet>();
|
||||
if (types)
|
||||
setResultTypeSet(types);
|
||||
}
|
||||
@ -2496,7 +2496,7 @@ ObjectOrSimplePrimitive(MDefinition *op)
|
||||
}
|
||||
|
||||
static bool
|
||||
CanDoValueBitwiseCmp(types::CompilerConstraintList *constraints,
|
||||
CanDoValueBitwiseCmp(CompilerConstraintList *constraints,
|
||||
MDefinition *lhs, MDefinition *rhs, bool looseEq)
|
||||
{
|
||||
// Only primitive (not double/string) or objects are supported.
|
||||
@ -2619,7 +2619,7 @@ MBinaryInstruction::tryUseUnsignedOperands()
|
||||
}
|
||||
|
||||
void
|
||||
MCompare::infer(types::CompilerConstraintList *constraints, BaselineInspector *inspector, jsbytecode *pc)
|
||||
MCompare::infer(CompilerConstraintList *constraints, BaselineInspector *inspector, jsbytecode *pc)
|
||||
{
|
||||
MOZ_ASSERT(operandMightEmulateUndefined());
|
||||
|
||||
@ -2827,7 +2827,7 @@ MTypeOf::foldsTo(TempAllocator &alloc)
|
||||
}
|
||||
|
||||
void
|
||||
MTypeOf::cacheInputMaybeCallableOrEmulatesUndefined(types::CompilerConstraintList *constraints)
|
||||
MTypeOf::cacheInputMaybeCallableOrEmulatesUndefined(CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(inputMaybeCallableOrEmulatesUndefined());
|
||||
|
||||
@ -3568,7 +3568,7 @@ MCompare::filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *f
|
||||
}
|
||||
|
||||
void
|
||||
MNot::cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints)
|
||||
MNot::cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(operandMightEmulateUndefined());
|
||||
|
||||
@ -4030,16 +4030,16 @@ InlinePropertyTable::hasFunction(JSFunction *func) const
|
||||
return false;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *
|
||||
TemporaryTypeSet *
|
||||
InlinePropertyTable::buildTypeSetForFunction(JSFunction *func) const
|
||||
{
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
types::TemporaryTypeSet *types = alloc->new_<types::TemporaryTypeSet>();
|
||||
TemporaryTypeSet *types = alloc->new_<TemporaryTypeSet>();
|
||||
if (!types)
|
||||
return nullptr;
|
||||
for (size_t i = 0; i < numEntries(); i++) {
|
||||
if (entries_[i]->func == func)
|
||||
types->addType(types::Type::ObjectType(entries_[i]->group), alloc);
|
||||
types->addType(TypeSet::ObjectType(entries_[i]->group), alloc);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
@ -4085,7 +4085,7 @@ MGetElementCache::allowDoubleResult() const
|
||||
if (!resultTypeSet())
|
||||
return true;
|
||||
|
||||
return resultTypeSet()->hasType(types::Type::DoubleType());
|
||||
return resultTypeSet()->hasType(TypeSet::DoubleType());
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -4277,7 +4277,7 @@ MArrayJoin::foldsTo(TempAllocator &alloc) {
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
||||
jit::ElementAccessIsDenseNative(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id)
|
||||
{
|
||||
if (obj->mightBeType(MIRType_String))
|
||||
@ -4286,7 +4286,7 @@ jit::ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
||||
if (id->type() != MIRType_Int32 && id->type() != MIRType_Double)
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
@ -4296,7 +4296,7 @@ jit::ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
||||
jit::ElementAccessIsAnyTypedArray(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id,
|
||||
Scalar::Type *arrayType)
|
||||
{
|
||||
@ -4306,7 +4306,7 @@ jit::ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
||||
if (id->type() != MIRType_Int32 && id->type() != MIRType_Double)
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
@ -4318,47 +4318,47 @@ jit::ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefinition *obj)
|
||||
jit::ElementAccessIsPacked(CompilerConstraintList *constraints, MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
return types && !types->hasObjectFlags(constraints, OBJECT_FLAG_NON_PACKED);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints, MDefinition *obj)
|
||||
jit::ElementAccessMightBeCopyOnWrite(CompilerConstraintList *constraints, MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
return !types || types->hasObjectFlags(constraints, OBJECT_FLAG_COPY_ON_WRITE);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
|
||||
jit::ElementAccessHasExtraIndexedProperty(CompilerConstraintList *constraints,
|
||||
MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
|
||||
if (!types || types->hasObjectFlags(constraints, OBJECT_FLAG_LENGTH_OVERFLOW))
|
||||
return true;
|
||||
|
||||
return types::TypeCanHaveExtraIndexedProperties(constraints, types);
|
||||
return TypeCanHaveExtraIndexedProperties(constraints, types);
|
||||
}
|
||||
|
||||
MIRType
|
||||
jit::DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj)
|
||||
jit::DenseNativeElementType(CompilerConstraintList *constraints, MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
MIRType elementType = MIRType_None;
|
||||
unsigned count = types->getObjectCount();
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
if (key->unknownProperties())
|
||||
return MIRType_None;
|
||||
|
||||
types::HeapTypeSetKey elementTypes = key->property(JSID_VOID);
|
||||
HeapTypeSetKey elementTypes = key->property(JSID_VOID);
|
||||
|
||||
MIRType type = elementTypes.knownMIRType(constraints);
|
||||
if (type == MIRType_None)
|
||||
@ -4374,9 +4374,9 @@ jit::DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinit
|
||||
}
|
||||
|
||||
static BarrierKind
|
||||
PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
types::TypeSetObjectKey *key, PropertyName *name,
|
||||
types::TypeSet *observed)
|
||||
PropertyReadNeedsTypeBarrier(CompilerConstraintList *constraints,
|
||||
TypeSet::ObjectKey *key, PropertyName *name,
|
||||
TypeSet *observed)
|
||||
{
|
||||
// If the object being read from has types for the property which haven't
|
||||
// been observed at this access site, the read could produce a new type and
|
||||
@ -4393,7 +4393,7 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
}
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (property.maybeTypes()) {
|
||||
if (!TypeSetIncludes(observed, MIRType_Value, property.maybeTypes())) {
|
||||
// If all possible objects have been observed, we don't have to
|
||||
@ -4412,7 +4412,7 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
// other than undefined, a barrier is required.
|
||||
if (key->isSingleton()) {
|
||||
JSObject *obj = key->singleton();
|
||||
if (name && types::CanHaveEmptyPropertyTypesForOwnProperty(obj) &&
|
||||
if (name && CanHaveEmptyPropertyTypesForOwnProperty(obj) &&
|
||||
(!property.maybeTypes() || property.maybeTypes()->empty()))
|
||||
{
|
||||
return BarrierKind::TypeSet;
|
||||
@ -4425,9 +4425,9 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
|
||||
BarrierKind
|
||||
jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
types::TypeSetObjectKey *key, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed, bool updateObserved)
|
||||
CompilerConstraintList *constraints,
|
||||
TypeSet::ObjectKey *key, PropertyName *name,
|
||||
TemporaryTypeSet *observed, bool updateObserved)
|
||||
{
|
||||
// If this access has never executed, try to add types to the observed set
|
||||
// according to any property which exists on the object or its prototype.
|
||||
@ -4442,14 +4442,14 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
if (!obj->getClass()->isNative())
|
||||
break;
|
||||
|
||||
types::TypeSetObjectKey *key = types::TypeSetObjectKey::get(obj);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(obj);
|
||||
if (propertycx)
|
||||
key->ensureTrackedProperty(propertycx, NameToId(name));
|
||||
|
||||
if (!key->unknownProperties()) {
|
||||
types::HeapTypeSetKey property = key->property(NameToId(name));
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
if (property.maybeTypes()) {
|
||||
types::TypeSet::TypeList types;
|
||||
TypeSet::TypeList types;
|
||||
if (!property.maybeTypes()->enumerateTypes(&types))
|
||||
break;
|
||||
if (types.length()) {
|
||||
@ -4469,14 +4469,14 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
|
||||
BarrierKind
|
||||
jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
TemporaryTypeSet *observed)
|
||||
{
|
||||
if (observed->unknown())
|
||||
return BarrierKind::NoBarrier;
|
||||
|
||||
types::TypeSet *types = obj->resultTypeSet();
|
||||
TypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return BarrierKind::TypeSet;
|
||||
|
||||
@ -4484,8 +4484,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
|
||||
bool updateObserved = types->getObjectCount() == 1;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
if (key) {
|
||||
if (TypeSet::ObjectKey *key = types->getObject(i)) {
|
||||
BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, key, name,
|
||||
observed, updateObserved);
|
||||
if (kind == BarrierKind::TypeSet)
|
||||
@ -4504,21 +4503,21 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
}
|
||||
|
||||
BarrierKind
|
||||
jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
jit::PropertyReadOnPrototypeNeedsTypeBarrier(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
TemporaryTypeSet *observed)
|
||||
{
|
||||
if (observed->unknown())
|
||||
return BarrierKind::NoBarrier;
|
||||
|
||||
types::TypeSet *types = obj->resultTypeSet();
|
||||
TypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return BarrierKind::TypeSet;
|
||||
|
||||
BarrierKind res = BarrierKind::NoBarrier;
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
while (true) {
|
||||
@ -4526,7 +4525,7 @@ jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *cons
|
||||
return BarrierKind::TypeSet;
|
||||
if (!key->proto().isObject())
|
||||
break;
|
||||
key = types::TypeSetObjectKey::get(key->proto().toObject());
|
||||
key = TypeSet::ObjectKey::get(key->proto().toObject());
|
||||
BarrierKind kind = PropertyReadNeedsTypeBarrier(constraints, key, name, observed);
|
||||
if (kind == BarrierKind::TypeSet)
|
||||
return BarrierKind::TypeSet;
|
||||
@ -4544,23 +4543,22 @@ jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *cons
|
||||
}
|
||||
|
||||
bool
|
||||
jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
||||
jit::PropertyReadIsIdempotent(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name)
|
||||
{
|
||||
// Determine if reading a property from obj is likely to be idempotent.
|
||||
|
||||
types::TypeSet *types = obj->resultTypeSet();
|
||||
TypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
if (key) {
|
||||
if (TypeSet::ObjectKey *key = types->getObject(i)) {
|
||||
if (key->unknownProperties())
|
||||
return false;
|
||||
|
||||
// Check if the property has been reconfigured or is a getter.
|
||||
types::HeapTypeSetKey property = key->property(NameToId(name));
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
if (property.nonData(constraints))
|
||||
return false;
|
||||
}
|
||||
@ -4571,62 +4569,61 @@ jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
||||
|
||||
void
|
||||
jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
TemporaryTypeSet *observed)
|
||||
{
|
||||
// Add objects to observed which *could* be observed by reading name from obj,
|
||||
// to hopefully avoid unnecessary type barriers and code invalidations.
|
||||
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
observed->addType(TypeSet::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
if (key->unknownProperties()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
observed->addType(TypeSet::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
types::HeapTypeSet *types = property.maybeTypes();
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSet *types = property.maybeTypes();
|
||||
if (!types)
|
||||
continue;
|
||||
|
||||
if (types->unknownObject()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
observed->addType(TypeSet::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
if (key)
|
||||
observed->addType(types::Type::ObjectType(key), alloc);
|
||||
if (TypeSet::ObjectKey *key = types->getObject(i))
|
||||
observed->addType(TypeSet::ObjectType(key), alloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
PropertyTypeIncludes(TempAllocator &alloc, types::HeapTypeSetKey property,
|
||||
PropertyTypeIncludes(TempAllocator &alloc, HeapTypeSetKey property,
|
||||
MDefinition *value, MIRType implicitType)
|
||||
{
|
||||
// If implicitType is not MIRType_None, it is an additional type which the
|
||||
// property implicitly includes. In this case, make a new type set which
|
||||
// explicitly contains the type.
|
||||
types::TypeSet *types = property.maybeTypes();
|
||||
TypeSet *types = property.maybeTypes();
|
||||
if (implicitType != MIRType_None) {
|
||||
types::Type newType = types::Type::PrimitiveType(ValueTypeFromMIRType(implicitType));
|
||||
TypeSet::Type newType = TypeSet::PrimitiveType(ValueTypeFromMIRType(implicitType));
|
||||
if (types)
|
||||
types = types->clone(alloc.lifoAlloc());
|
||||
else
|
||||
types = alloc.lifoAlloc()->new_<types::TemporaryTypeSet>();
|
||||
types = alloc.lifoAlloc()->new_<TemporaryTypeSet>();
|
||||
types->addType(newType, alloc.lifoAlloc());
|
||||
}
|
||||
|
||||
@ -4634,8 +4631,8 @@ PropertyTypeIncludes(TempAllocator &alloc, types::HeapTypeSetKey property,
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, types::TemporaryTypeSet *objTypes,
|
||||
TryAddTypeBarrierForWrite(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, TemporaryTypeSet *objTypes,
|
||||
PropertyName *name, MDefinition **pvalue, MIRType implicitType)
|
||||
{
|
||||
// Return whether pvalue was modified to include a type barrier ensuring
|
||||
@ -4645,10 +4642,10 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
||||
// All objects in the set must have the same types for name. Otherwise, we
|
||||
// could bail out without subsequently triggering a type change that
|
||||
// invalidates the compiled code.
|
||||
Maybe<types::HeapTypeSetKey> aggregateProperty;
|
||||
Maybe<HeapTypeSetKey> aggregateProperty;
|
||||
|
||||
for (size_t i = 0; i < objTypes->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = objTypes->getObject(i);
|
||||
TypeSet::ObjectKey *key = objTypes->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
@ -4656,7 +4653,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
||||
return false;
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (!property.maybeTypes() || property.couldBeConstant(constraints))
|
||||
return false;
|
||||
|
||||
@ -4704,7 +4701,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
||||
if ((*pvalue)->type() != MIRType_Value)
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
|
||||
TemporaryTypeSet *types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
@ -4721,7 +4718,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
||||
|
||||
static MInstruction *
|
||||
AddGroupGuard(TempAllocator &alloc, MBasicBlock *current, MDefinition *obj,
|
||||
types::TypeSetObjectKey *key, bool bailOnEquality)
|
||||
TypeSet::ObjectKey *key, bool bailOnEquality)
|
||||
{
|
||||
MInstruction *guard;
|
||||
|
||||
@ -4742,8 +4739,8 @@ AddGroupGuard(TempAllocator &alloc, MBasicBlock *current, MDefinition *obj,
|
||||
|
||||
// Whether value can be written to property without changing type information.
|
||||
bool
|
||||
jit::CanWriteProperty(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
types::HeapTypeSetKey property, MDefinition *value,
|
||||
jit::CanWriteProperty(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
HeapTypeSetKey property, MDefinition *value,
|
||||
MIRType implicitType /* = MIRType_None */)
|
||||
{
|
||||
if (property.couldBeConstant(constraints))
|
||||
@ -4752,7 +4749,7 @@ jit::CanWriteProperty(TempAllocator &alloc, types::CompilerConstraintList *const
|
||||
}
|
||||
|
||||
bool
|
||||
jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, MDefinition **pobj,
|
||||
PropertyName *name, MDefinition **pvalue,
|
||||
bool canModify, MIRType implicitType)
|
||||
@ -4763,7 +4760,7 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
||||
// properties that are accounted for by type information, i.e. normal data
|
||||
// properties and elements.
|
||||
|
||||
types::TemporaryTypeSet *types = (*pobj)->resultTypeSet();
|
||||
TemporaryTypeSet *types = (*pobj)->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return true;
|
||||
|
||||
@ -4774,7 +4771,7 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
||||
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key || key->unknownProperties())
|
||||
continue;
|
||||
|
||||
@ -4784,7 +4781,7 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
||||
continue;
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (!CanWriteProperty(alloc, constraints, property, *pvalue, implicitType)) {
|
||||
// Either pobj or pvalue needs to be modified to filter out the
|
||||
// types which the value could have but are not in the property,
|
||||
@ -4808,16 +4805,16 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
||||
if (types->getObjectCount() <= 1)
|
||||
return true;
|
||||
|
||||
types::TypeSetObjectKey *excluded = nullptr;
|
||||
TypeSet::ObjectKey *excluded = nullptr;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key || key->unknownProperties())
|
||||
continue;
|
||||
if (!name && IsAnyTypedArrayClass(key->clasp()))
|
||||
continue;
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (CanWriteProperty(alloc, constraints, property, *pvalue, implicitType))
|
||||
continue;
|
||||
|
||||
|
152
js/src/jit/MIR.h
152
js/src/jit/MIR.h
@ -363,7 +363,7 @@ class MDefinition : public MNode
|
||||
uint32_t flags_; // Bit flags.
|
||||
Range *range_; // Any computed range for this def.
|
||||
MIRType resultType_; // Representation of result type.
|
||||
types::TemporaryTypeSet *resultTypeSet_; // Optional refinement of the result type.
|
||||
TemporaryTypeSet *resultTypeSet_; // Optional refinement of the result type.
|
||||
union {
|
||||
MInstruction *dependency_; // Implicit dependency (store, call, etc.) of this instruction.
|
||||
// Used by alias analysis, GVN and LICM.
|
||||
@ -608,7 +608,7 @@ class MDefinition : public MNode
|
||||
return resultType_;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *resultTypeSet() const {
|
||||
TemporaryTypeSet *resultTypeSet() const {
|
||||
return resultTypeSet_;
|
||||
}
|
||||
bool emptyResultTypeSet() const;
|
||||
@ -781,7 +781,7 @@ class MDefinition : public MNode
|
||||
void setResultType(MIRType type) {
|
||||
resultType_ = type;
|
||||
}
|
||||
void setResultTypeSet(types::TemporaryTypeSet *types) {
|
||||
void setResultTypeSet(TemporaryTypeSet *types) {
|
||||
resultTypeSet_ = types;
|
||||
}
|
||||
|
||||
@ -1277,15 +1277,15 @@ class MConstant : public MNullaryInstruction
|
||||
Value value_;
|
||||
|
||||
protected:
|
||||
MConstant(const Value &v, types::CompilerConstraintList *constraints);
|
||||
MConstant(const Value &v, CompilerConstraintList *constraints);
|
||||
explicit MConstant(JSObject *obj);
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Constant)
|
||||
static MConstant *New(TempAllocator &alloc, const Value &v,
|
||||
types::CompilerConstraintList *constraints = nullptr);
|
||||
CompilerConstraintList *constraints = nullptr);
|
||||
static MConstant *NewTypedValue(TempAllocator &alloc, const Value &v, MIRType type,
|
||||
types::CompilerConstraintList *constraints = nullptr);
|
||||
CompilerConstraintList *constraints = nullptr);
|
||||
static MConstant *NewAsmJS(TempAllocator &alloc, const Value &v, MIRType type);
|
||||
static MConstant *NewConstraintlessObject(TempAllocator &alloc, JSObject *v);
|
||||
|
||||
@ -1335,12 +1335,12 @@ class MNurseryObject : public MNullaryInstruction
|
||||
uint32_t index_;
|
||||
|
||||
protected:
|
||||
MNurseryObject(JSObject *obj, uint32_t index, types::CompilerConstraintList *constraints);
|
||||
MNurseryObject(JSObject *obj, uint32_t index, CompilerConstraintList *constraints);
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NurseryObject)
|
||||
static MNurseryObject *New(TempAllocator &alloc, JSObject *obj, uint32_t index,
|
||||
types::CompilerConstraintList *constraints = nullptr);
|
||||
CompilerConstraintList *constraints = nullptr);
|
||||
|
||||
HashNumber valueHash() const MOZ_OVERRIDE;
|
||||
bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE;
|
||||
@ -2197,7 +2197,7 @@ class MParameter : public MNullaryInstruction
|
||||
public:
|
||||
static const int32_t THIS_SLOT = -1;
|
||||
|
||||
MParameter(int32_t index, types::TemporaryTypeSet *types)
|
||||
MParameter(int32_t index, TemporaryTypeSet *types)
|
||||
: index_(index)
|
||||
{
|
||||
setResultType(MIRType_Value);
|
||||
@ -2206,7 +2206,7 @@ class MParameter : public MNullaryInstruction
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Parameter)
|
||||
static MParameter *New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types);
|
||||
static MParameter *New(TempAllocator &alloc, int32_t index, TemporaryTypeSet *types);
|
||||
|
||||
int32_t index() const {
|
||||
return index_;
|
||||
@ -2540,7 +2540,7 @@ class MTest
|
||||
// background threads. So make callers explicitly call it if they want us
|
||||
// to check whether the operand might do this. If this method is never
|
||||
// called, we'll assume our operand can emulate undefined.
|
||||
void cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints);
|
||||
void cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints);
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
|
||||
bool *filtersNull);
|
||||
@ -2632,12 +2632,12 @@ class MThrow
|
||||
};
|
||||
|
||||
// Fabricate a type set containing only the type of the specified object.
|
||||
types::TemporaryTypeSet *
|
||||
MakeSingletonTypeSet(types::CompilerConstraintList *constraints, JSObject *obj);
|
||||
TemporaryTypeSet *
|
||||
MakeSingletonTypeSet(CompilerConstraintList *constraints, JSObject *obj);
|
||||
|
||||
bool
|
||||
MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, types::TemporaryTypeSet *newTypeSet);
|
||||
MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, TemporaryTypeSet *newTypeSet);
|
||||
|
||||
// Helper class to assert all GC pointers embedded in MIR instructions are
|
||||
// tenured. Off-thread Ion compilation and nursery GCs can happen in parallel,
|
||||
@ -2689,7 +2689,7 @@ class MNewArray
|
||||
// Allocate space at initialization or not
|
||||
AllocatingBehaviour allocating_;
|
||||
|
||||
MNewArray(types::CompilerConstraintList *constraints, uint32_t count, MConstant *templateConst,
|
||||
MNewArray(CompilerConstraintList *constraints, uint32_t count, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap, AllocatingBehaviour allocating)
|
||||
: MUnaryInstruction(templateConst),
|
||||
count_(count),
|
||||
@ -2705,7 +2705,7 @@ class MNewArray
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewArray)
|
||||
|
||||
static MNewArray *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MNewArray *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
uint32_t count, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap, AllocatingBehaviour allocating)
|
||||
{
|
||||
@ -2755,7 +2755,7 @@ class MNewArrayCopyOnWrite : public MNullaryInstruction
|
||||
AlwaysTenured<ArrayObject*> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MNewArrayCopyOnWrite(types::CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
MNewArrayCopyOnWrite(CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
: templateObject_(templateObject),
|
||||
initialHeap_(initialHeap)
|
||||
@ -2769,7 +2769,7 @@ class MNewArrayCopyOnWrite : public MNullaryInstruction
|
||||
INSTRUCTION_HEADER(NewArrayCopyOnWrite)
|
||||
|
||||
static MNewArrayCopyOnWrite *New(TempAllocator &alloc,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
ArrayObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
{
|
||||
@ -2796,7 +2796,7 @@ class MNewArrayDynamicLength
|
||||
AlwaysTenured<ArrayObject*> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MNewArrayDynamicLength(types::CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
MNewArrayDynamicLength(CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
gc::InitialHeap initialHeap, MDefinition *length)
|
||||
: MUnaryInstruction(length),
|
||||
templateObject_(templateObject),
|
||||
@ -2811,7 +2811,7 @@ class MNewArrayDynamicLength
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewArrayDynamicLength)
|
||||
|
||||
static MNewArrayDynamicLength *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MNewArrayDynamicLength *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
ArrayObject *templateObject, gc::InitialHeap initialHeap,
|
||||
MDefinition *length)
|
||||
{
|
||||
@ -2844,7 +2844,7 @@ class MNewObject
|
||||
gc::InitialHeap initialHeap_;
|
||||
Mode mode_;
|
||||
|
||||
MNewObject(types::CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
MNewObject(CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap, Mode mode)
|
||||
: MUnaryInstruction(templateConst),
|
||||
initialHeap_(initialHeap),
|
||||
@ -2867,7 +2867,7 @@ class MNewObject
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewObject)
|
||||
|
||||
static MNewObject *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MNewObject *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MConstant *templateConst, gc::InitialHeap initialHeap,
|
||||
Mode mode)
|
||||
{
|
||||
@ -2903,7 +2903,7 @@ class MNewTypedObject : public MNullaryInstruction
|
||||
AlwaysTenured<InlineTypedObject *> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MNewTypedObject(types::CompilerConstraintList *constraints,
|
||||
MNewTypedObject(CompilerConstraintList *constraints,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
: templateObject_(templateObject),
|
||||
@ -2917,7 +2917,7 @@ class MNewTypedObject : public MNullaryInstruction
|
||||
INSTRUCTION_HEADER(NewTypedObject)
|
||||
|
||||
static MNewTypedObject *New(TempAllocator &alloc,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
{
|
||||
@ -2978,7 +2978,7 @@ class MSimdBox
|
||||
AlwaysTenured<InlineTypedObject *> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MSimdBox(types::CompilerConstraintList *constraints,
|
||||
MSimdBox(CompilerConstraintList *constraints,
|
||||
MDefinition *op,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
@ -2996,7 +2996,7 @@ class MSimdBox
|
||||
INSTRUCTION_HEADER(SimdBox)
|
||||
|
||||
static MSimdBox *New(TempAllocator &alloc,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
MDefinition *op,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
@ -3910,7 +3910,7 @@ class MCompare
|
||||
void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
|
||||
bool *filtersNull);
|
||||
|
||||
void infer(types::CompilerConstraintList *constraints,
|
||||
void infer(CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, jsbytecode *pc);
|
||||
CompareType compareType() const {
|
||||
return compareType_;
|
||||
@ -4002,10 +4002,10 @@ class MBox
|
||||
if (ins->resultTypeSet()) {
|
||||
setResultTypeSet(ins->resultTypeSet());
|
||||
} else if (ins->type() != MIRType_Value) {
|
||||
types::Type ntype = ins->type() == MIRType_Object
|
||||
? types::Type::AnyObjectType()
|
||||
: types::Type::PrimitiveType(ValueTypeFromMIRType(ins->type()));
|
||||
setResultTypeSet(alloc.lifoAlloc()->new_<types::TemporaryTypeSet>(alloc.lifoAlloc(), ntype));
|
||||
TypeSet::Type ntype = ins->type() == MIRType_Object
|
||||
? TypeSet::AnyObjectType()
|
||||
: TypeSet::PrimitiveType(ValueTypeFromMIRType(ins->type()));
|
||||
setResultTypeSet(alloc.lifoAlloc()->new_<TemporaryTypeSet>(alloc.lifoAlloc(), ntype));
|
||||
}
|
||||
setMovable();
|
||||
}
|
||||
@ -4261,7 +4261,7 @@ class MCreateThisWithTemplate
|
||||
{
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MCreateThisWithTemplate(types::CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
MCreateThisWithTemplate(CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap)
|
||||
: MUnaryInstruction(templateConst),
|
||||
initialHeap_(initialHeap)
|
||||
@ -4272,7 +4272,7 @@ class MCreateThisWithTemplate
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(CreateThisWithTemplate)
|
||||
static MCreateThisWithTemplate *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MCreateThisWithTemplate *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MConstant *templateConst, gc::InitialHeap initialHeap)
|
||||
{
|
||||
return new(alloc) MCreateThisWithTemplate(constraints, templateConst, initialHeap);
|
||||
@ -4971,7 +4971,7 @@ class MTypeOf
|
||||
}
|
||||
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
void cacheInputMaybeCallableOrEmulatesUndefined(types::CompilerConstraintList *constraints);
|
||||
void cacheInputMaybeCallableOrEmulatesUndefined(CompilerConstraintList *constraints);
|
||||
|
||||
bool inputMaybeCallableOrEmulatesUndefined() const {
|
||||
return inputMaybeCallableOrEmulatesUndefined_;
|
||||
@ -6293,7 +6293,7 @@ class MStringSplit
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<StringPolicy<0>, StringPolicy<1> >::Data
|
||||
{
|
||||
MStringSplit(types::CompilerConstraintList *constraints, MDefinition *string, MDefinition *sep,
|
||||
MStringSplit(CompilerConstraintList *constraints, MDefinition *string, MDefinition *sep,
|
||||
MConstant *templateObject)
|
||||
: MTernaryInstruction(string, sep, templateObject)
|
||||
{
|
||||
@ -6304,7 +6304,7 @@ class MStringSplit
|
||||
public:
|
||||
INSTRUCTION_HEADER(StringSplit)
|
||||
|
||||
static MStringSplit *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MStringSplit *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *string, MDefinition *sep,
|
||||
MConstant *templateObject)
|
||||
{
|
||||
@ -6504,7 +6504,7 @@ class MPhi MOZ_FINAL
|
||||
|
||||
// Add types for this phi which speculate about new inputs that may come in
|
||||
// via a loop backedge.
|
||||
bool addBackedgeType(MIRType type, types::TemporaryTypeSet *typeSet);
|
||||
bool addBackedgeType(MIRType type, TemporaryTypeSet *typeSet);
|
||||
|
||||
// Initializes the operands vector to the given capacity,
|
||||
// permitting use of addInput() instead of addInputSlow().
|
||||
@ -6904,7 +6904,7 @@ class MRegExp : public MNullaryInstruction
|
||||
AlwaysTenured<RegExpObject *> source_;
|
||||
bool mustClone_;
|
||||
|
||||
MRegExp(types::CompilerConstraintList *constraints, RegExpObject *source, bool mustClone)
|
||||
MRegExp(CompilerConstraintList *constraints, RegExpObject *source, bool mustClone)
|
||||
: source_(source),
|
||||
mustClone_(mustClone)
|
||||
{
|
||||
@ -6915,7 +6915,7 @@ class MRegExp : public MNullaryInstruction
|
||||
public:
|
||||
INSTRUCTION_HEADER(RegExp)
|
||||
|
||||
static MRegExp *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MRegExp *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
RegExpObject *source, bool mustClone)
|
||||
{
|
||||
return new(alloc) MRegExp(constraints, source, mustClone);
|
||||
@ -7183,7 +7183,7 @@ class MLambda
|
||||
{
|
||||
LambdaFunctionInfo info_;
|
||||
|
||||
MLambda(types::CompilerConstraintList *constraints, MDefinition *scopeChain, MConstant *cst)
|
||||
MLambda(CompilerConstraintList *constraints, MDefinition *scopeChain, MConstant *cst)
|
||||
: MBinaryInstruction(scopeChain, cst), info_(&cst->value().toObject().as<JSFunction>())
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
@ -7194,7 +7194,7 @@ class MLambda
|
||||
public:
|
||||
INSTRUCTION_HEADER(Lambda)
|
||||
|
||||
static MLambda *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MLambda *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *scopeChain, MConstant *fun)
|
||||
{
|
||||
return new(alloc) MLambda(constraints, scopeChain, fun);
|
||||
@ -7220,7 +7220,7 @@ class MLambdaArrow
|
||||
{
|
||||
LambdaFunctionInfo info_;
|
||||
|
||||
MLambdaArrow(types::CompilerConstraintList *constraints, MDefinition *scopeChain,
|
||||
MLambdaArrow(CompilerConstraintList *constraints, MDefinition *scopeChain,
|
||||
MDefinition *this_, JSFunction *fun)
|
||||
: MBinaryInstruction(scopeChain, this_), info_(fun)
|
||||
{
|
||||
@ -7233,7 +7233,7 @@ class MLambdaArrow
|
||||
public:
|
||||
INSTRUCTION_HEADER(LambdaArrow)
|
||||
|
||||
static MLambdaArrow *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MLambdaArrow *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *scopeChain, MDefinition *this_, JSFunction *fun)
|
||||
{
|
||||
return new(alloc) MLambdaArrow(constraints, scopeChain, this_, fun);
|
||||
@ -7773,7 +7773,7 @@ class MNot
|
||||
|
||||
INSTRUCTION_HEADER(Not)
|
||||
|
||||
void cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints);
|
||||
void cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints);
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
|
||||
void markOperandCantEmulateUndefined() {
|
||||
@ -8514,7 +8514,7 @@ class MArrayConcat
|
||||
AlwaysTenured<ArrayObject*> templateObj_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MArrayConcat(types::CompilerConstraintList *constraints, MDefinition *lhs, MDefinition *rhs,
|
||||
MArrayConcat(CompilerConstraintList *constraints, MDefinition *lhs, MDefinition *rhs,
|
||||
ArrayObject *templateObj, gc::InitialHeap initialHeap)
|
||||
: MBinaryInstruction(lhs, rhs),
|
||||
templateObj_(templateObj),
|
||||
@ -8527,7 +8527,7 @@ class MArrayConcat
|
||||
public:
|
||||
INSTRUCTION_HEADER(ArrayConcat)
|
||||
|
||||
static MArrayConcat *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MArrayConcat *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *lhs, MDefinition *rhs,
|
||||
ArrayObject *templateObj, gc::InitialHeap initialHeap)
|
||||
{
|
||||
@ -9251,7 +9251,7 @@ class InlinePropertyTable : public TempObject
|
||||
}
|
||||
|
||||
bool hasFunction(JSFunction *func) const;
|
||||
types::TemporaryTypeSet *buildTypeSetForFunction(JSFunction *func) const;
|
||||
TemporaryTypeSet *buildTypeSetForFunction(JSFunction *func) const;
|
||||
|
||||
// Remove targets that vetoed inlining from the InlinePropertyTable.
|
||||
void trimTo(ObjectVector &targets, BoolVector &choiceSet);
|
||||
@ -11319,7 +11319,7 @@ class MRest
|
||||
public MRestCommon,
|
||||
public IntPolicy<0>::Data
|
||||
{
|
||||
MRest(types::CompilerConstraintList *constraints, MDefinition *numActuals, unsigned numFormals,
|
||||
MRest(CompilerConstraintList *constraints, MDefinition *numActuals, unsigned numFormals,
|
||||
ArrayObject *templateObject)
|
||||
: MUnaryInstruction(numActuals),
|
||||
MRestCommon(numFormals, templateObject)
|
||||
@ -11331,7 +11331,7 @@ class MRest
|
||||
public:
|
||||
INSTRUCTION_HEADER(Rest)
|
||||
|
||||
static MRest *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MRest *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *numActuals, unsigned numFormals,
|
||||
ArrayObject *templateObject)
|
||||
{
|
||||
@ -11354,7 +11354,7 @@ class MFilterTypeSet
|
||||
: public MUnaryInstruction,
|
||||
public FilterTypeSetPolicy::Data
|
||||
{
|
||||
MFilterTypeSet(MDefinition *def, types::TemporaryTypeSet *types)
|
||||
MFilterTypeSet(MDefinition *def, TemporaryTypeSet *types)
|
||||
: MUnaryInstruction(def)
|
||||
{
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
@ -11365,7 +11365,7 @@ class MFilterTypeSet
|
||||
public:
|
||||
INSTRUCTION_HEADER(FilterTypeSet)
|
||||
|
||||
static MFilterTypeSet *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types) {
|
||||
static MFilterTypeSet *New(TempAllocator &alloc, MDefinition *def, TemporaryTypeSet *types) {
|
||||
return new(alloc) MFilterTypeSet(def, types);
|
||||
}
|
||||
|
||||
@ -11388,7 +11388,7 @@ class MTypeBarrier
|
||||
{
|
||||
BarrierKind barrierKind_;
|
||||
|
||||
MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types, BarrierKind kind)
|
||||
MTypeBarrier(MDefinition *def, TemporaryTypeSet *types, BarrierKind kind)
|
||||
: MUnaryInstruction(def),
|
||||
barrierKind_(kind)
|
||||
{
|
||||
@ -11405,7 +11405,7 @@ class MTypeBarrier
|
||||
public:
|
||||
INSTRUCTION_HEADER(TypeBarrier)
|
||||
|
||||
static MTypeBarrier *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types,
|
||||
static MTypeBarrier *New(TempAllocator &alloc, MDefinition *def, TemporaryTypeSet *types,
|
||||
BarrierKind kind = BarrierKind::TypeSet) {
|
||||
return new(alloc) MTypeBarrier(def, types, kind);
|
||||
}
|
||||
@ -11444,10 +11444,10 @@ class MMonitorTypes
|
||||
: public MUnaryInstruction,
|
||||
public BoxInputsPolicy::Data
|
||||
{
|
||||
const types::TemporaryTypeSet *typeSet_;
|
||||
const TemporaryTypeSet *typeSet_;
|
||||
BarrierKind barrierKind_;
|
||||
|
||||
MMonitorTypes(MDefinition *def, const types::TemporaryTypeSet *types, BarrierKind kind)
|
||||
MMonitorTypes(MDefinition *def, const TemporaryTypeSet *types, BarrierKind kind)
|
||||
: MUnaryInstruction(def),
|
||||
typeSet_(types),
|
||||
barrierKind_(kind)
|
||||
@ -11461,12 +11461,12 @@ class MMonitorTypes
|
||||
public:
|
||||
INSTRUCTION_HEADER(MonitorTypes)
|
||||
|
||||
static MMonitorTypes *New(TempAllocator &alloc, MDefinition *def, const types::TemporaryTypeSet *types,
|
||||
static MMonitorTypes *New(TempAllocator &alloc, MDefinition *def, const TemporaryTypeSet *types,
|
||||
BarrierKind kind) {
|
||||
return new(alloc) MMonitorTypes(def, types, kind);
|
||||
}
|
||||
|
||||
const types::TemporaryTypeSet *typeSet() const {
|
||||
const TemporaryTypeSet *typeSet() const {
|
||||
return typeSet_;
|
||||
}
|
||||
BarrierKind barrierKind() const {
|
||||
@ -12701,35 +12701,35 @@ MControlInstruction *MDefinition::toControlInstruction() {
|
||||
|
||||
// Helper functions used to decide how to build MIR.
|
||||
|
||||
bool ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessIsDenseNative(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id);
|
||||
bool ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessIsAnyTypedArray(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id,
|
||||
Scalar::Type *arrayType);
|
||||
bool ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessIsPacked(CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessMightBeCopyOnWrite(CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessHasExtraIndexedProperty(CompilerConstraintList *constraints,
|
||||
MDefinition *obj);
|
||||
MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
MIRType DenseNativeElementType(CompilerConstraintList *constraints, MDefinition *obj);
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
types::TypeSetObjectKey *key, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed, bool updateObserved);
|
||||
CompilerConstraintList *constraints,
|
||||
TypeSet::ObjectKey *key, PropertyName *name,
|
||||
TemporaryTypeSet *observed, bool updateObserved);
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *observed);
|
||||
BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
bool PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *observed);
|
||||
bool PropertyReadIsIdempotent(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name);
|
||||
void AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
bool CanWriteProperty(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
types::HeapTypeSetKey property, MDefinition *value,
|
||||
TemporaryTypeSet *observed);
|
||||
bool CanWriteProperty(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
HeapTypeSetKey property, MDefinition *value,
|
||||
MIRType implicitType = MIRType_None);
|
||||
bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, MDefinition **pobj,
|
||||
PropertyName *name, MDefinition **pvalue,
|
||||
bool canModify, MIRType implicitType = MIRType_None);
|
||||
|
@ -37,17 +37,17 @@ namespace {
|
||||
// Emulate a TypeSet logic from a Type object to avoid duplicating the guard
|
||||
// logic.
|
||||
class TypeWrapper {
|
||||
types::Type t_;
|
||||
TypeSet::Type t_;
|
||||
|
||||
public:
|
||||
explicit TypeWrapper(types::Type t) : t_(t) {}
|
||||
explicit TypeWrapper(TypeSet::Type t) : t_(t) {}
|
||||
|
||||
inline bool unknown() const {
|
||||
return t_.isUnknown();
|
||||
}
|
||||
inline bool hasType(types::Type t) const {
|
||||
if (t == types::Type::Int32Type())
|
||||
return t == t_ || t_ == types::Type::DoubleType();
|
||||
inline bool hasType(TypeSet::Type t) const {
|
||||
if (t == TypeSet::Int32Type())
|
||||
return t == t_ || t_ == TypeSet::DoubleType();
|
||||
return t == t_;
|
||||
}
|
||||
inline unsigned getObjectCount() const {
|
||||
@ -69,30 +69,30 @@ class TypeWrapper {
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
template <typename Source, typename TypeSet> void
|
||||
MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, BarrierKind kind,
|
||||
template <typename Source, typename Set> void
|
||||
MacroAssembler::guardTypeSet(const Source &address, const Set *types, BarrierKind kind,
|
||||
Register scratch, Label *miss)
|
||||
{
|
||||
MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet);
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
|
||||
Label matched;
|
||||
types::Type tests[8] = {
|
||||
types::Type::Int32Type(),
|
||||
types::Type::UndefinedType(),
|
||||
types::Type::BooleanType(),
|
||||
types::Type::StringType(),
|
||||
types::Type::SymbolType(),
|
||||
types::Type::NullType(),
|
||||
types::Type::MagicArgType(),
|
||||
types::Type::AnyObjectType()
|
||||
TypeSet::Type tests[8] = {
|
||||
TypeSet::Int32Type(),
|
||||
TypeSet::UndefinedType(),
|
||||
TypeSet::BooleanType(),
|
||||
TypeSet::StringType(),
|
||||
TypeSet::SymbolType(),
|
||||
TypeSet::NullType(),
|
||||
TypeSet::MagicArgType(),
|
||||
TypeSet::AnyObjectType()
|
||||
};
|
||||
|
||||
// The double type also implies Int32.
|
||||
// So replace the int32 test with the double one.
|
||||
if (types->hasType(types::Type::DoubleType())) {
|
||||
MOZ_ASSERT(types->hasType(types::Type::Int32Type()));
|
||||
tests[0] = types::Type::DoubleType();
|
||||
if (types->hasType(TypeSet::DoubleType())) {
|
||||
MOZ_ASSERT(types->hasType(TypeSet::Int32Type()));
|
||||
tests[0] = TypeSet::DoubleType();
|
||||
}
|
||||
|
||||
Register tag = extractTag(address, scratch);
|
||||
@ -109,7 +109,7 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
||||
}
|
||||
|
||||
// If this is the last check, invert the last branch.
|
||||
if (types->hasType(types::Type::AnyObjectType()) || !types->getObjectCount()) {
|
||||
if (types->hasType(TypeSet::AnyObjectType()) || !types->getObjectCount()) {
|
||||
if (!lastBranch.isInitialized()) {
|
||||
jump(miss);
|
||||
return;
|
||||
@ -156,12 +156,12 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
||||
bind(&matched);
|
||||
}
|
||||
|
||||
template <typename TypeSet> void
|
||||
MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
template <typename Set> void
|
||||
MacroAssembler::guardObjectType(Register obj, const Set *types,
|
||||
Register scratch, Label *miss)
|
||||
{
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
MOZ_ASSERT(!types->hasType(types::Type::AnyObjectType()));
|
||||
MOZ_ASSERT(!types->hasType(TypeSet::AnyObjectType()));
|
||||
MOZ_ASSERT(types->getObjectCount());
|
||||
MOZ_ASSERT(scratch != InvalidReg);
|
||||
|
||||
@ -229,28 +229,28 @@ MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
}
|
||||
|
||||
template <typename Source> void
|
||||
MacroAssembler::guardType(const Source &address, types::Type type,
|
||||
MacroAssembler::guardType(const Source &address, TypeSet::Type type,
|
||||
Register scratch, Label *miss)
|
||||
{
|
||||
TypeWrapper wrapper(type);
|
||||
guardTypeSet(address, &wrapper, BarrierKind::TypeSet, scratch, miss);
|
||||
}
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const types::TemporaryTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const TemporaryTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::TemporaryTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TemporaryTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const types::HeapTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const HeapTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::HeapTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const HeapTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const TypedOrValueRegister ®, const types::HeapTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const TypedOrValueRegister ®, const HeapTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const types::TypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const TypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::TypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const TypeWrapper *types,
|
||||
@ -258,16 +258,16 @@ template void MacroAssembler::guardTypeSet(const Address &address, const TypeWra
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TypeWrapper *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardObjectType(Register obj, const types::TemporaryTypeSet *types,
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TemporaryTypeSet *types,
|
||||
Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardObjectType(Register obj, const types::TypeSet *types,
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TypeWrapper *types,
|
||||
Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardType(const Address &address, types::Type type,
|
||||
template void MacroAssembler::guardType(const Address &address, TypeSet::Type type,
|
||||
Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardType(const ValueOperand &value, types::Type type,
|
||||
template void MacroAssembler::guardType(const ValueOperand &value, TypeSet::Type type,
|
||||
Register scratch, Label *miss);
|
||||
|
||||
template<typename S, typename T>
|
||||
|
@ -118,20 +118,20 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a branch based on a specific types::Type.
|
||||
* Note: emits number test (int/double) for types::Type::DoubleType()
|
||||
* Creates a branch based on a specific TypeSet::Type.
|
||||
* Note: emits number test (int/double) for TypeSet::DoubleType()
|
||||
*/
|
||||
class BranchType : public Branch
|
||||
{
|
||||
types::Type type_;
|
||||
TypeSet::Type type_;
|
||||
|
||||
public:
|
||||
BranchType()
|
||||
: Branch(),
|
||||
type_(types::Type::UnknownType())
|
||||
type_(TypeSet::UnknownType())
|
||||
{ }
|
||||
|
||||
BranchType(Condition cond, Register reg, types::Type type, Label *jump)
|
||||
BranchType(Condition cond, Register reg, TypeSet::Type type, Label *jump)
|
||||
: Branch(cond, reg, jump),
|
||||
type_(type)
|
||||
{ }
|
||||
@ -278,7 +278,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
template <typename TypeSet>
|
||||
void guardObjectType(Register obj, const TypeSet *types, Register scratch, Label *miss);
|
||||
template <typename Source>
|
||||
void guardType(const Source &address, types::Type type, Register scratch, Label *miss);
|
||||
void guardType(const Source &address, TypeSet::Type type, Register scratch, Label *miss);
|
||||
|
||||
void loadObjShape(Register objReg, Register dest) {
|
||||
loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
|
||||
|
@ -138,7 +138,7 @@ SpewTempOptimizationTypeInfoVector(const TempOptimizationTypeInfoVector *types,
|
||||
indent ? indent : "",
|
||||
TrackedTypeSiteString(t->site()), StringFromMIRType(t->mirType()));
|
||||
for (uint32_t i = 0; i < t->types().length(); i++)
|
||||
JitSpewCont(JitSpew_OptimizationTracking, " %s", types::TypeString(t->types()[i]));
|
||||
JitSpewCont(JitSpew_OptimizationTracking, " %s", TypeSet::TypeString(t->types()[i]));
|
||||
JitSpewFin(JitSpew_OptimizationTracking);
|
||||
}
|
||||
#endif
|
||||
@ -166,7 +166,7 @@ TrackedOptimizations::spew() const
|
||||
}
|
||||
|
||||
bool
|
||||
OptimizationTypeInfo::trackTypeSet(types::TemporaryTypeSet *typeSet)
|
||||
OptimizationTypeInfo::trackTypeSet(TemporaryTypeSet *typeSet)
|
||||
{
|
||||
if (!typeSet)
|
||||
return true;
|
||||
@ -174,7 +174,7 @@ OptimizationTypeInfo::trackTypeSet(types::TemporaryTypeSet *typeSet)
|
||||
}
|
||||
|
||||
bool
|
||||
OptimizationTypeInfo::trackType(types::Type type)
|
||||
OptimizationTypeInfo::trackType(TypeSet::Type type)
|
||||
{
|
||||
return types_.append(type);
|
||||
}
|
||||
@ -202,15 +202,15 @@ CombineHash(HashNumber h, HashNumber n)
|
||||
}
|
||||
|
||||
static inline HashNumber
|
||||
HashType(types::Type ty)
|
||||
HashType(TypeSet::Type ty)
|
||||
{
|
||||
if (ty.isObjectUnchecked())
|
||||
return PointerHasher<types::TypeSetObjectKey *, 3>::hash(ty.objectKey());
|
||||
return PointerHasher<TypeSet::ObjectKey *, 3>::hash(ty.objectKey());
|
||||
return HashNumber(ty.raw());
|
||||
}
|
||||
|
||||
static HashNumber
|
||||
HashTypeList(const types::TypeSet::TypeList &types)
|
||||
HashTypeList(const TypeSet::TypeList &types)
|
||||
{
|
||||
HashNumber h = 0;
|
||||
for (uint32_t i = 0; i < types.length(); i++)
|
||||
@ -348,18 +348,18 @@ class jit::UniqueTrackedTypes
|
||||
public:
|
||||
struct TypeHasher
|
||||
{
|
||||
typedef types::Type Lookup;
|
||||
typedef TypeSet::Type Lookup;
|
||||
|
||||
static HashNumber hash(const Lookup &ty) { return HashType(ty); }
|
||||
static bool match(const types::Type &ty1, const types::Type &ty2) { return ty1 == ty2; }
|
||||
static bool match(const TypeSet::Type &ty1, const TypeSet::Type &ty2) { return ty1 == ty2; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Map of unique types::Types to indices.
|
||||
typedef HashMap<types::Type, uint8_t, TypeHasher> TypesMap;
|
||||
// Map of unique TypeSet::Types to indices.
|
||||
typedef HashMap<TypeSet::Type, uint8_t, TypeHasher> TypesMap;
|
||||
TypesMap map_;
|
||||
|
||||
Vector<types::Type, 1> list_;
|
||||
Vector<TypeSet::Type, 1> list_;
|
||||
|
||||
public:
|
||||
explicit UniqueTrackedTypes(JSContext *cx)
|
||||
@ -368,14 +368,14 @@ class jit::UniqueTrackedTypes
|
||||
{ }
|
||||
|
||||
bool init() { return map_.init(); }
|
||||
bool getIndexOf(types::Type ty, uint8_t *indexp);
|
||||
bool getIndexOf(TypeSet::Type ty, uint8_t *indexp);
|
||||
|
||||
uint32_t count() const { MOZ_ASSERT(map_.count() == list_.length()); return list_.length(); }
|
||||
bool enumerate(types::TypeSet::TypeList *types) const;
|
||||
bool enumerate(TypeSet::TypeList *types) const;
|
||||
};
|
||||
|
||||
bool
|
||||
UniqueTrackedTypes::getIndexOf(types::Type ty, uint8_t *indexp)
|
||||
UniqueTrackedTypes::getIndexOf(TypeSet::Type ty, uint8_t *indexp)
|
||||
{
|
||||
TypesMap::AddPtr p = map_.lookupForAdd(ty);
|
||||
if (p) {
|
||||
@ -398,7 +398,7 @@ UniqueTrackedTypes::getIndexOf(types::Type ty, uint8_t *indexp)
|
||||
}
|
||||
|
||||
bool
|
||||
UniqueTrackedTypes::enumerate(types::TypeSet::TypeList *types) const
|
||||
UniqueTrackedTypes::enumerate(TypeSet::TypeList *types) const
|
||||
{
|
||||
return types->append(list_.begin(), list_.end());
|
||||
}
|
||||
@ -814,19 +814,19 @@ WriteOffsetsTable(CompactBufferWriter &writer, const Vector<uint32_t, 16> &offse
|
||||
}
|
||||
|
||||
static JSFunction *
|
||||
MaybeConstructorFromType(types::Type ty)
|
||||
MaybeConstructorFromType(TypeSet::Type ty)
|
||||
{
|
||||
if (ty.isUnknown() || ty.isAnyObject() || !ty.isGroup())
|
||||
return nullptr;
|
||||
ObjectGroup *obj = ty.group();
|
||||
types::TypeNewScript *newScript = obj->newScript();
|
||||
TypeNewScript *newScript = obj->newScript();
|
||||
if (!newScript && obj->maybeUnboxedLayout())
|
||||
newScript = obj->unboxedLayout().newScript();
|
||||
return newScript ? newScript->function() : nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
SpewConstructor(types::Type ty, JSFunction *constructor)
|
||||
SpewConstructor(TypeSet::Type ty, JSFunction *constructor)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char buf[512];
|
||||
@ -843,16 +843,16 @@ SpewConstructor(types::Type ty, JSFunction *constructor)
|
||||
}
|
||||
|
||||
JitSpew(JitSpew_OptimizationTracking, " Unique type %s has constructor %s (%s:%u)",
|
||||
types::TypeString(ty), buf, filename, lineno);
|
||||
TypeSet::TypeString(ty), buf, filename, lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SpewAllocationSite(types::Type ty, JSScript *script, uint32_t offset)
|
||||
SpewAllocationSite(TypeSet::Type ty, JSScript *script, uint32_t offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JitSpew(JitSpew_OptimizationTracking, " Unique type %s has alloc site %s:%u",
|
||||
types::TypeString(ty), script->filename(),
|
||||
TypeSet::TypeString(ty), script->filename(),
|
||||
PCToLineNumber(script, script->offsetToPC(offset)));
|
||||
#endif
|
||||
}
|
||||
@ -942,11 +942,11 @@ jit::WriteIonTrackedOptimizationsTable(JSContext *cx, CompactBufferWriter &write
|
||||
// instead of during profiling to avoid touching compartment tables during
|
||||
// profiling. Additionally, TypeNewScript is subject to GC in the
|
||||
// meantime.
|
||||
types::TypeSet::TypeList uniqueTypeList;
|
||||
TypeSet::TypeList uniqueTypeList;
|
||||
if (!uniqueTypes.enumerate(&uniqueTypeList))
|
||||
return false;
|
||||
for (uint32_t i = 0; i < uniqueTypeList.length(); i++) {
|
||||
types::Type ty = uniqueTypeList[i];
|
||||
TypeSet::Type ty = uniqueTypeList[i];
|
||||
if (JSFunction *constructor = MaybeConstructorFromType(ty)) {
|
||||
if (!allTypes->append(IonTrackedTypeWithAddendum(ty, constructor)))
|
||||
return false;
|
||||
@ -954,7 +954,9 @@ jit::WriteIonTrackedOptimizationsTable(JSContext *cx, CompactBufferWriter &write
|
||||
} else {
|
||||
JSScript *script;
|
||||
uint32_t offset;
|
||||
if (ObjectGroup::findAllocationSiteForType(cx, ty, &script, &offset)) {
|
||||
if (!ty.isUnknown() && !ty.isAnyObject() && ty.isGroup() &&
|
||||
ObjectGroup::findAllocationSite(cx, ty.group(), &script, &offset))
|
||||
{
|
||||
if (!allTypes->append(IonTrackedTypeWithAddendum(ty, script, offset)))
|
||||
return false;
|
||||
SpewAllocationSite(ty, script, offset);
|
||||
@ -1032,7 +1034,7 @@ IonBuilder::startTrackingOptimizations()
|
||||
|
||||
void
|
||||
IonBuilder::trackTypeInfoUnchecked(TrackedTypeSite kind, MIRType mirType,
|
||||
types::TemporaryTypeSet *typeSet)
|
||||
TemporaryTypeSet *typeSet)
|
||||
{
|
||||
BytecodeSite *site = current->trackedSite();
|
||||
// OOMs are handled as if optimization tracking were turned off.
|
||||
@ -1051,7 +1053,7 @@ IonBuilder::trackTypeInfoUnchecked(TrackedTypeSite kind, JSObject *obj)
|
||||
BytecodeSite *site = current->trackedSite();
|
||||
// OOMs are handled as if optimization tracking were turned off.
|
||||
OptimizationTypeInfo typeInfo(kind, MIRType_Object);
|
||||
if (!typeInfo.trackType(types::Type::ObjectType(obj)))
|
||||
if (!typeInfo.trackType(TypeSet::ObjectType(obj)))
|
||||
return;
|
||||
if (!site->optimizations()->trackTypeInfo(mozilla::Move(typeInfo)))
|
||||
site->setOptimizations(nullptr);
|
||||
@ -1068,7 +1070,7 @@ IonBuilder::trackTypeInfoUnchecked(CallInfo &callInfo)
|
||||
trackTypeInfoUnchecked(TrackedTypeSite::Call_Arg, arg->type(), arg->resultTypeSet());
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
trackTypeInfoUnchecked(TrackedTypeSite::Call_Return, returnTypes->getKnownMIRType(),
|
||||
returnTypes);
|
||||
}
|
||||
@ -1140,7 +1142,7 @@ InterpretedFunctionFromTrackedType(const IonTrackedTypeWithAddendum &tracked)
|
||||
if (tracked.hasConstructor())
|
||||
return tracked.constructor;
|
||||
|
||||
types::Type ty = tracked.type;
|
||||
TypeSet::Type ty = tracked.type;
|
||||
|
||||
if (ty.isSingleton()) {
|
||||
JSObject *obj = ty.singleton();
|
||||
@ -1162,10 +1164,10 @@ class ForEachTypeInfoAdapter : public IonTrackedOptimizationsTypeInfo::ForEachOp
|
||||
{ }
|
||||
|
||||
void readType(const IonTrackedTypeWithAddendum &tracked) MOZ_OVERRIDE {
|
||||
types::Type ty = tracked.type;
|
||||
TypeSet::Type ty = tracked.type;
|
||||
|
||||
if (ty.isPrimitive() || ty.isUnknown() || ty.isAnyObject()) {
|
||||
op_.readType("primitive", types::NonObjectTypeString(ty), nullptr, 0);
|
||||
op_.readType("primitive", TypeSet::NonObjectTypeString(ty), nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class OptimizationTypeInfo
|
||||
{
|
||||
JS::TrackedTypeSite site_;
|
||||
MIRType mirType_;
|
||||
types::TypeSet::TypeList types_;
|
||||
TypeSet::TypeList types_;
|
||||
|
||||
public:
|
||||
OptimizationTypeInfo(OptimizationTypeInfo &&other)
|
||||
@ -73,12 +73,12 @@ class OptimizationTypeInfo
|
||||
mirType_(mirType)
|
||||
{ }
|
||||
|
||||
bool trackTypeSet(types::TemporaryTypeSet *typeSet);
|
||||
bool trackType(types::Type type);
|
||||
bool trackTypeSet(TemporaryTypeSet *typeSet);
|
||||
bool trackType(TypeSet::Type type);
|
||||
|
||||
JS::TrackedTypeSite site() const { return site_; }
|
||||
MIRType mirType() const { return mirType_; }
|
||||
const types::TypeSet::TypeList &types() const { return types_; }
|
||||
const TypeSet::TypeList &types() const { return types_; }
|
||||
|
||||
bool operator ==(const OptimizationTypeInfo &other) const;
|
||||
bool operator !=(const OptimizationTypeInfo &other) const;
|
||||
@ -421,7 +421,7 @@ class IonTrackedOptimizationsAttempts
|
||||
|
||||
struct IonTrackedTypeWithAddendum
|
||||
{
|
||||
types::Type type;
|
||||
TypeSet::Type type;
|
||||
|
||||
enum HasAddendum {
|
||||
HasNothing,
|
||||
@ -441,19 +441,19 @@ struct IonTrackedTypeWithAddendum
|
||||
JSFunction *constructor;
|
||||
};
|
||||
|
||||
explicit IonTrackedTypeWithAddendum(types::Type type)
|
||||
explicit IonTrackedTypeWithAddendum(TypeSet::Type type)
|
||||
: type(type),
|
||||
hasAddendum(HasNothing)
|
||||
{ }
|
||||
|
||||
IonTrackedTypeWithAddendum(types::Type type, JSScript *script, uint32_t offset)
|
||||
IonTrackedTypeWithAddendum(TypeSet::Type type, JSScript *script, uint32_t offset)
|
||||
: type(type),
|
||||
hasAddendum(HasAllocationSite),
|
||||
script(script),
|
||||
offset(offset)
|
||||
{ }
|
||||
|
||||
IonTrackedTypeWithAddendum(types::Type type, JSFunction *constructor)
|
||||
IonTrackedTypeWithAddendum(TypeSet::Type type, JSFunction *constructor)
|
||||
: type(type),
|
||||
hasAddendum(HasConstructor),
|
||||
constructor(constructor)
|
||||
@ -482,7 +482,7 @@ class IonTrackedOptimizationsTypeInfo
|
||||
// Unlike IonTrackedOptimizationAttempts,
|
||||
// JS::ForEachTrackedOptimizaitonTypeInfoOp cannot be used directly. The
|
||||
// internal API needs to deal with engine-internal data structures (e.g.,
|
||||
// types::Type) directly.
|
||||
// TypeSet::Type) directly.
|
||||
struct ForEachOp
|
||||
{
|
||||
virtual void readType(const IonTrackedTypeWithAddendum &tracked) = 0;
|
||||
|
@ -99,7 +99,7 @@ InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Val
|
||||
if (obj->is<JSFunction>()) {
|
||||
jsbytecode *pc;
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
types::TypeScript::Monitor(cx, script, pc, rv.get());
|
||||
TypeScript::Monitor(cx, script, pc, rv.get());
|
||||
}
|
||||
|
||||
*rval = rv;
|
||||
@ -330,7 +330,7 @@ ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
|
||||
// have to monitor the return value.
|
||||
rval.set(argv[0]);
|
||||
if (rval.isUndefined())
|
||||
types::TypeScript::Monitor(cx, rval);
|
||||
TypeScript::Monitor(cx, rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -380,7 +380,7 @@ ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
|
||||
// have to monitor the return value.
|
||||
rval.set(argv[0]);
|
||||
if (rval.isUndefined())
|
||||
types::TypeScript::Monitor(cx, rval);
|
||||
TypeScript::Monitor(cx, rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -583,7 +583,7 @@ GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rva
|
||||
// purposes, as its side effect is not observable from JS. We are
|
||||
// guaranteed to bail out after this function, but because of its AliasSet,
|
||||
// type info will not be reflowed. Manually monitor here.
|
||||
types::TypeScript::Monitor(cx, rval);
|
||||
TypeScript::Monitor(cx, rval);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -874,7 +874,7 @@ class ReadTempAttemptsVectorOp : public JS::ForEachTrackedOptimizationAttemptOp
|
||||
struct ReadTempTypeInfoVectorOp : public IonTrackedOptimizationsTypeInfo::ForEachOp
|
||||
{
|
||||
TempOptimizationTypeInfoVector *types_;
|
||||
types::TypeSet::TypeList accTypes_;
|
||||
TypeSet::TypeList accTypes_;
|
||||
|
||||
public:
|
||||
explicit ReadTempTypeInfoVectorOp(TempOptimizationTypeInfoVector *types)
|
||||
|
@ -97,7 +97,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::PodCopy;
|
||||
|
@ -44,7 +44,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::Abs;
|
||||
using mozilla::ArrayLength;
|
||||
@ -1225,8 +1224,7 @@ InitArrayTypes(JSContext *cx, ObjectGroup *group, const Value *vector, unsigned
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (vector[i].isMagic(JS_ELEMENTS_HOLE))
|
||||
continue;
|
||||
Type valtype = GetValueType(vector[i]);
|
||||
types->addType(cx, valtype);
|
||||
types->addType(cx, TypeSet::GetValueType(vector[i]));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "vm/BooleanObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
const Class BooleanObject::class_ = {
|
||||
"Boolean",
|
||||
|
@ -253,7 +253,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode)
|
||||
* This printing depends on atoms still existing.
|
||||
*/
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||
types::PrintTypes(cx, c, false);
|
||||
PrintTypes(cx, c, false);
|
||||
}
|
||||
if (mode == DCM_FORCE_GC) {
|
||||
MOZ_ASSERT(!rt->isHeapBusy());
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::IsFinite;
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::PodArrayZero;
|
||||
|
@ -49,7 +49,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
using namespace js::frontend;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
|
@ -2218,7 +2218,7 @@ GCRuntime::sweepTypesAfterCompacting(Zone *zone)
|
||||
FreeOp *fop = rt->defaultFreeOp();
|
||||
zone->beginSweepTypes(fop, rt->gc.releaseObservedTypes && !zone->isPreservingCode());
|
||||
|
||||
types::AutoClearTypeInferenceStateOnOOM oom(zone);
|
||||
AutoClearTypeInferenceStateOnOOM oom(zone);
|
||||
|
||||
for (ZoneCellIterUnderGC i(zone, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
@ -5191,13 +5191,13 @@ SweepThing(Shape *shape)
|
||||
}
|
||||
|
||||
static void
|
||||
SweepThing(JSScript *script, types::AutoClearTypeInferenceStateOnOOM *oom)
|
||||
SweepThing(JSScript *script, AutoClearTypeInferenceStateOnOOM *oom)
|
||||
{
|
||||
script->maybeSweepTypes(oom);
|
||||
}
|
||||
|
||||
static void
|
||||
SweepThing(ObjectGroup *group, types::AutoClearTypeInferenceStateOnOOM *oom)
|
||||
SweepThing(ObjectGroup *group, AutoClearTypeInferenceStateOnOOM *oom)
|
||||
{
|
||||
group->maybeSweep(oom);
|
||||
}
|
||||
@ -5245,7 +5245,7 @@ GCRuntime::sweepPhase(SliceBudget &sliceBudget)
|
||||
for (; sweepZone; sweepZone = sweepZone->nextNodeInGroup()) {
|
||||
ArenaLists &al = sweepZone->arenas;
|
||||
|
||||
types::AutoClearTypeInferenceStateOnOOM oom(sweepZone);
|
||||
AutoClearTypeInferenceStateOnOOM oom(sweepZone);
|
||||
|
||||
if (!SweepArenaList<JSScript>(&al.gcScriptArenasToUpdate, sliceBudget, &oom))
|
||||
return NotFinished;
|
||||
|
@ -41,7 +41,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::Maybe;
|
||||
@ -76,7 +75,7 @@ id_caller(JSContext *cx)
|
||||
}
|
||||
|
||||
const char *
|
||||
types::TypeIdStringImpl(jsid id)
|
||||
js::TypeIdStringImpl(jsid id)
|
||||
{
|
||||
if (JSID_IS_VOID(id))
|
||||
return "(index)";
|
||||
@ -97,8 +96,8 @@ types::TypeIdStringImpl(jsid id)
|
||||
// Logging
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *
|
||||
types::NonObjectTypeString(Type type)
|
||||
/* static */ const char *
|
||||
TypeSet::NonObjectTypeString(TypeSet::Type type)
|
||||
{
|
||||
if (type.isPrimitive()) {
|
||||
switch (type.primitive()) {
|
||||
@ -170,7 +169,7 @@ static bool InferSpewColorable()
|
||||
}
|
||||
|
||||
const char *
|
||||
types::InferSpewColorReset()
|
||||
js::InferSpewColorReset()
|
||||
{
|
||||
if (!InferSpewColorable())
|
||||
return "";
|
||||
@ -178,7 +177,7 @@ types::InferSpewColorReset()
|
||||
}
|
||||
|
||||
const char *
|
||||
types::InferSpewColor(TypeConstraint *constraint)
|
||||
js::InferSpewColor(TypeConstraint *constraint)
|
||||
{
|
||||
/* Type constraints are printed out using foreground colors. */
|
||||
static const char * const colors[] = { "\x1b[31m", "\x1b[32m", "\x1b[33m",
|
||||
@ -190,7 +189,7 @@ types::InferSpewColor(TypeConstraint *constraint)
|
||||
}
|
||||
|
||||
const char *
|
||||
types::InferSpewColor(TypeSet *types)
|
||||
js::InferSpewColor(TypeSet *types)
|
||||
{
|
||||
/* Type sets are printed out using bold colors. */
|
||||
static const char * const colors[] = { "\x1b[1;31m", "\x1b[1;32m", "\x1b[1;33m",
|
||||
@ -201,8 +200,8 @@ types::InferSpewColor(TypeSet *types)
|
||||
return colors[DefaultHasher<TypeSet *>::hash(types) % 7];
|
||||
}
|
||||
|
||||
const char *
|
||||
types::TypeString(Type type)
|
||||
/* static */ const char *
|
||||
TypeSet::TypeString(TypeSet::Type type)
|
||||
{
|
||||
if (type.isPrimitive() || type.isUnknown() || type.isAnyObject())
|
||||
return NonObjectTypeString(type);
|
||||
@ -219,14 +218,14 @@ types::TypeString(Type type)
|
||||
return bufs[which];
|
||||
}
|
||||
|
||||
const char *
|
||||
types::ObjectGroupString(ObjectGroup *group)
|
||||
/* static */ const char *
|
||||
TypeSet::ObjectGroupString(ObjectGroup *group)
|
||||
{
|
||||
return TypeString(Type::ObjectType(group));
|
||||
return TypeString(TypeSet::ObjectType(group));
|
||||
}
|
||||
|
||||
void
|
||||
types::InferSpew(SpewChannel channel, const char *fmt, ...)
|
||||
js::InferSpew(SpewChannel channel, const char *fmt, ...)
|
||||
{
|
||||
if (!InferSpewActive(channel))
|
||||
return;
|
||||
@ -240,7 +239,7 @@ types::InferSpew(SpewChannel channel, const char *fmt, ...)
|
||||
}
|
||||
|
||||
bool
|
||||
types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
js::ObjectGroupHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
{
|
||||
/*
|
||||
* Check the correctness of the type information in the object's property
|
||||
@ -253,7 +252,7 @@ types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &
|
||||
if (id == id___proto__(cx) || id == id_constructor(cx) || id == id_caller(cx))
|
||||
return true;
|
||||
|
||||
Type type = GetValueType(value);
|
||||
TypeSet::Type type = TypeSet::GetValueType(value);
|
||||
|
||||
// Type set guards might miss when an object's group changes and its
|
||||
// properties become unknown.
|
||||
@ -277,7 +276,8 @@ types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &
|
||||
|
||||
if (!types->hasType(type)) {
|
||||
TypeFailure(cx, "Missing type in object %s %s: %s",
|
||||
ObjectGroupString(group), TypeIdString(id), TypeString(type));
|
||||
TypeSet::ObjectGroupString(group), TypeIdString(id),
|
||||
TypeSet::TypeString(type));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -286,7 +286,7 @@ types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &
|
||||
#endif
|
||||
|
||||
void
|
||||
types::TypeFailure(JSContext *cx, const char *fmt, ...)
|
||||
js::TypeFailure(JSContext *cx, const char *fmt, ...)
|
||||
{
|
||||
char msgbuf[1024]; /* Larger error messages will be truncated */
|
||||
char errbuf[1024];
|
||||
@ -323,12 +323,12 @@ TemporaryTypeSet::TemporaryTypeSet(LifoAlloc *alloc, Type type)
|
||||
flags |= TYPE_FLAG_ANYOBJECT;
|
||||
} else {
|
||||
setBaseObjectCount(1);
|
||||
objectSet = reinterpret_cast<TypeSetObjectKey**>(type.objectKey());
|
||||
objectSet = reinterpret_cast<ObjectKey**>(type.objectKey());
|
||||
|
||||
if (type.isGroup()) {
|
||||
ObjectGroup *ngroup = type.group();
|
||||
if (ngroup->newScript() && ngroup->newScript()->initializedGroup())
|
||||
addType(Type::ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
addType(ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -387,10 +387,10 @@ TypeSet::objectsAreSubset(TypeSet *other)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(key)))
|
||||
if (!other->hasType(ObjectType(key)))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -407,10 +407,10 @@ TypeSet::isSubset(const TypeSet *other) const
|
||||
MOZ_ASSERT(other->unknownObject());
|
||||
} else {
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(key)))
|
||||
if (!other->hasType(ObjectType(key)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -423,12 +423,12 @@ TypeSet::enumerateTypes(TypeList *list) const
|
||||
{
|
||||
/* If any type is possible, there's no need to worry about specifics. */
|
||||
if (flags & TYPE_FLAG_UNKNOWN)
|
||||
return list->append(Type::UnknownType());
|
||||
return list->append(UnknownType());
|
||||
|
||||
/* Enqueue type set members stored as bits. */
|
||||
for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
|
||||
if (flags & flag) {
|
||||
Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
|
||||
Type type = PrimitiveType(TypeFlagPrimitive(flag));
|
||||
if (!list->append(type))
|
||||
return false;
|
||||
}
|
||||
@ -436,14 +436,14 @@ TypeSet::enumerateTypes(TypeList *list) const
|
||||
|
||||
/* If any object is possible, skip specifics. */
|
||||
if (flags & TYPE_FLAG_ANYOBJECT)
|
||||
return list->append(Type::AnyObjectType());
|
||||
return list->append(AnyObjectType());
|
||||
|
||||
/* Enqueue specific object types. */
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key) {
|
||||
if (!list->append(Type::ObjectType(key)))
|
||||
if (!list->append(ObjectType(key)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -532,9 +532,9 @@ TypeSet::addType(Type type, LifoAlloc *alloc)
|
||||
|
||||
{
|
||||
uint32_t objectCount = baseObjectCount();
|
||||
TypeSetObjectKey *key = type.objectKey();
|
||||
TypeSetObjectKey **pentry = HashSetInsert<TypeSetObjectKey *,TypeSetObjectKey,TypeSetObjectKey>
|
||||
(*alloc, objectSet, objectCount, key);
|
||||
ObjectKey *key = type.objectKey();
|
||||
ObjectKey **pentry = TypeHashSet::Insert<ObjectKey *, ObjectKey, ObjectKey>
|
||||
(*alloc, objectSet, objectCount, key);
|
||||
if (!pentry)
|
||||
goto unknownObject;
|
||||
if (*pentry)
|
||||
@ -579,7 +579,7 @@ TypeSet::addType(Type type, LifoAlloc *alloc)
|
||||
// corresponding fully initialized group, as an object's group may change
|
||||
// from the former to the latter via the acquired properties analysis.
|
||||
if (ngroup->newScript() && ngroup->newScript()->initializedGroup())
|
||||
addType(Type::ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
addType(ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
}
|
||||
|
||||
if (false) {
|
||||
@ -600,7 +600,7 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type)
|
||||
TypeSet::addType(type, &cxArg->typeLifoAlloc());
|
||||
|
||||
if (type.isObjectUnchecked() && unknownObject())
|
||||
type = Type::AnyObjectType();
|
||||
type = AnyObjectType();
|
||||
|
||||
InferSpew(ISpewOps, "addType: %sT%p%s %s",
|
||||
InferSpewColor(this), this, InferSpewColorReset(),
|
||||
@ -663,9 +663,9 @@ TypeSet::print()
|
||||
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key)
|
||||
fprintf(stderr, " %s", TypeString(Type::ObjectType(key)));
|
||||
fprintf(stderr, " %s", TypeString(ObjectType(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -677,7 +677,7 @@ TypeSet::readBarrier(const TypeSet *types)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < types->getObjectCount(); i++) {
|
||||
if (TypeSetObjectKey *key = types->getObject(i)) {
|
||||
if (ObjectKey *key = types->getObject(i)) {
|
||||
if (key->isSingleton())
|
||||
(void) key->singleton();
|
||||
else
|
||||
@ -692,11 +692,11 @@ TypeSet::clone(LifoAlloc *alloc, TemporaryTypeSet *result) const
|
||||
MOZ_ASSERT(result->empty());
|
||||
|
||||
unsigned objectCount = baseObjectCount();
|
||||
unsigned capacity = (objectCount >= 2) ? HashSetCapacity(objectCount) : 0;
|
||||
unsigned capacity = (objectCount >= 2) ? TypeHashSet::Capacity(objectCount) : 0;
|
||||
|
||||
TypeSetObjectKey **newSet;
|
||||
ObjectKey **newSet;
|
||||
if (capacity) {
|
||||
newSet = alloc->newArray<TypeSetObjectKey*>(capacity);
|
||||
newSet = alloc->newArray<ObjectKey*>(capacity);
|
||||
if (!newSet)
|
||||
return false;
|
||||
PodCopy(newSet, objectSet, capacity);
|
||||
@ -759,18 +759,18 @@ TypeSet::cloneWithoutObjects(LifoAlloc *alloc)
|
||||
TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
|
||||
{
|
||||
TemporaryTypeSet *res = alloc->new_<TemporaryTypeSet>(a->baseFlags() | b->baseFlags(),
|
||||
static_cast<TypeSetObjectKey**>(nullptr));
|
||||
static_cast<ObjectKey**>(nullptr));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
if (!res->unknownObject()) {
|
||||
for (size_t i = 0; i < a->getObjectCount() && !res->unknownObject(); i++) {
|
||||
if (TypeSetObjectKey *key = a->getObject(i))
|
||||
res->addType(Type::ObjectType(key), alloc);
|
||||
if (ObjectKey *key = a->getObject(i))
|
||||
res->addType(ObjectType(key), alloc);
|
||||
}
|
||||
for (size_t i = 0; i < b->getObjectCount() && !res->unknownObject(); i++) {
|
||||
if (TypeSetObjectKey *key = b->getObject(i))
|
||||
res->addType(Type::ObjectType(key), alloc);
|
||||
if (ObjectKey *key = b->getObject(i))
|
||||
res->addType(ObjectType(key), alloc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -782,7 +782,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
||||
{
|
||||
TemporaryTypeSet *res;
|
||||
res = alloc->new_<TemporaryTypeSet>(a->baseFlags() & b->baseFlags(),
|
||||
static_cast<TypeSetObjectKey**>(nullptr));
|
||||
static_cast<ObjectKey**>(nullptr));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
@ -795,7 +795,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
||||
if (a->unknownObject()) {
|
||||
for (size_t i = 0; i < b->getObjectCount(); i++) {
|
||||
if (b->getObject(i))
|
||||
res->addType(Type::ObjectType(b->getObject(i)), alloc);
|
||||
res->addType(ObjectType(b->getObject(i)), alloc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -803,7 +803,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
||||
if (b->unknownObject()) {
|
||||
for (size_t i = 0; i < a->getObjectCount(); i++) {
|
||||
if (b->getObject(i))
|
||||
res->addType(Type::ObjectType(a->getObject(i)), alloc);
|
||||
res->addType(ObjectType(a->getObject(i)), alloc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -816,7 +816,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
||||
continue;
|
||||
if (!b->getObject(j))
|
||||
continue;
|
||||
res->addType(Type::ObjectType(b->getObject(j)), alloc);
|
||||
res->addType(ObjectType(b->getObject(j)), alloc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -869,7 +869,7 @@ class CompilerConstraint
|
||||
virtual bool generateTypeConstraint(JSContext *cx, RecompileInfo recompileInfo) = 0;
|
||||
};
|
||||
|
||||
class types::CompilerConstraintList
|
||||
class js::CompilerConstraintList
|
||||
{
|
||||
public:
|
||||
struct FrozenScript
|
||||
@ -949,7 +949,7 @@ class types::CompilerConstraintList
|
||||
};
|
||||
|
||||
CompilerConstraintList *
|
||||
types::NewCompilerConstraintList(jit::TempAllocator &alloc)
|
||||
js::NewCompilerConstraintList(jit::TempAllocator &alloc)
|
||||
{
|
||||
return alloc.lifoAlloc()->new_<CompilerConstraintList>(alloc);
|
||||
}
|
||||
@ -1015,7 +1015,7 @@ class TypeCompilerConstraint : public TypeConstraint
|
||||
|
||||
const char *kind() { return data.kind(); }
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {
|
||||
if (data.invalidateOnNewType(type))
|
||||
cx->zone()->types.addPendingRecompile(cx, compilation);
|
||||
}
|
||||
@ -1061,19 +1061,19 @@ CompilerConstraintInstance<T>::generateTypeConstraint(JSContext *cx, RecompileIn
|
||||
} /* anonymous namespace */
|
||||
|
||||
const Class *
|
||||
TypeSetObjectKey::clasp()
|
||||
TypeSet::ObjectKey::clasp()
|
||||
{
|
||||
return isGroup() ? group()->clasp() : singleton()->getClass();
|
||||
}
|
||||
|
||||
TaggedProto
|
||||
TypeSetObjectKey::proto()
|
||||
TypeSet::ObjectKey::proto()
|
||||
{
|
||||
return isGroup() ? group()->proto() : singleton()->getTaggedProto();
|
||||
}
|
||||
|
||||
TypeNewScript *
|
||||
TypeSetObjectKey::newScript()
|
||||
TypeSet::ObjectKey::newScript()
|
||||
{
|
||||
if (isGroup() && group()->newScript())
|
||||
return group()->newScript();
|
||||
@ -1081,7 +1081,7 @@ TypeSetObjectKey::newScript()
|
||||
}
|
||||
|
||||
ObjectGroup *
|
||||
TypeSetObjectKey::maybeGroup()
|
||||
TypeSet::ObjectKey::maybeGroup()
|
||||
{
|
||||
if (isGroup())
|
||||
return group();
|
||||
@ -1091,7 +1091,7 @@ TypeSetObjectKey::maybeGroup()
|
||||
}
|
||||
|
||||
bool
|
||||
TypeSetObjectKey::unknownProperties()
|
||||
TypeSet::ObjectKey::unknownProperties()
|
||||
{
|
||||
if (ObjectGroup *group = maybeGroup())
|
||||
return group->unknownProperties();
|
||||
@ -1099,7 +1099,7 @@ TypeSetObjectKey::unknownProperties()
|
||||
}
|
||||
|
||||
HeapTypeSetKey
|
||||
TypeSetObjectKey::property(jsid id)
|
||||
TypeSet::ObjectKey::property(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
@ -1113,7 +1113,7 @@ TypeSetObjectKey::property(jsid id)
|
||||
}
|
||||
|
||||
void
|
||||
TypeSetObjectKey::ensureTrackedProperty(JSContext *cx, jsid id)
|
||||
TypeSet::ObjectKey::ensureTrackedProperty(JSContext *cx, jsid id)
|
||||
{
|
||||
// If we are accessing a lazily defined property which actually exists in
|
||||
// the VM and has not been instantiated yet, instantiate it now if we are
|
||||
@ -1182,7 +1182,7 @@ class TypeConstraintFreezeStack : public TypeConstraint
|
||||
|
||||
const char *kind() { return "freezeStack"; }
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {
|
||||
/*
|
||||
* Unlike TypeConstraintFreeze, triggering this constraint once does
|
||||
* not disable it on future changes to the type set.
|
||||
@ -1201,7 +1201,7 @@ class TypeConstraintFreezeStack : public TypeConstraint
|
||||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
types::FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintList *constraints,
|
||||
js::FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintList *constraints,
|
||||
RecompileInfo *precompileInfo)
|
||||
{
|
||||
if (constraints->failed())
|
||||
@ -1254,13 +1254,13 @@ types::FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintL
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CheckFrozenTypeSet(cx, entry.thisTypes, types::TypeScript::ThisTypes(entry.script)))
|
||||
if (!CheckFrozenTypeSet(cx, entry.thisTypes, TypeScript::ThisTypes(entry.script)))
|
||||
succeeded = false;
|
||||
unsigned nargs = entry.script->functionNonDelazifying()
|
||||
? entry.script->functionNonDelazifying()->nargs()
|
||||
: 0;
|
||||
for (size_t i = 0; i < nargs; i++) {
|
||||
if (!CheckFrozenTypeSet(cx, &entry.argTypes[i], types::TypeScript::ArgTypes(entry.script, i)))
|
||||
if (!CheckFrozenTypeSet(cx, &entry.argTypes[i], TypeScript::ArgTypes(entry.script, i)))
|
||||
succeeded = false;
|
||||
}
|
||||
for (size_t i = 0; i < entry.script->nTypeSets(); i++) {
|
||||
@ -1310,7 +1310,7 @@ CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTyp
|
||||
}
|
||||
|
||||
void
|
||||
types::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
|
||||
js::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Assert no new types have been added to the StackTypeSets. Do this before
|
||||
@ -1364,7 +1364,7 @@ class ConstraintDataFreeze
|
||||
|
||||
const char *kind() { return "freeze"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return true; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return true; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return true; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) { return false; }
|
||||
|
||||
@ -1559,7 +1559,7 @@ class ConstraintDataFreezeObjectFlags
|
||||
|
||||
const char *kind() { return "freezeObjectFlags"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) {
|
||||
return group->hasAnyFlags(flags);
|
||||
@ -1577,7 +1577,7 @@ class ConstraintDataFreezeObjectFlags
|
||||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
TypeSetObjectKey::hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags)
|
||||
TypeSet::ObjectKey::hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags)
|
||||
{
|
||||
MOZ_ASSERT(flags);
|
||||
|
||||
@ -1595,7 +1595,7 @@ TypeSetObjectKey::hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags
|
||||
}
|
||||
|
||||
bool
|
||||
TypeSetObjectKey::hasStableClassAndProto(CompilerConstraintList *constraints)
|
||||
TypeSet::ObjectKey::hasStableClassAndProto(CompilerConstraintList *constraints)
|
||||
{
|
||||
return !hasFlags(constraints, OBJECT_FLAG_UNKNOWN_PROPERTIES);
|
||||
}
|
||||
@ -1615,7 +1615,7 @@ TemporaryTypeSet::hasObjectFlags(CompilerConstraintList *constraints, ObjectGrou
|
||||
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key && key->hasFlags(constraints, flags))
|
||||
return true;
|
||||
}
|
||||
@ -1636,7 +1636,7 @@ ObjectGroup::initialHeap(CompilerConstraintList *constraints)
|
||||
if (!canPreTenure())
|
||||
return gc::DefaultHeap;
|
||||
|
||||
HeapTypeSetKey objectProperty = TypeSetObjectKey::get(this)->property(JSID_EMPTY);
|
||||
HeapTypeSetKey objectProperty = TypeSet::ObjectKey::get(this)->property(JSID_EMPTY);
|
||||
LifoAlloc *alloc = constraints->alloc();
|
||||
|
||||
typedef CompilerConstraintInstance<ConstraintDataFreezeObjectFlags> T;
|
||||
@ -1659,7 +1659,7 @@ class ConstraintDataFreezeObjectForInlinedCall
|
||||
|
||||
const char *kind() { return "freezeObjectForInlinedCall"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) {
|
||||
// We don't keep track of the exact dependencies the caller has on its
|
||||
@ -1691,7 +1691,7 @@ class ConstraintDataFreezeObjectForTypedArrayData
|
||||
|
||||
const char *kind() { return "freezeObjectForTypedArrayData"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) {
|
||||
TypedArrayObject &tarray = group->singleton()->as<TypedArrayObject>();
|
||||
@ -1713,7 +1713,7 @@ class ConstraintDataFreezeObjectForTypedArrayData
|
||||
} /* anonymous namespace */
|
||||
|
||||
void
|
||||
TypeSetObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constraints)
|
||||
TypeSet::ObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constraints)
|
||||
{
|
||||
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
|
||||
LifoAlloc *alloc = constraints->alloc();
|
||||
@ -1723,7 +1723,7 @@ TypeSetObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constra
|
||||
}
|
||||
|
||||
void
|
||||
TypeSetObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList *constraints)
|
||||
TypeSet::ObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList *constraints)
|
||||
{
|
||||
TypedArrayObject &tarray = singleton()->as<TypedArrayObject>();
|
||||
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
|
||||
@ -1776,7 +1776,7 @@ class ConstraintDataFreezePropertyState
|
||||
|
||||
const char *kind() { return (which == NON_DATA) ? "freezeNonDataProperty" : "freezeNonWritableProperty"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) {
|
||||
return (which == NON_DATA)
|
||||
? property->nonDataProperty()
|
||||
@ -1832,7 +1832,7 @@ class ConstraintDataConstantProperty
|
||||
|
||||
const char *kind() { return "constantProperty"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) {
|
||||
return property->nonConstantProperty();
|
||||
}
|
||||
@ -1894,7 +1894,7 @@ class ConstraintDataInert
|
||||
|
||||
const char *kind() { return "inert"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) { return false; }
|
||||
|
||||
@ -1937,7 +1937,7 @@ TemporaryTypeSet::filtersType(const TemporaryTypeSet *other, Type filteredType)
|
||||
return unknown();
|
||||
|
||||
for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
|
||||
Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
|
||||
Type type = PrimitiveType(TypeFlagPrimitive(flag));
|
||||
if (type != filteredType && other->hasType(type) && !hasType(type))
|
||||
return false;
|
||||
}
|
||||
@ -1946,9 +1946,9 @@ TemporaryTypeSet::filtersType(const TemporaryTypeSet *other, Type filteredType)
|
||||
return unknownObject();
|
||||
|
||||
for (size_t i = 0; i < other->getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = other->getObject(i);
|
||||
ObjectKey *key = other->getObject(i);
|
||||
if (key) {
|
||||
Type type = Type::ObjectType(key);
|
||||
Type type = ObjectType(key);
|
||||
if (type != filteredType && !hasType(type))
|
||||
return false;
|
||||
}
|
||||
@ -1968,7 +1968,7 @@ TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
|
||||
bool dontConvert = false;
|
||||
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
@ -1985,7 +1985,7 @@ TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
|
||||
// information incorrect), nor for non-array objects (as their elements
|
||||
// may point to emptyObjectElements, which cannot be converted).
|
||||
if (!property.maybeTypes() ||
|
||||
!property.maybeTypes()->hasType(Type::DoubleType()) ||
|
||||
!property.maybeTypes()->hasType(DoubleType()) ||
|
||||
key->clasp() != &ArrayObject::class_)
|
||||
{
|
||||
dontConvert = true;
|
||||
@ -2040,7 +2040,7 @@ TemporaryTypeSet::getKnownClass(CompilerConstraintList *constraints)
|
||||
|
||||
if (clasp) {
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key && !key->hasStableClassAndProto(constraints))
|
||||
return nullptr;
|
||||
}
|
||||
@ -2182,7 +2182,7 @@ TemporaryTypeSet::getCommonPrototype(CompilerConstraintList *constraints)
|
||||
unsigned count = getObjectCount();
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
@ -2202,7 +2202,7 @@ TemporaryTypeSet::getCommonPrototype(CompilerConstraintList *constraints)
|
||||
|
||||
// Guard against mutating __proto__.
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key)
|
||||
JS_ALWAYS_TRUE(key->hasStableClassAndProto(constraints));
|
||||
}
|
||||
@ -2217,7 +2217,7 @@ TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList *constraints, jsid
|
||||
return true;
|
||||
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
@ -2241,11 +2241,11 @@ ClassCanHaveExtraProperties(const Class *clasp)
|
||||
|| IsAnyTypedArrayClass(clasp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
PrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSObject *obj)
|
||||
{
|
||||
do {
|
||||
TypeSetObjectKey *key = TypeSetObjectKey::get(obj);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(obj);
|
||||
if (ClassCanHaveExtraProperties(key->clasp()))
|
||||
return true;
|
||||
if (key->unknownProperties())
|
||||
@ -2260,7 +2260,7 @@ PrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSObject *obj)
|
||||
}
|
||||
|
||||
bool
|
||||
types::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSScript *script)
|
||||
js::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSScript *script)
|
||||
{
|
||||
if (JSObject *proto = script->global().maybeGetArrayPrototype())
|
||||
return PrototypeHasIndexedProperty(constraints, proto);
|
||||
@ -2268,8 +2268,8 @@ types::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSS
|
||||
}
|
||||
|
||||
bool
|
||||
types::TypeCanHaveExtraIndexedProperties(CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *types)
|
||||
js::TypeCanHaveExtraIndexedProperties(CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *types)
|
||||
{
|
||||
const Class *clasp = types->getKnownClass(constraints);
|
||||
|
||||
@ -2348,7 +2348,7 @@ TypeZone::addPendingRecompile(JSContext *cx, JSScript *script)
|
||||
}
|
||||
|
||||
void
|
||||
types::PrintTypes(JSContext *cx, JSCompartment *comp, bool force)
|
||||
js::PrintTypes(JSContext *cx, JSCompartment *comp, bool force)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
gc::AutoSuppressGC suppressGC(cx);
|
||||
@ -2388,7 +2388,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
|
||||
|
||||
if (shape->hasGetterValue() || shape->hasSetterValue()) {
|
||||
types->setNonDataProperty(cx);
|
||||
types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc());
|
||||
types->TypeSet::addType(TypeSet::UnknownType(), &cx->typeLifoAlloc());
|
||||
} else if (shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
if (!indexed && types->canSetDefinite(shape->slot()))
|
||||
types->setDefinite(shape->slot());
|
||||
@ -2403,11 +2403,11 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
|
||||
* Also don't add untracked values (initial uninitialized lexical
|
||||
* magic values and optimized out values) as appearing in CallObjects.
|
||||
*/
|
||||
MOZ_ASSERT_IF(IsUntrackedValue(value), obj->is<CallObject>());
|
||||
MOZ_ASSERT_IF(TypeSet::IsUntrackedValue(value), obj->is<CallObject>());
|
||||
if ((indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) &&
|
||||
!IsUntrackedValue(value))
|
||||
!TypeSet::IsUntrackedValue(value))
|
||||
{
|
||||
Type type = GetValueType(value);
|
||||
TypeSet::Type type = TypeSet::GetValueType(value);
|
||||
types->TypeSet::addType(type, &cx->typeLifoAlloc());
|
||||
}
|
||||
|
||||
@ -2416,7 +2416,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
|
||||
} else {
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s - setConstant",
|
||||
InferSpewColor(types), types, InferSpewColorReset(),
|
||||
ObjectGroupString(obj->group()), TypeIdString(shape->propid()));
|
||||
TypeSet::ObjectGroupString(obj->group()), TypeIdString(shape->propid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2426,7 +2426,7 @@ ObjectGroup::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *
|
||||
{
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
|
||||
InferSpewColor(types), types, InferSpewColorReset(),
|
||||
ObjectGroupString(this), TypeIdString(id));
|
||||
TypeSet::ObjectGroupString(this), TypeIdString(id));
|
||||
|
||||
if (!singleton() || !singleton()->isNative()) {
|
||||
types->setNonConstantProperty(cx);
|
||||
@ -2455,7 +2455,7 @@ ObjectGroup::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *
|
||||
for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
|
||||
const Value &value = obj->getDenseElement(i);
|
||||
if (!value.isMagic(JS_ELEMENTS_HOLE)) {
|
||||
Type type = GetValueType(value);
|
||||
TypeSet::Type type = TypeSet::GetValueType(value);
|
||||
types->TypeSet::addType(type, &cx->typeLifoAlloc());
|
||||
}
|
||||
}
|
||||
@ -2531,7 +2531,7 @@ ObjectGroup::matchDefiniteProperties(HandleObject obj)
|
||||
}
|
||||
|
||||
void
|
||||
types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type type)
|
||||
js::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, TypeSet::Type type)
|
||||
{
|
||||
MOZ_ASSERT(id == IdToTypeId(id));
|
||||
|
||||
@ -2547,7 +2547,7 @@ types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type
|
||||
// Clear any constant flag if it exists.
|
||||
if (!types->empty() && !types->nonConstantProperty()) {
|
||||
InferSpew(ISpewOps, "constantMutated: %sT%p%s %s",
|
||||
InferSpewColor(types), types, InferSpewColorReset(), TypeString(type));
|
||||
InferSpewColor(types), types, InferSpewColorReset(), TypeSet::TypeString(type));
|
||||
types->setNonConstantProperty(cx);
|
||||
}
|
||||
|
||||
@ -2555,7 +2555,7 @@ types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type
|
||||
return;
|
||||
|
||||
InferSpew(ISpewOps, "externalType: property %s %s: %s",
|
||||
ObjectGroupString(group), TypeIdString(id), TypeString(type));
|
||||
TypeSet::ObjectGroupString(group), TypeIdString(id), TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
|
||||
// Propagate new types from partially initialized groups to fully
|
||||
@ -2565,15 +2565,15 @@ types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type
|
||||
// from acquiring the fully initialized group.
|
||||
if (group->newScript() && group->newScript()->initializedGroup()) {
|
||||
if (type.isObjectUnchecked() && types->unknownObject())
|
||||
type = Type::AnyObjectType();
|
||||
type = TypeSet::AnyObjectType();
|
||||
AddTypePropertyId(cx, group->newScript()->initializedGroup(), id, type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
js::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
{
|
||||
AddTypePropertyId(cx, group, id, GetValueType(value));
|
||||
AddTypePropertyId(cx, group, id, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
void
|
||||
@ -2655,7 +2655,7 @@ ObjectGroup::setFlags(ExclusiveContext *cx, ObjectGroupFlags flags)
|
||||
|
||||
addFlags(flags);
|
||||
|
||||
InferSpew(ISpewOps, "%s: setFlags 0x%x", ObjectGroupString(this), flags);
|
||||
InferSpew(ISpewOps, "%s: setFlags 0x%x", TypeSet::ObjectGroupString(this), flags);
|
||||
|
||||
ObjectStateChange(cx, this, false);
|
||||
|
||||
@ -2673,7 +2673,7 @@ ObjectGroup::markUnknown(ExclusiveContext *cx)
|
||||
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
InferSpew(ISpewOps, "UnknownProperties: %s", ObjectGroupString(this));
|
||||
InferSpew(ISpewOps, "UnknownProperties: %s", TypeSet::ObjectGroupString(this));
|
||||
|
||||
clearNewScript(cx);
|
||||
ObjectStateChange(cx, this, true);
|
||||
@ -2691,7 +2691,7 @@ ObjectGroup::markUnknown(ExclusiveContext *cx)
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
Property *prop = getProperty(i);
|
||||
if (prop) {
|
||||
prop->types.addType(cx, Type::UnknownType());
|
||||
prop->types.addType(cx, TypeSet::UnknownType());
|
||||
prop->types.setNonDataProperty(cx);
|
||||
}
|
||||
}
|
||||
@ -2800,8 +2800,8 @@ ObjectGroup::print()
|
||||
{
|
||||
TaggedProto tagged(proto());
|
||||
fprintf(stderr, "%s : %s",
|
||||
ObjectGroupString(this),
|
||||
tagged.isObject() ? TypeString(Type::ObjectType(tagged.toObject()))
|
||||
TypeSet::ObjectGroupString(this),
|
||||
tagged.isObject() ? TypeSet::TypeString(TypeSet::ObjectType(tagged.toObject()))
|
||||
: (tagged.isLazy() ? "(lazy)" : "(null)"));
|
||||
|
||||
if (unknownProperties()) {
|
||||
@ -2881,7 +2881,7 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
|
||||
group->clearNewScript(cx);
|
||||
}
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {}
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {}
|
||||
|
||||
bool sweep(TypeZone &zone, TypeConstraint **res) {
|
||||
if (IsObjectGroupAboutToBeFinalized(&group))
|
||||
@ -2892,7 +2892,7 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
|
||||
};
|
||||
|
||||
bool
|
||||
types::AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, ObjectGroup *group, HandleId id)
|
||||
js::AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, ObjectGroup *group, HandleId id)
|
||||
{
|
||||
/*
|
||||
* Ensure that if the properties named here could have a getter, setter or
|
||||
@ -2929,7 +2929,7 @@ class TypeConstraintClearDefiniteSingle : public TypeConstraint
|
||||
|
||||
const char *kind() { return "clearDefiniteSingle"; }
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {
|
||||
if (source->baseFlags() || source->getObjectCount() > 1)
|
||||
group->clearNewScript(cx);
|
||||
}
|
||||
@ -2943,7 +2943,7 @@ class TypeConstraintClearDefiniteSingle : public TypeConstraint
|
||||
};
|
||||
|
||||
bool
|
||||
types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
||||
js::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
||||
JSScript *script, JSScript *calleeScript)
|
||||
{
|
||||
// Look for any uses of the specified calleeScript in type sets for
|
||||
@ -2954,7 +2954,8 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
||||
// contain a single object, as IonBuilder does not inline polymorphic sites
|
||||
// during the definite properties analysis.
|
||||
|
||||
TypeSetObjectKey *calleeKey = Type::ObjectType(calleeScript->functionNonDelazifying()).objectKey();
|
||||
TypeSet::ObjectKey *calleeKey =
|
||||
TypeSet::ObjectType(calleeScript->functionNonDelazifying()).objectKey();
|
||||
|
||||
unsigned count = TypeScript::NumTypeSets(script);
|
||||
StackTypeSet *typeArray = script->types()->typeArray();
|
||||
@ -2990,8 +2991,7 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args,
|
||||
bool constructing)
|
||||
js::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args, bool constructing)
|
||||
{
|
||||
unsigned nargs = callee->as<JSFunction>().nargs();
|
||||
JSScript *script = callee->as<JSFunction>().nonLazyScript();
|
||||
@ -3014,18 +3014,18 @@ types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsAboutToBeFinalized(TypeSetObjectKey **keyp)
|
||||
IsAboutToBeFinalized(TypeSet::ObjectKey **keyp)
|
||||
{
|
||||
// Mask out the low bit indicating whether this is a group or JS object.
|
||||
uintptr_t flagBit = uintptr_t(*keyp) & 1;
|
||||
gc::Cell *tmp = reinterpret_cast<gc::Cell *>(uintptr_t(*keyp) & ~1);
|
||||
bool isAboutToBeFinalized = IsCellAboutToBeFinalized(&tmp);
|
||||
*keyp = reinterpret_cast<TypeSetObjectKey *>(uintptr_t(tmp) | flagBit);
|
||||
*keyp = reinterpret_cast<TypeSet::ObjectKey *>(uintptr_t(tmp) | flagBit);
|
||||
return isAboutToBeFinalized;
|
||||
}
|
||||
|
||||
void
|
||||
types::FillBytecodeTypeMap(JSScript *script, uint32_t *bytecodeMap)
|
||||
js::FillBytecodeTypeMap(JSScript *script, uint32_t *bytecodeMap)
|
||||
{
|
||||
uint32_t added = 0;
|
||||
for (jsbytecode *pc = script->code(); pc < script->codeEnd(); pc += GetBytecodeLength(pc)) {
|
||||
@ -3040,7 +3040,7 @@ types::FillBytecodeTypeMap(JSScript *script, uint32_t *bytecodeMap)
|
||||
}
|
||||
|
||||
void
|
||||
types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
js::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
{
|
||||
/* Allow the non-TYPESET scenario to simplify stubs used in compound opcodes. */
|
||||
if (!(js_CodeSpec[*pc].format & JOF_TYPESET))
|
||||
@ -3051,13 +3051,13 @@ types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const
|
||||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
Type type = GetValueType(rval);
|
||||
TypeSet::Type type = TypeSet::GetValueType(rval);
|
||||
StackTypeSet *types = TypeScript::BytecodeTypes(script, pc);
|
||||
if (types->hasType(type))
|
||||
return;
|
||||
|
||||
InferSpew(ISpewOps, "bytecodeType: %p %05u: %s",
|
||||
script, script->pcToOffset(pc), TypeString(type));
|
||||
script, script->pcToOffset(pc), TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
|
||||
@ -3688,18 +3688,18 @@ ConstraintTypeSet::sweep(Zone *zone, AutoClearTypeInferenceStateOnOOM &oom)
|
||||
*/
|
||||
unsigned objectCount = baseObjectCount();
|
||||
if (objectCount >= 2) {
|
||||
unsigned oldCapacity = HashSetCapacity(objectCount);
|
||||
TypeSetObjectKey **oldArray = objectSet;
|
||||
unsigned oldCapacity = TypeHashSet::Capacity(objectCount);
|
||||
ObjectKey **oldArray = objectSet;
|
||||
|
||||
clearObjects();
|
||||
objectCount = 0;
|
||||
for (unsigned i = 0; i < oldCapacity; i++) {
|
||||
TypeSetObjectKey *key = oldArray[i];
|
||||
ObjectKey *key = oldArray[i];
|
||||
if (!key)
|
||||
continue;
|
||||
if (!IsAboutToBeFinalized(&key)) {
|
||||
TypeSetObjectKey **pentry =
|
||||
HashSetInsert<TypeSetObjectKey *,TypeSetObjectKey,TypeSetObjectKey>
|
||||
ObjectKey **pentry =
|
||||
TypeHashSet::Insert<ObjectKey *, ObjectKey, ObjectKey>
|
||||
(zone->types.typeLifoAlloc, objectSet, objectCount, key);
|
||||
if (pentry) {
|
||||
*pentry = key;
|
||||
@ -3722,9 +3722,9 @@ ConstraintTypeSet::sweep(Zone *zone, AutoClearTypeInferenceStateOnOOM &oom)
|
||||
}
|
||||
setBaseObjectCount(objectCount);
|
||||
} else if (objectCount == 1) {
|
||||
TypeSetObjectKey *key = (TypeSetObjectKey *) objectSet;
|
||||
ObjectKey *key = (ObjectKey *) objectSet;
|
||||
if (!IsAboutToBeFinalized(&key)) {
|
||||
objectSet = reinterpret_cast<TypeSetObjectKey **>(key);
|
||||
objectSet = reinterpret_cast<ObjectKey **>(key);
|
||||
} else {
|
||||
// As above, mark type sets containing objects with unknown
|
||||
// properties as unknown.
|
||||
@ -3823,7 +3823,7 @@ ObjectGroup::maybeSweep(AutoClearTypeInferenceStateOnOOM *oom)
|
||||
*/
|
||||
unsigned propertyCount = basePropertyCount();
|
||||
if (propertyCount >= 2) {
|
||||
unsigned oldCapacity = HashSetCapacity(propertyCount);
|
||||
unsigned oldCapacity = TypeHashSet::Capacity(propertyCount);
|
||||
Property **oldArray = propertySet;
|
||||
|
||||
clearProperties();
|
||||
@ -3843,9 +3843,8 @@ ObjectGroup::maybeSweep(AutoClearTypeInferenceStateOnOOM *oom)
|
||||
|
||||
Property *newProp = typeLifoAlloc.new_<Property>(*prop);
|
||||
if (newProp) {
|
||||
Property **pentry =
|
||||
HashSetInsert<jsid,Property,Property>
|
||||
(typeLifoAlloc, propertySet, propertyCount, prop->id);
|
||||
Property **pentry = TypeHashSet::Insert<jsid, Property, Property>
|
||||
(typeLifoAlloc, propertySet, propertyCount, prop->id);
|
||||
if (pentry) {
|
||||
*pentry = newProp;
|
||||
newProp->types.sweep(zone(), *oom);
|
||||
|
570
js/src/jsinfer.h
570
js/src/jsinfer.h
@ -23,7 +23,6 @@
|
||||
#include "js/UbiNode.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/ObjectGroup.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -33,122 +32,12 @@ namespace jit {
|
||||
class TempAllocator;
|
||||
}
|
||||
|
||||
namespace types {
|
||||
|
||||
class TaggedProto;
|
||||
struct TypeZone;
|
||||
class TypeSet;
|
||||
struct TypeSetObjectKey;
|
||||
|
||||
/*
|
||||
* Information about a single concrete type. We pack this into a single word,
|
||||
* where small values are particular primitive or other singleton types, and
|
||||
* larger values are either specific JS objects or object groups.
|
||||
*/
|
||||
class Type
|
||||
{
|
||||
uintptr_t data;
|
||||
explicit Type(uintptr_t data) : data(data) {}
|
||||
|
||||
public:
|
||||
|
||||
uintptr_t raw() const { return data; }
|
||||
|
||||
bool isPrimitive() const {
|
||||
return data < JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isPrimitive(JSValueType type) const {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_OBJECT);
|
||||
return (uintptr_t) type == data;
|
||||
}
|
||||
|
||||
JSValueType primitive() const {
|
||||
MOZ_ASSERT(isPrimitive());
|
||||
return (JSValueType) data;
|
||||
}
|
||||
|
||||
bool isMagicArguments() const {
|
||||
return primitive() == JSVAL_TYPE_MAGIC;
|
||||
}
|
||||
|
||||
bool isSomeObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT || data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isAnyObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isUnknown() const {
|
||||
return data == JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Accessors for types that are either JSObject or ObjectGroup. */
|
||||
|
||||
bool isObject() const {
|
||||
MOZ_ASSERT(!isAnyObject() && !isUnknown());
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isObjectUnchecked() const {
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
inline TypeSetObjectKey *objectKey() const;
|
||||
|
||||
/* Accessors for JSObject types */
|
||||
|
||||
bool isSingleton() const {
|
||||
return isObject() && !!(data & 1);
|
||||
}
|
||||
|
||||
inline JSObject *singleton() const;
|
||||
inline JSObject *singletonNoBarrier() const;
|
||||
|
||||
/* Accessors for ObjectGroup types */
|
||||
|
||||
bool isGroup() const {
|
||||
return isObject() && !(data & 1);
|
||||
}
|
||||
|
||||
inline ObjectGroup *group() const;
|
||||
inline ObjectGroup *groupNoBarrier() const;
|
||||
|
||||
bool operator == (Type o) const { return data == o.data; }
|
||||
bool operator != (Type o) const { return data != o.data; }
|
||||
|
||||
static inline Type UndefinedType() { return Type(JSVAL_TYPE_UNDEFINED); }
|
||||
static inline Type NullType() { return Type(JSVAL_TYPE_NULL); }
|
||||
static inline Type BooleanType() { return Type(JSVAL_TYPE_BOOLEAN); }
|
||||
static inline Type Int32Type() { return Type(JSVAL_TYPE_INT32); }
|
||||
static inline Type DoubleType() { return Type(JSVAL_TYPE_DOUBLE); }
|
||||
static inline Type StringType() { return Type(JSVAL_TYPE_STRING); }
|
||||
static inline Type SymbolType() { return Type(JSVAL_TYPE_SYMBOL); }
|
||||
static inline Type MagicArgType() { return Type(JSVAL_TYPE_MAGIC); }
|
||||
static inline Type AnyObjectType() { return Type(JSVAL_TYPE_OBJECT); }
|
||||
static inline Type UnknownType() { return Type(JSVAL_TYPE_UNKNOWN); }
|
||||
|
||||
static inline Type PrimitiveType(JSValueType type) {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_UNKNOWN);
|
||||
return Type(type);
|
||||
}
|
||||
|
||||
static inline Type ObjectType(JSObject *obj);
|
||||
static inline Type ObjectType(ObjectGroup *group);
|
||||
static inline Type ObjectType(TypeSetObjectKey *key);
|
||||
|
||||
static js::ThingRootKind rootKind() { return js::THING_ROOT_TYPE; }
|
||||
};
|
||||
|
||||
/* Get the type of a jsval, or zero for an unknown special value. */
|
||||
inline Type GetValueType(const Value &val);
|
||||
|
||||
/*
|
||||
* Get the type of a possibly optimized out or uninitialized let value. This
|
||||
* generally only happens on unconditional type monitors on bailing out of
|
||||
* Ion, such as for argument and local types.
|
||||
*/
|
||||
inline Type GetMaybeUntrackedValueType(const Value &val);
|
||||
class TypeConstraint;
|
||||
class TypeNewScript;
|
||||
class CompilerConstraintList;
|
||||
class HeapTypeSetKey;
|
||||
|
||||
/*
|
||||
* Type inference memory management overview.
|
||||
@ -162,46 +51,6 @@ inline Type GetMaybeUntrackedValueType(const Value &val);
|
||||
* Thus, type set and constraints only hold weak references.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A constraint which listens to additions to a type set and propagates those
|
||||
* changes to other type sets.
|
||||
*/
|
||||
class TypeConstraint
|
||||
{
|
||||
public:
|
||||
/* Next constraint listening to the same type set. */
|
||||
TypeConstraint *next;
|
||||
|
||||
TypeConstraint()
|
||||
: next(nullptr)
|
||||
{}
|
||||
|
||||
/* Debugging name for this kind of constraint. */
|
||||
virtual const char *kind() = 0;
|
||||
|
||||
/* Register a new type for the set this constraint is listening to. */
|
||||
virtual void newType(JSContext *cx, TypeSet *source, Type type) = 0;
|
||||
|
||||
/*
|
||||
* For constraints attached to an object property's type set, mark the
|
||||
* property as having changed somehow.
|
||||
*/
|
||||
virtual void newPropertyState(JSContext *cx, TypeSet *source) {}
|
||||
|
||||
/*
|
||||
* For constraints attached to the JSID_EMPTY type set on an object,
|
||||
* indicate a change in one of the object's dynamic property flags or other
|
||||
* state.
|
||||
*/
|
||||
virtual void newObjectState(JSContext *cx, ObjectGroup *group) {}
|
||||
|
||||
/*
|
||||
* If the data this constraint refers to is still live, copy it into the
|
||||
* zone's new allocator. Type constraints only hold weak references.
|
||||
*/
|
||||
virtual bool sweep(TypeZone &zone, TypeConstraint **res) = 0;
|
||||
};
|
||||
|
||||
/* Flags and other state stored in TypeSet::flags */
|
||||
enum : uint32_t {
|
||||
TYPE_FLAG_UNDEFINED = 0x1,
|
||||
@ -261,6 +110,81 @@ enum : uint32_t {
|
||||
};
|
||||
typedef uint32_t TypeFlags;
|
||||
|
||||
/* Flags and other state stored in ObjectGroup::Flags */
|
||||
enum : uint32_t {
|
||||
/* Whether this group is associated with some allocation site. */
|
||||
OBJECT_FLAG_FROM_ALLOCATION_SITE = 0x1,
|
||||
|
||||
/* (0x2 and 0x4 are unused) */
|
||||
|
||||
/* Mask/shift for the number of properties in propertySet */
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK = 0xfff8,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_SHIFT = 3,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_LIMIT =
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT,
|
||||
|
||||
/* Whether any objects this represents may have sparse indexes. */
|
||||
OBJECT_FLAG_SPARSE_INDEXES = 0x00010000,
|
||||
|
||||
/* Whether any objects this represents may not have packed dense elements. */
|
||||
OBJECT_FLAG_NON_PACKED = 0x00020000,
|
||||
|
||||
/*
|
||||
* Whether any objects this represents may be arrays whose length does not
|
||||
* fit in an int32.
|
||||
*/
|
||||
OBJECT_FLAG_LENGTH_OVERFLOW = 0x00040000,
|
||||
|
||||
/* Whether any objects have been iterated over. */
|
||||
OBJECT_FLAG_ITERATED = 0x00080000,
|
||||
|
||||
/* For a global object, whether flags were set on the RegExpStatics. */
|
||||
OBJECT_FLAG_REGEXP_FLAGS_SET = 0x00100000,
|
||||
|
||||
/*
|
||||
* For the function on a run-once script, whether the function has actually
|
||||
* run multiple times.
|
||||
*/
|
||||
OBJECT_FLAG_RUNONCE_INVALIDATED = 0x00200000,
|
||||
|
||||
/*
|
||||
* For a global object, whether any array buffers in this compartment with
|
||||
* typed object views have been neutered.
|
||||
*/
|
||||
OBJECT_FLAG_TYPED_OBJECT_NEUTERED = 0x00400000,
|
||||
|
||||
/*
|
||||
* Whether objects with this type should be allocated directly in the
|
||||
* tenured heap.
|
||||
*/
|
||||
OBJECT_FLAG_PRE_TENURE = 0x00800000,
|
||||
|
||||
/* Whether objects with this type might have copy on write elements. */
|
||||
OBJECT_FLAG_COPY_ON_WRITE = 0x01000000,
|
||||
|
||||
/* Whether this type has had its 'new' script cleared in the past. */
|
||||
OBJECT_FLAG_NEW_SCRIPT_CLEARED = 0x02000000,
|
||||
|
||||
/*
|
||||
* Whether all properties of this object are considered unknown.
|
||||
* If set, all other flags in DYNAMIC_MASK will also be set.
|
||||
*/
|
||||
OBJECT_FLAG_UNKNOWN_PROPERTIES = 0x04000000,
|
||||
|
||||
/* Flags which indicate dynamic properties of represented objects. */
|
||||
OBJECT_FLAG_DYNAMIC_MASK = 0x07ff0000,
|
||||
|
||||
// Mask/shift for the kind of addendum attached to this group.
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x38000000,
|
||||
OBJECT_FLAG_ADDENDUM_SHIFT = 27,
|
||||
|
||||
// Mask/shift for this group's generation. If out of sync with the
|
||||
// TypeZone's generation, this group hasn't been swept yet.
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x40000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 30,
|
||||
};
|
||||
typedef uint32_t ObjectGroupFlags;
|
||||
|
||||
class StackTypeSet;
|
||||
class HeapTypeSet;
|
||||
class TemporaryTypeSet;
|
||||
@ -271,11 +195,12 @@ class TemporaryTypeSet;
|
||||
*
|
||||
* - StackTypeSet are associated with TypeScripts, for arguments and values
|
||||
* observed at property reads. These are implicitly frozen on compilation
|
||||
* and do not have constraints attached to them.
|
||||
* and only have constraints added to them which can trigger invalidation of
|
||||
* TypeNewScript information.
|
||||
*
|
||||
* - HeapTypeSet are associated with the properties of ObjectGroups. These
|
||||
* may have constraints added to them to trigger invalidation of compiled
|
||||
* code.
|
||||
* may have constraints added to them to trigger invalidation of either
|
||||
* compiled code or TypeNewScript information.
|
||||
*
|
||||
* - TemporaryTypeSet are created during compilation and do not outlive
|
||||
* that compilation.
|
||||
@ -289,12 +214,162 @@ class TemporaryTypeSet;
|
||||
*/
|
||||
class TypeSet
|
||||
{
|
||||
public:
|
||||
// Type set entry for either a JSObject with singleton type or a
|
||||
// non-singleton ObjectGroup.
|
||||
class ObjectKey {
|
||||
public:
|
||||
static intptr_t keyBits(ObjectKey *obj) { return (intptr_t) obj; }
|
||||
static ObjectKey *getKey(ObjectKey *obj) { return obj; }
|
||||
|
||||
static inline ObjectKey *get(JSObject *obj);
|
||||
static inline ObjectKey *get(ObjectGroup *group);
|
||||
|
||||
bool isGroup() {
|
||||
return (uintptr_t(this) & 1) == 0;
|
||||
}
|
||||
bool isSingleton() {
|
||||
return (uintptr_t(this) & 1) != 0;
|
||||
}
|
||||
|
||||
inline ObjectGroup *group();
|
||||
inline JSObject *singleton();
|
||||
|
||||
inline ObjectGroup *groupNoBarrier();
|
||||
inline JSObject *singletonNoBarrier();
|
||||
|
||||
const Class *clasp();
|
||||
TaggedProto proto();
|
||||
TypeNewScript *newScript();
|
||||
|
||||
bool unknownProperties();
|
||||
bool hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags);
|
||||
bool hasStableClassAndProto(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
|
||||
HeapTypeSetKey property(jsid id);
|
||||
void ensureTrackedProperty(JSContext *cx, jsid id);
|
||||
|
||||
ObjectGroup *maybeGroup();
|
||||
};
|
||||
|
||||
// Information about a single concrete type. We pack this into one word,
|
||||
// where small values are particular primitive or other singleton types and
|
||||
// larger values are either specific JS objects or object groups.
|
||||
class Type
|
||||
{
|
||||
friend class TypeSet;
|
||||
|
||||
uintptr_t data;
|
||||
explicit Type(uintptr_t data) : data(data) {}
|
||||
|
||||
public:
|
||||
|
||||
uintptr_t raw() const { return data; }
|
||||
|
||||
bool isPrimitive() const {
|
||||
return data < JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isPrimitive(JSValueType type) const {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_OBJECT);
|
||||
return (uintptr_t) type == data;
|
||||
}
|
||||
|
||||
JSValueType primitive() const {
|
||||
MOZ_ASSERT(isPrimitive());
|
||||
return (JSValueType) data;
|
||||
}
|
||||
|
||||
bool isMagicArguments() const {
|
||||
return primitive() == JSVAL_TYPE_MAGIC;
|
||||
}
|
||||
|
||||
bool isSomeObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT || data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isAnyObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isUnknown() const {
|
||||
return data == JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Accessors for types that are either JSObject or ObjectGroup. */
|
||||
|
||||
bool isObject() const {
|
||||
MOZ_ASSERT(!isAnyObject() && !isUnknown());
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isObjectUnchecked() const {
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
inline ObjectKey *objectKey() const;
|
||||
|
||||
/* Accessors for JSObject types */
|
||||
|
||||
bool isSingleton() const {
|
||||
return isObject() && !!(data & 1);
|
||||
}
|
||||
|
||||
inline JSObject *singleton() const;
|
||||
inline JSObject *singletonNoBarrier() const;
|
||||
|
||||
/* Accessors for ObjectGroup types */
|
||||
|
||||
bool isGroup() const {
|
||||
return isObject() && !(data & 1);
|
||||
}
|
||||
|
||||
inline ObjectGroup *group() const;
|
||||
inline ObjectGroup *groupNoBarrier() const;
|
||||
|
||||
bool operator == (Type o) const { return data == o.data; }
|
||||
bool operator != (Type o) const { return data != o.data; }
|
||||
|
||||
static ThingRootKind rootKind() { return THING_ROOT_TYPE; }
|
||||
};
|
||||
|
||||
static inline Type UndefinedType() { return Type(JSVAL_TYPE_UNDEFINED); }
|
||||
static inline Type NullType() { return Type(JSVAL_TYPE_NULL); }
|
||||
static inline Type BooleanType() { return Type(JSVAL_TYPE_BOOLEAN); }
|
||||
static inline Type Int32Type() { return Type(JSVAL_TYPE_INT32); }
|
||||
static inline Type DoubleType() { return Type(JSVAL_TYPE_DOUBLE); }
|
||||
static inline Type StringType() { return Type(JSVAL_TYPE_STRING); }
|
||||
static inline Type SymbolType() { return Type(JSVAL_TYPE_SYMBOL); }
|
||||
static inline Type MagicArgType() { return Type(JSVAL_TYPE_MAGIC); }
|
||||
static inline Type AnyObjectType() { return Type(JSVAL_TYPE_OBJECT); }
|
||||
static inline Type UnknownType() { return Type(JSVAL_TYPE_UNKNOWN); }
|
||||
|
||||
static inline Type PrimitiveType(JSValueType type) {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_UNKNOWN);
|
||||
return Type(type);
|
||||
}
|
||||
|
||||
static inline Type ObjectType(JSObject *obj);
|
||||
static inline Type ObjectType(ObjectGroup *group);
|
||||
static inline Type ObjectType(ObjectKey *key);
|
||||
|
||||
static const char *NonObjectTypeString(Type type);
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *TypeString(Type type);
|
||||
static const char *ObjectGroupString(ObjectGroup *group);
|
||||
#else
|
||||
static const char *TypeString(Type type) { return nullptr; }
|
||||
static const char *ObjectGroupString(ObjectGroup *group) { return nullptr; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/* Flags for this type set. */
|
||||
TypeFlags flags;
|
||||
|
||||
/* Possible objects this type set can represent. */
|
||||
TypeSetObjectKey **objectSet;
|
||||
ObjectKey **objectSet;
|
||||
|
||||
public:
|
||||
|
||||
@ -350,7 +425,7 @@ class TypeSet
|
||||
* may return nullptr.
|
||||
*/
|
||||
inline unsigned getObjectCount() const;
|
||||
inline TypeSetObjectKey *getObject(unsigned i) const;
|
||||
inline ObjectKey *getObject(unsigned i) const;
|
||||
inline JSObject *getSingleton(unsigned i) const;
|
||||
inline ObjectGroup *getGroup(unsigned i) const;
|
||||
inline JSObject *getSingletonNoBarrier(unsigned i) const;
|
||||
@ -412,6 +487,58 @@ class TypeSet
|
||||
inline void setBaseObjectCount(uint32_t count);
|
||||
|
||||
void clearObjects();
|
||||
|
||||
public:
|
||||
static inline Type GetValueType(const Value &val);
|
||||
|
||||
static inline bool IsUntrackedValue(const Value &val);
|
||||
|
||||
// Get the type of a possibly optimized out or uninitialized let value.
|
||||
// This generally only happens on unconditional type monitors on bailing
|
||||
// out of Ion, such as for argument and local types.
|
||||
static inline Type GetMaybeUntrackedValueType(const Value &val);
|
||||
|
||||
static void MarkTypeRoot(JSTracer *trc, Type *v, const char *name);
|
||||
};
|
||||
|
||||
/*
|
||||
* A constraint which listens to additions to a type set and propagates those
|
||||
* changes to other type sets.
|
||||
*/
|
||||
class TypeConstraint
|
||||
{
|
||||
public:
|
||||
/* Next constraint listening to the same type set. */
|
||||
TypeConstraint *next;
|
||||
|
||||
TypeConstraint()
|
||||
: next(nullptr)
|
||||
{}
|
||||
|
||||
/* Debugging name for this kind of constraint. */
|
||||
virtual const char *kind() = 0;
|
||||
|
||||
/* Register a new type for the set this constraint is listening to. */
|
||||
virtual void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) = 0;
|
||||
|
||||
/*
|
||||
* For constraints attached to an object property's type set, mark the
|
||||
* property as having changed somehow.
|
||||
*/
|
||||
virtual void newPropertyState(JSContext *cx, TypeSet *source) {}
|
||||
|
||||
/*
|
||||
* For constraints attached to the JSID_EMPTY type set on an object,
|
||||
* indicate a change in one of the object's dynamic property flags or other
|
||||
* state.
|
||||
*/
|
||||
virtual void newObjectState(JSContext *cx, ObjectGroup *group) {}
|
||||
|
||||
/*
|
||||
* If the data this constraint refers to is still live, copy it into the
|
||||
* zone's new allocator. Type constraints only hold weak references.
|
||||
*/
|
||||
virtual bool sweep(TypeZone &zone, TypeConstraint **res) = 0;
|
||||
};
|
||||
|
||||
// If there is an OOM while sweeping types, the type information is deoptimized
|
||||
@ -487,7 +614,7 @@ class TemporaryTypeSet : public TypeSet
|
||||
TemporaryTypeSet() {}
|
||||
TemporaryTypeSet(LifoAlloc *alloc, Type type);
|
||||
|
||||
TemporaryTypeSet(uint32_t flags, TypeSetObjectKey **objectSet) {
|
||||
TemporaryTypeSet(uint32_t flags, ObjectKey **objectSet) {
|
||||
this->flags = flags;
|
||||
this->objectSet = objectSet;
|
||||
}
|
||||
@ -772,66 +899,6 @@ class TypeNewScript
|
||||
/* Is this a reasonable PC to be doing inlining on? */
|
||||
inline bool isInlinableCall(jsbytecode *pc);
|
||||
|
||||
/*
|
||||
* Type information about a property.
|
||||
*
|
||||
* The type sets in the properties of a group describe the possible values
|
||||
* that can be read out of that property in actual JS objects. In native
|
||||
* objects, property types account for plain data properties (those with a
|
||||
* slot and no getter or setter hook) and dense elements. In typed objects
|
||||
* and unboxed objects, property types account for object and value
|
||||
* properties and elements in the object.
|
||||
*
|
||||
* For accesses on these properties, the correspondence is as follows:
|
||||
*
|
||||
* 1. If the group has unknownProperties(), the possible properties and
|
||||
* value types for associated JSObjects are unknown.
|
||||
*
|
||||
* 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
|
||||
* in |obj|, before obj->getProperty(id) the property in |group| for
|
||||
* |id| must reflect the result of the getProperty.
|
||||
*
|
||||
* There are several exceptions to this:
|
||||
*
|
||||
* 1. For properties of global JS objects which are undefined at the point
|
||||
* where the property was (lazily) generated, the property type set will
|
||||
* remain empty, and the 'undefined' type will only be added after a
|
||||
* subsequent assignment or deletion. After these properties have been
|
||||
* assigned a defined value, the only way they can become undefined
|
||||
* again is after such an assign or deletion.
|
||||
*
|
||||
* 2. Array lengths are special cased by the compiler and VM and are not
|
||||
* reflected in property types.
|
||||
*
|
||||
* 3. In typed objects (but not unboxed objects), the initial values of
|
||||
* properties (null pointers and undefined values) are not reflected in
|
||||
* the property types. These values are always possible when reading the
|
||||
* property.
|
||||
*
|
||||
* We establish these by using write barriers on calls to setProperty and
|
||||
* defineProperty which are on native properties, and on any jitcode which
|
||||
* might update the property with a new type.
|
||||
*/
|
||||
struct Property
|
||||
{
|
||||
/* Identifier for this property, JSID_VOID for the aggregate integer index property. */
|
||||
HeapId id;
|
||||
|
||||
/* Possible types for this property, including types inherited from prototypes. */
|
||||
HeapTypeSet types;
|
||||
|
||||
explicit Property(jsid id)
|
||||
: id(id)
|
||||
{}
|
||||
|
||||
Property(const Property &o)
|
||||
: id(o.id.get()), types(o.types)
|
||||
{}
|
||||
|
||||
static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
|
||||
static jsid getKey(Property *p) { return p->id; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Whether Array.prototype, or an object on its proto chain, has an
|
||||
* indexed property.
|
||||
@ -894,9 +961,10 @@ class TypeScript
|
||||
static inline void MonitorAssign(JSContext *cx, HandleObject obj, jsid id);
|
||||
|
||||
/* Add a type for a variable in a script. */
|
||||
static inline void SetThis(JSContext *cx, JSScript *script, Type type);
|
||||
static inline void SetThis(JSContext *cx, JSScript *script, TypeSet::Type type);
|
||||
static inline void SetThis(JSContext *cx, JSScript *script, const js::Value &value);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg,
|
||||
TypeSet::Type type);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg,
|
||||
const js::Value &value);
|
||||
|
||||
@ -940,45 +1008,6 @@ FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintList *co
|
||||
void
|
||||
FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints);
|
||||
|
||||
class HeapTypeSetKey;
|
||||
|
||||
// Type set entry for either a JSObject with singleton type or a non-singleton ObjectGroup.
|
||||
struct TypeSetObjectKey
|
||||
{
|
||||
static intptr_t keyBits(TypeSetObjectKey *obj) { return (intptr_t) obj; }
|
||||
static TypeSetObjectKey *getKey(TypeSetObjectKey *obj) { return obj; }
|
||||
|
||||
static inline TypeSetObjectKey *get(JSObject *obj);
|
||||
static inline TypeSetObjectKey *get(ObjectGroup *group);
|
||||
|
||||
bool isGroup() {
|
||||
return (uintptr_t(this) & 1) == 0;
|
||||
}
|
||||
bool isSingleton() {
|
||||
return (uintptr_t(this) & 1) != 0;
|
||||
}
|
||||
|
||||
inline ObjectGroup *group();
|
||||
inline JSObject *singleton();
|
||||
|
||||
inline ObjectGroup *groupNoBarrier();
|
||||
inline JSObject *singletonNoBarrier();
|
||||
|
||||
const Class *clasp();
|
||||
TaggedProto proto();
|
||||
TypeNewScript *newScript();
|
||||
|
||||
bool unknownProperties();
|
||||
bool hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags);
|
||||
bool hasStableClassAndProto(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
|
||||
HeapTypeSetKey property(jsid id);
|
||||
void ensureTrackedProperty(JSContext *cx, jsid id);
|
||||
|
||||
ObjectGroup *maybeGroup();
|
||||
};
|
||||
|
||||
// Representation of a heap type property which may or may not be instantiated.
|
||||
// Heap properties for singleton types are instantiated lazily as they are used
|
||||
// by the compiler, but this is only done on the main thread. If we are
|
||||
@ -989,10 +1018,10 @@ struct TypeSetObjectKey
|
||||
// during generation of baseline caches.
|
||||
class HeapTypeSetKey
|
||||
{
|
||||
friend struct TypeSetObjectKey;
|
||||
friend class TypeSet::ObjectKey;
|
||||
|
||||
// Object and property being accessed.
|
||||
TypeSetObjectKey *object_;
|
||||
TypeSet::ObjectKey *object_;
|
||||
jsid id_;
|
||||
|
||||
// If instantiated, the underlying heap type set.
|
||||
@ -1003,7 +1032,7 @@ class HeapTypeSetKey
|
||||
: object_(nullptr), id_(JSID_EMPTY), maybeTypes_(nullptr)
|
||||
{}
|
||||
|
||||
TypeSetObjectKey *object() const { return object_; }
|
||||
TypeSet::ObjectKey *object() const { return object_; }
|
||||
jsid id() const { return id_; }
|
||||
HeapTypeSet *maybeTypes() const { return maybeTypes_; }
|
||||
|
||||
@ -1166,8 +1195,6 @@ enum SpewChannel {
|
||||
SPEW_COUNT
|
||||
};
|
||||
|
||||
const char *NonObjectTypeString(Type type);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const char * InferSpewColorReset();
|
||||
@ -1175,11 +1202,9 @@ const char * InferSpewColor(TypeConstraint *constraint);
|
||||
const char * InferSpewColor(TypeSet *types);
|
||||
|
||||
void InferSpew(SpewChannel which, const char *fmt, ...);
|
||||
const char * TypeString(Type type);
|
||||
const char * ObjectGroupString(ObjectGroup *group);
|
||||
|
||||
/* Check that the type property for id in group contains value. */
|
||||
bool TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value);
|
||||
bool ObjectGroupHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value);
|
||||
|
||||
#else
|
||||
|
||||
@ -1187,8 +1212,6 @@ inline const char * InferSpewColorReset() { return nullptr; }
|
||||
inline const char * InferSpewColor(TypeConstraint *constraint) { return nullptr; }
|
||||
inline const char * InferSpewColor(TypeSet *types) { return nullptr; }
|
||||
inline void InferSpew(SpewChannel which, const char *fmt, ...) {}
|
||||
inline const char * TypeString(Type type) { return nullptr; }
|
||||
inline const char * ObjectGroupString(ObjectGroup *group) { return nullptr; }
|
||||
|
||||
#endif
|
||||
|
||||
@ -1199,7 +1222,6 @@ MOZ_NORETURN MOZ_COLD void TypeFailure(JSContext *cx, const char *fmt, ...);
|
||||
void
|
||||
PrintTypes(JSContext *cx, JSCompartment *comp, bool force);
|
||||
|
||||
} /* namespace types */
|
||||
} /* namespace js */
|
||||
|
||||
// JS::ubi::Nodes can point to object groups; they're js::gc::Cell instances
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "jscntxtinlines.h"
|
||||
|
||||
namespace js {
|
||||
namespace types {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// CompilerOutput & RecompileInfo
|
||||
@ -92,40 +91,40 @@ RecompileInfo::shouldSweep(TypeZone &types)
|
||||
// Types
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* static */ inline TypeSetObjectKey *
|
||||
TypeSetObjectKey::get(JSObject *obj)
|
||||
/* static */ inline TypeSet::ObjectKey *
|
||||
TypeSet::ObjectKey::get(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
if (obj->isSingleton())
|
||||
return (TypeSetObjectKey *) (uintptr_t(obj) | 1);
|
||||
return (TypeSetObjectKey *) obj->group();
|
||||
return (ObjectKey *) (uintptr_t(obj) | 1);
|
||||
return (ObjectKey *) obj->group();
|
||||
}
|
||||
|
||||
/* static */ inline TypeSetObjectKey *
|
||||
TypeSetObjectKey::get(ObjectGroup *group)
|
||||
/* static */ inline TypeSet::ObjectKey *
|
||||
TypeSet::ObjectKey::get(ObjectGroup *group)
|
||||
{
|
||||
MOZ_ASSERT(group);
|
||||
if (group->singleton())
|
||||
return (TypeSetObjectKey *) (uintptr_t(group->singleton()) | 1);
|
||||
return (TypeSetObjectKey *) group;
|
||||
return (ObjectKey *) (uintptr_t(group->singleton()) | 1);
|
||||
return (ObjectKey *) group;
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSetObjectKey::groupNoBarrier()
|
||||
TypeSet::ObjectKey::groupNoBarrier()
|
||||
{
|
||||
MOZ_ASSERT(isGroup());
|
||||
return (ObjectGroup *) this;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeSetObjectKey::singletonNoBarrier()
|
||||
TypeSet::ObjectKey::singletonNoBarrier()
|
||||
{
|
||||
MOZ_ASSERT(isSingleton());
|
||||
return (JSObject *) (uintptr_t(this) & ~1);
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSetObjectKey::group()
|
||||
TypeSet::ObjectKey::group()
|
||||
{
|
||||
ObjectGroup *res = groupNoBarrier();
|
||||
ObjectGroup::readBarrier(res);
|
||||
@ -133,56 +132,56 @@ TypeSetObjectKey::group()
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeSetObjectKey::singleton()
|
||||
TypeSet::ObjectKey::singleton()
|
||||
{
|
||||
JSObject *res = singletonNoBarrier();
|
||||
JSObject::readBarrier(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(JSObject *obj)
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(JSObject *obj)
|
||||
{
|
||||
if (obj->isSingleton())
|
||||
return Type(uintptr_t(obj) | 1);
|
||||
return Type(uintptr_t(obj->group()));
|
||||
}
|
||||
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(ObjectGroup *group)
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(ObjectGroup *group)
|
||||
{
|
||||
if (group->singleton())
|
||||
return Type(uintptr_t(group->singleton()) | 1);
|
||||
return Type(uintptr_t(group));
|
||||
}
|
||||
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(TypeSetObjectKey *obj)
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(ObjectKey *obj)
|
||||
{
|
||||
return Type(uintptr_t(obj));
|
||||
}
|
||||
|
||||
inline Type
|
||||
GetValueType(const Value &val)
|
||||
inline TypeSet::Type
|
||||
TypeSet::GetValueType(const Value &val)
|
||||
{
|
||||
if (val.isDouble())
|
||||
return Type::DoubleType();
|
||||
return TypeSet::DoubleType();
|
||||
if (val.isObject())
|
||||
return Type::ObjectType(&val.toObject());
|
||||
return Type::PrimitiveType(val.extractNonDoubleType());
|
||||
return TypeSet::ObjectType(&val.toObject());
|
||||
return TypeSet::PrimitiveType(val.extractNonDoubleType());
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsUntrackedValue(const Value &val)
|
||||
TypeSet::IsUntrackedValue(const Value &val)
|
||||
{
|
||||
return val.isMagic() && (val.whyMagic() == JS_OPTIMIZED_OUT ||
|
||||
val.whyMagic() == JS_UNINITIALIZED_LEXICAL);
|
||||
}
|
||||
|
||||
inline Type
|
||||
GetMaybeUntrackedValueType(const Value &val)
|
||||
inline TypeSet::Type
|
||||
TypeSet::GetMaybeUntrackedValueType(const Value &val)
|
||||
{
|
||||
return IsUntrackedValue(val) ? Type::UnknownType() : GetValueType(val);
|
||||
return IsUntrackedValue(val) ? UnknownType() : GetValueType(val);
|
||||
}
|
||||
|
||||
inline TypeFlags
|
||||
@ -398,7 +397,7 @@ PropertyHasBeenMarkedNonConstant(JSObject *obj, jsid id)
|
||||
}
|
||||
|
||||
inline bool
|
||||
HasTypePropertyId(JSObject *obj, jsid id, Type type)
|
||||
HasTypePropertyId(JSObject *obj, jsid id, TypeSet::Type type)
|
||||
{
|
||||
if (obj->hasLazyGroup())
|
||||
return true;
|
||||
@ -415,15 +414,15 @@ HasTypePropertyId(JSObject *obj, jsid id, Type type)
|
||||
inline bool
|
||||
HasTypePropertyId(JSObject *obj, jsid id, const Value &value)
|
||||
{
|
||||
return HasTypePropertyId(obj, id, GetValueType(value));
|
||||
return HasTypePropertyId(obj, id, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
void AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type type);
|
||||
void AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, TypeSet::Type type);
|
||||
void AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, const Value &value);
|
||||
|
||||
/* Add a possible type for a property of obj. */
|
||||
inline void
|
||||
AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, Type type)
|
||||
AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, TypeSet::Type type)
|
||||
{
|
||||
id = IdToTypeId(id);
|
||||
if (TrackPropertyTypes(cx, obj, id))
|
||||
@ -489,10 +488,8 @@ MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
/* Interface helpers for JSScript*. */
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
const js::Value &rval);
|
||||
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
js::types::Type type);
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &rval);
|
||||
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet::Type type);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Script interface functions
|
||||
@ -622,7 +619,7 @@ TypeScript::MonitorAssign(JSContext *cx, HandleObject obj, jsid id)
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, TypeSet::Type type)
|
||||
{
|
||||
StackTypeSet *types = ThisTypes(script);
|
||||
if (!types)
|
||||
@ -632,7 +629,7 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setThis %p: %s",
|
||||
script, TypeString(type));
|
||||
script, TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
}
|
||||
@ -640,11 +637,11 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
||||
/* static */ inline void
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, const js::Value &value)
|
||||
{
|
||||
SetThis(cx, script, GetValueType(value));
|
||||
SetThis(cx, script, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type)
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, TypeSet::Type type)
|
||||
{
|
||||
StackTypeSet *types = ArgTypes(script, arg);
|
||||
if (!types)
|
||||
@ -654,7 +651,7 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setArg %p %u: %s",
|
||||
script, arg, TypeString(type));
|
||||
script, arg, TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
}
|
||||
@ -662,210 +659,211 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
|
||||
/* static */ inline void
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value)
|
||||
{
|
||||
Type type = GetValueType(value);
|
||||
SetArgument(cx, script, arg, type);
|
||||
SetArgument(cx, script, arg, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeHashSet
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Hashing code shared by objects in TypeSets and properties in ObjectGroups.
|
||||
struct TypeHashSet
|
||||
{
|
||||
// The sets of objects in a type set grow monotonically, are usually empty,
|
||||
// almost always small, and sometimes big. For empty or singleton sets, the
|
||||
// the pointer refers directly to the value. For sets fitting into
|
||||
// SET_ARRAY_SIZE, an array of this length is used to store the elements.
|
||||
// For larger sets, a hash table filled to 25%-50% of capacity is used,
|
||||
// with collisions resolved by linear probing.
|
||||
static const unsigned SET_ARRAY_SIZE = 8;
|
||||
static const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;
|
||||
|
||||
// Get the capacity of a set with the given element count.
|
||||
static inline unsigned
|
||||
Capacity(unsigned count)
|
||||
{
|
||||
MOZ_ASSERT(count >= 2);
|
||||
MOZ_ASSERT(count < SET_CAPACITY_OVERFLOW);
|
||||
|
||||
if (count <= SET_ARRAY_SIZE)
|
||||
return SET_ARRAY_SIZE;
|
||||
|
||||
return 1u << (mozilla::FloorLog2(count) + 2);
|
||||
}
|
||||
|
||||
// Compute the FNV hash for the low 32 bits of v.
|
||||
template <class T, class KEY>
|
||||
static inline uint32_t
|
||||
HashKey(T v)
|
||||
{
|
||||
uint32_t nv = KEY::keyBits(v);
|
||||
|
||||
uint32_t hash = 84696351 ^ (nv & 0xff);
|
||||
hash = (hash * 16777619) ^ ((nv >> 8) & 0xff);
|
||||
hash = (hash * 16777619) ^ ((nv >> 16) & 0xff);
|
||||
return (hash * 16777619) ^ ((nv >> 24) & 0xff);
|
||||
}
|
||||
|
||||
// Insert space for an element into the specified set and grow its capacity
|
||||
// if needed. returned value is an existing or new entry (nullptr if new).
|
||||
template <class T, class U, class KEY>
|
||||
static U **
|
||||
InsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
unsigned capacity = Capacity(count);
|
||||
unsigned insertpos = HashKey<T,KEY>(key) & (capacity - 1);
|
||||
|
||||
// Whether we are converting from a fixed array to hashtable.
|
||||
bool converting = (count == SET_ARRAY_SIZE);
|
||||
|
||||
if (!converting) {
|
||||
while (values[insertpos] != nullptr) {
|
||||
if (KEY::getKey(values[insertpos]) == key)
|
||||
return &values[insertpos];
|
||||
insertpos = (insertpos + 1) & (capacity - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= SET_CAPACITY_OVERFLOW)
|
||||
return nullptr;
|
||||
|
||||
count++;
|
||||
unsigned newCapacity = Capacity(count);
|
||||
|
||||
if (newCapacity == capacity) {
|
||||
MOZ_ASSERT(!converting);
|
||||
return &values[insertpos];
|
||||
}
|
||||
|
||||
U **newValues = alloc.newArray<U*>(newCapacity);
|
||||
if (!newValues)
|
||||
return nullptr;
|
||||
mozilla::PodZero(newValues, newCapacity);
|
||||
|
||||
for (unsigned i = 0; i < capacity; i++) {
|
||||
if (values[i]) {
|
||||
unsigned pos = HashKey<T,KEY>(KEY::getKey(values[i])) & (newCapacity - 1);
|
||||
while (newValues[pos] != nullptr)
|
||||
pos = (pos + 1) & (newCapacity - 1);
|
||||
newValues[pos] = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
values = newValues;
|
||||
|
||||
insertpos = HashKey<T,KEY>(key) & (newCapacity - 1);
|
||||
while (values[insertpos] != nullptr)
|
||||
insertpos = (insertpos + 1) & (newCapacity - 1);
|
||||
return &values[insertpos];
|
||||
}
|
||||
|
||||
// Insert an element into the specified set if it is not already there,
|
||||
// returning an entry which is nullptr if the element was not there.
|
||||
template <class T, class U, class KEY>
|
||||
static inline U **
|
||||
Insert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
if (count == 0) {
|
||||
MOZ_ASSERT(values == nullptr);
|
||||
count++;
|
||||
return (U **) &values;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
U *oldData = (U*) values;
|
||||
if (KEY::getKey(oldData) == key)
|
||||
return (U **) &values;
|
||||
|
||||
values = alloc.newArray<U*>(SET_ARRAY_SIZE);
|
||||
if (!values) {
|
||||
values = (U **) oldData;
|
||||
return nullptr;
|
||||
}
|
||||
mozilla::PodZero(values, SET_ARRAY_SIZE);
|
||||
count++;
|
||||
|
||||
values[0] = oldData;
|
||||
return &values[1];
|
||||
}
|
||||
|
||||
if (count <= SET_ARRAY_SIZE) {
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (KEY::getKey(values[i]) == key)
|
||||
return &values[i];
|
||||
}
|
||||
|
||||
if (count < SET_ARRAY_SIZE) {
|
||||
count++;
|
||||
return &values[count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return InsertTry<T,U,KEY>(alloc, values, count, key);
|
||||
}
|
||||
|
||||
// Lookup an entry in a hash set, return nullptr if it does not exist.
|
||||
template <class T, class U, class KEY>
|
||||
static inline U *
|
||||
Lookup(U **values, unsigned count, T key)
|
||||
{
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
|
||||
if (count == 1)
|
||||
return (KEY::getKey((U *) values) == key) ? (U *) values : nullptr;
|
||||
|
||||
if (count <= SET_ARRAY_SIZE) {
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (KEY::getKey(values[i]) == key)
|
||||
return values[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned capacity = Capacity(count);
|
||||
unsigned pos = HashKey<T,KEY>(key) & (capacity - 1);
|
||||
|
||||
while (values[pos] != nullptr) {
|
||||
if (KEY::getKey(values[pos]) == key)
|
||||
return values[pos];
|
||||
pos = (pos + 1) & (capacity - 1);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeSet
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* The sets of objects and scripts in a type set grow monotonically, are usually
|
||||
* empty, almost always small, and sometimes big. For empty or singleton sets,
|
||||
* the pointer refers directly to the value. For sets fitting into SET_ARRAY_SIZE,
|
||||
* an array of this length is used to store the elements. For larger sets, a hash
|
||||
* table filled to 25%-50% of capacity is used, with collisions resolved by linear
|
||||
* probing. TODO: replace these with jshashtables.
|
||||
*/
|
||||
const unsigned SET_ARRAY_SIZE = 8;
|
||||
const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;
|
||||
|
||||
/* Get the capacity of a set with the given element count. */
|
||||
static inline unsigned
|
||||
HashSetCapacity(unsigned count)
|
||||
{
|
||||
MOZ_ASSERT(count >= 2);
|
||||
MOZ_ASSERT(count < SET_CAPACITY_OVERFLOW);
|
||||
|
||||
if (count <= SET_ARRAY_SIZE)
|
||||
return SET_ARRAY_SIZE;
|
||||
|
||||
return 1u << (mozilla::FloorLog2(count) + 2);
|
||||
}
|
||||
|
||||
/* Compute the FNV hash for the low 32 bits of v. */
|
||||
template <class T, class KEY>
|
||||
static inline uint32_t
|
||||
HashKey(T v)
|
||||
{
|
||||
uint32_t nv = KEY::keyBits(v);
|
||||
|
||||
uint32_t hash = 84696351 ^ (nv & 0xff);
|
||||
hash = (hash * 16777619) ^ ((nv >> 8) & 0xff);
|
||||
hash = (hash * 16777619) ^ ((nv >> 16) & 0xff);
|
||||
return (hash * 16777619) ^ ((nv >> 24) & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert space for an element into the specified set and grow its capacity if needed.
|
||||
* returned value is an existing or new entry (nullptr if new).
|
||||
*/
|
||||
template <class T, class U, class KEY>
|
||||
static U **
|
||||
HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
unsigned capacity = HashSetCapacity(count);
|
||||
unsigned insertpos = HashKey<T,KEY>(key) & (capacity - 1);
|
||||
|
||||
/* Whether we are converting from a fixed array to hashtable. */
|
||||
bool converting = (count == SET_ARRAY_SIZE);
|
||||
|
||||
if (!converting) {
|
||||
while (values[insertpos] != nullptr) {
|
||||
if (KEY::getKey(values[insertpos]) == key)
|
||||
return &values[insertpos];
|
||||
insertpos = (insertpos + 1) & (capacity - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= SET_CAPACITY_OVERFLOW)
|
||||
return nullptr;
|
||||
|
||||
count++;
|
||||
unsigned newCapacity = HashSetCapacity(count);
|
||||
|
||||
if (newCapacity == capacity) {
|
||||
MOZ_ASSERT(!converting);
|
||||
return &values[insertpos];
|
||||
}
|
||||
|
||||
U **newValues = alloc.newArray<U*>(newCapacity);
|
||||
if (!newValues)
|
||||
return nullptr;
|
||||
mozilla::PodZero(newValues, newCapacity);
|
||||
|
||||
for (unsigned i = 0; i < capacity; i++) {
|
||||
if (values[i]) {
|
||||
unsigned pos = HashKey<T,KEY>(KEY::getKey(values[i])) & (newCapacity - 1);
|
||||
while (newValues[pos] != nullptr)
|
||||
pos = (pos + 1) & (newCapacity - 1);
|
||||
newValues[pos] = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
values = newValues;
|
||||
|
||||
insertpos = HashKey<T,KEY>(key) & (newCapacity - 1);
|
||||
while (values[insertpos] != nullptr)
|
||||
insertpos = (insertpos + 1) & (newCapacity - 1);
|
||||
return &values[insertpos];
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert an element into the specified set if it is not already there, returning
|
||||
* an entry which is nullptr if the element was not there.
|
||||
*/
|
||||
template <class T, class U, class KEY>
|
||||
static inline U **
|
||||
HashSetInsert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
if (count == 0) {
|
||||
MOZ_ASSERT(values == nullptr);
|
||||
count++;
|
||||
return (U **) &values;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
U *oldData = (U*) values;
|
||||
if (KEY::getKey(oldData) == key)
|
||||
return (U **) &values;
|
||||
|
||||
values = alloc.newArray<U*>(SET_ARRAY_SIZE);
|
||||
if (!values) {
|
||||
values = (U **) oldData;
|
||||
return nullptr;
|
||||
}
|
||||
mozilla::PodZero(values, SET_ARRAY_SIZE);
|
||||
count++;
|
||||
|
||||
values[0] = oldData;
|
||||
return &values[1];
|
||||
}
|
||||
|
||||
if (count <= SET_ARRAY_SIZE) {
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (KEY::getKey(values[i]) == key)
|
||||
return &values[i];
|
||||
}
|
||||
|
||||
if (count < SET_ARRAY_SIZE) {
|
||||
count++;
|
||||
return &values[count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return HashSetInsertTry<T,U,KEY>(alloc, values, count, key);
|
||||
}
|
||||
|
||||
/* Lookup an entry in a hash set, return nullptr if it does not exist. */
|
||||
template <class T, class U, class KEY>
|
||||
static inline U *
|
||||
HashSetLookup(U **values, unsigned count, T key)
|
||||
{
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
|
||||
if (count == 1)
|
||||
return (KEY::getKey((U *) values) == key) ? (U *) values : nullptr;
|
||||
|
||||
if (count <= SET_ARRAY_SIZE) {
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (KEY::getKey(values[i]) == key)
|
||||
return values[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned capacity = HashSetCapacity(count);
|
||||
unsigned pos = HashKey<T,KEY>(key) & (capacity - 1);
|
||||
|
||||
while (values[pos] != nullptr) {
|
||||
if (KEY::getKey(values[pos]) == key)
|
||||
return values[pos];
|
||||
pos = (pos + 1) & (capacity - 1);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline TypeSetObjectKey *
|
||||
Type::objectKey() const
|
||||
inline TypeSet::ObjectKey *
|
||||
TypeSet::Type::objectKey() const
|
||||
{
|
||||
MOZ_ASSERT(isObject());
|
||||
return (TypeSetObjectKey *) data;
|
||||
return (ObjectKey *) data;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
Type::singleton() const
|
||||
TypeSet::Type::singleton() const
|
||||
{
|
||||
return objectKey()->singleton();
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
Type::group() const
|
||||
TypeSet::Type::group() const
|
||||
{
|
||||
return objectKey()->group();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
Type::singletonNoBarrier() const
|
||||
TypeSet::Type::singletonNoBarrier() const
|
||||
{
|
||||
return objectKey()->singletonNoBarrier();
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
Type::groupNoBarrier() const
|
||||
TypeSet::Type::groupNoBarrier() const
|
||||
{
|
||||
return objectKey()->groupNoBarrier();
|
||||
}
|
||||
@ -884,8 +882,8 @@ TypeSet::hasType(Type type) const
|
||||
return !!(flags & TYPE_FLAG_ANYOBJECT);
|
||||
} else {
|
||||
return !!(flags & TYPE_FLAG_ANYOBJECT) ||
|
||||
HashSetLookup<TypeSetObjectKey*,TypeSetObjectKey,TypeSetObjectKey>
|
||||
(objectSet, baseObjectCount(), type.objectKey()) != nullptr;
|
||||
TypeHashSet::Lookup<ObjectKey*, ObjectKey, ObjectKey>
|
||||
(objectSet, baseObjectCount(), type.objectKey()) != nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -947,18 +945,18 @@ TypeSet::getObjectCount() const
|
||||
{
|
||||
MOZ_ASSERT(!unknownObject());
|
||||
uint32_t count = baseObjectCount();
|
||||
if (count > SET_ARRAY_SIZE)
|
||||
return HashSetCapacity(count);
|
||||
if (count > TypeHashSet::SET_ARRAY_SIZE)
|
||||
return TypeHashSet::Capacity(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
inline TypeSetObjectKey *
|
||||
inline TypeSet::ObjectKey *
|
||||
TypeSet::getObject(unsigned i) const
|
||||
{
|
||||
MOZ_ASSERT(i < getObjectCount());
|
||||
if (baseObjectCount() == 1) {
|
||||
MOZ_ASSERT(i == 0);
|
||||
return (TypeSetObjectKey *) objectSet;
|
||||
return (ObjectKey *) objectSet;
|
||||
}
|
||||
return objectSet[i];
|
||||
}
|
||||
@ -966,28 +964,28 @@ TypeSet::getObject(unsigned i) const
|
||||
inline JSObject *
|
||||
TypeSet::getSingleton(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isSingleton()) ? key->singleton() : nullptr;
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSet::getGroup(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isGroup()) ? key->group() : nullptr;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeSet::getSingletonNoBarrier(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isSingleton()) ? key->singletonNoBarrier() : nullptr;
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSet::getGroupNoBarrier(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isGroup()) ? key->groupNoBarrier() : nullptr;
|
||||
}
|
||||
|
||||
@ -1016,8 +1014,6 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
|
||||
newScript->trace(zone->barrierTracer());
|
||||
}
|
||||
|
||||
} // namespace types
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// ObjectGroup
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -1037,25 +1033,25 @@ ObjectGroup::setBasePropertyCount(uint32_t count)
|
||||
| (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
|
||||
}
|
||||
|
||||
inline types::HeapTypeSet *
|
||||
inline HeapTypeSet *
|
||||
ObjectGroup::getProperty(ExclusiveContext *cx, jsid id)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == types::IdToTypeId(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
if (types::HeapTypeSet *types = maybeGetProperty(id))
|
||||
if (HeapTypeSet *types = maybeGetProperty(id))
|
||||
return types;
|
||||
|
||||
types::Property *base = cx->typeLifoAlloc().new_<types::Property>(id);
|
||||
Property *base = cx->typeLifoAlloc().new_<Property>(id);
|
||||
if (!base) {
|
||||
markUnknown(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t propertyCount = basePropertyCount();
|
||||
types::Property **pprop = types::HashSetInsert<jsid,types::Property,types::Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
Property **pprop = TypeHashSet::Insert<jsid, Property, Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
markUnknown(cx);
|
||||
return nullptr;
|
||||
@ -1078,15 +1074,15 @@ ObjectGroup::getProperty(ExclusiveContext *cx, jsid id)
|
||||
return &base->types;
|
||||
}
|
||||
|
||||
inline types::HeapTypeSet *
|
||||
inline HeapTypeSet *
|
||||
ObjectGroup::maybeGetProperty(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == types::IdToTypeId(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
types::Property *prop = types::HashSetLookup<jsid,types::Property,types::Property>
|
||||
(propertySet, basePropertyCount(), id);
|
||||
Property *prop = TypeHashSet::Lookup<jsid, Property, Property>
|
||||
(propertySet, basePropertyCount(), id);
|
||||
|
||||
return prop ? &prop->types : nullptr;
|
||||
}
|
||||
@ -1095,37 +1091,37 @@ inline unsigned
|
||||
ObjectGroup::getPropertyCount()
|
||||
{
|
||||
uint32_t count = basePropertyCount();
|
||||
if (count > types::SET_ARRAY_SIZE)
|
||||
return types::HashSetCapacity(count);
|
||||
if (count > TypeHashSet::SET_ARRAY_SIZE)
|
||||
return TypeHashSet::Capacity(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
inline types::Property *
|
||||
inline ObjectGroup::Property *
|
||||
ObjectGroup::getProperty(unsigned i)
|
||||
{
|
||||
MOZ_ASSERT(i < getPropertyCount());
|
||||
if (basePropertyCount() == 1) {
|
||||
MOZ_ASSERT(i == 0);
|
||||
return (types::Property *) propertySet;
|
||||
return (Property *) propertySet;
|
||||
}
|
||||
return propertySet[i];
|
||||
}
|
||||
|
||||
template <>
|
||||
struct GCMethods<const types::Type>
|
||||
struct GCMethods<const TypeSet::Type>
|
||||
{
|
||||
static types::Type initial() { return types::Type::UnknownType(); }
|
||||
static bool poisoned(const types::Type &v) {
|
||||
static TypeSet::Type initial() { return TypeSet::UnknownType(); }
|
||||
static bool poisoned(TypeSet::Type v) {
|
||||
return (v.isGroup() && IsPoisonedPtr(v.group()))
|
||||
|| (v.isSingleton() && IsPoisonedPtr(v.singleton()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GCMethods<types::Type>
|
||||
struct GCMethods<TypeSet::Type>
|
||||
{
|
||||
static types::Type initial() { return types::Type::UnknownType(); }
|
||||
static bool poisoned(const types::Type &v) {
|
||||
static TypeSet::Type initial() { return TypeSet::UnknownType(); }
|
||||
static bool poisoned(TypeSet::Type v) {
|
||||
return (v.isGroup() && IsPoisonedPtr(v.group()))
|
||||
|| (v.isSingleton() && IsPoisonedPtr(v.singleton()));
|
||||
}
|
||||
@ -1133,7 +1129,7 @@ struct GCMethods<types::Type>
|
||||
|
||||
} // namespace js
|
||||
|
||||
inline js::types::TypeScript *
|
||||
inline js::TypeScript *
|
||||
JSScript::types()
|
||||
{
|
||||
maybeSweepTypes(nullptr);
|
||||
|
@ -580,7 +580,7 @@ VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVecto
|
||||
|
||||
if (obj->isSingleton() && !obj->setIteratedSingleton(cx))
|
||||
return false;
|
||||
types::MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
|
||||
Rooted<PropertyIteratorObject *> iterobj(cx, NewPropertyIteratorObject(cx, flags));
|
||||
if (!iterobj)
|
||||
@ -623,7 +623,7 @@ VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVec
|
||||
|
||||
if (obj->isSingleton() && !obj->setIteratedSingleton(cx))
|
||||
return false;
|
||||
types::MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
|
||||
Rooted<PropertyIteratorObject*> iterobj(cx, NewPropertyIteratorObject(cx, flags));
|
||||
if (!iterobj)
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "vm/String-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::Abs;
|
||||
using mozilla::ArrayLength;
|
||||
|
@ -67,7 +67,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::Maybe;
|
||||
@ -1605,7 +1604,7 @@ CreateThisForFunctionWithGroup(JSContext *cx, HandleObjectGroup group, JSObject
|
||||
if (group->maybeUnboxedLayout() && newKind != SingletonObject)
|
||||
return UnboxedPlainObject::create(cx, group, newKind);
|
||||
|
||||
if (types::TypeNewScript *newScript = group->newScript()) {
|
||||
if (TypeNewScript *newScript = group->newScript()) {
|
||||
if (newScript->analyzed()) {
|
||||
// The definite properties analysis has been performed for this
|
||||
// group, so get the shape and finalize kind to use from the
|
||||
@ -1685,7 +1684,7 @@ js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject
|
||||
JSScript *script = callee->as<JSFunction>().getOrCreateScript(cx);
|
||||
if (!script)
|
||||
return nullptr;
|
||||
TypeScript::SetThis(cx, script, types::Type::ObjectType(res));
|
||||
TypeScript::SetThis(cx, script, TypeSet::ObjectType(res));
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -1711,7 +1710,7 @@ js::CreateThisForFunction(JSContext *cx, HandleObject callee, NewObjectKind newK
|
||||
NativeObject::clear(cx, nobj);
|
||||
|
||||
JSScript *calleeScript = callee->as<JSFunction>().nonLazyScript();
|
||||
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj));
|
||||
TypeScript::SetThis(cx, calleeScript, TypeSet::ObjectType(nobj));
|
||||
|
||||
return nobj;
|
||||
}
|
||||
@ -3335,7 +3334,7 @@ js::WatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id, JS::Hand
|
||||
if (!NativeObject::sparsifyDenseElements(cx, obj.as<NativeObject>()))
|
||||
return false;
|
||||
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
}
|
||||
|
||||
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
|
||||
|
@ -177,7 +177,7 @@ js::GetElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t in
|
||||
inline bool
|
||||
js::DeleteProperty(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
|
||||
{
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
if (DeletePropertyOp op = obj->getOps()->deleteProperty)
|
||||
return op(cx, obj, id, succeeded);
|
||||
return NativeDeleteProperty(cx, obj.as<NativeObject>(), id, succeeded);
|
||||
@ -198,7 +198,7 @@ js::DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeed
|
||||
inline bool
|
||||
js::SetPropertyAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
|
||||
{
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
SetAttributesOp op = obj->getOps()->setAttributes;
|
||||
if (op)
|
||||
return op(cx, obj, id, attrsp);
|
||||
@ -758,7 +758,7 @@ NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
|
||||
{
|
||||
// Use AutoEnterAnalysis to prohibit both any GC activity under the
|
||||
// callback, and any reentering of JS via Invoke() etc.
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!cx->compartment()->callObjectMetadataCallback(cx, pmetadata))
|
||||
return false;
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::IsFinite;
|
||||
using mozilla::Maybe;
|
||||
|
@ -823,7 +823,7 @@ class JSScript : public js::gc::TenuredCell
|
||||
|
||||
private:
|
||||
/* Persistent type information retained across GCs. */
|
||||
js::types::TypeScript *types_;
|
||||
js::TypeScript *types_;
|
||||
|
||||
// This script's ScriptSourceObject, or a CCW thereof.
|
||||
//
|
||||
@ -1455,9 +1455,9 @@ class JSScript : public js::gc::TenuredCell
|
||||
/* Ensure the script has a TypeScript. */
|
||||
inline bool ensureHasTypes(JSContext *cx);
|
||||
|
||||
inline js::types::TypeScript *types();
|
||||
inline js::TypeScript *types();
|
||||
|
||||
void maybeSweepTypes(js::types::AutoClearTypeInferenceStateOnOOM *oom);
|
||||
void maybeSweepTypes(js::AutoClearTypeInferenceStateOnOOM *oom);
|
||||
|
||||
inline js::GlobalObject &global() const;
|
||||
js::GlobalObject &uninlinedGlobal() const;
|
||||
|
@ -52,7 +52,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
using namespace js::unicode;
|
||||
|
||||
using JS::Symbol;
|
||||
@ -3788,7 +3787,7 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
|
||||
RootedObjectGroup group(cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array));
|
||||
if (!group)
|
||||
return false;
|
||||
AddTypePropertyId(cx, group, JSID_VOID, Type::StringType());
|
||||
AddTypePropertyId(cx, group, JSID_VOID, TypeSet::StringType());
|
||||
|
||||
/* Step 5: Use the second argument as the split limit, if given. */
|
||||
uint32_t limit;
|
||||
|
@ -340,7 +340,7 @@ ArgSetter(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHand
|
||||
if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
|
||||
argsobj->setElement(cx, arg, vp);
|
||||
if (arg < script->functionNonDelazifying()->nargs())
|
||||
types::TypeScript::SetArgument(cx, script, arg, vp);
|
||||
TypeScript::SetArgument(cx, script, arg, vp);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -58,7 +58,6 @@ using mozilla::UniquePtr;
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
/*
|
||||
* Convert |v| to an array index for an array of length |length| per
|
||||
@ -523,7 +522,7 @@ ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer,
|
||||
// flag change will be observed.
|
||||
if (!cx->global()->getGroup(cx))
|
||||
CrashAtUnhandlableOOM("ArrayBufferObject::neuter");
|
||||
types::MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_NEUTERED);
|
||||
MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_NEUTERED);
|
||||
cx->compartment()->neuteredTypedObjects = 1;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ ArrayObject::setLength(ExclusiveContext *cx, uint32_t length)
|
||||
|
||||
if (length > INT32_MAX) {
|
||||
/* Track objects with overflowing lengths in type information. */
|
||||
types::MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
|
||||
MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
|
||||
}
|
||||
|
||||
getElementsHeader()->length = length;
|
||||
|
@ -1910,7 +1910,7 @@ UpdateExecutionObservabilityOfScriptsInZone(JSContext *cx, Zone *zone,
|
||||
// Iterate through observable scripts, invalidating their Ion scripts and
|
||||
// appending them to a vector for discarding their baseline scripts later.
|
||||
{
|
||||
types::AutoEnterAnalysis enter(fop, zone);
|
||||
AutoEnterAnalysis enter(fop, zone);
|
||||
if (JSScript *script = obs.singleScriptForZoneInvalidation()) {
|
||||
if (obs.shouldRecompileOrInvalidate(script)) {
|
||||
if (!AppendAndInvalidateScript(cx, zone, script, scripts))
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
JSObject *
|
||||
GeneratorObject::create(JSContext *cx, AbstractFramePtr frame)
|
||||
|
@ -199,7 +199,7 @@ GlobalObject::resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JS
|
||||
if (clasp->spec.shouldDefineConstructor()) {
|
||||
// Stash type information, so that what we do here is equivalent to
|
||||
// initBuiltinConstructor.
|
||||
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -224,7 +224,7 @@ GlobalObject::initBuiltinConstructor(JSContext *cx, Handle<GlobalObject*> global
|
||||
global->setPrototype(key, ObjectValue(*proto));
|
||||
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
|
||||
|
||||
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::NumberEqualsInt32;
|
||||
@ -1322,7 +1321,7 @@ static MOZ_ALWAYS_INLINE bool
|
||||
SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, const Value &value,
|
||||
bool strict, JSScript *script = nullptr, jsbytecode *pc = nullptr)
|
||||
{
|
||||
types::TypeScript::MonitorAssign(cx, obj, id);
|
||||
TypeScript::MonitorAssign(cx, obj, id);
|
||||
|
||||
if (obj->isNative() && JSID_IS_INT(id)) {
|
||||
uint32_t length = obj->as<NativeObject>().getDenseInitializedLength();
|
||||
@ -3963,8 +3962,7 @@ js::RunOnceScriptPrologue(JSContext *cx, HandleScript script)
|
||||
if (!script->functionNonDelazifying()->getGroup(cx))
|
||||
return false;
|
||||
|
||||
types::MarkObjectGroupFlags(cx, script->functionNonDelazifying(),
|
||||
OBJECT_FLAG_RUNONCE_INVALIDATED);
|
||||
MarkObjectGroupFlags(cx, script->functionNonDelazifying(), OBJECT_FLAG_RUNONCE_INVALIDATED);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -81,9 +81,9 @@ NativeObject::setDenseElementWithType(ExclusiveContext *cx, uint32_t index,
|
||||
{
|
||||
// Avoid a slow AddTypePropertyId call if the type is the same as the type
|
||||
// of the previous element.
|
||||
types::Type thisType = types::GetValueType(val);
|
||||
if (index == 0 || types::GetValueType(elements_[index - 1]) != thisType)
|
||||
types::AddTypePropertyId(cx, this, JSID_VOID, thisType);
|
||||
TypeSet::Type thisType = TypeSet::GetValueType(val);
|
||||
if (index == 0 || TypeSet::GetValueType(elements_[index - 1]) != thisType)
|
||||
AddTypePropertyId(cx, this, JSID_VOID, thisType);
|
||||
setDenseElementMaybeConvertDouble(index, val);
|
||||
}
|
||||
|
||||
@ -92,14 +92,14 @@ NativeObject::initDenseElementWithType(ExclusiveContext *cx, uint32_t index,
|
||||
const Value &val)
|
||||
{
|
||||
MOZ_ASSERT(!shouldConvertDoubleElements());
|
||||
types::AddTypePropertyId(cx, this, JSID_VOID, val);
|
||||
AddTypePropertyId(cx, this, JSID_VOID, val);
|
||||
initDenseElement(index, val);
|
||||
}
|
||||
|
||||
inline void
|
||||
NativeObject::setDenseElementHole(ExclusiveContext *cx, uint32_t index)
|
||||
{
|
||||
types::MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
setDenseElement(index, MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
|
||||
@ -107,9 +107,7 @@ NativeObject::setDenseElementHole(ExclusiveContext *cx, uint32_t index)
|
||||
NativeObject::removeDenseElementForSparseIndex(ExclusiveContext *cx,
|
||||
HandleNativeObject obj, uint32_t index)
|
||||
{
|
||||
types::MarkObjectGroupFlags(cx, obj,
|
||||
OBJECT_FLAG_NON_PACKED |
|
||||
OBJECT_FLAG_SPARSE_INDEXES);
|
||||
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_NON_PACKED | OBJECT_FLAG_SPARSE_INDEXES);
|
||||
if (obj->containsDenseElement(index))
|
||||
obj->setDenseElement(index, MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
@ -124,7 +122,7 @@ inline void
|
||||
NativeObject::markDenseElementsNotPacked(ExclusiveContext *cx)
|
||||
{
|
||||
MOZ_ASSERT(isNative());
|
||||
types::MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -320,7 +318,7 @@ NativeObject::setSlotWithType(ExclusiveContext *cx, Shape *shape,
|
||||
if (overwriting)
|
||||
shape->setOverwritten();
|
||||
|
||||
types::AddTypePropertyId(cx, this, shape->propid(), value);
|
||||
AddTypePropertyId(cx, this, shape->propid(), value);
|
||||
}
|
||||
|
||||
/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
|
||||
|
@ -1118,15 +1118,15 @@ UpdateShapeTypeAndValue(ExclusiveContext *cx, NativeObject *obj, Shape *shape, c
|
||||
// Per the acquired properties analysis, when the shape of a partially
|
||||
// initialized object is changed to its fully initialized shape, its
|
||||
// group can be updated as well.
|
||||
if (types::TypeNewScript *newScript = obj->groupRaw()->newScript()) {
|
||||
if (TypeNewScript *newScript = obj->groupRaw()->newScript()) {
|
||||
if (newScript->initializedShape() == shape)
|
||||
obj->setGroup(newScript->initializedGroup());
|
||||
}
|
||||
}
|
||||
if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter())
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
if (!shape->writable())
|
||||
types::MarkTypePropertyNonWritable(cx, obj, id);
|
||||
MarkTypePropertyNonWritable(cx, obj, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1596,7 +1596,7 @@ GetExistingProperty(JSContext *cx,
|
||||
!obj->isSingleton() &&
|
||||
!obj->template is<ScopeObject>() &&
|
||||
shape->hasDefaultGetter(),
|
||||
js::types::TypeHasProperty(cx, obj->group(), shape->propid(), vp));
|
||||
ObjectGroupHasProperty(cx, obj->group(), shape->propid(), vp));
|
||||
} else {
|
||||
vp.setUndefined();
|
||||
}
|
||||
@ -2294,7 +2294,7 @@ js::NativeSetPropertyAttributes(JSContext *cx, HandleNativeObject obj, HandleId
|
||||
if (!NativeObject::changePropertyAttributes(cx, nobj.as<NativeObject>(), shape, *attrsp))
|
||||
return false;
|
||||
if (*attrsp & JSPROP_READONLY)
|
||||
types::MarkTypePropertyNonWritable(cx, nobj, id);
|
||||
MarkTypePropertyNonWritable(cx, nobj, id);
|
||||
return true;
|
||||
} else {
|
||||
return SetPropertyAttributes(cx, nobj, id, attrsp);
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::PodZero;
|
||||
|
||||
@ -549,22 +548,22 @@ ObjectGroup::defaultNewGroup(ExclusiveContext *cx, const Class *clasp,
|
||||
const JSAtomState &names = cx->names();
|
||||
|
||||
if (obj->is<RegExpObject>()) {
|
||||
AddTypePropertyId(cx, group, NameToId(names.source), Type::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.global), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.ignoreCase), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.multiline), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.sticky), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lastIndex), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.source), TypeSet::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.global), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.ignoreCase), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.multiline), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.sticky), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lastIndex), TypeSet::Int32Type());
|
||||
}
|
||||
|
||||
if (obj->is<StringObject>())
|
||||
AddTypePropertyId(cx, group, NameToId(names.length), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.length), TypeSet::Int32Type());
|
||||
|
||||
if (obj->is<ErrorObject>()) {
|
||||
AddTypePropertyId(cx, group, NameToId(names.fileName), Type::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lineNumber), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.columnNumber), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.stack), Type::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.fileName), TypeSet::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lineNumber), TypeSet::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.columnNumber), TypeSet::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.stack), TypeSet::StringType());
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,14 +714,14 @@ ObjectGroup::defaultNewGroup(JSContext *cx, JSProtoKey key)
|
||||
|
||||
struct ObjectGroupCompartment::ArrayObjectKey : public DefaultHasher<ArrayObjectKey>
|
||||
{
|
||||
Type type;
|
||||
TypeSet::Type type;
|
||||
JSObject *proto;
|
||||
|
||||
ArrayObjectKey()
|
||||
: type(Type::UndefinedType()), proto(nullptr)
|
||||
: type(TypeSet::UndefinedType()), proto(nullptr)
|
||||
{}
|
||||
|
||||
ArrayObjectKey(Type type, JSObject *proto)
|
||||
ArrayObjectKey(TypeSet::Type type, JSObject *proto)
|
||||
: type(type), proto(proto)
|
||||
{}
|
||||
|
||||
@ -744,7 +743,7 @@ struct ObjectGroupCompartment::ArrayObjectKey : public DefaultHasher<ArrayObject
|
||||
};
|
||||
|
||||
static inline bool
|
||||
NumberTypes(Type a, Type b)
|
||||
NumberTypes(TypeSet::Type a, TypeSet::Type b)
|
||||
{
|
||||
return (a.isPrimitive(JSVAL_TYPE_INT32) || a.isPrimitive(JSVAL_TYPE_DOUBLE))
|
||||
&& (b.isPrimitive(JSVAL_TYPE_INT32) || b.isPrimitive(JSVAL_TYPE_DOUBLE));
|
||||
@ -755,10 +754,10 @@ NumberTypes(Type a, Type b)
|
||||
* their default prototype. These are the only values that should appear in
|
||||
* arrays and objects whose type can be fixed.
|
||||
*/
|
||||
static inline Type
|
||||
static inline TypeSet::Type
|
||||
GetValueTypeForTable(const Value &v)
|
||||
{
|
||||
Type type = GetValueType(v);
|
||||
TypeSet::Type type = TypeSet::GetValueType(v);
|
||||
MOZ_ASSERT(!type.isSingleton());
|
||||
return type;
|
||||
}
|
||||
@ -779,13 +778,13 @@ ObjectGroup::fixArrayGroup(ExclusiveContext *cx, ArrayObject *obj)
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
Type type = GetValueTypeForTable(obj->getDenseElement(0));
|
||||
TypeSet::Type type = GetValueTypeForTable(obj->getDenseElement(0));
|
||||
|
||||
for (unsigned i = 1; i < len; i++) {
|
||||
Type ntype = GetValueTypeForTable(obj->getDenseElement(i));
|
||||
TypeSet::Type ntype = GetValueTypeForTable(obj->getDenseElement(i));
|
||||
if (ntype != type) {
|
||||
if (NumberTypes(type, ntype))
|
||||
type = Type::DoubleType();
|
||||
type = TypeSet::DoubleType();
|
||||
else
|
||||
return;
|
||||
}
|
||||
@ -801,11 +800,12 @@ ObjectGroup::fixRestArgumentsGroup(ExclusiveContext *cx, ArrayObject *obj)
|
||||
|
||||
// Tracking element types for rest argument arrays is not worth it, but we
|
||||
// still want it to be known that it's a dense array.
|
||||
setGroupToHomogenousArray(cx, obj, Type::UnknownType());
|
||||
setGroupToHomogenousArray(cx, obj, TypeSet::UnknownType());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ObjectGroup::setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj, Type elementType)
|
||||
ObjectGroup::setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj,
|
||||
TypeSet::Type elementType)
|
||||
{
|
||||
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
|
||||
|
||||
@ -888,7 +888,7 @@ struct ObjectGroupCompartment::PlainObjectEntry
|
||||
{
|
||||
ReadBarrieredObjectGroup group;
|
||||
ReadBarrieredShape shape;
|
||||
Type *types;
|
||||
TypeSet::Type *types;
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
@ -898,8 +898,8 @@ ObjectGroupCompartment::updatePlainObjectEntryTypes(ExclusiveContext *cx, PlainO
|
||||
if (entry.group->unknownProperties())
|
||||
return;
|
||||
for (size_t i = 0; i < nproperties; i++) {
|
||||
Type type = entry.types[i];
|
||||
Type ntype = GetValueTypeForTable(properties[i].value);
|
||||
TypeSet::Type type = entry.types[i];
|
||||
TypeSet::Type ntype = GetValueTypeForTable(properties[i].value);
|
||||
if (ntype == type)
|
||||
continue;
|
||||
if (ntype.isPrimitive(JSVAL_TYPE_INT32) &&
|
||||
@ -911,7 +911,7 @@ ObjectGroupCompartment::updatePlainObjectEntryTypes(ExclusiveContext *cx, PlainO
|
||||
type.isPrimitive(JSVAL_TYPE_INT32))
|
||||
{
|
||||
/* Include 'double' in the property types to avoid the update below later. */
|
||||
entry.types[i] = Type::DoubleType();
|
||||
entry.types[i] = TypeSet::DoubleType();
|
||||
}
|
||||
AddTypePropertyId(cx, entry.group, IdToTypeId(properties[i].id), ntype);
|
||||
}
|
||||
@ -986,7 +986,8 @@ ObjectGroup::fixPlainObjectGroup(ExclusiveContext *cx, PlainObject *obj)
|
||||
if (!ids)
|
||||
return;
|
||||
|
||||
ScopedJSFreePtr<Type> types(group->zone()->pod_calloc<Type>(properties.length()));
|
||||
ScopedJSFreePtr<TypeSet::Type> types(
|
||||
group->zone()->pod_calloc<TypeSet::Type>(properties.length()));
|
||||
if (!types)
|
||||
return;
|
||||
|
||||
@ -1240,16 +1241,12 @@ ObjectGroup::getCopyOnWriteObject(JSScript *script, jsbytecode *pc)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ObjectGroup::findAllocationSiteForType(JSContext *cx, Type type,
|
||||
JSScript **script, uint32_t *offset)
|
||||
ObjectGroup::findAllocationSite(JSContext *cx, ObjectGroup *group,
|
||||
JSScript **script, uint32_t *offset)
|
||||
{
|
||||
*script = nullptr;
|
||||
*offset = 0;
|
||||
|
||||
if (type.isUnknown() || type.isAnyObject() || !type.isGroup())
|
||||
return false;
|
||||
ObjectGroup *obj = type.group();
|
||||
|
||||
const ObjectGroupCompartment::AllocationSiteTable *table =
|
||||
cx->compartment()->objectGroups.allocationSiteTable;
|
||||
|
||||
@ -1260,7 +1257,7 @@ ObjectGroup::findAllocationSiteForType(JSContext *cx, Type type,
|
||||
!r.empty();
|
||||
r.popFront())
|
||||
{
|
||||
if (obj == r.front().value()) {
|
||||
if (group == r.front().value()) {
|
||||
*script = r.front().key().script;
|
||||
*offset = r.front().key().offset;
|
||||
return true;
|
||||
@ -1395,7 +1392,7 @@ ObjectGroupCompartment::sweep(FreeOp *fop)
|
||||
if (IsObjectGroupAboutToBeFinalizedFromAnyThread(&group))
|
||||
remove = true;
|
||||
else
|
||||
key.type = Type::ObjectType(group);
|
||||
key.type = TypeSet::ObjectType(group);
|
||||
}
|
||||
if (key.proto && key.proto != TaggedProto::LazyProto &&
|
||||
IsObjectAboutToBeFinalizedFromAnyThread(&key.proto))
|
||||
@ -1441,7 +1438,7 @@ ObjectGroupCompartment::sweep(FreeOp *fop)
|
||||
if (IsObjectGroupAboutToBeFinalizedFromAnyThread(&group))
|
||||
remove = true;
|
||||
else if (group != entry.types[i].groupNoBarrier())
|
||||
entry.types[i] = Type::ObjectType(group);
|
||||
entry.types[i] = TypeSet::ObjectType(group);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "jsbytecode.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsinfer.h"
|
||||
|
||||
#include "ds/IdValuePair.h"
|
||||
#include "gc/Barrier.h"
|
||||
@ -18,17 +19,11 @@ namespace js {
|
||||
class TypeDescr;
|
||||
class UnboxedLayout;
|
||||
|
||||
namespace types {
|
||||
|
||||
class Type;
|
||||
class TypeNewScript;
|
||||
class HeapTypeSet;
|
||||
struct Property;
|
||||
class AutoClearTypeInferenceStateOnOOM;
|
||||
class CompilerConstraintList;
|
||||
|
||||
} // namespace types
|
||||
|
||||
// Information about an object prototype, which can be either a particular
|
||||
// object, null, or a lazily generated object. The latter is only used by
|
||||
// certain kinds of proxies.
|
||||
@ -118,81 +113,6 @@ class RootedBase<TaggedProto> : public TaggedProtoOperations<Rooted<TaggedProto>
|
||||
}
|
||||
};
|
||||
|
||||
/* Flags and other state stored in ObjectGroupFlags */
|
||||
enum : uint32_t {
|
||||
/* Whether this group is associated with some allocation site. */
|
||||
OBJECT_FLAG_FROM_ALLOCATION_SITE = 0x1,
|
||||
|
||||
/* (0x2 and 0x4 are unused) */
|
||||
|
||||
/* Mask/shift for the number of properties in propertySet */
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK = 0xfff8,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_SHIFT = 3,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_LIMIT =
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT,
|
||||
|
||||
/* Whether any objects this represents may have sparse indexes. */
|
||||
OBJECT_FLAG_SPARSE_INDEXES = 0x00010000,
|
||||
|
||||
/* Whether any objects this represents may not have packed dense elements. */
|
||||
OBJECT_FLAG_NON_PACKED = 0x00020000,
|
||||
|
||||
/*
|
||||
* Whether any objects this represents may be arrays whose length does not
|
||||
* fit in an int32.
|
||||
*/
|
||||
OBJECT_FLAG_LENGTH_OVERFLOW = 0x00040000,
|
||||
|
||||
/* Whether any objects have been iterated over. */
|
||||
OBJECT_FLAG_ITERATED = 0x00080000,
|
||||
|
||||
/* For a global object, whether flags were set on the RegExpStatics. */
|
||||
OBJECT_FLAG_REGEXP_FLAGS_SET = 0x00100000,
|
||||
|
||||
/*
|
||||
* For the function on a run-once script, whether the function has actually
|
||||
* run multiple times.
|
||||
*/
|
||||
OBJECT_FLAG_RUNONCE_INVALIDATED = 0x00200000,
|
||||
|
||||
/*
|
||||
* For a global object, whether any array buffers in this compartment with
|
||||
* typed object views have been neutered.
|
||||
*/
|
||||
OBJECT_FLAG_TYPED_OBJECT_NEUTERED = 0x00400000,
|
||||
|
||||
/*
|
||||
* Whether objects with this type should be allocated directly in the
|
||||
* tenured heap.
|
||||
*/
|
||||
OBJECT_FLAG_PRE_TENURE = 0x00800000,
|
||||
|
||||
/* Whether objects with this type might have copy on write elements. */
|
||||
OBJECT_FLAG_COPY_ON_WRITE = 0x01000000,
|
||||
|
||||
/* Whether this type has had its 'new' script cleared in the past. */
|
||||
OBJECT_FLAG_NEW_SCRIPT_CLEARED = 0x02000000,
|
||||
|
||||
/*
|
||||
* Whether all properties of this object are considered unknown.
|
||||
* If set, all other flags in DYNAMIC_MASK will also be set.
|
||||
*/
|
||||
OBJECT_FLAG_UNKNOWN_PROPERTIES = 0x04000000,
|
||||
|
||||
/* Flags which indicate dynamic properties of represented objects. */
|
||||
OBJECT_FLAG_DYNAMIC_MASK = 0x07ff0000,
|
||||
|
||||
// Mask/shift for the kind of addendum attached to this group.
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x38000000,
|
||||
OBJECT_FLAG_ADDENDUM_SHIFT = 27,
|
||||
|
||||
// Mask/shift for this group's generation. If out of sync with the
|
||||
// TypeZone's generation, this group hasn't been swept yet.
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x40000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 30,
|
||||
};
|
||||
typedef uint32_t ObjectGroupFlags;
|
||||
|
||||
/*
|
||||
* Lazy object groups overview.
|
||||
*
|
||||
@ -301,9 +221,9 @@ class ObjectGroup : public gc::TenuredCell
|
||||
((flags_ & OBJECT_FLAG_ADDENDUM_MASK) >> OBJECT_FLAG_ADDENDUM_SHIFT);
|
||||
}
|
||||
|
||||
types::TypeNewScript *newScriptDontCheckGeneration() const {
|
||||
TypeNewScript *newScriptDontCheckGeneration() const {
|
||||
if (addendumKind() == Addendum_NewScript)
|
||||
return reinterpret_cast<types::TypeNewScript *>(addendum_);
|
||||
return reinterpret_cast<TypeNewScript *>(addendum_);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -313,7 +233,7 @@ class ObjectGroup : public gc::TenuredCell
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
types::TypeNewScript *anyNewScript();
|
||||
TypeNewScript *anyNewScript();
|
||||
void detachNewScript(bool writeBarrier);
|
||||
|
||||
public:
|
||||
@ -333,12 +253,12 @@ class ObjectGroup : public gc::TenuredCell
|
||||
flags_ &= ~flags;
|
||||
}
|
||||
|
||||
types::TypeNewScript *newScript() {
|
||||
TypeNewScript *newScript() {
|
||||
maybeSweep(nullptr);
|
||||
return newScriptDontCheckGeneration();
|
||||
}
|
||||
|
||||
void setNewScript(types::TypeNewScript *newScript) {
|
||||
void setNewScript(TypeNewScript *newScript) {
|
||||
setAddendum(Addendum_NewScript, newScript);
|
||||
}
|
||||
|
||||
@ -385,13 +305,71 @@ class ObjectGroup : public gc::TenuredCell
|
||||
setAddendum(Addendum_InterpretedFunction, fun);
|
||||
}
|
||||
|
||||
class Property
|
||||
{
|
||||
public:
|
||||
// Identifier for this property, JSID_VOID for the aggregate integer
|
||||
// index property, or JSID_EMPTY for properties holding constraints
|
||||
// listening to changes in the group's state.
|
||||
HeapId id;
|
||||
|
||||
// Possible own types for this property.
|
||||
HeapTypeSet types;
|
||||
|
||||
explicit Property(jsid id)
|
||||
: id(id)
|
||||
{}
|
||||
|
||||
Property(const Property &o)
|
||||
: id(o.id.get()), types(o.types)
|
||||
{}
|
||||
|
||||
static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
|
||||
static jsid getKey(Property *p) { return p->id; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Properties of this object. This may contain JSID_VOID, representing the
|
||||
// types of all integer indexes of the object, and/or JSID_EMPTY, holding
|
||||
// constraints listening to changes to the object's state.
|
||||
//
|
||||
// See types::Property for more detail about the types represented here.
|
||||
types::Property **propertySet;
|
||||
/*
|
||||
* Properties of this object.
|
||||
*
|
||||
* The type sets in the properties of a group describe the possible values
|
||||
* that can be read out of that property in actual JS objects. In native
|
||||
* objects, property types account for plain data properties (those with a
|
||||
* slot and no getter or setter hook) and dense elements. In typed objects
|
||||
* and unboxed objects, property types account for object and value
|
||||
* properties and elements in the object.
|
||||
*
|
||||
* For accesses on these properties, the correspondence is as follows:
|
||||
*
|
||||
* 1. If the group has unknownProperties(), the possible properties and
|
||||
* value types for associated JSObjects are unknown.
|
||||
*
|
||||
* 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
|
||||
* in |obj|, before obj->getProperty(id) the property in |group| for
|
||||
* |id| must reflect the result of the getProperty.
|
||||
*
|
||||
* There are several exceptions to this:
|
||||
*
|
||||
* 1. For properties of global JS objects which are undefined at the point
|
||||
* where the property was (lazily) generated, the property type set will
|
||||
* remain empty, and the 'undefined' type will only be added after a
|
||||
* subsequent assignment or deletion. After these properties have been
|
||||
* assigned a defined value, the only way they can become undefined
|
||||
* again is after such an assign or deletion.
|
||||
*
|
||||
* 2. Array lengths are special cased by the compiler and VM and are not
|
||||
* reflected in property types.
|
||||
*
|
||||
* 3. In typed objects (but not unboxed objects), the initial values of
|
||||
* properties (null pointers and undefined values) are not reflected in
|
||||
* the property types. These values are always possible when reading the
|
||||
* property.
|
||||
*
|
||||
* We establish these by using write barriers on calls to setProperty and
|
||||
* defineProperty which are on native properties, and on any jitcode which
|
||||
* might update the property with a new type.
|
||||
*/
|
||||
Property **propertySet;
|
||||
public:
|
||||
|
||||
inline ObjectGroup(const Class *clasp, TaggedProto proto, ObjectGroupFlags initialFlags);
|
||||
@ -415,7 +393,7 @@ class ObjectGroup : public gc::TenuredCell
|
||||
return hasAnyFlags(OBJECT_FLAG_PRE_TENURE) && !unknownProperties();
|
||||
}
|
||||
|
||||
gc::InitialHeap initialHeap(types::CompilerConstraintList *constraints);
|
||||
gc::InitialHeap initialHeap(CompilerConstraintList *constraints);
|
||||
|
||||
bool canPreTenure() {
|
||||
return !unknownProperties();
|
||||
@ -434,17 +412,17 @@ class ObjectGroup : public gc::TenuredCell
|
||||
* Get or create a property of this object. Only call this for properties which
|
||||
* a script accesses explicitly.
|
||||
*/
|
||||
inline types::HeapTypeSet *getProperty(ExclusiveContext *cx, jsid id);
|
||||
inline HeapTypeSet *getProperty(ExclusiveContext *cx, jsid id);
|
||||
|
||||
/* Get a property only if it already exists. */
|
||||
inline types::HeapTypeSet *maybeGetProperty(jsid id);
|
||||
inline HeapTypeSet *maybeGetProperty(jsid id);
|
||||
|
||||
inline unsigned getPropertyCount();
|
||||
inline types::Property *getProperty(unsigned i);
|
||||
inline Property *getProperty(unsigned i);
|
||||
|
||||
/* Helpers */
|
||||
|
||||
void updateNewPropertyTypes(ExclusiveContext *cx, jsid id, types::HeapTypeSet *types);
|
||||
void updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types);
|
||||
bool addDefiniteProperties(ExclusiveContext *cx, Shape *shape);
|
||||
bool matchDefiniteProperties(HandleObject obj);
|
||||
void markPropertyNonData(ExclusiveContext *cx, jsid id);
|
||||
@ -460,7 +438,7 @@ class ObjectGroup : public gc::TenuredCell
|
||||
void print();
|
||||
|
||||
inline void clearProperties();
|
||||
void maybeSweep(types::AutoClearTypeInferenceStateOnOOM *oom);
|
||||
void maybeSweep(AutoClearTypeInferenceStateOnOOM *oom);
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
@ -568,12 +546,13 @@ class ObjectGroup : public gc::TenuredCell
|
||||
static ArrayObject *getCopyOnWriteObject(JSScript *script, jsbytecode *pc);
|
||||
|
||||
// Returns false if not found.
|
||||
static bool findAllocationSiteForType(JSContext *cx, types::Type type,
|
||||
JSScript **script, uint32_t *offset);
|
||||
static bool findAllocationSite(JSContext *cx, ObjectGroup *group,
|
||||
JSScript **script, uint32_t *offset);
|
||||
|
||||
private:
|
||||
static ObjectGroup *defaultNewGroup(JSContext *cx, JSProtoKey key);
|
||||
static void setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj, types::Type type);
|
||||
static void setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj,
|
||||
TypeSet::Type type);
|
||||
};
|
||||
|
||||
// Structure used to manage the groups in a compartment.
|
||||
|
@ -66,7 +66,7 @@ ProxyObject::New(JSContext *cx, const BaseProxyHandler *handler, HandleValue pri
|
||||
|
||||
/* Don't track types of properties of non-DOM and non-singleton proxies. */
|
||||
if (newKind != SingletonObject && !clasp->isDOMClass())
|
||||
types::MarkObjectGroupUnknownProperties(cx, proxy->group());
|
||||
MarkObjectGroupUnknownProperties(cx, proxy->group());
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
@ -738,8 +738,8 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext *cx)
|
||||
|
||||
// Make sure type information reflects the indexed properties which might
|
||||
// be added.
|
||||
types::AddTypePropertyId(cx, templateObject, JSID_VOID, types::Type::StringType());
|
||||
types::AddTypePropertyId(cx, templateObject, JSID_VOID, types::Type::UndefinedType());
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::StringType());
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
|
||||
|
||||
matchResultTemplateObject_.set(templateObject);
|
||||
|
||||
|
@ -76,7 +76,7 @@ RegExpStatics::markFlagsSet(JSContext *cx)
|
||||
// always be performed).
|
||||
MOZ_ASSERT_IF(cx->global()->hasRegExpStatics(), this == cx->global()->getRegExpStatics(cx));
|
||||
|
||||
types::MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_REGEXP_FLAGS_SET);
|
||||
MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_REGEXP_FLAGS_SET);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -24,7 +24,7 @@ ScopeObject::setAliasedVar(JSContext *cx, ScopeCoordinate sc, PropertyName *name
|
||||
|
||||
if (isSingleton()) {
|
||||
MOZ_ASSERT(name);
|
||||
types::AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
|
||||
// Keep track of properties which have ever been overwritten.
|
||||
if (!getSlot(sc.slot()).isUndefined()) {
|
||||
@ -42,7 +42,7 @@ CallObject::setAliasedVar(JSContext *cx, AliasedFormalIter fi, PropertyName *nam
|
||||
MOZ_ASSERT(name == fi->name());
|
||||
setSlot(fi.scopeSlot(), v);
|
||||
if (isSingleton())
|
||||
types::AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -50,7 +50,7 @@ CallObject::setAliasedVarFromArguments(JSContext *cx, const Value &argsValue, js
|
||||
{
|
||||
setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v);
|
||||
if (isSingleton())
|
||||
types::AddTypePropertyId(cx, this, id, v);
|
||||
AddTypePropertyId(cx, this, id, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::PodZero;
|
||||
|
||||
|
@ -893,7 +893,7 @@ NativeObject::changeProperty(ExclusiveContext *cx, HandleNativeObject obj,
|
||||
MOZ_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
|
||||
!(attrs & JSPROP_SHARED));
|
||||
|
||||
types::MarkTypePropertyNonData(cx, obj, shape->propid());
|
||||
MarkTypePropertyNonData(cx, obj, shape->propid());
|
||||
|
||||
if (!CheckCanChangeAttrs(cx, obj, shape, &attrs))
|
||||
return nullptr;
|
||||
|
@ -47,7 +47,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::IsNaN;
|
||||
using mozilla::NegativeInfinity;
|
||||
|
@ -47,7 +47,6 @@
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::IsNaN;
|
||||
using mozilla::NegativeInfinity;
|
||||
|
@ -42,10 +42,10 @@ UnboxedLayout::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
}
|
||||
|
||||
void
|
||||
UnboxedLayout::setNewScript(types::TypeNewScript *newScript, bool writeBarrier /* = true */)
|
||||
UnboxedLayout::setNewScript(TypeNewScript *newScript, bool writeBarrier /* = true */)
|
||||
{
|
||||
if (newScript_ && writeBarrier)
|
||||
types::TypeNewScript::writeBarrierPre(newScript_);
|
||||
TypeNewScript::writeBarrierPre(newScript_);
|
||||
newScript_ = newScript;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ UnboxedPlainObject::setValue(JSContext *cx, const UnboxedLayout::Property &prope
|
||||
// Update property types when writing object properties. Types for
|
||||
// other properties were captured when the unboxed layout was
|
||||
// created.
|
||||
types::AddTypePropertyId(cx, this, NameToId(property.name), v);
|
||||
AddTypePropertyId(cx, this, NameToId(property.name), v);
|
||||
|
||||
*reinterpret_cast<HeapPtrObject*>(p) = v.toObjectOrNull();
|
||||
return true;
|
||||
@ -440,7 +440,7 @@ PropertiesAreSuperset(const UnboxedLayout::PropertyVector &properties, UnboxedLa
|
||||
|
||||
bool
|
||||
js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
ObjectGroup *group, types::PreliminaryObjectArray *objects)
|
||||
ObjectGroup *group, PreliminaryObjectArray *objects)
|
||||
{
|
||||
if (!cx->runtime()->options().unboxedObjects())
|
||||
return true;
|
||||
@ -453,7 +453,7 @@ js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
return false;
|
||||
|
||||
size_t objectCount = 0;
|
||||
for (size_t i = 0; i < types::PreliminaryObjectArray::COUNT; i++) {
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
JSObject *obj = objects->get(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
@ -625,7 +625,7 @@ js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
Vector<Value, 0, SystemAllocPolicy> values;
|
||||
if (!values.reserve(objectCount * templateShape->slotSpan()))
|
||||
return false;
|
||||
for (size_t i = 0; i < types::PreliminaryObjectArray::COUNT; i++) {
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
if (!objects->get(i))
|
||||
continue;
|
||||
|
||||
@ -639,14 +639,14 @@ js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
obj->setLastPropertyMakeNonNative(newShape);
|
||||
}
|
||||
|
||||
if (types::TypeNewScript *newScript = group->newScript())
|
||||
if (TypeNewScript *newScript = group->newScript())
|
||||
layout->setNewScript(newScript);
|
||||
|
||||
group->setClasp(&UnboxedPlainObject::class_);
|
||||
group->setUnboxedLayout(layout.get());
|
||||
|
||||
size_t valueCursor = 0;
|
||||
for (size_t i = 0; i < types::PreliminaryObjectArray::COUNT; i++) {
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
if (!objects->get(i))
|
||||
continue;
|
||||
UnboxedPlainObject *obj = &objects->get(i)->as<UnboxedPlainObject>();
|
||||
|
@ -58,7 +58,7 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
|
||||
size_t size_;
|
||||
|
||||
// Any 'new' script information associated with this layout.
|
||||
types::TypeNewScript *newScript_;
|
||||
TypeNewScript *newScript_;
|
||||
|
||||
// List for use in tracing objects with this layout. This has the same
|
||||
// structure as the trace list on a TypeDescr.
|
||||
@ -80,11 +80,11 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
|
||||
return properties_;
|
||||
}
|
||||
|
||||
types::TypeNewScript *newScript() const {
|
||||
TypeNewScript *newScript() const {
|
||||
return newScript_;
|
||||
}
|
||||
|
||||
void setNewScript(types::TypeNewScript *newScript, bool writeBarrier = true);
|
||||
void setNewScript(TypeNewScript *newScript, bool writeBarrier = true);
|
||||
|
||||
const int32_t *traceList() const {
|
||||
return traceList_;
|
||||
@ -182,7 +182,7 @@ class UnboxedPlainObject : public JSObject
|
||||
// preliminary objects and their group to the new unboxed representation.
|
||||
bool
|
||||
TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
ObjectGroup *group, types::PreliminaryObjectArray *objects);
|
||||
ObjectGroup *group, PreliminaryObjectArray *objects);
|
||||
|
||||
inline gc::AllocKind
|
||||
UnboxedLayout::getAllocKind() const
|
||||
|
@ -1,4 +1,4 @@
|
||||
#filter substitution;
|
||||
#filter substitution
|
||||
/* 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/. */
|
||||
@ -63,13 +63,6 @@ let AppConstants = Object.freeze({
|
||||
false,
|
||||
#endif
|
||||
|
||||
MOZ_DEVICES:
|
||||
#ifdef MOZ_DEVICES
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
MOZ_SAFE_BROWSING:
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
true,
|
||||
|
Loading…
Reference in New Issue
Block a user